Skip to content

Commit

Permalink
Fix returned promises
Browse files Browse the repository at this point in the history
  • Loading branch information
mattphillips committed Sep 28, 2022
1 parent 51e5a0e commit 7dbdf04
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 57 deletions.
11 changes: 9 additions & 2 deletions src/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ class JestAssertionError extends Error {
const chainMatchers = (matchers, originalMatchers = matchers) => {
const mappedMatchers = Object.keys(matchers).map((name) => {
const matcher = matchers[name];

if (typeof matcher === "function") {
const newMatcher = (...args) => {
try {
matcher(...args); // run matcher
return chainMatchers(originalMatchers); // chain the original matchers again
const result = matcher(...args); // run matcher
if (result && typeof result.then === "function") {
return Object.assign(Promise.resolve(result), chainMatchers(originalMatchers));
} else {
return chainMatchers(originalMatchers); // chain the original matchers again
}
} catch (error) {
if (!error.matcherResult) {
throw error;
Expand All @@ -27,10 +32,12 @@ const chainMatchers = (matchers, originalMatchers = matchers) => {
};
return { [name]: newMatcher };
}

return {
[name]: chainMatchers(matcher, originalMatchers), // recurse on .not/.resolves/.rejects
};
});

return Object.assign({}, ...mappedMatchers);
};

Expand Down
100 changes: 46 additions & 54 deletions src/index.test.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,79 @@
import './index';
import "./index";

describe('jest-chain', () => {
it('chains top level matchers', () => {
expect(1)
.toBe(1)
.toBeGreaterThan(0)
.toBeLessThan(2);
describe("jest-chain", () => {
it("chains top level matchers", () => {
expect(1).toBe(1).toBeGreaterThan(0).toBeLessThan(2);
});

it('chains nested level matchers', () => {
expect(1)
.toBe(1)
.not.toBe(0)
.toBeGreaterThan(0)
.not.toBeGreaterThan(1)
.toBeLessThan(2)
.not.toBeLessThan(1);
it("chains nested level matchers", () => {
expect(1).toBe(1).not.toBe(0).toBeGreaterThan(0).not.toBeGreaterThan(1).toBeLessThan(2).not.toBeLessThan(1);
});

it('chains custom matchers from jest-extended', () => {
expect(1)
.toBe(1)
.toBeGreaterThan(0)
.toBeLessThan(2)
.toBePositive()
.not.toBeNegative();
it("chains custom matchers from jest-extended", () => {
expect(1).toBe(1).toBeGreaterThan(0).toBeLessThan(2).toBePositive().not.toBeNegative();
});

describe('fails fast', () => {
it('throws error from first matcher: toBe when 1 != 2', () => {
expect(() =>
expect(1)
.toBe(2)
.toBeGreaterThan(1)
.toBeLessThan(1)
).toThrowErrorMatchingSnapshot();
describe("fails fast", () => {
it("throws error from first matcher: toBe when 1 != 2", () => {
expect(() => expect(1).toBe(2).toBeGreaterThan(1).toBeLessThan(1)).toThrowErrorMatchingSnapshot();
});

it('throws error from second matcher: toBeGreaterThan when 1 !> 1', () => {
expect(() =>
expect(1)
.toBe(1)
.toBeGreaterThan(1)
.toBeLessThan(1)
).toThrowErrorMatchingSnapshot();
it("throws error from second matcher: toBeGreaterThan when 1 !> 1", () => {
expect(() => expect(1).toBe(1).toBeGreaterThan(1).toBeLessThan(1)).toThrowErrorMatchingSnapshot();
});

it('throws error from second matcher: toBeLessThan when 1 !< 1', () => {
expect(() =>
expect(1)
.toBe(1)
.toBeGreaterThan(0)
.toBeLessThan(1)
).toThrowErrorMatchingSnapshot();
it("throws error from second matcher: toBeLessThan when 1 !< 1", () => {
expect(() => expect(1).toBe(1).toBeGreaterThan(0).toBeLessThan(1)).toThrowErrorMatchingSnapshot();
});
});

describe('supports custom matchers registered after jest-chain', () => {
describe("supports custom matchers registered after jest-chain", () => {
expect.extend({
toBeDivisibleBy(received, argument) {
const pass = received % argument == 0;
const message = pass
? () => `expected ${received} not to be divisible by ${argument}`
: () => `expected ${received} to be divisible by ${argument}`;
return { message, pass };
}
},
});

it('chains new custom matchers with existing ones', () => {
it("chains new custom matchers with existing ones", () => {
expect(100).toBeDivisibleBy(2);
expect(101).not.toBeDivisibleBy(2);
expect(100)
.toBeDivisibleBy(2)
.toBePositive()
.not.toBeNegative()
.toBe(100);
expect(100).toBeDivisibleBy(2).toBePositive().not.toBeNegative().toBe(100);
});

it('supports custom asymmetric matchers', () => {
it("supports custom asymmetric matchers", () => {
expect({ apples: 6, bananas: 3 }).toEqual({
apples: expect.toBeDivisibleBy(2),
bananas: expect.not.toBeDivisibleBy(2)
bananas: expect.not.toBeDivisibleBy(2),
});
});
});

// I don't think this is something that needs solving in this library
it.failing("can be used as the direct return value for a test function", () =>
expect(3).toBeGreaterThan(1).toBeLessThan(5)
);

describe("Supports promises", () => {
it("can be used with resolves", () =>
expect(Promise.resolve(7)).resolves.toBeLessThan(10).resolves.not.toBeLessThan(5));

it("can be used with rejects", () =>
expect(Promise.reject(7)).rejects.toBeLessThan(10).rejects.not.toBeLessThan(5));

it("can be used with async/await", async () => {
expect.assertions(2);
expect(await Promise.resolve("lemon"))
.toBe("lemon")
.not.toBe("banana");
});

it("can be used with async/await with throwing promise", async () => {
expect.assertions(2);
await expect(Promise.reject("lemon")).rejects.toBe("lemon").not.toBe("banana");
});
});
});
2 changes: 1 addition & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ declare namespace jest {
interface ChainedMatchers<T>
extends jest.JestMatchersShape<
Matchers<ChainedMatchers<T>, T>,
Matchers<Promise<ChainedMatchers<T>>, T>
Matchers<Promise<ChainedMatchers<T>> & ChainedMatchers<T>, T>
> {}

interface Expect {
Expand Down

0 comments on commit 7dbdf04

Please sign in to comment.