Skip to content

Commit

Permalink
test: add toWarnDev custom Jest matcher (#3574)
Browse files Browse the repository at this point in the history
  • Loading branch information
francoischalifour authored Mar 4, 2019
1 parent 9f84c67 commit adebe38
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 43 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"lint:fix": "eslint . --fix && tslint --project . --fix",
"type-check": "tsc",
"type-check:watch": "yarn type-check --watch",
"test": "jest",
"test:watch": "jest --watch --bail",
"test": "jest --config scripts/jest/config.js",
"test:watch": "jest --config scripts/jest/config.js --watch --bail",
"test:size": "bundlesize",
"test:functional": "wdio functional-tests/wdio.conf.js",
"test:functional:dev": "babel-node scripts/dev-functional-tests",
Expand Down Expand Up @@ -78,6 +78,7 @@
"@types/enzyme": "^3.1.15",
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/jest": "^24.0.0",
"@types/jest-diff": "^20.0.1",
"@types/lodash": "^4.14.120",
"@types/react": "^16.7.20",
"@types/react-dom": "^16.0.11",
Expand Down Expand Up @@ -113,6 +114,7 @@
"express": "4.16.4",
"inquirer": "6.2.2",
"jest": "24.1.0",
"jest-diff": "24.0.0",
"jest-watch-typeahead": "0.2.1",
"jsdom-global": "3.0.2",
"json": "9.0.6",
Expand Down
3 changes: 2 additions & 1 deletion jest.config.js → scripts/jest/config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable import/no-commonjs */

module.exports = {
rootDir: process.cwd(),
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/dist*',
'<rootDir>/functional-tests',
],
setupFilesAfterEnv: ['./scripts/jestInit.js'],
setupFilesAfterEnv: ['./scripts/jest/setupTests.js'],
watchPlugins: [
'jest-watch-typeahead/filename',
'jest-watch-typeahead/testname',
Expand Down
50 changes: 50 additions & 0 deletions scripts/jest/matchers/__tests__/toWarnDev-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* tslint:disable:no-console */

describe('toWarnDev', () => {
describe('usage', () => {
test('fails with incorrect type of message', () => {
expect(() => {
// @ts-ignore:next-line
expect(() => {}).toWarnDev(false);
}).toThrowErrorMatchingInlineSnapshot(
`"toWarnDev() requires a parameter of type string but was given boolean."`
);
});
});

if (__DEV__) {
describe('without message', () => {
test('does not fail if called', () => {
expect(() => {
expect(() => {
console.warn('warning');
}).toWarnDev();
}).not.toThrow();
});

test('fails if not called', () => {
expect(() => {
expect(() => {}).toWarnDev();
}).toThrowErrorMatchingInlineSnapshot(`"No warning recorded."`);
});
});

describe('with message', () => {
test('does not fail with correct message', () => {
expect(() => {
expect(() => {
console.warn('warning');
}).toWarnDev('warning');
}).not.toThrow();
});

test('fails if a warning is not correct', () => {
expect(() => {
expect(() => {
console.warn('warning');
}).toWarnDev('another warning');
}).toThrow(/Unexpected warning recorded./);
});
});
}
});
1 change: 1 addition & 0 deletions scripts/jest/matchers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as toWarnDev } from './toWarnDev';
64 changes: 64 additions & 0 deletions scripts/jest/matchers/toWarnDev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* tslint:disable:no-console */
import jestDiff from 'jest-diff';

declare global {
namespace jest {
interface Matchers<R> {
toWarnDev(expectedMessage?: string): R;
}
}
}

const matcher = {
toWarnDev: (callback: () => void, expectedMessage: string) => {
if (expectedMessage !== undefined && typeof expectedMessage !== 'string') {
throw new Error(
`toWarnDev() requires a parameter of type string but was given ${typeof expectedMessage}.`
);
}

if (!__DEV__) {
callback();

return { pass: true };
}

const originalWarnMethod = console.warn;
let calledTimes = 0;
let actualWarning = '';

console.warn = (message: string) => {
calledTimes++;
actualWarning = message;
};

callback();

console.warn = originalWarnMethod;

// Expectation without any message.
// We only check that `console.warn` was called.
if (expectedMessage === undefined && calledTimes === 0) {
return {
pass: false,
message: () => 'No warning recorded.',
};
}

// Expectation with a message.
if (expectedMessage !== undefined && actualWarning !== expectedMessage) {
return {
pass: false,
message: () => `Unexpected warning recorded.
Difference:
${jestDiff(expectedMessage, actualWarning)}`,
};
}

return { pass: true };
},
};

export default matcher;
2 changes: 2 additions & 0 deletions scripts/jestInit.js → scripts/jest/setupTests.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { createSerializer } from 'enzyme-to-json';
import { toWarnDev } from './matchers';

Enzyme.configure({ adapter: new Adapter() });
expect.addSnapshotSerializer(createSerializer({ mode: 'deep' }));
expect.extend(toWarnDev);
9 changes: 3 additions & 6 deletions src/connectors/breadcrumb/__tests__/connectBreadcrumb-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,13 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
}

