From 0e935bdf9030fa14acaf68d34290b119623e4416 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 00:54:40 +0100 Subject: [PATCH 01/31] Add jest-each dependencies --- packages/jest-jasmine2/package.json | 1 + yarn.lock | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index ca7cfe6a401b..6d220d83f2e7 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -14,6 +14,7 @@ "graceful-fs": "^4.1.11", "is-generator-fn": "^1.0.0", "jest-diff": "^22.4.0", + "jest-each": "^0.5.0", "jest-matcher-utils": "^22.4.0", "jest-message-util": "^22.4.0", "jest-snapshot": "^22.4.0", diff --git a/yarn.lock b/yarn.lock index 42375b3dc0b8..a7defb7c45b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5152,6 +5152,12 @@ jest-docblock@^21, jest-docblock@^21.0.0, jest-docblock@^21.2.0: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" +jest-each@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-0.5.0.tgz#7065a599e18349163d0dcde40f49f09df6901666" + dependencies: + sprintf-js "^1.0.3" + jest-haste-map@^21: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" @@ -8768,6 +8774,10 @@ split@^1.0.0: dependencies: through "2" +sprintf-js@^1.0.3: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" From 82587f7d29950c918ece1dbfe29d9a2f0349a30c Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 00:55:13 +0100 Subject: [PATCH 02/31] Add each binding to test globals --- .../jest-jasmine2/src/__tests__/each.test.js | 69 +++++++++++++++++++ packages/jest-jasmine2/src/index.js | 35 ++++++++++ 2 files changed, 104 insertions(+) create mode 100644 packages/jest-jasmine2/src/__tests__/each.test.js diff --git a/packages/jest-jasmine2/src/__tests__/each.test.js b/packages/jest-jasmine2/src/__tests__/each.test.js new file mode 100644 index 000000000000..bdd22d34115f --- /dev/null +++ b/packages/jest-jasmine2/src/__tests__/each.test.js @@ -0,0 +1,69 @@ +describe('Data driven tests', () => { + describe('jest-each.array', () => { + describe('.test.each', () => { + test.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + 'returns result of adding %s to %s', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + ); + }); + + describe('.it.each', () => { + it.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + 'returns result of adding %s to %s', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + ); + }); + + describe('.describe.each', () => { + describe.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + '.add(%s, %s)', + (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + }, + ); + }); + }); + + describe('jest-each.template', () => { + describe('.test.each', () => { + test.each` + a | b | expected + ${0} | ${0} | ${0} + ${1} | ${1} | ${2} + ${5} | ${10} | ${15} + `('returns $expected when adding $a to $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + }); + + describe('.it.each', () => { + it.each` + a | b | expected + ${0} | ${0} | ${0} + ${1} | ${1} | ${2} + ${5} | ${10} | ${15} + `('returns $expected when adding $a to $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + }); + + describe('.describe.each', () => { + describe.each` + a | b | expected + ${0} | ${0} | ${0} + ${1} | ${1} | ${2} + ${5} | ${10} | ${15} + `('.add($a, $b)', ({a, b, expected}) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + }); + }); + }); +}); diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 3e822d1420c8..c7f2ad70490a 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -16,6 +16,7 @@ import type Runtime from 'jest-runtime'; import path from 'path'; import fs from 'graceful-fs'; +import each from 'jest-each'; import {getCallsite} from 'jest-util'; import JasmineReporter from './reporter'; import {install as jasmineAsyncInstall} from './jasmine_async'; @@ -69,6 +70,40 @@ async function jasmine2( environment.global.describe.skip = environment.global.xdescribe; environment.global.describe.only = environment.global.fdescribe; + const bindEach = key => { + environment.global[key].each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + [key](title, test); + }; + + const bindEachToNested = (parent, child) => { + environment.global[parent][child].each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + [parent][child](title, test); + }; + + [ + 'test', + 'xtest', + 'it', + 'describe', + 'fit', + 'xdescribe', + 'fdescribe', + 'xit', + ].forEach(key => bindEach(key)); + + [ + ['test', 'only'], + ['test', 'skip'], + ['it', 'only'], + ['it', 'skip'], + ['describe', 'only'], + ['describe', 'skip'], + ].forEach(entry => bindEachToNested(...entry)); + if (config.timers === 'fake') { environment.fakeTimers.useFakeTimers(); } From 246018dc19253cf242a0f0e82b08c39732de7bd9 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 01:12:46 +0100 Subject: [PATCH 03/31] Update changelog with PR --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f54f01397e32..79bddedd52cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +* `[jest-jasmine2]` Add data driven testing with `jest-each` + ([#6102](https://github.com/facebook/jest/pull/6102)) * `[jest-message-util]` Don't ignore messages with `vendor` anymore ([#6117](https://github.com/facebook/jest/pull/6117)) * `[jest-validate]` Get rid of `jest-config` dependency From cdf325c3cc9d7a3e3ccca6bd3177057203ae9c12 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 01:29:03 +0100 Subject: [PATCH 04/31] Add test for nested each property on test.only.each --- packages/jest-jasmine2/src/__tests__/each-only.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 packages/jest-jasmine2/src/__tests__/each-only.test.js diff --git a/packages/jest-jasmine2/src/__tests__/each-only.test.js b/packages/jest-jasmine2/src/__tests__/each-only.test.js new file mode 100644 index 000000000000..5b9d677bd3af --- /dev/null +++ b/packages/jest-jasmine2/src/__tests__/each-only.test.js @@ -0,0 +1,8 @@ +describe('.test.only.each', () => { + test.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + 'returns result of adding %s to %s', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + ); +}); From 4b9f59dfac55e39ec9b33265d9e1e6e1f2e53a12 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 08:55:33 +0100 Subject: [PATCH 05/31] Refactor programatic binding to be explicit --- packages/jest-jasmine2/src/index.js | 64 ++++++++++++++--------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index c7f2ad70490a..77446402e8d1 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -63,6 +63,36 @@ async function jasmine2( jasmineAsyncInstall(environment.global); + environment.global.it.each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + .it(title, test); + + environment.global.fit.each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + .fit(title, test); + + environment.global.xit.each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + .xit(title, test); + + environment.global.describe.each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + .describe(title, test); + + environment.global.xdescribe.each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + .xdescribe(title, test); + + environment.global.fdescribe.each = (...args) => (title, test) => + each + .withGlobal(environment.global)(...args) + .fdescribe(title, test); + environment.global.test = environment.global.it; environment.global.it.only = environment.global.fit; environment.global.it.skip = environment.global.xit; @@ -70,40 +100,6 @@ async function jasmine2( environment.global.describe.skip = environment.global.xdescribe; environment.global.describe.only = environment.global.fdescribe; - const bindEach = key => { - environment.global[key].each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - [key](title, test); - }; - - const bindEachToNested = (parent, child) => { - environment.global[parent][child].each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - [parent][child](title, test); - }; - - [ - 'test', - 'xtest', - 'it', - 'describe', - 'fit', - 'xdescribe', - 'fdescribe', - 'xit', - ].forEach(key => bindEach(key)); - - [ - ['test', 'only'], - ['test', 'skip'], - ['it', 'only'], - ['it', 'skip'], - ['describe', 'only'], - ['describe', 'skip'], - ].forEach(entry => bindEachToNested(...entry)); - if (config.timers === 'fake') { environment.fakeTimers.useFakeTimers(); } From c642c0e0b9a52748cb996fe3f7fb466dfd09a415 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 08:55:58 +0100 Subject: [PATCH 06/31] Add missing .only --- packages/jest-jasmine2/src/__tests__/each-only.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-jasmine2/src/__tests__/each-only.test.js b/packages/jest-jasmine2/src/__tests__/each-only.test.js index 5b9d677bd3af..013dc28cd298 100644 --- a/packages/jest-jasmine2/src/__tests__/each-only.test.js +++ b/packages/jest-jasmine2/src/__tests__/each-only.test.js @@ -1,5 +1,5 @@ describe('.test.only.each', () => { - test.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + test.only.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( 'returns result of adding %s to %s', (a, b, expected) => { expect(a + b).toBe(expected); From 9e480616ebe67dce26313416a41d3c5d4da4d8ea Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:17:39 +0100 Subject: [PATCH 07/31] Remove jest-each and add sprint-f --- packages/jest-jasmine2/package.json | 4 ++-- yarn.lock | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 6d220d83f2e7..5c2fe5635282 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -14,13 +14,13 @@ "graceful-fs": "^4.1.11", "is-generator-fn": "^1.0.0", "jest-diff": "^22.4.0", - "jest-each": "^0.5.0", "jest-matcher-utils": "^22.4.0", "jest-message-util": "^22.4.0", "jest-snapshot": "^22.4.0", "jest-util": "^22.4.1", "pretty-format": "^22.4.0", - "source-map-support": "^0.5.0" + "source-map-support": "^0.5.0", + "sprintf-js": "^1.1.1" }, "devDependencies": { "jest-runtime": "^22.4.2" diff --git a/yarn.lock b/yarn.lock index a7defb7c45b0..a8cb568a7d88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5152,12 +5152,6 @@ jest-docblock@^21, jest-docblock@^21.0.0, jest-docblock@^21.2.0: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" -jest-each@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-0.5.0.tgz#7065a599e18349163d0dcde40f49f09df6901666" - dependencies: - sprintf-js "^1.0.3" - jest-haste-map@^21: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" @@ -8774,7 +8768,7 @@ split@^1.0.0: dependencies: through "2" -sprintf-js@^1.0.3: +sprintf-js@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" From ded9335d32dfd38ec7d6024d91e76ec2a3b89827 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:18:26 +0100 Subject: [PATCH 08/31] Add jest each array source --- .../jest-jasmine2/src/__tests__/each.test.js | 165 ++++++++++++------ packages/jest-jasmine2/src/each.js | 27 +++ 2 files changed, 135 insertions(+), 57 deletions(-) create mode 100644 packages/jest-jasmine2/src/each.js diff --git a/packages/jest-jasmine2/src/__tests__/each.test.js b/packages/jest-jasmine2/src/__tests__/each.test.js index bdd22d34115f..0ae1766a1041 100644 --- a/packages/jest-jasmine2/src/__tests__/each.test.js +++ b/packages/jest-jasmine2/src/__tests__/each.test.js @@ -1,68 +1,119 @@ -describe('Data driven tests', () => { - describe('jest-each.array', () => { - describe('.test.each', () => { - test.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - 'returns result of adding %s to %s', - (a, b, expected) => { - expect(a + b).toBe(expected); - }, - ); - }); +import installEach from '../each'; - describe('.it.each', () => { - it.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - 'returns result of adding %s to %s', - (a, b, expected) => { - expect(a + b).toBe(expected); - }, - ); - }); +const noop = () => {}; +const expectFunction = expect.any(Function); - describe('.describe.each', () => { - describe.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - '.add(%s, %s)', - (a, b, expected) => { - test(`returns ${expected}`, () => { - expect(a + b).toBe(expected); - }); - }, - ); - }); - }); +describe('installEach', () => { + [ + ['it'], + ['fit'], + ['xit'], + ['describe'], + ['fdescribe'], + ['xdescribe'], + ].forEach(keyPath => { + describe(`.${keyPath.join('.')}`, () => { + const getEnvironmentMock = () => { + return { + global: { + describe: jest.fn(), + fdescribe: jest.fn(), + fit: jest.fn(), + it: jest.fn(), + xdescribe: jest.fn(), + xit: jest.fn(), + }, + }; + }; + + test('calls global function with given title', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; - describe('jest-each.template', () => { - describe('.test.each', () => { - test.each` - a | b | expected - ${0} | ${0} | ${0} - ${1} | ${1} | ${2} - ${5} | ${10} | ${15} - `('returns $expected when adding $a to $b', ({a, b, expected}) => { - expect(a + b).toBe(expected); + globalMock.each([[]])('expected string', noop); + + expect(globalMock).toHaveBeenCalledTimes(1); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); }); - }); - describe('.it.each', () => { - it.each` - a | b | expected - ${0} | ${0} | ${0} - ${1} | ${1} | ${2} - ${5} | ${10} | ${15} - `('returns $expected when adding $a to $b', ({a, b, expected}) => { - expect(a + b).toBe(expected); + test('calls global function with given title when multiple tests cases exist', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + + globalMock.each([[], []])('expected string', noop); + + expect(globalMock).toHaveBeenCalledTimes(2); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); }); - }); - describe('.describe.each', () => { - describe.each` - a | b | expected - ${0} | ${0} | ${0} - ${1} | ${1} | ${2} - ${5} | ${10} | ${15} - `('.add($a, $b)', ({a, b, expected}) => { - test(`returns ${expected}`, () => { - expect(a + b).toBe(expected); + test('calls global function with title containing param values when using sprintf format', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + + globalMock.each([['hello', 1], ['world', 2]])( + 'expected string: %s %s', + noop, + ); + + expect(globalMock).toHaveBeenCalledTimes(2); + expect(globalMock).toHaveBeenCalledWith( + 'expected string: hello 1', + expectFunction, + ); + expect(globalMock).toHaveBeenCalledWith( + 'expected string: world 2', + expectFunction, + ); + }); + + test('calls global function with cb function containing all parameters of each test case', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + const testCallBack = jest.fn(); + globalMock.each([['hello', 'world'], ['joe', 'bloggs']])( + 'expected string: %s %s', + testCallBack, + ); + + globalMock.mock.calls[0][1](); + expect(testCallBack).toHaveBeenCalledTimes(1); + expect(testCallBack).toHaveBeenCalledWith('hello', 'world'); + + globalMock.mock.calls[1][1](); + expect(testCallBack).toHaveBeenCalledTimes(2); + expect(testCallBack).toHaveBeenCalledWith('joe', 'bloggs'); + }); + + test('calls global function with async done when cb function has more args than params of given test row', () => { + expect.hasAssertions(); + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + globalMock.each([['hello']])('a title', (hello, done) => { + expect(hello).toBe('hello'); + expect(done).toBe('DONE'); }); + + globalMock.mock.calls[0][1]('DONE'); }); }); }); diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js new file mode 100644 index 000000000000..b6659706dea4 --- /dev/null +++ b/packages/jest-jasmine2/src/each.js @@ -0,0 +1,27 @@ +import type {Environment} from 'types/Environment'; + +import {vsprintf} from 'sprintf-js'; + +type Table = Array>; + +export default (environment: Environment): void => { + environment.global.it.each = bindEach(environment.global.it); + environment.global.fit.each = bindEach(environment.global.fit); + environment.global.xit.each = bindEach(environment.global.xit); + environment.global.describe.each = bindEach(environment.global.describe); + environment.global.xdescribe.each = bindEach(environment.global.xdescribe); + environment.global.fdescribe.each = bindEach(environment.global.fdescribe); +}; + +const bindEach = (cb: Function) => (table: Table) => ( + title: string, + test: Function, +): void => { + table.forEach(row => cb(vsprintf(title, row), applyRestParams(row, test))); +}; + +const applyRestParams = (params: Array, test: Function) => { + if (params.length < test.length) return done => test(...params, done); + + return () => test(...params); +}; From e8c4d77c8ffc4efb2f3d2ec81ae426e5eb2b20a5 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:19:11 +0100 Subject: [PATCH 09/31] Remove jest-each for internal each installation --- packages/jest-jasmine2/src/index.js | 32 ++--------------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 77446402e8d1..785fa5cf0548 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -16,7 +16,7 @@ import type Runtime from 'jest-runtime'; import path from 'path'; import fs from 'graceful-fs'; -import each from 'jest-each'; +import installEach from './each'; import {getCallsite} from 'jest-util'; import JasmineReporter from './reporter'; import {install as jasmineAsyncInstall} from './jasmine_async'; @@ -63,35 +63,7 @@ async function jasmine2( jasmineAsyncInstall(environment.global); - environment.global.it.each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - .it(title, test); - - environment.global.fit.each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - .fit(title, test); - - environment.global.xit.each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - .xit(title, test); - - environment.global.describe.each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - .describe(title, test); - - environment.global.xdescribe.each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - .xdescribe(title, test); - - environment.global.fdescribe.each = (...args) => (title, test) => - each - .withGlobal(environment.global)(...args) - .fdescribe(title, test); + installEach(environment); environment.global.test = environment.global.it; environment.global.it.only = environment.global.fit; From bb1680c1b91be1c0032f31ab3a5232a0b61dbb51 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:32:43 +0100 Subject: [PATCH 10/31] Add tagged template literal each logic --- .../__tests__/__snapshots__/each.test.js.snap | 73 +++++ .../jest-jasmine2/src/__tests__/each.test.js | 288 +++++++++++++----- packages/jest-jasmine2/src/each.js | 58 +++- 3 files changed, 346 insertions(+), 73 deletions(-) create mode 100644 packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap diff --git a/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap b/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap new file mode 100644 index 000000000000..42036299e4f2 --- /dev/null +++ b/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`installEach .describe Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1,1,1,1" +`; + +exports[`installEach .describe Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1" +`; + +exports[`installEach .fdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1,1,1,1" +`; + +exports[`installEach .fdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1" +`; + +exports[`installEach .fit Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1,1,1,1" +`; + +exports[`installEach .fit Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1" +`; + +exports[`installEach .it Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1,1,1,1" +`; + +exports[`installEach .it Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1" +`; + +exports[`installEach .xdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1,1,1,1" +`; + +exports[`installEach .xdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1" +`; + +exports[`installEach .xit Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1,1,1,1" +`; + +exports[`installEach .xit Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` +"Tagged Template Literal test error: +Not enough arguments supplied for given headings: a | b | expected +Received: 0,1" +`; diff --git a/packages/jest-jasmine2/src/__tests__/each.test.js b/packages/jest-jasmine2/src/__tests__/each.test.js index 0ae1766a1041..9b43b00adb4c 100644 --- a/packages/jest-jasmine2/src/__tests__/each.test.js +++ b/packages/jest-jasmine2/src/__tests__/each.test.js @@ -26,94 +26,240 @@ describe('installEach', () => { }; }; - test('calls global function with given title', () => { - const environmentMock = getEnvironmentMock(); - installEach(environmentMock); + describe('Table Array', () => { + test('calls global function with given title', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); - const globalMock = environmentMock.global[keyPath]; + const globalMock = environmentMock.global[keyPath]; - globalMock.each([[]])('expected string', noop); + globalMock.each([[]])('expected string', noop); - expect(globalMock).toHaveBeenCalledTimes(1); - expect(globalMock).toHaveBeenCalledWith( - 'expected string', - expectFunction, - ); - }); + expect(globalMock).toHaveBeenCalledTimes(1); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + }); - test('calls global function with given title when multiple tests cases exist', () => { - const environmentMock = getEnvironmentMock(); - installEach(environmentMock); + test('calls global function with given title when multiple tests cases exist', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); - const globalMock = environmentMock.global[keyPath]; + const globalMock = environmentMock.global[keyPath]; - globalMock.each([[], []])('expected string', noop); + globalMock.each([[], []])('expected string', noop); - expect(globalMock).toHaveBeenCalledTimes(2); - expect(globalMock).toHaveBeenCalledWith( - 'expected string', - expectFunction, - ); - expect(globalMock).toHaveBeenCalledWith( - 'expected string', - expectFunction, - ); - }); + expect(globalMock).toHaveBeenCalledTimes(2); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + }); - test('calls global function with title containing param values when using sprintf format', () => { - const environmentMock = getEnvironmentMock(); - installEach(environmentMock); - - const globalMock = environmentMock.global[keyPath]; - - globalMock.each([['hello', 1], ['world', 2]])( - 'expected string: %s %s', - noop, - ); - - expect(globalMock).toHaveBeenCalledTimes(2); - expect(globalMock).toHaveBeenCalledWith( - 'expected string: hello 1', - expectFunction, - ); - expect(globalMock).toHaveBeenCalledWith( - 'expected string: world 2', - expectFunction, - ); - }); + test('calls global function with title containing param values when using sprintf format', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; - test('calls global function with cb function containing all parameters of each test case', () => { - const environmentMock = getEnvironmentMock(); - installEach(environmentMock); + globalMock.each([['hello', 1], ['world', 2]])( + 'expected string: %s %s', + noop, + ); - const globalMock = environmentMock.global[keyPath]; - const testCallBack = jest.fn(); - globalMock.each([['hello', 'world'], ['joe', 'bloggs']])( - 'expected string: %s %s', - testCallBack, - ); + expect(globalMock).toHaveBeenCalledTimes(2); + expect(globalMock).toHaveBeenCalledWith( + 'expected string: hello 1', + expectFunction, + ); + expect(globalMock).toHaveBeenCalledWith( + 'expected string: world 2', + expectFunction, + ); + }); + + test('calls global function with cb function containing all parameters of each test case', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + const testCallBack = jest.fn(); + globalMock.each([['hello', 'world'], ['joe', 'bloggs']])( + 'expected string: %s %s', + testCallBack, + ); + + globalMock.mock.calls[0][1](); + expect(testCallBack).toHaveBeenCalledTimes(1); + expect(testCallBack).toHaveBeenCalledWith('hello', 'world'); + + globalMock.mock.calls[1][1](); + expect(testCallBack).toHaveBeenCalledTimes(2); + expect(testCallBack).toHaveBeenCalledWith('joe', 'bloggs'); + }); - globalMock.mock.calls[0][1](); - expect(testCallBack).toHaveBeenCalledTimes(1); - expect(testCallBack).toHaveBeenCalledWith('hello', 'world'); + test('calls global function with async done when cb function has more args than params of given test row', () => { + expect.hasAssertions(); + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); - globalMock.mock.calls[1][1](); - expect(testCallBack).toHaveBeenCalledTimes(2); - expect(testCallBack).toHaveBeenCalledWith('joe', 'bloggs'); + const globalMock = environmentMock.global[keyPath]; + globalMock.each([['hello']])('a title', (hello, done) => { + expect(hello).toBe('hello'); + expect(done).toBe('DONE'); + }); + + globalMock.mock.calls[0][1]('DONE'); + }); }); - test('calls global function with async done when cb function has more args than params of given test row', () => { - expect.hasAssertions(); - const environmentMock = getEnvironmentMock(); - installEach(environmentMock); + describe('Table Tagged Template Literal', () => { + test('throws error when there are fewer arguments than headings when given one row', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + const testCallBack = jest.fn(); - const globalMock = environmentMock.global[keyPath]; - globalMock.each([['hello']])('a title', (hello, done) => { - expect(hello).toBe('hello'); - expect(done).toBe('DONE'); + globalMock.each` + a | b | expected + ${0} | ${1} | + `('this will blow up :(', testCallBack); + + expect(() => + globalMock.mock.calls[0][1](), + ).toThrowErrorMatchingSnapshot(); + expect(testCallBack).not.toHaveBeenCalled(); }); - globalMock.mock.calls[0][1]('DONE'); + test('throws error when there are fewer arguments than headings over multiple rows', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + const testCallBack = jest.fn(); + + globalMock.each` + a | b | expected + ${0} | ${1} | ${1} + ${1} | ${1} | + `('this will blow up :(', testCallBack); + + expect(() => + globalMock.mock.calls[0][1](), + ).toThrowErrorMatchingSnapshot(); + expect(testCallBack).not.toHaveBeenCalled(); + }); + + test('calls global function with given title', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + + globalMock.each` + a | b | expected + ${0} | ${1} | ${1} + `('expected string', noop); + + expect(globalMock).toHaveBeenCalledTimes(1); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + }); + + test('calls global function with given title when multiple tests cases exist', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + + globalMock.each` + a | b | expected + ${0} | ${1} | ${1} + ${1} | ${1} | ${2} + `('expected string', noop); + + expect(globalMock).toHaveBeenCalledTimes(2); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + expect(globalMock).toHaveBeenCalledWith( + 'expected string', + expectFunction, + ); + }); + + test('calls global function with title containing param values when using $variable format', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + + globalMock.each` + a | b | expected + ${0} | ${1} | ${1} + ${1} | ${1} | ${2} + `('expected string: a=$a, b=$b, expected=$expected', noop); + + expect(globalMock).toHaveBeenCalledTimes(2); + expect(globalMock).toHaveBeenCalledWith( + 'expected string: a=0, b=1, expected=1', + expectFunction, + ); + expect(globalMock).toHaveBeenCalledWith( + 'expected string: a=1, b=1, expected=2', + expectFunction, + ); + }); + + test('calls global function with cb function containing all parameters of each test case', () => { + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + const testCallBack = jest.fn(); + globalMock.each` + a | b | expected + ${0} | ${1} | ${1} + ${1} | ${1} | ${2} + `('expected string: %s %s', testCallBack); + + globalMock.mock.calls[0][1](); + expect(testCallBack).toHaveBeenCalledTimes(1); + + expect(testCallBack).toHaveBeenCalledWith({a: 0, b: 1, expected: 1}); + + globalMock.mock.calls[1][1](); + expect(testCallBack).toHaveBeenCalledTimes(2); + expect(testCallBack).toHaveBeenCalledWith({a: 1, b: 1, expected: 2}); + }); + + test('calls global function with async done when cb function has more than one argument', () => { + expect.hasAssertions(); + const environmentMock = getEnvironmentMock(); + installEach(environmentMock); + + const globalMock = environmentMock.global[keyPath]; + globalMock.each` + a | b | expected + ${0} | ${1} | ${1} + `('a title', ({a, b, expected}, done) => { + expect(a).toBe(0); + expect(b).toBe(1); + expect(expected).toBe(1); + expect(done).toBe('DONE'); + }); + + globalMock.mock.calls[0][1]('DONE'); + }); }); }); }); diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index b6659706dea4..b77866a11653 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -13,11 +13,36 @@ export default (environment: Environment): void => { environment.global.fdescribe.each = bindEach(environment.global.fdescribe); }; -const bindEach = (cb: Function) => (table: Table) => ( +const bindEach = (cb: Function) => (...args: any) => ( title: string, test: Function, ): void => { - table.forEach(row => cb(vsprintf(title, row), applyRestParams(row, test))); + if (args.length === 1) { + const table: Table = args[0]; + return table.forEach(row => + cb(vsprintf(title, row), applyRestParams(row, test)), + ); + } + + const templateStrings = args[0]; + const data = args.slice(1); + + const keys = getHeadingKeys(templateStrings[0]); + const table = buildTable(data, keys.length, keys); + + if (data.length % keys.length !== 0) { + cb(title, () => { + throw new Error( + `Tagged Template Literal test error:\nNot enough arguments supplied for given headings: ${keys.join( + ' | ', + )}\nReceived: ${data}`, + ); + }); + } + + table.forEach(row => + cb(interpolate(title, row), applyObjectParams(row, test)), + ); }; const applyRestParams = (params: Array, test: Function) => { @@ -25,3 +50,32 @@ const applyRestParams = (params: Array, test: Function) => { return () => test(...params); }; + +const getHeadingKeys = (headings: string): Array => + headings.replace(/\s/g, '').split('|'); + +const buildTable = ( + data: Array, + rowSize: number, + keys: Array, +): Table => + Array.from({length: data.length / rowSize}) + .map((_, index) => data.slice(index * rowSize, index * rowSize + rowSize)) + .map(row => + row.reduce( + (acc, value, index) => Object.assign({}, acc, {[keys[index]]: value}), + {}, + ), + ); + +const interpolate = (title: string, data: any) => + Object.keys(data).reduce( + (acc, key) => acc.replace('$' + key, data[key]), + title, + ); + +const applyObjectParams = (obj: any, test: Function) => { + if (test.length > 1) return done => test(obj, done); + + return () => test(obj); +}; From 121ba14e18028740e2cf2d03531ab165e32ec02e Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:34:44 +0100 Subject: [PATCH 11/31] Add integration tests --- .../{ => integration}/each-only.test.js | 0 .../__tests__/integration/each-skip.test.js | 8 +++ .../src/__tests__/integration/each.test.js | 69 +++++++++++++++++++ 3 files changed, 77 insertions(+) rename packages/jest-jasmine2/src/__tests__/{ => integration}/each-only.test.js (100%) create mode 100644 packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js create mode 100644 packages/jest-jasmine2/src/__tests__/integration/each.test.js diff --git a/packages/jest-jasmine2/src/__tests__/each-only.test.js b/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js similarity index 100% rename from packages/jest-jasmine2/src/__tests__/each-only.test.js rename to packages/jest-jasmine2/src/__tests__/integration/each-only.test.js diff --git a/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js b/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js new file mode 100644 index 000000000000..68734f970dc1 --- /dev/null +++ b/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js @@ -0,0 +1,8 @@ +describe('.test.skip.each', () => { + test.skip.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + 'returns result of adding %s to %s', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + ); +}); diff --git a/packages/jest-jasmine2/src/__tests__/integration/each.test.js b/packages/jest-jasmine2/src/__tests__/integration/each.test.js new file mode 100644 index 000000000000..9a3cda1475a0 --- /dev/null +++ b/packages/jest-jasmine2/src/__tests__/integration/each.test.js @@ -0,0 +1,69 @@ +describe('Data driven tests', () => { + describe('array table', () => { + describe('.test.each', () => { + test.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + 'returns result of adding %s to %s', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + ); + }); + + describe('.it.each', () => { + it.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + 'returns result of adding %s to %s', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, + ); + }); + + describe('.describe.each', () => { + describe.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( + '.add(%s, %s)', + (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + }, + ); + }); + }); + + describe('template literal table', () => { + describe('.test.each', () => { + test.each` + a | b | expected + ${0} | ${0} | ${0} + ${1} | ${1} | ${2} + ${5} | ${10} | ${15} + `('returns $expected when adding $a to $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + }); + + describe('.it.each', () => { + it.each` + a | b | expected + ${0} | ${0} | ${0} + ${1} | ${1} | ${2} + ${5} | ${10} | ${15} + `('returns $expected when adding $a to $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + }); + + describe('.describe.each', () => { + describe.each` + a | b | expected + ${0} | ${0} | ${0} + ${1} | ${1} | ${2} + ${5} | ${10} | ${15} + `('.add($a, $b)', ({a, b, expected}) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + }); + }); + }); +}); From 9eb4d5bfe98c3397acf0ea373f1beda0b6fd407e Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:37:26 +0100 Subject: [PATCH 12/31] Add flow comment --- packages/jest-jasmine2/src/each.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index b77866a11653..5e503466748c 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -1,3 +1,6 @@ +/** + * @flow + */ import type {Environment} from 'types/Environment'; import {vsprintf} from 'sprintf-js'; From eabf14fb7cdcbe453f2b78e102a99c9867b81d78 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:43:03 +0100 Subject: [PATCH 13/31] Remove sprintf for node util.format --- packages/jest-jasmine2/package.json | 3 +-- packages/jest-jasmine2/src/each.js | 4 ++-- yarn.lock | 4 ---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 5c2fe5635282..ca7cfe6a401b 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -19,8 +19,7 @@ "jest-snapshot": "^22.4.0", "jest-util": "^22.4.1", "pretty-format": "^22.4.0", - "source-map-support": "^0.5.0", - "sprintf-js": "^1.1.1" + "source-map-support": "^0.5.0" }, "devDependencies": { "jest-runtime": "^22.4.2" diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index 5e503466748c..6bfc5929c01f 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -3,7 +3,7 @@ */ import type {Environment} from 'types/Environment'; -import {vsprintf} from 'sprintf-js'; +import util from 'util'; type Table = Array>; @@ -23,7 +23,7 @@ const bindEach = (cb: Function) => (...args: any) => ( if (args.length === 1) { const table: Table = args[0]; return table.forEach(row => - cb(vsprintf(title, row), applyRestParams(row, test)), + cb(util.format(title, ...row), applyRestParams(row, test)), ); } diff --git a/yarn.lock b/yarn.lock index a8cb568a7d88..42375b3dc0b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8768,10 +8768,6 @@ split@^1.0.0: dependencies: through "2" -sprintf-js@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" From 652737bd006cba36d7deb19e35d4abb109a5c4a9 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 11:45:58 +0100 Subject: [PATCH 14/31] Add license to new files --- packages/jest-jasmine2/src/__tests__/each.test.js | 8 ++++++++ .../src/__tests__/integration/each-only.test.js | 8 ++++++++ .../src/__tests__/integration/each-skip.test.js | 8 ++++++++ .../jest-jasmine2/src/__tests__/integration/each.test.js | 8 ++++++++ packages/jest-jasmine2/src/each.js | 6 ++++++ 5 files changed, 38 insertions(+) diff --git a/packages/jest-jasmine2/src/__tests__/each.test.js b/packages/jest-jasmine2/src/__tests__/each.test.js index 9b43b00adb4c..98a5c79f6c66 100644 --- a/packages/jest-jasmine2/src/__tests__/each.test.js +++ b/packages/jest-jasmine2/src/__tests__/each.test.js @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + import installEach from '../each'; const noop = () => {}; diff --git a/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js b/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js index 013dc28cd298..0aeeba989d21 100644 --- a/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js +++ b/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + describe('.test.only.each', () => { test.only.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( 'returns result of adding %s to %s', diff --git a/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js b/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js index 68734f970dc1..bcb84fe994c6 100644 --- a/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js +++ b/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + describe('.test.skip.each', () => { test.skip.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( 'returns result of adding %s to %s', diff --git a/packages/jest-jasmine2/src/__tests__/integration/each.test.js b/packages/jest-jasmine2/src/__tests__/integration/each.test.js index 9a3cda1475a0..b91ecf732761 100644 --- a/packages/jest-jasmine2/src/__tests__/integration/each.test.js +++ b/packages/jest-jasmine2/src/__tests__/integration/each.test.js @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + describe('Data driven tests', () => { describe('array table', () => { describe('.test.each', () => { diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index 6bfc5929c01f..47746608c1a9 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -1,6 +1,12 @@ /** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * * @flow */ + import type {Environment} from 'types/Environment'; import util from 'util'; From 45a88549d6d287cbf4a90598e37b9519d8b7e766 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 12:06:19 +0100 Subject: [PATCH 15/31] Add integration tests --- .../each/__tests__/each-exception.test.js | 17 ++++ .../each/__tests__/each-only.test.js | 39 ++++++++++ .../each/__tests__/each-skip.test.js | 39 ++++++++++ .../each/__tests__/failure.test.js | 55 +++++++++++++ .../each/__tests__/success.test.js | 55 +++++++++++++ integration-tests/each/package.json | 5 ++ .../__tests__/integration/each-only.test.js | 16 ---- .../__tests__/integration/each-skip.test.js | 16 ---- .../src/__tests__/integration/each.test.js | 77 ------------------- 9 files changed, 210 insertions(+), 109 deletions(-) create mode 100644 integration-tests/each/__tests__/each-exception.test.js create mode 100644 integration-tests/each/__tests__/each-only.test.js create mode 100644 integration-tests/each/__tests__/each-skip.test.js create mode 100644 integration-tests/each/__tests__/failure.test.js create mode 100644 integration-tests/each/__tests__/success.test.js create mode 100644 integration-tests/each/package.json delete mode 100644 packages/jest-jasmine2/src/__tests__/integration/each-only.test.js delete mode 100644 packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js delete mode 100644 packages/jest-jasmine2/src/__tests__/integration/each.test.js diff --git a/integration-tests/each/__tests__/each-exception.test.js b/integration-tests/each/__tests__/each-exception.test.js new file mode 100644 index 000000000000..766fd719f649 --- /dev/null +++ b/integration-tests/each/__tests__/each-exception.test.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +it.each` + left | right + ${true} | ${true} + ${true} | +`( + 'throws exception when not enough arguments are supplied $left == $right', + ({left, right}) => { + expect(left).toBe(right); + } +); diff --git a/integration-tests/each/__tests__/each-only.test.js b/integration-tests/each/__tests__/each-only.test.js new file mode 100644 index 000000000000..a434a48f2b78 --- /dev/null +++ b/integration-tests/each/__tests__/each-only.test.js @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +it.only.each([[true, true], [true, true]])( + 'passes one row expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +it.each([[true, false], [true, true]])( + 'Should not be ran: fails all rows expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +it.only.each` + left | right + ${true} | ${true} + ${true} | ${true} +`('passes one row expected $left == $right', ({left, right}) => { + expect(left).toBe(right); +}); + +it.each` + left | right + ${true} | ${false} + ${true} | ${false} +`( + 'Should not be ran: fails all rows expected $left == $right', + ({left, right}) => { + expect(left).toBe(right); + } +); diff --git a/integration-tests/each/__tests__/each-skip.test.js b/integration-tests/each/__tests__/each-skip.test.js new file mode 100644 index 000000000000..08945a527331 --- /dev/null +++ b/integration-tests/each/__tests__/each-skip.test.js @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +it.each([[true, true], [true, true]])( + 'passes one row expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +it.skip.each([[true, false], [true, true]])( + 'Should not be ran: fails all rows expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +it.each` + left | right + ${true} | ${true} + ${true} | ${true} +`('passes one row expected $left == $right', ({left, right}) => { + expect(left).toBe(right); +}); + +it.skip.each` + left | right + ${true} | ${false} + ${true} | ${false} +`( + 'Should not be ran: fails all rows expected $left == $right', + ({left, right}) => { + expect(left).toBe(right); + } +); diff --git a/integration-tests/each/__tests__/failure.test.js b/integration-tests/each/__tests__/failure.test.js new file mode 100644 index 000000000000..1ab3069983ab --- /dev/null +++ b/integration-tests/each/__tests__/failure.test.js @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +it.each([[true, true], [true, false]])( + 'fails one row expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +it.each([[true, false], [true, false]])( + 'fails all rows expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +describe.each([[false, true], [true, false]])( + 'fails all rows expected %s == %s', + (left, right) => { + it('fails', () => { + expect(left).toBe(right); + }); + } +); + +it.each` + left | right + ${true} | ${false} + ${true} | ${true} +`('fails one row expected $left == $right', ({left, right}) => { + expect(left).toBe(right); +}); + +it.each` + left | right + ${true} | ${false} + ${true} | ${true} +`('fails all rows expected $left == $right', ({left, right}) => { + expect(left).toBe(right); +}); + +describe.each` + left | right + ${true} | ${false} + ${false} | ${true} +`('fails all rows expected $left == $right', ({left, right}) => { + it('fails ', () => { + expect(left).toBe(right); + }); +}); diff --git a/integration-tests/each/__tests__/success.test.js b/integration-tests/each/__tests__/success.test.js new file mode 100644 index 000000000000..9964f3c74c08 --- /dev/null +++ b/integration-tests/each/__tests__/success.test.js @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +it.each([[true, true], [true, true]])( + 'passes one row expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +it.each([[true, true], [true, true]])( + 'passes all rows expected %s == %s', + (left, right) => { + expect(left).toBe(right); + } +); + +describe.each([[true, true], [true, true]])( + 'passes all rows expected %s == %s', + (left, right) => { + it('passes', () => { + expect(left).toBe(right); + }); + } +); + +it.each` + left | right + ${true} | ${true} + ${true} | ${true} +`('passes one row expected $left == $right', ({left, right}) => { + expect(left).toBe(right); +}); + +it.each` + left | right + ${true} | ${true} + ${true} | ${true} +`('passes all rows expected $left == $right', ({left, right}) => { + expect(left).toBe(right); +}); + +describe.each` + left | right + ${true} | ${true} + ${true} | ${true} +`('passes all rows expected $left == $right', ({left, right}) => { + it('passes ', () => { + expect(left).toBe(right); + }); +}); diff --git a/integration-tests/each/package.json b/integration-tests/each/package.json new file mode 100644 index 000000000000..148788b25446 --- /dev/null +++ b/integration-tests/each/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "node" + } +} diff --git a/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js b/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js deleted file mode 100644 index 0aeeba989d21..000000000000 --- a/packages/jest-jasmine2/src/__tests__/integration/each-only.test.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -describe('.test.only.each', () => { - test.only.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - 'returns result of adding %s to %s', - (a, b, expected) => { - expect(a + b).toBe(expected); - }, - ); -}); diff --git a/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js b/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js deleted file mode 100644 index bcb84fe994c6..000000000000 --- a/packages/jest-jasmine2/src/__tests__/integration/each-skip.test.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -describe('.test.skip.each', () => { - test.skip.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - 'returns result of adding %s to %s', - (a, b, expected) => { - expect(a + b).toBe(expected); - }, - ); -}); diff --git a/packages/jest-jasmine2/src/__tests__/integration/each.test.js b/packages/jest-jasmine2/src/__tests__/integration/each.test.js deleted file mode 100644 index b91ecf732761..000000000000 --- a/packages/jest-jasmine2/src/__tests__/integration/each.test.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -describe('Data driven tests', () => { - describe('array table', () => { - describe('.test.each', () => { - test.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - 'returns result of adding %s to %s', - (a, b, expected) => { - expect(a + b).toBe(expected); - }, - ); - }); - - describe('.it.each', () => { - it.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - 'returns result of adding %s to %s', - (a, b, expected) => { - expect(a + b).toBe(expected); - }, - ); - }); - - describe('.describe.each', () => { - describe.each([[0, 0, 0], [1, 1, 2], [5, 10, 15]])( - '.add(%s, %s)', - (a, b, expected) => { - test(`returns ${expected}`, () => { - expect(a + b).toBe(expected); - }); - }, - ); - }); - }); - - describe('template literal table', () => { - describe('.test.each', () => { - test.each` - a | b | expected - ${0} | ${0} | ${0} - ${1} | ${1} | ${2} - ${5} | ${10} | ${15} - `('returns $expected when adding $a to $b', ({a, b, expected}) => { - expect(a + b).toBe(expected); - }); - }); - - describe('.it.each', () => { - it.each` - a | b | expected - ${0} | ${0} | ${0} - ${1} | ${1} | ${2} - ${5} | ${10} | ${15} - `('returns $expected when adding $a to $b', ({a, b, expected}) => { - expect(a + b).toBe(expected); - }); - }); - - describe('.describe.each', () => { - describe.each` - a | b | expected - ${0} | ${0} | ${0} - ${1} | ${1} | ${2} - ${5} | ${10} | ${15} - `('.add($a, $b)', ({a, b, expected}) => { - test(`returns ${expected}`, () => { - expect(a + b).toBe(expected); - }); - }); - }); - }); -}); From 34a6fb7d917abcd9fb2c199f5520e2ec5fbbdbdd Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 12:14:14 +0100 Subject: [PATCH 16/31] Fix flowtypes --- packages/jest-jasmine2/src/each.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index 47746608c1a9..2131416ee0bb 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -11,7 +11,7 @@ import type {Environment} from 'types/Environment'; import util from 'util'; -type Table = Array>; +type Table = Array>; export default (environment: Environment): void => { environment.global.it.each = bindEach(environment.global.it); @@ -67,7 +67,7 @@ const buildTable = ( data: Array, rowSize: number, keys: Array, -): Table => +): Array => Array.from({length: data.length / rowSize}) .map((_, index) => data.slice(index * rowSize, index * rowSize + rowSize)) .map(row => From df2ce3357bc2f8a9f27db0fe0639fe0e8da45ddf Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 12:30:29 +0100 Subject: [PATCH 17/31] Add assertions to integration tests --- .../__tests__/__snapshots__/each.test.js.snap | 212 ++++++++++++++++++ integration-tests/__tests__/each.test.js | 74 ++++++ 2 files changed, 286 insertions(+) create mode 100644 integration-tests/__tests__/__snapshots__/each.test.js.snap create mode 100644 integration-tests/__tests__/each.test.js diff --git a/integration-tests/__tests__/__snapshots__/each.test.js.snap b/integration-tests/__tests__/__snapshots__/each.test.js.snap new file mode 100644 index 000000000000..096799256689 --- /dev/null +++ b/integration-tests/__tests__/__snapshots__/each.test.js.snap @@ -0,0 +1,212 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`shows error message when not enough arguments are supplied to tests 1`] = ` +"FAIL __tests__/each-exception.test.js + ✕ throws exception when not enough arguments are supplied $left == $right + ✓ throws exception when not enough arguments are supplied true == true + + ● throws exception when not enough arguments are supplied $left == $right + + Tagged Template Literal test error: + Not enough arguments supplied for given headings: left | right + Received: true,true,true + + at packages/jest-jasmine2/build/each.js:75:17 + +" +`; + +exports[`shows only the tests with .only as being ran 1`] = ` +"PASS __tests__/each-only.test.js + ✓ passes one row expected true == true + ✓ passes one row expected true == true + ✓ passes one row expected true == true + ✓ passes one row expected true == true + ○ skipped 4 tests + +" +`; + +exports[`shows only the tests without .skip as being ran 1`] = ` +"PASS __tests__/each-skip.test.js + ✓ passes one row expected true == true + ✓ passes one row expected true == true + ✓ passes one row expected true == true + ✓ passes one row expected true == true + ○ skipped 4 tests + +" +`; + +exports[`shows the correct errors in stderr when failing tests 1`] = ` +"FAIL __tests__/failure.test.js +✓ fails one row expected true == true +✕ fails one row expected true == false +✕ fails all rows expected true == false +✕ fails all rows expected true == false +✕ fails one row expected true == false +✓ fails one row expected true == true +✕ fails all rows expected true == false +✓ fails all rows expected true == true +fails all rows expected false == true +✕ fails +✕ fails +fails all rows expected true == false +✕ fails +✕ fails + +● fails one row expected true == false + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +9 | 'fails one row expected %s == %s', +10 | (left, right) => { +> 11 | expect(left).toBe(right); +| ^ +12 | } +13 | ); +14 | + +at __tests__/failure.test.js:11:18 + +● fails all rows expected true == false + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +16 | 'fails all rows expected %s == %s', +17 | (left, right) => { +> 18 | expect(left).toBe(right); +| ^ +19 | } +20 | ); +21 | + +at __tests__/failure.test.js:18:18 + +● fails all rows expected true == false + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +16 | 'fails all rows expected %s == %s', +17 | (left, right) => { +> 18 | expect(left).toBe(right); +| ^ +19 | } +20 | ); +21 | + +at __tests__/failure.test.js:18:18 + +● fails all rows expected false == true › fails + +expect(received).toBe(expected) // Object.is equality + +Expected: true +Received: false + +24 | (left, right) => { +25 | it('fails', () => { +> 26 | expect(left).toBe(right); +| ^ +27 | }); +28 | } +29 | ); + +at __tests__/failure.test.js:26:20 + +● fails all rows expected true == false › fails + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +24 | (left, right) => { +25 | it('fails', () => { +> 26 | expect(left).toBe(right); +| ^ +27 | }); +28 | } +29 | ); + +at __tests__/failure.test.js:26:20 + +● fails one row expected true == false + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +34 | \${true} | \${true} +35 | \`('fails one row expected $left == $right', ({left, right}) => { +> 36 | expect(left).toBe(right); +| ^ +37 | }); +38 | +39 | it.each\` + +at __tests__/failure.test.js:36:16 + +● fails all rows expected true == false + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +42 | \${true} | \${true} +43 | \`('fails all rows expected $left == $right', ({left, right}) => { +> 44 | expect(left).toBe(right); +| ^ +45 | }); +46 | +47 | describe.each\` + +at __tests__/failure.test.js:44:16 + +● fails all rows expected true == false › fails + +expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true + +51 | \`('fails all rows expected $left == $right', ({left, right}) => { +52 | it('fails ', () => { +> 53 | expect(left).toBe(right); +| ^ +54 | }); +55 | }); +56 | + +at __tests__/failure.test.js:53:18 + +● fails all rows expected false == true › fails + +expect(received).toBe(expected) // Object.is equality + +Expected: true +Received: false + +51 | \`('fails all rows expected $left == $right', ({left, right}) => { +52 | it('fails ', () => { +> 53 | expect(left).toBe(right); +| ^ +54 | }); +55 | }); +56 | + +at __tests__/failure.test.js:53:18 + +" +`; diff --git a/integration-tests/__tests__/each.test.js b/integration-tests/__tests__/each.test.js new file mode 100644 index 000000000000..2cc5ae6f9eab --- /dev/null +++ b/integration-tests/__tests__/each.test.js @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +'use strict'; + +const path = require('path'); +const SkipOnWindows = require('../../scripts/SkipOnWindows'); +const runJest = require('../runJest'); +const {extractSummary} = require('../Utils'); +const dir = path.resolve(__dirname, '../each'); + +SkipOnWindows.suite(); + +test('works with passing tests', () => { + const result = runJest(dir, ['success.test.js']); + expect(result.status).toBe(0); +}); + +test('shows error message when not enough arguments are supplied to tests', () => { + const result = runJest(dir, ['each-exception.test.js']); + const rest = extractSummary(result.stderr) + .rest.split('\n') + .filter(line => line.indexOf('packages/expect/build/index.js') === -1) + .join('\n'); + + expect(result.status).toBe(1); + expect(rest).toMatchSnapshot(); +}); + +test('shows the correct errors in stderr when failing tests', () => { + const result = runJest(dir, ['failure.test.js']); + + expect(result.status).toBe(1); + + const rest = extractSummary(result.stderr) + .rest.split('\n') + .filter(line => line.indexOf('packages/expect/build/index.js') === -1) + .map(line => line.trim()) + .join('\n'); + + expect(rest).toMatchSnapshot(); +}); + +test('shows only the tests with .only as being ran', () => { + const result = runJest(dir, ['each-only.test.js']); + + expect(result.status).toBe(0); + + const rest = extractSummary(result.stderr) + .rest.split('\n') + .filter(line => line.indexOf('packages/expect/build/index.js') === -1) + .join('\n'); + + expect(rest).toMatchSnapshot(); +}); + +test('shows only the tests without .skip as being ran', () => { + const result = runJest(dir, ['each-skip.test.js']); + + expect(result.status).toBe(0); + + const rest = extractSummary(result.stderr) + .rest.split('\n') + .filter(line => line.indexOf('packages/expect/build/index.js') === -1) + .join('\n'); + + expect(rest).toMatchSnapshot(); +}); From 7e38e1de60ef7be3bc7ef859e384dae745074833 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 12:36:08 +0100 Subject: [PATCH 18/31] Fix linter --- packages/jest-jasmine2/src/each.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index 2131416ee0bb..bb9954ea9295 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -40,7 +40,7 @@ const bindEach = (cb: Function) => (...args: any) => ( const table = buildTable(data, keys.length, keys); if (data.length % keys.length !== 0) { - cb(title, () => { + return cb(title, () => { throw new Error( `Tagged Template Literal test error:\nNot enough arguments supplied for given headings: ${keys.join( ' | ', @@ -49,7 +49,7 @@ const bindEach = (cb: Function) => (...args: any) => ( }); } - table.forEach(row => + return table.forEach(row => cb(interpolate(title, row), applyObjectParams(row, test)), ); }; From e550eab7a71fe17497c53ad36ab11236d985d945 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 13:00:53 +0100 Subject: [PATCH 19/31] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79bddedd52cb..2bc126498f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -* `[jest-jasmine2]` Add data driven testing with `jest-each` +* `[jest-jasmine2]` Add data driven testing based on `jest-each` ([#6102](https://github.com/facebook/jest/pull/6102)) * `[jest-message-util]` Don't ignore messages with `vendor` anymore ([#6117](https://github.com/facebook/jest/pull/6117)) From 53016ac960f4da7732e5b13179d3dd2e9671f6dc Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 13:04:59 +0100 Subject: [PATCH 20/31] Remove normalisation of snapshots --- .../__tests__/__snapshots__/each.test.js.snap | 334 +++++++++--------- integration-tests/__tests__/each.test.js | 31 +- 2 files changed, 171 insertions(+), 194 deletions(-) diff --git a/integration-tests/__tests__/__snapshots__/each.test.js.snap b/integration-tests/__tests__/__snapshots__/each.test.js.snap index 096799256689..b3ffdb1e6394 100644 --- a/integration-tests/__tests__/__snapshots__/each.test.js.snap +++ b/integration-tests/__tests__/__snapshots__/each.test.js.snap @@ -40,173 +40,173 @@ exports[`shows only the tests without .skip as being ran 1`] = ` exports[`shows the correct errors in stderr when failing tests 1`] = ` "FAIL __tests__/failure.test.js -✓ fails one row expected true == true -✕ fails one row expected true == false -✕ fails all rows expected true == false -✕ fails all rows expected true == false -✕ fails one row expected true == false -✓ fails one row expected true == true -✕ fails all rows expected true == false -✓ fails all rows expected true == true -fails all rows expected false == true -✕ fails -✕ fails -fails all rows expected true == false -✕ fails -✕ fails - -● fails one row expected true == false - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -9 | 'fails one row expected %s == %s', -10 | (left, right) => { -> 11 | expect(left).toBe(right); -| ^ -12 | } -13 | ); -14 | - -at __tests__/failure.test.js:11:18 - -● fails all rows expected true == false - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -16 | 'fails all rows expected %s == %s', -17 | (left, right) => { -> 18 | expect(left).toBe(right); -| ^ -19 | } -20 | ); -21 | - -at __tests__/failure.test.js:18:18 - -● fails all rows expected true == false - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -16 | 'fails all rows expected %s == %s', -17 | (left, right) => { -> 18 | expect(left).toBe(right); -| ^ -19 | } -20 | ); -21 | - -at __tests__/failure.test.js:18:18 - -● fails all rows expected false == true › fails - -expect(received).toBe(expected) // Object.is equality - -Expected: true -Received: false - -24 | (left, right) => { -25 | it('fails', () => { -> 26 | expect(left).toBe(right); -| ^ -27 | }); -28 | } -29 | ); - -at __tests__/failure.test.js:26:20 - -● fails all rows expected true == false › fails - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -24 | (left, right) => { -25 | it('fails', () => { -> 26 | expect(left).toBe(right); -| ^ -27 | }); -28 | } -29 | ); - -at __tests__/failure.test.js:26:20 - -● fails one row expected true == false - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -34 | \${true} | \${true} -35 | \`('fails one row expected $left == $right', ({left, right}) => { -> 36 | expect(left).toBe(right); -| ^ -37 | }); -38 | -39 | it.each\` - -at __tests__/failure.test.js:36:16 - -● fails all rows expected true == false - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -42 | \${true} | \${true} -43 | \`('fails all rows expected $left == $right', ({left, right}) => { -> 44 | expect(left).toBe(right); -| ^ -45 | }); -46 | -47 | describe.each\` - -at __tests__/failure.test.js:44:16 - -● fails all rows expected true == false › fails - -expect(received).toBe(expected) // Object.is equality - -Expected: false -Received: true - -51 | \`('fails all rows expected $left == $right', ({left, right}) => { -52 | it('fails ', () => { -> 53 | expect(left).toBe(right); -| ^ -54 | }); -55 | }); -56 | - -at __tests__/failure.test.js:53:18 - -● fails all rows expected false == true › fails - -expect(received).toBe(expected) // Object.is equality - -Expected: true -Received: false - -51 | \`('fails all rows expected $left == $right', ({left, right}) => { -52 | it('fails ', () => { -> 53 | expect(left).toBe(right); -| ^ -54 | }); -55 | }); -56 | - -at __tests__/failure.test.js:53:18 + ✓ fails one row expected true == true + ✕ fails one row expected true == false + ✕ fails all rows expected true == false + ✕ fails all rows expected true == false + ✕ fails one row expected true == false + ✓ fails one row expected true == true + ✕ fails all rows expected true == false + ✓ fails all rows expected true == true + fails all rows expected false == true + ✕ fails + ✕ fails + fails all rows expected true == false + ✕ fails + ✕ fails + + ● fails one row expected true == false + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 9 | 'fails one row expected %s == %s', + 10 | (left, right) => { + > 11 | expect(left).toBe(right); + | ^ + 12 | } + 13 | ); + 14 | + + at __tests__/failure.test.js:11:18 + + ● fails all rows expected true == false + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 16 | 'fails all rows expected %s == %s', + 17 | (left, right) => { + > 18 | expect(left).toBe(right); + | ^ + 19 | } + 20 | ); + 21 | + + at __tests__/failure.test.js:18:18 + + ● fails all rows expected true == false + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 16 | 'fails all rows expected %s == %s', + 17 | (left, right) => { + > 18 | expect(left).toBe(right); + | ^ + 19 | } + 20 | ); + 21 | + + at __tests__/failure.test.js:18:18 + + ● fails all rows expected false == true › fails + + expect(received).toBe(expected) // Object.is equality + + Expected: true + Received: false + + 24 | (left, right) => { + 25 | it('fails', () => { + > 26 | expect(left).toBe(right); + | ^ + 27 | }); + 28 | } + 29 | ); + + at __tests__/failure.test.js:26:20 + + ● fails all rows expected true == false › fails + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 24 | (left, right) => { + 25 | it('fails', () => { + > 26 | expect(left).toBe(right); + | ^ + 27 | }); + 28 | } + 29 | ); + + at __tests__/failure.test.js:26:20 + + ● fails one row expected true == false + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 34 | \${true} | \${true} + 35 | \`('fails one row expected $left == $right', ({left, right}) => { + > 36 | expect(left).toBe(right); + | ^ + 37 | }); + 38 | + 39 | it.each\` + + at __tests__/failure.test.js:36:16 + + ● fails all rows expected true == false + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 42 | \${true} | \${true} + 43 | \`('fails all rows expected $left == $right', ({left, right}) => { + > 44 | expect(left).toBe(right); + | ^ + 45 | }); + 46 | + 47 | describe.each\` + + at __tests__/failure.test.js:44:16 + + ● fails all rows expected true == false › fails + + expect(received).toBe(expected) // Object.is equality + + Expected: false + Received: true + + 51 | \`('fails all rows expected $left == $right', ({left, right}) => { + 52 | it('fails ', () => { + > 53 | expect(left).toBe(right); + | ^ + 54 | }); + 55 | }); + 56 | + + at __tests__/failure.test.js:53:18 + + ● fails all rows expected false == true › fails + + expect(received).toBe(expected) // Object.is equality + + Expected: true + Received: false + + 51 | \`('fails all rows expected $left == $right', ({left, right}) => { + 52 | it('fails ', () => { + > 53 | expect(left).toBe(right); + | ^ + 54 | }); + 55 | }); + 56 | + + at __tests__/failure.test.js:53:18 " `; diff --git a/integration-tests/__tests__/each.test.js b/integration-tests/__tests__/each.test.js index 2cc5ae6f9eab..186d0055ac39 100644 --- a/integration-tests/__tests__/each.test.js +++ b/integration-tests/__tests__/each.test.js @@ -24,51 +24,28 @@ test('works with passing tests', () => { test('shows error message when not enough arguments are supplied to tests', () => { const result = runJest(dir, ['each-exception.test.js']); - const rest = extractSummary(result.stderr) - .rest.split('\n') - .filter(line => line.indexOf('packages/expect/build/index.js') === -1) - .join('\n'); - expect(result.status).toBe(1); + const {rest} = extractSummary(result.stderr); expect(rest).toMatchSnapshot(); }); test('shows the correct errors in stderr when failing tests', () => { const result = runJest(dir, ['failure.test.js']); - expect(result.status).toBe(1); - - const rest = extractSummary(result.stderr) - .rest.split('\n') - .filter(line => line.indexOf('packages/expect/build/index.js') === -1) - .map(line => line.trim()) - .join('\n'); - + const {rest} = extractSummary(result.stderr); expect(rest).toMatchSnapshot(); }); test('shows only the tests with .only as being ran', () => { const result = runJest(dir, ['each-only.test.js']); - expect(result.status).toBe(0); - - const rest = extractSummary(result.stderr) - .rest.split('\n') - .filter(line => line.indexOf('packages/expect/build/index.js') === -1) - .join('\n'); - + const {rest} = extractSummary(result.stderr); expect(rest).toMatchSnapshot(); }); test('shows only the tests without .skip as being ran', () => { const result = runJest(dir, ['each-skip.test.js']); - expect(result.status).toBe(0); - - const rest = extractSummary(result.stderr) - .rest.split('\n') - .filter(line => line.indexOf('packages/expect/build/index.js') === -1) - .join('\n'); - + const {rest} = extractSummary(result.stderr); expect(rest).toMatchSnapshot(); }); From 944fbf02882e7cdddb8588eb17017245fc289ea6 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 13:07:39 +0100 Subject: [PATCH 21/31] Remove skip on windows --- integration-tests/__tests__/each.test.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/integration-tests/__tests__/each.test.js b/integration-tests/__tests__/each.test.js index 186d0055ac39..2664a2d75c53 100644 --- a/integration-tests/__tests__/each.test.js +++ b/integration-tests/__tests__/each.test.js @@ -10,13 +10,10 @@ 'use strict'; const path = require('path'); -const SkipOnWindows = require('../../scripts/SkipOnWindows'); const runJest = require('../runJest'); const {extractSummary} = require('../Utils'); const dir = path.resolve(__dirname, '../each'); -SkipOnWindows.suite(); - test('works with passing tests', () => { const result = runJest(dir, ['success.test.js']); expect(result.status).toBe(0); From aab141b2a8058ef7c835b53a80f2fc3ad8cf0e5b Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 14:58:12 +0100 Subject: [PATCH 22/31] Add pretty printing to error message --- .../__tests__/__snapshots__/each.test.js.snap | 19 +- .../__tests__/__snapshots__/each.test.js.snap | 174 ++++++++++++++---- packages/jest-jasmine2/src/each.js | 15 +- 3 files changed, 163 insertions(+), 45 deletions(-) diff --git a/integration-tests/__tests__/__snapshots__/each.test.js.snap b/integration-tests/__tests__/__snapshots__/each.test.js.snap index b3ffdb1e6394..f31b2ecedc68 100644 --- a/integration-tests/__tests__/__snapshots__/each.test.js.snap +++ b/integration-tests/__tests__/__snapshots__/each.test.js.snap @@ -3,15 +3,22 @@ exports[`shows error message when not enough arguments are supplied to tests 1`] = ` "FAIL __tests__/each-exception.test.js ✕ throws exception when not enough arguments are supplied $left == $right - ✓ throws exception when not enough arguments are supplied true == true ● throws exception when not enough arguments are supplied $left == $right - Tagged Template Literal test error: - Not enough arguments supplied for given headings: left | right - Received: true,true,true + Not enough arguments supplied for given headings: + left | right + + Received: + Array [ + true, + true, + true, + ] + + Missing 1 arguments - at packages/jest-jasmine2/build/each.js:75:17 + at packages/jest-jasmine2/build/each.js:84:17 " `; @@ -50,7 +57,7 @@ exports[`shows the correct errors in stderr when failing tests 1`] = ` ✓ fails all rows expected true == true fails all rows expected false == true ✕ fails - ✕ fails + ✕ fails fails all rows expected true == false ✕ fails ✕ fails diff --git a/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap b/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap index 42036299e4f2..f3b4ed19fd97 100644 --- a/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap +++ b/packages/jest-jasmine2/src/__tests__/__snapshots__/each.test.js.snap @@ -1,73 +1,175 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`installEach .describe Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1,1,1,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, + 1, + 1, + 1, +] + +Missing 2 arguments" `; exports[`installEach .describe Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, +] + +Missing 2 arguments" `; exports[`installEach .fdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1,1,1,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, + 1, + 1, + 1, +] + +Missing 2 arguments" `; exports[`installEach .fdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, +] + +Missing 2 arguments" `; exports[`installEach .fit Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1,1,1,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, + 1, + 1, + 1, +] + +Missing 2 arguments" `; exports[`installEach .fit Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, +] + +Missing 2 arguments" `; exports[`installEach .it Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1,1,1,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, + 1, + 1, + 1, +] + +Missing 2 arguments" `; exports[`installEach .it Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, +] + +Missing 2 arguments" `; exports[`installEach .xdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1,1,1,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, + 1, + 1, + 1, +] + +Missing 2 arguments" `; exports[`installEach .xdescribe Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, +] + +Missing 2 arguments" `; exports[`installEach .xit Table Tagged Template Literal throws error when there are fewer arguments than headings over multiple rows 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1,1,1,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, + 1, + 1, + 1, +] + +Missing 2 arguments" `; exports[`installEach .xit Table Tagged Template Literal throws error when there are fewer arguments than headings when given one row 1`] = ` -"Tagged Template Literal test error: -Not enough arguments supplied for given headings: a | b | expected -Received: 0,1" +"Not enough arguments supplied for given headings: +a | b | expected + +Received: +Array [ + 0, + 1, +] + +Missing 2 arguments" `; diff --git a/packages/jest-jasmine2/src/each.js b/packages/jest-jasmine2/src/each.js index bb9954ea9295..92fcacdb2c6e 100644 --- a/packages/jest-jasmine2/src/each.js +++ b/packages/jest-jasmine2/src/each.js @@ -10,9 +10,14 @@ import type {Environment} from 'types/Environment'; import util from 'util'; +import chalk from 'chalk'; +import pretty from 'pretty-format'; type Table = Array>; +const EXPECTED_COLOR = chalk.green; +const RECEIVED_COLOR = chalk.red; + export default (environment: Environment): void => { environment.global.it.each = bindEach(environment.global.it); environment.global.fit.each = bindEach(environment.global.fit); @@ -42,9 +47,13 @@ const bindEach = (cb: Function) => (...args: any) => ( if (data.length % keys.length !== 0) { return cb(title, () => { throw new Error( - `Tagged Template Literal test error:\nNot enough arguments supplied for given headings: ${keys.join( - ' | ', - )}\nReceived: ${data}`, + 'Not enough arguments supplied for given headings:\n' + + EXPECTED_COLOR(keys.join(' | ')) + + '\n\n' + + 'Received:\n' + + RECEIVED_COLOR(pretty(data)) + + '\n\n' + + `Missing ${RECEIVED_COLOR(`${data.length % keys.length}`)} arguments`, ); }); } From 2321c289219c66b097b8d1c0c9ef73a32bdc7a95 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 16:16:19 +0100 Subject: [PATCH 23/31] Add test.each and describe.each docs --- docs/GlobalAPI.md | 129 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index 79d292f0dd2c..bffcb52d75f7 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -256,6 +256,81 @@ describe('binaryStringToNumber', () => { }); ``` +### `describe.each(table)(name, fn)` + +Use `describe.each` if you keep duplicating the same test suites with different +data. `describe.each` allows you to write the test suite once and pass data in. + +`describe.each` is available with two APIs: + +#### 1. `describe.each(table)(name, fn)` + +* `table`: `Array` of Arrays with the arguments that are passed into the `fn` + for each row. +* `name`: `String` the title of the test suite, use `%s` to positionally inject + test data into the suite title. +* `fn`: `Function` the suite of tests to be ran, this is the function that will + receive the parameters in each row as function arguments. + +Example: + +```js +describe.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%s, %s)', + (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + + test('does not mutate first arg', () => { + a + b; + expect(a).toBe(a); + }); + + test('does not mutate second arg', () => { + a + b; + expect(b).toBe(b); + }); + }, +); +``` + +#### 2. `` describe.each`table`(name, fn) `` + +* `table`: `Tagged Template Literal` + * First row of variable name column headings separated with `|` + * One or more subsequent rows of data supplied as template literal expressions + using `${value}` syntax. +* `name`: `String` the title of the test suite, use `$variable` to inject test + data into the suite title from the tagged template expressions. +* `fn`: `Function` the suite of tests to be ran, this is the function that will + receive the test data object. + +Example: + +```js +describe.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('$a + $b', ({a, b, expected}) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + + test('does not mutate first arg', () => { + a + b; + expect(a).toBe(a); + }); + + test('does not mutate second arg', () => { + a + b; + expect(b).toBe(b); + }); +}); +``` + ### `describe.only(name, fn)` Also under the alias: `fdescribe(name, fn)` @@ -353,6 +428,60 @@ test('has lemon in it', () => { Even though the call to `test` will return right away, the test doesn't complete until the promise resolves as well. +### `test.each(table)(name, fn)` + +Also under the alias: `it.each(table)(name, fn)` and +`` it.each`table`(name, fn) `` + +Use `test.each` if you keep duplicating the same test with different data. +`test.each` allows you to write the test once and pass data in. + +`test.each` is available with two APIs: + +#### 1. `test.each(table)(name, fn)` + +* `table`: `Array` of Arrays with the arguments that are passed into the test + `fn` for each row. +* `name`: `String` the title of the test block, use `%s` to positionally inject + parameter values into the test title. +* `fn`: `Function` the test to be ran, this is the function that will receive + the parameters in each row as function arguments. + +Example: + +```js +test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%s, %s)', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, +); +``` + +#### 2. `` test.each`table`(name, fn) `` + +* `table`: `Tagged Template Literal` + * First row of variable name column headings separated with `|` + * One or more subsequent rows of data supplied as template literal expressions + using `${value}` syntax. +* `name`: `String` the title of the test, use `$variable` to inject test data + into the test title from the tagged template expressions. +* `fn`: `Function` the test to be ran, this is the function that will receive + the test data object. + +Example: + +```js +test.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); +}); +``` + ### `test.only(name, fn, timeout)` Also under the aliases: `it.only(name, fn, timeout)` or `fit(name, fn, timeout)` From 9601b8d71c726070ef7149d94193e7fef715b0f4 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 16:40:09 +0100 Subject: [PATCH 24/31] Add test.only.each docs --- docs/GlobalAPI.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index bffcb52d75f7..447a754a1dda 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -512,6 +512,49 @@ Usually you wouldn't check code using `test.only` into source control - you would use it just for debugging, and remove it once you have fixed the broken tests. +### `test.only.each(table)(name, fn)` + +Also under the aliases: `it.only.each(table)(name, fn)`, +`fit.each(table)(name, fn)`, `` it.only.each`table`(name, fn) `` and +`` fit.each`table`(name, fn) `` + +Use `test.only.each` if you want to only run specific tests with different test +data. + +`test.only.each` is available with two APIs: + +#### `test.only.each(table)(name, fn)` + +```js +test.only.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%s, %s)', + (a, b, expected) => { + expect(a + b).toBe(expected); + }, +); + +test('will not be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + +#### `` test.each`table`(name, fn) `` + +```js +test.only.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); +}); + +test('will not be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + ### `test.skip(name, fn)` Also under the aliases: `it.skip(name, fn)` or `xit(name, fn)` or From 6d1b43085152862c32fa9e0d88ba7fd5ea6df135 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 16:44:27 +0100 Subject: [PATCH 25/31] Add test.skip.each docs --- docs/GlobalAPI.md | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index 447a754a1dda..c3c093260375 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -538,7 +538,7 @@ test('will not be ran', () => { }); ``` -#### `` test.each`table`(name, fn) `` +#### `` test.only.each`table`(name, fn) `` ```js test.only.each` @@ -582,3 +582,47 @@ Only the "it is raining" test will run, since the other test is run with You could simply comment the test out, but it's often a bit nicer to use `test.skip` because it will maintain indentation and syntax highlighting. + +### `test.skip.each(table)(name, fn)` + +Also under the aliases: `it.skip.each(table)(name, fn)`, +`xit.each(table)(name, fn)`, `xtest.each(table)(name, fn)`, +`` it.skip.each`table`(name, fn) ``, `` xit.each`table`(name, fn) `` and +`` xtest.each`table`(name, fn) `` + +Use `test.skip.each` if you want to stop running a collection of data driven +tests. + +`test.skip.each` is available with two APIs: + +#### `test.skip.each(table)(name, fn)` + +```js +test.skip.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%s, %s)', + (a, b, expected) => { + expect(a + b).toBe(expected); // will not be ran + }, +); + +test('will be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + +#### `` test.skip.each`table`(name, fn) `` + +```js +test.skip.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({a, b, expected}) => { + expect(a + b).toBe(expected); // will not be ran +}); + +test('will be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` From 160111d75b5c054f97e3d96c7c8143ea54d770f8 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 16:47:29 +0100 Subject: [PATCH 26/31] Add describe.skip.each docs --- docs/GlobalAPI.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index c3c093260375..c8eb9c768243 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -379,6 +379,52 @@ describe.skip('my other beverage', () => { Using `describe.skip` is often just an easier alternative to temporarily commenting out a chunk of tests. +### `describe.skip.each(table)(name, fn)` + +Also under the aliases: `xdescribe.each(table)(name, fn)` and +`` xdescribe.each`table`(name, fn) `` + +Use `describe.skip.each` if you want to stop running a suite of data driven +tests. + +`describe.skip.each` is available with two APIs: + +#### `describe.skip.each(table)(name, fn)` + +```js +describe.skip.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%s, %s)', + (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); // will not be ran + }); + }, +); + +test('will be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + +#### `` describe.skip.each`table`(name, fn) `` + +```js +describe.skip.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({a, b, expected}) => { + test('will not be ran', () => { + expect(a + b).toBe(expected); // will not be ran + }); +}); + +test('will be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + ### `require.requireActual(moduleName)` Returns the actual module instead of a mock, bypassing all checks on whether the From a22ad08e98f477558933a4a10107db601b4f160b Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 1 May 2018 16:50:10 +0100 Subject: [PATCH 27/31] Add describe.only.each docs --- docs/GlobalAPI.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index c8eb9c768243..510eef2a50be 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -353,6 +353,52 @@ describe('my other beverage', () => { }); ``` +### `describe.only.each(table)(name, fn)` + +Also under the aliases: `fdescribe.each(table)(name, fn)` and +`` fdescribe.each`table`(name, fn) `` + +Use `describe.only.each` if you want to only run specific tests suites of data +driven tests. + +`describe.only.each` is available with two APIs: + +#### `describe.only.each(table)(name, fn)` + +```js +describe.only.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( + '.add(%s, %s)', + (a, b, expected) => { + test(`returns ${expected}`, () => { + expect(a + b).toBe(expected); + }); + }, +); + +test('will not be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + +#### `` describe.only.each`table`(name, fn) `` + +```js +describe.only.each` + a | b | expected + ${1} | ${1} | ${2} + ${1} | ${2} | ${3} + ${2} | ${1} | ${3} +`('returns $expected when $a is added $b', ({a, b, expected}) => { + test('passes', () => { + expect(a + b).toBe(expected); + }); +}); + +test('will not be ran', () => { + expect(1 / 0).toBe(Infinity); +}); +``` + ### `describe.skip(name, fn)` Also under the alias: `xdescribe(name, fn)` From afc57973a8952fab8d9eaa4a5d09a4d50ff90bab Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Wed, 2 May 2018 09:56:28 +0100 Subject: [PATCH 28/31] Add skip windows --- integration-tests/__tests__/each.test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration-tests/__tests__/each.test.js b/integration-tests/__tests__/each.test.js index 2664a2d75c53..f530a3b05ccf 100644 --- a/integration-tests/__tests__/each.test.js +++ b/integration-tests/__tests__/each.test.js @@ -13,6 +13,9 @@ const path = require('path'); const runJest = require('../runJest'); const {extractSummary} = require('../Utils'); const dir = path.resolve(__dirname, '../each'); +const SkipOnWindows = require('../../scripts/SkipOnWindows'); + +SkipOnWindows.suite(); test('works with passing tests', () => { const result = runJest(dir, ['success.test.js']); From a4e1f9110823c9a80a7464fadc8a051126e27c32 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Wed, 2 May 2018 09:57:02 +0100 Subject: [PATCH 29/31] Update snapshot --- integration-tests/__tests__/__snapshots__/each.test.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/__tests__/__snapshots__/each.test.js.snap b/integration-tests/__tests__/__snapshots__/each.test.js.snap index f31b2ecedc68..e0284c080d45 100644 --- a/integration-tests/__tests__/__snapshots__/each.test.js.snap +++ b/integration-tests/__tests__/__snapshots__/each.test.js.snap @@ -57,10 +57,10 @@ exports[`shows the correct errors in stderr when failing tests 1`] = ` ✓ fails all rows expected true == true fails all rows expected false == true ✕ fails - ✕ fails + ✕ fails fails all rows expected true == false ✕ fails - ✕ fails + ✕ fails ● fails one row expected true == false From 78b628b2948fe181517b762c5b9b39ad8a94e915 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Wed, 2 May 2018 11:54:56 +0100 Subject: [PATCH 30/31] Normalise stderr output snapshot --- .../__tests__/__snapshots__/each.test.js.snap | 199 ++++++++++-------- integration-tests/__tests__/each.test.js | 7 +- .../each/__tests__/failure.test.js | 59 +++--- 3 files changed, 148 insertions(+), 117 deletions(-) diff --git a/integration-tests/__tests__/__snapshots__/each.test.js.snap b/integration-tests/__tests__/__snapshots__/each.test.js.snap index e0284c080d45..f76a1b92fe86 100644 --- a/integration-tests/__tests__/__snapshots__/each.test.js.snap +++ b/integration-tests/__tests__/__snapshots__/each.test.js.snap @@ -47,78 +47,80 @@ exports[`shows only the tests without .skip as being ran 1`] = ` exports[`shows the correct errors in stderr when failing tests 1`] = ` "FAIL __tests__/failure.test.js - ✓ fails one row expected true == true - ✕ fails one row expected true == false - ✕ fails all rows expected true == false - ✕ fails all rows expected true == false - ✕ fails one row expected true == false - ✓ fails one row expected true == true - ✕ fails all rows expected true == false - ✓ fails all rows expected true == true - fails all rows expected false == true + ✓ array table fails on one row: expected true == true + ✕ array table fails on one row: expected true == false + ✕ array table fails on all rows expected 1 == 2 + ✕ array table fails on all rows expected 3 == 4 + ✕ template table fails on one row expected: true == false + ✓ template table fails on one row expected: true == true + ✕ template table fails on all rows expected: 1 == 2 + ✕ template table fails on all rows expected: 3 == 4 + array table describe fails on all rows expected a == b ✕ fails - ✕ fails - fails all rows expected true == false + array table describe fails on all rows expected c == d + ✕ fails + template table describe fails on all rows expected a == b + ✕ fails + template table describe fails on all rows expected c == d ✕ fails - ✕ fails - ● fails one row expected true == false + ● array table fails on one row: expected true == false expect(received).toBe(expected) // Object.is equality - + Expected: false Received: true - 9 | 'fails one row expected %s == %s', + 9 | 'array table fails on one row: expected %s == %s', 10 | (left, right) => { > 11 | expect(left).toBe(right); | ^ 12 | } 13 | ); - 14 | - + 14 | + at __tests__/failure.test.js:11:18 - ● fails all rows expected true == false + ● array table fails on all rows expected 1 == 2 expect(received).toBe(expected) // Object.is equality - - Expected: false - Received: true - 16 | 'fails all rows expected %s == %s', + Expected: 2 + Received: 1 + + 16 | 'array table fails on all rows expected %s == %s', 17 | (left, right) => { > 18 | expect(left).toBe(right); | ^ 19 | } 20 | ); - 21 | - + 21 | + at __tests__/failure.test.js:18:18 - ● fails all rows expected true == false + ● array table fails on all rows expected 3 == 4 expect(received).toBe(expected) // Object.is equality - - Expected: false - Received: true - 16 | 'fails all rows expected %s == %s', + Expected: 4 + Received: 3 + + 16 | 'array table fails on all rows expected %s == %s', 17 | (left, right) => { > 18 | expect(left).toBe(right); | ^ 19 | } 20 | ); - 21 | - + 21 | + at __tests__/failure.test.js:18:18 - ● fails all rows expected false == true › fails + ● array table describe fails on all rows expected a == b › fails expect(received).toBe(expected) // Object.is equality - - Expected: true - Received: false + + Expected: \\"b\\" + Received: \\"a\\" 24 | (left, right) => { 25 | it('fails', () => { @@ -127,15 +129,15 @@ exports[`shows the correct errors in stderr when failing tests 1`] = ` 27 | }); 28 | } 29 | ); - + at __tests__/failure.test.js:26:20 - ● fails all rows expected true == false › fails + ● array table describe fails on all rows expected c == d › fails expect(received).toBe(expected) // Object.is equality - - Expected: false - Received: true + + Expected: \\"d\\" + Received: \\"c\\" 24 | (left, right) => { 25 | it('fails', () => { @@ -144,76 +146,93 @@ exports[`shows the correct errors in stderr when failing tests 1`] = ` 27 | }); 28 | } 29 | ); - + at __tests__/failure.test.js:26:20 - ● fails one row expected true == false + ● template table fails on one row expected: true == false expect(received).toBe(expected) // Object.is equality - + Expected: false Received: true - 34 | \${true} | \${true} - 35 | \`('fails one row expected $left == $right', ({left, right}) => { - > 36 | expect(left).toBe(right); - | ^ - 37 | }); - 38 | - 39 | it.each\` - - at __tests__/failure.test.js:36:16 + 36 | 'template table fails on one row expected: $left == $right', + 37 | ({left, right}) => { + > 38 | expect(left).toBe(right); + | ^ + 39 | } + 40 | ); + 41 | - ● fails all rows expected true == false + at __tests__/failure.test.js:38:18 + + ● template table fails on all rows expected: 1 == 2 expect(received).toBe(expected) // Object.is equality - - Expected: false - Received: true - 42 | \${true} | \${true} - 43 | \`('fails all rows expected $left == $right', ({left, right}) => { - > 44 | expect(left).toBe(right); - | ^ - 45 | }); - 46 | - 47 | describe.each\` - - at __tests__/failure.test.js:44:16 + Expected: 2 + Received: 1 - ● fails all rows expected true == false › fails + 47 | 'template table fails on all rows expected: $left == $right', + 48 | ({left, right}) => { + > 49 | expect(left).toBe(right); + | ^ + 50 | } + 51 | ); + 52 | + + at __tests__/failure.test.js:49:18 + + ● template table fails on all rows expected: 3 == 4 expect(received).toBe(expected) // Object.is equality - - Expected: false - Received: true - 51 | \`('fails all rows expected $left == $right', ({left, right}) => { - 52 | it('fails ', () => { - > 53 | expect(left).toBe(right); + Expected: 4 + Received: 3 + + 47 | 'template table fails on all rows expected: $left == $right', + 48 | ({left, right}) => { + > 49 | expect(left).toBe(right); | ^ - 54 | }); - 55 | }); - 56 | - - at __tests__/failure.test.js:53:18 + 50 | } + 51 | ); + 52 | - ● fails all rows expected false == true › fails + at __tests__/failure.test.js:49:18 + + ● template table describe fails on all rows expected a == b › fails expect(received).toBe(expected) // Object.is equality - - Expected: true - Received: false - 51 | \`('fails all rows expected $left == $right', ({left, right}) => { - 52 | it('fails ', () => { - > 53 | expect(left).toBe(right); - | ^ - 54 | }); - 55 | }); - 56 | - - at __tests__/failure.test.js:53:18 + Expected: \\"b\\" + Received: \\"a\\" + + 59 | ({left, right}) => { + 60 | it('fails ', () => { + > 61 | expect(left).toBe(right); + | ^ + 62 | }); + 63 | } + 64 | ); + + at __tests__/failure.test.js:61:20 + + ● template table describe fails on all rows expected c == d › fails + + expect(received).toBe(expected) // Object.is equality + + Expected: \\"d\\" + Received: \\"c\\" + + 59 | ({left, right}) => { + 60 | it('fails ', () => { + > 61 | expect(left).toBe(right); + | ^ + 62 | }); + 63 | } + 64 | ); + + at __tests__/failure.test.js:61:20 " `; diff --git a/integration-tests/__tests__/each.test.js b/integration-tests/__tests__/each.test.js index f530a3b05ccf..54e16cfda251 100644 --- a/integration-tests/__tests__/each.test.js +++ b/integration-tests/__tests__/each.test.js @@ -32,8 +32,11 @@ test('shows error message when not enough arguments are supplied to tests', () = test('shows the correct errors in stderr when failing tests', () => { const result = runJest(dir, ['failure.test.js']); expect(result.status).toBe(1); - const {rest} = extractSummary(result.stderr); - expect(rest).toMatchSnapshot(); + const output = extractSummary(result.stderr) + .rest.split('\n') + .map(line => line.trimRight()) + .join('\n'); + expect(output).toMatchSnapshot(); }); test('shows only the tests with .only as being ran', () => { diff --git a/integration-tests/each/__tests__/failure.test.js b/integration-tests/each/__tests__/failure.test.js index 1ab3069983ab..44c132073063 100644 --- a/integration-tests/each/__tests__/failure.test.js +++ b/integration-tests/each/__tests__/failure.test.js @@ -6,21 +6,21 @@ */ it.each([[true, true], [true, false]])( - 'fails one row expected %s == %s', + 'array table fails on one row: expected %s == %s', (left, right) => { expect(left).toBe(right); } ); -it.each([[true, false], [true, false]])( - 'fails all rows expected %s == %s', +it.each([[1, 2], [3, 4]])( + 'array table fails on all rows expected %s == %s', (left, right) => { expect(left).toBe(right); } ); -describe.each([[false, true], [true, false]])( - 'fails all rows expected %s == %s', +describe.each([['a', 'b'], ['c', 'd']])( + 'array table describe fails on all rows expected %s == %s', (left, right) => { it('fails', () => { expect(left).toBe(right); @@ -29,27 +29,36 @@ describe.each([[false, true], [true, false]])( ); it.each` - left | right - ${true} | ${false} - ${true} | ${true} -`('fails one row expected $left == $right', ({left, right}) => { - expect(left).toBe(right); -}); + left | right + ${true} | ${false} + ${true} | ${true} + `( + 'template table fails on one row expected: $left == $right', + ({left, right}) => { + expect(left).toBe(right); + } +); it.each` - left | right - ${true} | ${false} - ${true} | ${true} -`('fails all rows expected $left == $right', ({left, right}) => { - expect(left).toBe(right); -}); + left | right + ${1} | ${2} + ${3} | ${4} + `( + 'template table fails on all rows expected: $left == $right', + ({left, right}) => { + expect(left).toBe(right); + } +); describe.each` - left | right - ${true} | ${false} - ${false} | ${true} -`('fails all rows expected $left == $right', ({left, right}) => { - it('fails ', () => { - expect(left).toBe(right); - }); -}); + left | right + ${'a'} | ${'b'} + ${'c'} | ${'d'} + `( + 'template table describe fails on all rows expected $left == $right', + ({left, right}) => { + it('fails ', () => { + expect(left).toBe(right); + }); + } +); From 9983616372635e2bb1a8574387754145653103ec Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Thu, 3 May 2018 20:59:52 +0100 Subject: [PATCH 31/31] Update each doc examples --- docs/GlobalAPI.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index 510eef2a50be..4c31a99530b3 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -282,14 +282,12 @@ describe.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])( expect(a + b).toBe(expected); }); - test('does not mutate first arg', () => { - a + b; - expect(a).toBe(a); + test(`returned value not be greater than ${expected}`, () => { + expect(a + b).not.toBeGreaterThan(expected); }); - test('does not mutate second arg', () => { - a + b; - expect(b).toBe(b); + test(`returned value not be less than ${expected}`, () => { + expect(a + b).not.toBeLessThan(expected); }); }, ); @@ -319,14 +317,12 @@ describe.each` expect(a + b).toBe(expected); }); - test('does not mutate first arg', () => { - a + b; - expect(a).toBe(a); + test(`returned value not be greater than ${expected}`, () => { + expect(a + b).not.toBeGreaterThan(expected); }); - test('does not mutate second arg', () => { - a + b; - expect(b).toBe(b); + test(`returned value not be less than ${expected}`, () => { + expect(a + b).not.toBeLessThan(expected); }); }); ```