Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate if spy or mock was passed when expected #203

Merged
merged 2 commits into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ Received second mock with invocationCallOrder:
<red>[]</>"
`;

exports[`.toHaveBeenCalledAfter fails when given first value is not a jest spy or mock 1`] = `
"<dim>expect(</><red>received</><dim>).toHaveBeenCalledAfter(</><green>expected</><dim>)</>

Matcher error: <red>\\"received\\"</> must be a mock or spy function

Received has type: function
Received has value: <red>[Function mock1]</>"
`;

exports[`.toHaveBeenCalledAfter fails when given second mock is called after first mock 1`] = `
"<dim>expect(</><red>received</><dim>).toHaveBeenCalledAfter(</><green>expected</><dim>)</>

Expand All @@ -53,3 +62,12 @@ Expected first mock to have been called after, invocationCallOrder:
Received second mock with invocationCallOrder:
<red>[5000]</>"
`;

exports[`.toHaveBeenCalledAfter fails when given second value is not a jest spy or mock 1`] = `
"<dim>expect(</><red>received</><dim>).toHaveBeenCalledAfter(</><green>expected</><dim>)</>

Matcher error: <green>\\"expected\\"</> must be a mock or spy function

Expected has type: function
Expected has value: <green>[Function mock2]</>"
`;
25 changes: 24 additions & 1 deletion src/matchers/toHaveBeenCalledAfter/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils';
import { matcherHint, printExpected, printReceived, printWithType } from 'jest-matcher-utils';

import { isJestMockOrSpy } from '../../utils';

import predicate from './predicate';

Expand All @@ -18,8 +20,29 @@ const failMessage = (firstInvocationCallOrder, secondInvocationCallOrder) => ()
'Received second mock with invocationCallOrder:\n' +
` ${printReceived(secondInvocationCallOrder)}`;

const mockCheckFailMessage = (value, isReceivedValue) => () => {
const valueKind = isReceivedValue ? 'Received' : 'Expected';
const valueKindPrintFunc = isReceivedValue ? printReceived : printExpected;

return (
matcherHint('.toHaveBeenCalledAfter') +
'\n\n' +
`Matcher error: ${valueKindPrintFunc(valueKind.toLowerCase())} must be a mock or spy function` +
'\n\n' +
printWithType(valueKind, value, valueKindPrintFunc)
);
};

export default {
toHaveBeenCalledAfter: (firstMock, secondMock) => {
if (!isJestMockOrSpy(firstMock)) {
return { pass: false, message: mockCheckFailMessage(firstMock, true) };
}

if (!isJestMockOrSpy(secondMock)) {
return { pass: false, message: mockCheckFailMessage(secondMock, false) };
}

const firstInvocationCallOrder = firstMock.mock.invocationCallOrder;
const secondInvocationCallOrder = secondMock.mock.invocationCallOrder;
const pass = predicate(firstInvocationCallOrder, secondInvocationCallOrder);
Expand Down
12 changes: 12 additions & 0 deletions src/matchers/toHaveBeenCalledAfter/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ describe('.toHaveBeenCalledAfter', () => {
mock2.mock.invocationCallOrder[0] = 4000;
expect(mock1).toHaveBeenCalledAfter(mock2);
});

test('fails when given first value is not a jest spy or mock', () => {
const mock1 = () => {};
const mock2 = jest.fn();
expect(() => expect(mock1).toHaveBeenCalledAfter(mock2)).toThrowErrorMatchingSnapshot();
});

test('fails when given second value is not a jest spy or mock', () => {
const mock1 = jest.fn();
const mock2 = () => {};
expect(() => expect(mock1).toHaveBeenCalledAfter(mock2)).toThrowErrorMatchingSnapshot();
});
});

describe('.not.toHaveBeenCalledAfter', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,21 @@ Expected first mock to have been called before, invocationCallOrder:
Received second mock with invocationCallOrder:
<red>[4000]</>"
`;

exports[`.toHaveBeenCalledBefore fails when given first value is not a jest spy or mock 1`] = `
"<dim>expect(</><red>received</><dim>).toHaveBeenCalledAfter(</><green>expected</><dim>)</>

Matcher error: <red>\\"received\\"</> must be a mock or spy function

Received has type: function
Received has value: <red>[Function mock1]</>"
`;