// when there is an identical hierarchicalFacets into current configuration
{
const spy = jest.spyOn(global.console, 'warn');
expect(() => {
const config = widget.getConfiguration({
hierarchicalFacets: [{ name: 'category' }],
});

expect(config).toEqual({});
expect(spy).toHaveBeenCalled();
spy.mockReset();
spy.mockRestore();
}
}).toWarnDev();

// when there is already a different hierarchicalFacets into current configuration
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,13 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica
}

// when there is an identical hierarchicalFacets into current configuration
{
const spy = jest.spyOn(global.console, 'warn');
expect(() => {
const config = widget.getConfiguration({
hierarchicalFacets: [{ name: 'category' }],
});

expect(config).toEqual({});
expect(spy).toHaveBeenCalled();
spy.mockReset();
spy.mockRestore();
}
}).toWarnDev();

// when there is already a different hierarchicalFacets into current configuration
{
Expand Down
27 changes: 11 additions & 16 deletions src/widgets/hits-per-page/__tests__/hits-per-page-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,9 @@ describe('hitsPerPage()', () => {
let widget;
let helper;
let results;
let consoleWarn;
let state;

beforeEach(() => {
consoleWarn = jest.spyOn(window.console, 'warn');

container = document.createElement('div');
items = [
{ value: 10, label: '10 results' },
Expand Down Expand Up @@ -117,22 +114,24 @@ describe('hitsPerPage()', () => {
expect(helper.search).toHaveBeenCalledTimes(1, 'search called once');
});

it('should throw if there is no name attribute in a passed object', () => {
it('should warn without name attribute in a passed item', () => {
items.length = 0;
items.push({ label: 'Label without a value' });
widget.init({ state: helper.state, helper });
expect(consoleWarn).toHaveBeenCalledTimes(1, 'console.warn called once');
expect(consoleWarn.mock.calls[0][0]).toMatchInlineSnapshot(
`"[InstantSearch.js]: No items in HitsPerPage \`items\` with \`value: hitsPerPage\` (hitsPerPage: 20)"`

expect(() => {
widget.init({ state: helper.state, helper });
}).toWarnDev(
'[InstantSearch.js]: No items in HitsPerPage `items` with `value: hitsPerPage` (hitsPerPage: 20)'
);
});

it('must include the current hitsPerPage at initialization time', () => {
helper.state.hitsPerPage = -1;
widget.init({ state: helper.state, helper });
expect(consoleWarn).toHaveBeenCalledTimes(1, 'console.warn called once');
expect(consoleWarn.mock.calls[0][0]).toMatchInlineSnapshot(
`"[InstantSearch.js]: No items in HitsPerPage \`items\` with \`value: hitsPerPage\` (hitsPerPage: -1)"`

expect(() => {
widget.init({ state: helper.state, helper });
}).toWarnDev(
'[InstantSearch.js]: No items in HitsPerPage `items` with `value: hitsPerPage` (hitsPerPage: -1)'
);
});

Expand All @@ -142,8 +141,4 @@ describe('hitsPerPage()', () => {
widget.init({ state: helper.state, helper });
}).not.toThrow(/No item in `items`/);
});

afterEach(() => {
consoleWarn.mockRestore();
});
});
15 changes: 5 additions & 10 deletions src/widgets/panel/__tests__/panel-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,13 @@ describe('Usage', () => {
});

test('with `hidden` as boolean warns', () => {
const warn = jest.spyOn(global.console, 'warn');
warn.mockImplementation(() => {});

panel({
hidden: true,
});

expect(warn).toHaveBeenCalledWith(
expect(() => {
panel({
hidden: true,
});
}).toWarnDev(
'[InstantSearch.js]: The `hidden` option in the "panel" widget expects a function returning a boolean (received "boolean" type).'
);

warn.mockRestore();
});

test('with a widget without `container` throws', () => {
Expand Down
3 changes: 2 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"object-literal-sort-keys": false,
"ordered-imports": false,
"prettier": true,
"jsx-no-lambda": false
"jsx-no-lambda": false,
"no-empty": false
}
}
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,11 @@
"@types/minimatch" "*"
"@types/node" "*"

"@types/jest-diff@^20.0.1":
version "20.0.1"
resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89"
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==

"@types/jest@^24.0.0":
version "24.0.1"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.1.tgz#8945411140e7cdfd5ea76380e5f5fa7bf17646ea"
Expand Down Expand Up @@ -7028,7 +7033,7 @@ jest-config@^24.1.0:
pretty-format "^24.0.0"
realpath-native "^1.0.2"

jest-diff@^24.0.0:
jest-diff@24.0.0, jest-diff@^24.0.0:
version "24.0.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34"
integrity sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA==
Expand Down

0 comments on commit adebe38

Please sign in to comment.