exports[`.toHaveBeenCalledBefore fails when given second value is not a jest spy or mock 1`] = `
"<dim>expect(</><red>received</><dim>).toHaveBeenCalledAfter(</><green>expected</><dim>)</>

Matcher error: <green>\\"expected\\"</> must be a mock or spy function

Expected has type: function
Expected has value: <green>[Function mock2]</>"
`;
25 changes: 24 additions & 1 deletion src/matchers/toHaveBeenCalledBefore/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils';
import { matcherHint, printExpected, printReceived, printWithType } from 'jest-matcher-utils';

import { isJestMockOrSpy } from '../../utils';
atsikov marked this conversation as resolved.
Show resolved Hide resolved

import predicate from './predicate';

Expand All @@ -18,8 +20,29 @@ const failMessage = (firstInvocationCallOrder, secondInvocationCallOrder) => ()
'Received second mock with invocationCallOrder:\n' +
` ${printReceived(secondInvocationCallOrder)}`;

const mockCheckFailMessage = (value, isReceivedValue) => () => {
const valueKind = isReceivedValue ? 'Received' : 'Expected';
const valueKindPrintFunc = isReceivedValue ? printReceived : printExpected;

return (
matcherHint('.toHaveBeenCalledAfter') +
'\n\n' +
`Matcher error: ${valueKindPrintFunc(valueKind.toLowerCase())} must be a mock or spy function` +
'\n\n' +
printWithType(valueKind, value, valueKindPrintFunc)
);
};

export default {
toHaveBeenCalledBefore: (firstMock, secondMock) => {
if (!isJestMockOrSpy(firstMock)) {
return { pass: false, message: mockCheckFailMessage(firstMock, true) };
}

if (!isJestMockOrSpy(secondMock)) {
return { pass: false, message: mockCheckFailMessage(secondMock, false) };
}

const firstInvocationCallOrder = firstMock.mock.invocationCallOrder;
const secondInvocationCallOrder = secondMock.mock.invocationCallOrder;
const pass = predicate(firstInvocationCallOrder, secondInvocationCallOrder);
Expand Down
12 changes: 12 additions & 0 deletions src/matchers/toHaveBeenCalledBefore/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ describe('.toHaveBeenCalledBefore', () => {
mock2.mock.invocationCallOrder[0] = 4000;
expect(() => expect(mock1).toHaveBeenCalledBefore(mock2)).toThrowErrorMatchingSnapshot();
});

test('fails when given first value is not a jest spy or mock', () => {
const mock1 = () => {};
const mock2 = jest.fn();
expect(() => expect(mock1).toHaveBeenCalledBefore(mock2)).toThrowErrorMatchingSnapshot();
});

test('fails when given second value is not a jest spy or mock', () => {
const mock1 = jest.fn();
const mock2 = () => {};
expect(() => expect(mock1).toHaveBeenCalledBefore(mock2)).toThrowErrorMatchingSnapshot();
});
});

describe('.not.toHaveBeenCalledBefore', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ export const determinePropertyMessage = (actual, property, message = 'Not Access
return actual && Object.hasOwnProperty.call(actual, property) ? actual[property] : message;
};

export const isJestMockOrSpy = value => {
return !!(value && value._isMockFunction === true && typeof value.mock === 'object');
};

export { equals };
14 changes: 13 additions & 1 deletion src/utils/index.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { contains, determinePropertyMessage } from './';
import { contains, determinePropertyMessage, isJestMockOrSpy } from './';

describe('Utils', () => {
describe('.contains', () => {
Expand Down Expand Up @@ -48,4 +48,16 @@ describe('Utils', () => {
});
}
});

describe('.isJestMockOrSpy', () => {
test('returns true if value is a jest mock', () => {
const spy = jest.fn();
expect(isJestMockOrSpy(spy)).toBe(true);
});

test('returns false if value is not a jest mock', () => {
const fn = () => {};
expect(isJestMockOrSpy(fn)).toBe(false);
});
});
});