From 7d8d01c4854aa83e82cc11cefdd084a7d9b8bdfc Mon Sep 17 00:00:00 2001 From: Yusuf Date: Thu, 18 Aug 2022 01:03:23 +0530 Subject: [PATCH] feat(circus): added each to failing tests (#13142) --- CHANGELOG.md | 1 + docs/GlobalAPI.md | 24 ++ .../__snapshots__/testFailing.test.ts.snap | 306 +++++++++++++++--- .../testFailingJasmine.test.ts.snap | 96 ++++-- e2e/test-failing/__tests__/statuses.test.js | 8 + .../__tests__/worksWithConcurrentMode.test.js | 8 + .../worksWithConcurrentOnlyMode.test.js | 8 + .../__tests__/worksWithOnlyMode.test.js | 8 + .../__tests__/worksWithSkipMode.test.js | 8 + packages/jest-circus/src/index.ts | 6 +- packages/jest-jasmine2/src/index.ts | 7 + .../jest-jasmine2/src/jasmineAsyncInstall.ts | 17 +- .../jest-types/__typetests__/globals.test.ts | 8 + packages/jest-types/src/Global.ts | 9 +- 14 files changed, 430 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2de38243f4f3..1eaf6a8a436d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features - `[expect]` [**BREAKING**] Differentiate between `MatcherContext` `MatcherUtils` and `MatcherState` types ([#13141](https://github.com/facebook/jest/pull/13141)) +- `[jest-circus]` Add support for `test.failing.each` ([#13142](https://github.com/facebook/jest/pull/13142)) - `[jest-config]` [**BREAKING**] Make `snapshotFormat` default to `escapeString: false` and `printBasicPrototype: false` ([#13036](https://github.com/facebook/jest/pull/13036)) - `[jest-environment-jsdom]` [**BREAKING**] Upgrade to `jsdom@20` ([#13037](https://github.com/facebook/jest/pull/13037), [#13058](https://github.com/facebook/jest/pull/13058)) - `[@jest/globals]` Add `jest.Mocked`, `jest.MockedClass`, `jest.MockedFunction` and `jest.MockedObject` utility types ([#12727](https://github.com/facebook/jest/pull/12727)) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index ad68f1389c15..383ce6845e98 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -763,6 +763,30 @@ test.failing('it is equal', () => { }); ``` +### `test.failing.each(name, fn, timeout)` + +Also under the alias: `it.failing.each(table)(name, fn)` and `` it.failing.each`table`(name, fn) `` + +:::note + +This is only available with the default [jest-circus](https://github.com/facebook/jest/tree/main/packages/jest-circus) runner. + +::: + +You can also run multiple tests at once by adding `each` after `failing`. + +Example: + +```js +test.failing.each([ + {a: 1, b: 1, expected: 2}, + {a: 1, b: 2, expected: 3}, + {a: 2, b: 1, expected: 3}, +])('.add($a, $b)', ({a, b, expected}) => { + expect(a + b).toBe(expected); +}); +``` + ### `test.only.failing(name, fn, timeout)` Also under the aliases: `it.only.failing(name, fn, timeout)`, `fit.failing(name, fn, timeout)` diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap index d9772b8e05ae..516759332ef7 100644 --- a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -6,6 +6,9 @@ exports[`works with all statuses 1`] = ` ✕ fails ✓ failing fails = passes ✓ failing fails = passes with test syntax + ✕ .add(1, 1) + ✕ .add(1, 2) + ✕ .add(2, 1) ✕ failing passes = fails ○ skipped skips ○ skipped skipped failing 1 @@ -31,25 +34,76 @@ exports[`works with all statuses 1`] = ` at Object.toBe (__tests__/statuses.test.js:13:14) + ● .add(1, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 28 | }); + 29 | + > 30 | test.failing.each([ + | ^ + 31 | {a: 1, b: 1, expected: 2}, + 32 | {a: 1, b: 2, expected: 3}, + 33 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at Object. (__tests__/statuses.test.js:30:1) + + ● .add(1, 2) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 28 | }); + 29 | + > 30 | test.failing.each([ + | ^ + 31 | {a: 1, b: 1, expected: 2}, + 32 | {a: 1, b: 2, expected: 3}, + 33 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at Object. (__tests__/statuses.test.js:30:1) + + ● .add(2, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 28 | }); + 29 | + > 30 | test.failing.each([ + | ^ + 31 | {a: 1, b: 1, expected: 2}, + 32 | {a: 1, b: 2, expected: 3}, + 33 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at Object. (__tests__/statuses.test.js:30:1) + ● failing passes = fails Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. - 36 | }); - 37 | - > 38 | it.failing('failing passes = fails', () => { + 44 | }); + 45 | + > 46 | it.failing('failing passes = fails', () => { | ^ - 39 | expect(10).toBe(10); - 40 | }); - 41 | + 47 | expect(10).toBe(10); + 48 | }); + 49 | - at Object.failing (__tests__/statuses.test.js:38:4)" + at Object.failing (__tests__/statuses.test.js:46:4)" `; exports[`works with concurrent and only mode 1`] = ` "FAIL __tests__/worksWithConcurrentOnlyMode.test.js block with concurrent ✕ failing passes = fails + ✕ .add(1, 1) + ✕ .add(1, 2) + ✕ .add(2, 1) ✓ failing fails = passes ○ skipped skipped failing test ○ skipped skipped failing fails @@ -67,6 +121,57 @@ exports[`works with concurrent and only mode 1`] = ` 16 | at failing (__tests__/worksWithConcurrentOnlyMode.test.js:13:22) + at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1) + + ● block with concurrent › .add(1, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 15 | }); + 16 | + > 17 | test.concurrent.only.failing.each([ + | ^ + 18 | {a: 1, b: 1, expected: 2}, + 19 | {a: 1, b: 2, expected: 3}, + 20 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithConcurrentOnlyMode.test.js:17:3 + at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1) + + ● block with concurrent › .add(1, 2) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 15 | }); + 16 | + > 17 | test.concurrent.only.failing.each([ + | ^ + 18 | {a: 1, b: 1, expected: 2}, + 19 | {a: 1, b: 2, expected: 3}, + 20 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithConcurrentOnlyMode.test.js:17:3 + at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1) + + ● block with concurrent › .add(2, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 15 | }); + 16 | + > 17 | test.concurrent.only.failing.each([ + | ^ + 18 | {a: 1, b: 1, expected: 2}, + 19 | {a: 1, b: 2, expected: 3}, + 20 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithConcurrentOnlyMode.test.js:17:3 at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1)" `; @@ -75,6 +180,9 @@ exports[`works with concurrent mode 1`] = ` block with concurrent ✕ failing test ✕ failing passes = fails + ✕ .add(1, 1) + ✕ .add(1, 2) + ✕ .add(2, 1) ✓ failing fails = passes ○ skipped skipped failing fails @@ -108,6 +216,57 @@ exports[`works with concurrent mode 1`] = ` 16 | at failing (__tests__/worksWithConcurrentMode.test.js:13:17) + at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1) + + ● block with concurrent › .add(1, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 15 | }); + 16 | + > 17 | test.concurrent.failing.each([ + | ^ + 18 | {a: 1, b: 1, expected: 2}, + 19 | {a: 1, b: 2, expected: 3}, + 20 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithConcurrentMode.test.js:17:3 + at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1) + + ● block with concurrent › .add(1, 2) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 15 | }); + 16 | + > 17 | test.concurrent.failing.each([ + | ^ + 18 | {a: 1, b: 1, expected: 2}, + 19 | {a: 1, b: 2, expected: 3}, + 20 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithConcurrentMode.test.js:17:3 + at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1) + + ● block with concurrent › .add(2, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 15 | }); + 16 | + > 17 | test.concurrent.failing.each([ + | ^ + 18 | {a: 1, b: 1, expected: 2}, + 19 | {a: 1, b: 2, expected: 3}, + 20 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithConcurrentMode.test.js:17:3 at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1)" `; @@ -115,6 +274,9 @@ exports[`works with only mode 1`] = ` "FAIL __tests__/worksWithOnlyMode.test.js block with only, should pass ✓ failing fails = passes, should pass + ✕ .add(1, 1) + ✕ .add(1, 2) + ✕ .add(2, 1) ○ skipped failing test but skipped ○ skipped passing test but skipped block with only, should fail @@ -131,20 +293,71 @@ exports[`works with only mode 1`] = ` ○ skipped failing test but skipped ○ skipped passing test but skipped + ● block with only, should pass › .add(1, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 11 | }); + 12 | + > 13 | it.only.failing.each([ + | ^ + 14 | {a: 1, b: 1, expected: 2}, + 15 | {a: 1, b: 2, expected: 3}, + 16 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithOnlyMode.test.js:13:3 + at Object.describe (__tests__/worksWithOnlyMode.test.js:8:1) + + ● block with only, should pass › .add(1, 2) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 11 | }); + 12 | + > 13 | it.only.failing.each([ + | ^ + 14 | {a: 1, b: 1, expected: 2}, + 15 | {a: 1, b: 2, expected: 3}, + 16 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithOnlyMode.test.js:13:3 + at Object.describe (__tests__/worksWithOnlyMode.test.js:8:1) + + ● block with only, should pass › .add(2, 1) + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 11 | }); + 12 | + > 13 | it.only.failing.each([ + | ^ + 14 | {a: 1, b: 1, expected: 2}, + 15 | {a: 1, b: 2, expected: 3}, + 16 | {a: 2, b: 1, expected: 3}, + + at ../../packages/jest-each/build/bind.js:45:11 + at Array.forEach () + at __tests__/worksWithOnlyMode.test.js:13:3 + at Object.describe (__tests__/worksWithOnlyMode.test.js:8:1) + ● block with only, should fail › failing passes = fails, should fail Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. - 21 | - 22 | describe('block with only, should fail', () => { - > 23 | it.only.failing('failing passes = fails, should fail', () => { + 29 | + 30 | describe('block with only, should fail', () => { + > 31 | it.only.failing('failing passes = fails, should fail', () => { | ^ - 24 | expect(10).toBe(10); - 25 | }); - 26 | + 32 | expect(10).toBe(10); + 33 | }); + 34 | - at failing (__tests__/worksWithOnlyMode.test.js:23:11) - at Object.describe (__tests__/worksWithOnlyMode.test.js:22:1) + at failing (__tests__/worksWithOnlyMode.test.js:31:11) + at Object.describe (__tests__/worksWithOnlyMode.test.js:30:1) ● block with only in other it, should skip › failing test @@ -153,45 +366,45 @@ exports[`works with only mode 1`] = ` Expected: 101 Received: 10 - 40 | - 41 | it.only('failing test', () => { - > 42 | expect(10).toBe(101); + 48 | + 49 | it.only('failing test', () => { + > 50 | expect(10).toBe(101); | ^ - 43 | }); - 44 | - 45 | it('passing test but skipped', () => { + 51 | }); + 52 | + 53 | it('passing test but skipped', () => { - at Object.toBe (__tests__/worksWithOnlyMode.test.js:42:16) + at Object.toBe (__tests__/worksWithOnlyMode.test.js:50:16) ● block with only with different syntax, should fail › failing passes = fails, should fail 1 Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. - 49 | - 50 | describe('block with only with different syntax, should fail', () => { - > 51 | fit.failing('failing passes = fails, should fail 1', () => { + 57 | + 58 | describe('block with only with different syntax, should fail', () => { + > 59 | fit.failing('failing passes = fails, should fail 1', () => { | ^ - 52 | expect(10).toBe(10); - 53 | }); - 54 | + 60 | expect(10).toBe(10); + 61 | }); + 62 | - at failing (__tests__/worksWithOnlyMode.test.js:51:7) - at Object.describe (__tests__/worksWithOnlyMode.test.js:50:1) + at failing (__tests__/worksWithOnlyMode.test.js:59:7) + at Object.describe (__tests__/worksWithOnlyMode.test.js:58:1) ● block with only with different syntax, should fail › failing passes = fails, should fail 2 Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. - 53 | }); - 54 | - > 55 | test.only.failing('failing passes = fails, should fail 2', () => { + 61 | }); + 62 | + > 63 | test.only.failing('failing passes = fails, should fail 2', () => { | ^ - 56 | expect(10).toBe(10); - 57 | }); - 58 | + 64 | expect(10).toBe(10); + 65 | }); + 66 | - at failing (__tests__/worksWithOnlyMode.test.js:55:13) - at Object.describe (__tests__/worksWithOnlyMode.test.js:50:1)" + at failing (__tests__/worksWithOnlyMode.test.js:63:13) + at Object.describe (__tests__/worksWithOnlyMode.test.js:58:1)" `; exports[`works with skip mode 1`] = ` @@ -200,6 +413,9 @@ exports[`works with skip mode 1`] = ` ✕ failing test ✓ failing fails = passes ○ skipped skipped failing fails = passes, should pass + ○ skipped .add(1, 1) + ○ skipped .add(1, 2) + ○ skipped .add(2, 1) ○ skipped passing test block with only, should fail ✓ passing test @@ -214,13 +430,13 @@ exports[`works with skip mode 1`] = ` Expected: 101 Received: 10 - 12 | - 13 | it('failing test', () => { - > 14 | expect(10).toBe(101); + 20 | + 21 | it('failing test', () => { + > 22 | expect(10).toBe(101); | ^ - 15 | }); - 16 | - 17 | it.skip('passing test', () => { + 23 | }); + 24 | + 25 | it.skip('passing test', () => { - at Object.toBe (__tests__/worksWithSkipMode.test.js:14:16)" + at Object.toBe (__tests__/worksWithSkipMode.test.js:22:16)" `; diff --git a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap index 2760cfd57937..2a6200f91f69 100644 --- a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap @@ -34,6 +34,22 @@ FAIL __tests__/worksWithConcurrentMode.test.js at Object.toBe (__tests__/worksWithConcurrentMode.test.js:10:16) + ● block with concurrent › encountered a declaration exception + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 11 | }); + 12 | + > 13 | it.concurrent.failing('failing passes = fails', () => { + | ^ + 14 | expect(10).toBe(10); + 15 | }); + 16 | + + at Function.failing (../../packages/jest-jasmine2/build/jasmineAsyncInstall.js:197:11) + at Suite.failing (__tests__/worksWithConcurrentMode.test.js:13:17) + at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1) + FAIL __tests__/worksWithConcurrentOnlyMode.test.js ● block with concurrent › skipped failing test @@ -52,6 +68,22 @@ FAIL __tests__/worksWithConcurrentOnlyMode.test.js at Object.toBe (__tests__/worksWithConcurrentOnlyMode.test.js:10:16) + ● block with concurrent › encountered a declaration exception + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 11 | }); + 12 | + > 13 | it.concurrent.only.failing('failing passes = fails', () => { + | ^ + 14 | expect(10).toBe(10); + 15 | }); + 16 | + + at Function.failing (../../packages/jest-jasmine2/build/jasmineAsyncInstall.js:197:11) + at Suite.failing (__tests__/worksWithConcurrentOnlyMode.test.js:13:22) + at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1) + FAIL __tests__/worksWithOnlyMode.test.js ● block with only, should pass › encountered a declaration exception @@ -72,46 +104,46 @@ FAIL __tests__/worksWithOnlyMode.test.js Jest: \`failing\` tests are only supported in \`jest-circus\`. - 21 | - 22 | describe('block with only, should fail', () => { - > 23 | it.only.failing('failing passes = fails, should fail', () => { + 29 | + 30 | describe('block with only, should fail', () => { + > 31 | it.only.failing('failing passes = fails, should fail', () => { | ^ - 24 | expect(10).toBe(10); - 25 | }); - 26 | + 32 | expect(10).toBe(10); + 33 | }); + 34 | - at Suite.failing (__tests__/worksWithOnlyMode.test.js:23:11) - at Object.describe (__tests__/worksWithOnlyMode.test.js:22:1) + at Suite.failing (__tests__/worksWithOnlyMode.test.js:31:11) + at Object.describe (__tests__/worksWithOnlyMode.test.js:30:1) ● block with only in other it, should skip › encountered a declaration exception Jest: \`failing\` tests are only supported in \`jest-circus\`. - 35 | - 36 | describe('block with only in other it, should skip', () => { - > 37 | it.failing('failing passes = fails, should fail but skipped', () => { + 43 | + 44 | describe('block with only in other it, should skip', () => { + > 45 | it.failing('failing passes = fails, should fail but skipped', () => { | ^ - 38 | expect(10).toBe(10); - 39 | }); - 40 | + 46 | expect(10).toBe(10); + 47 | }); + 48 | - at Suite.failing (__tests__/worksWithOnlyMode.test.js:37:6) - at Object.describe (__tests__/worksWithOnlyMode.test.js:36:1) + at Suite.failing (__tests__/worksWithOnlyMode.test.js:45:6) + at Object.describe (__tests__/worksWithOnlyMode.test.js:44:1) ● block with only with different syntax, should fail › encountered a declaration exception Jest: \`failing\` tests are only supported in \`jest-circus\`. - 49 | - 50 | describe('block with only with different syntax, should fail', () => { - > 51 | fit.failing('failing passes = fails, should fail 1', () => { + 57 | + 58 | describe('block with only with different syntax, should fail', () => { + > 59 | fit.failing('failing passes = fails, should fail 1', () => { | ^ - 52 | expect(10).toBe(10); - 53 | }); - 54 | + 60 | expect(10).toBe(10); + 61 | }); + 62 | - at Suite.failing (__tests__/worksWithOnlyMode.test.js:51:7) - at Object.describe (__tests__/worksWithOnlyMode.test.js:50:1) + at Suite.failing (__tests__/worksWithOnlyMode.test.js:59:7) + at Object.describe (__tests__/worksWithOnlyMode.test.js:58:1) FAIL __tests__/worksWithSkipMode.test.js ● block with only, should pass › encountered a declaration exception @@ -133,14 +165,14 @@ FAIL __tests__/worksWithSkipMode.test.js Jest: \`failing\` tests are only supported in \`jest-circus\`. - 25 | - 26 | describe('block with only, should fail', () => { - > 27 | it.skip.failing('failing passes = fails, should fail', () => { + 33 | + 34 | describe('block with only, should fail', () => { + > 35 | it.skip.failing('failing passes = fails, should fail', () => { | ^ - 28 | expect(10).toBe(10); - 29 | }); - 30 | + 36 | expect(10).toBe(10); + 37 | }); + 38 | - at Suite.failing (__tests__/worksWithSkipMode.test.js:27:11) - at Object.describe (__tests__/worksWithSkipMode.test.js:26:1)" + at Suite.failing (__tests__/worksWithSkipMode.test.js:35:11) + at Object.describe (__tests__/worksWithSkipMode.test.js:34:1)" `; diff --git a/e2e/test-failing/__tests__/statuses.test.js b/e2e/test-failing/__tests__/statuses.test.js index a75235f1367b..45d15b671496 100644 --- a/e2e/test-failing/__tests__/statuses.test.js +++ b/e2e/test-failing/__tests__/statuses.test.js @@ -27,6 +27,14 @@ test.failing('failing fails = passes with test syntax', () => { expect(10).toBe(101); }); +test.failing.each([ + {a: 1, b: 1, expected: 2}, + {a: 1, b: 2, expected: 3}, + {a: 2, b: 1, expected: 3}, +])('.add($a, $b)', ({a, b, expected}) => { + expect(a + b).toBe(expected); +}); + it.skip.failing('skipped failing 1', () => { expect(10).toBe(10); }); diff --git a/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js b/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js index 950b01c29d08..8328d3d6c1f4 100644 --- a/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js +++ b/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js @@ -14,6 +14,14 @@ describe('block with concurrent', () => { expect(10).toBe(10); }); + test.concurrent.failing.each([ + {a: 1, b: 1, expected: 2}, + {a: 1, b: 2, expected: 3}, + {a: 2, b: 1, expected: 3}, + ])('.add($a, $b)', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + it.concurrent.failing('failing fails = passes', () => { expect(10).toBe(101); }); diff --git a/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js index 93d8850d90ed..21b7af8e8d2d 100644 --- a/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js +++ b/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js @@ -14,6 +14,14 @@ describe('block with concurrent', () => { expect(10).toBe(10); }); + test.concurrent.only.failing.each([ + {a: 1, b: 1, expected: 2}, + {a: 1, b: 2, expected: 3}, + {a: 2, b: 1, expected: 3}, + ])('.add($a, $b)', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + it.concurrent.only.failing('failing fails = passes', () => { expect(10).toBe(101); }); diff --git a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js index d08dbc58315c..1e99bd80c640 100644 --- a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js +++ b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js @@ -10,6 +10,14 @@ describe('block with only, should pass', () => { expect(10).toBe(101); }); + it.only.failing.each([ + {a: 1, b: 1, expected: 2}, + {a: 1, b: 2, expected: 3}, + {a: 2, b: 1, expected: 3}, + ])('.add($a, $b)', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + it('failing test but skipped', () => { expect(10).toBe(101); }); diff --git a/e2e/test-failing/__tests__/worksWithSkipMode.test.js b/e2e/test-failing/__tests__/worksWithSkipMode.test.js index 36cb4d1e43bd..164d3f9f02eb 100644 --- a/e2e/test-failing/__tests__/worksWithSkipMode.test.js +++ b/e2e/test-failing/__tests__/worksWithSkipMode.test.js @@ -10,6 +10,14 @@ describe('block with only, should pass', () => { expect(10).toBe(101); }); + it.skip.failing.each([ + {a: 1, b: 1, expected: 2}, + {a: 1, b: 2, expected: 3}, + {a: 2, b: 1, expected: 3}, + ])('.add($a, $b)', ({a, b, expected}) => { + expect(a + b).toBe(expected); + }); + it('failing test', () => { expect(10).toBe(101); }); diff --git a/packages/jest-circus/src/index.ts b/packages/jest-circus/src/index.ts index 21974ebc5e18..cb885c6d6a5e 100644 --- a/packages/jest-circus/src/index.ts +++ b/packages/jest-circus/src/index.ts @@ -140,11 +140,15 @@ const test: Global.It = (() => { ): void => _addTest(testName, 'only', true, fn, concurrentOnly, timeout); const bindFailing = (concurrent: boolean, mode: Circus.TestMode) => { - const failing = ( + type FailingReturn = typeof concurrent extends true + ? Global.ConcurrentTestFn + : Global.TestFn; + const failing: Global.Failing = ( testName: Circus.TestNameLike, fn?: Circus.TestFn, timeout?: number, ): void => _addTest(testName, mode, concurrent, fn, failing, timeout, true); + failing.each = bindEach(failing, false); return failing; }; diff --git a/packages/jest-jasmine2/src/index.ts b/packages/jest-jasmine2/src/index.ts index 417c5262f0be..2157e12dc1de 100644 --- a/packages/jest-jasmine2/src/index.ts +++ b/packages/jest-jasmine2/src/index.ts @@ -88,6 +88,13 @@ export default async function jasmine2( ); }; + failing.each = () => { + throw new ErrorWithStack( + 'Jest: `failing` tests are only supported in `jest-circus`.', + failing.each, + ); + }; + environment.global.it.failing = failing; environment.global.fit.failing = failing; environment.global.xit.failing = failing; diff --git a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts index c4d2a115046d..693966fded07 100644 --- a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts +++ b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts @@ -226,14 +226,23 @@ function makeConcurrent( return spec; }; - // each is bound after the function is made concurrent, so for now it is made noop - // eslint-disable-next-line @typescript-eslint/no-empty-function - concurrentFn.each = () => () => {}; - concurrentFn.failing = () => () => { + + const failing = () => { throw new Error( 'Jest: `failing` tests are only supported in `jest-circus`.', ); }; + + failing.each = () => { + throw new Error( + 'Jest: `failing` tests are only supported in `jest-circus`.', + ); + }; + // each is bound after the function is made concurrent, so for now it is made noop + // eslint-disable-next-line @typescript-eslint/no-empty-function + concurrentFn.each = () => () => {}; + concurrentFn.failing = failing; + return concurrentFn; } diff --git a/packages/jest-types/__typetests__/globals.test.ts b/packages/jest-types/__typetests__/globals.test.ts index 24fd9db72efb..0694a1fe0d00 100644 --- a/packages/jest-types/__typetests__/globals.test.ts +++ b/packages/jest-types/__typetests__/globals.test.ts @@ -269,17 +269,21 @@ expectType(test.concurrent.failing(function named() {}, asyncFn)); expectType(test.concurrent.failing(class {}, asyncFn)); expectType(test.concurrent.failing(class Named {}, asyncFn)); +expectType(test.concurrent.failing.each); + expectError(test.concurrent.failing(testName, fn)); // test.concurrent.only expectType(test.concurrent.only.each); expectType(test.concurrent.only.failing); +expectType(test.concurrent.only.failing.each); // test.concurrent.skip expectType(test.concurrent.skip.each); expectType(test.concurrent.skip.failing); +expectType(test.concurrent.skip.failing.each); // test.each @@ -303,6 +307,8 @@ expectType(test.failing(function named() {}, fn)); expectType(test.failing(class {}, fn)); expectType(test.failing(class Named {}, fn)); +expectType(test.failing.each); + // test.only expectType(test.only(testName, fn)); @@ -316,6 +322,7 @@ expectType(test.only(class Named {}, fn)); expectType(test.only.each); expectType(test.only.failing); +expectType(test.only.failing.each); // test.skip @@ -330,6 +337,7 @@ expectType(test.skip(class Named {}, fn)); expectType(test.skip.each); expectType(test.skip.failing); +expectType(test.skip.failing.each); // test.todo diff --git a/packages/jest-types/src/Global.ts b/packages/jest-types/src/Global.ts index b99d659b4be7..0aa451f5ea98 100644 --- a/packages/jest-types/src/Global.ts +++ b/packages/jest-types/src/Global.ts @@ -106,10 +106,15 @@ export interface HookBase { (fn: HookFn, timeout?: number): void; } +export interface Failing { + (testName: TestNameLike, fn: T, timeout?: number): void; + each: Each; +} + export interface ItBase { (testName: TestNameLike, fn: TestFn, timeout?: number): void; each: Each; - failing(testName: TestNameLike, fn: TestFn, timeout?: number): void; + failing: Failing; } export interface It extends ItBase { @@ -121,7 +126,7 @@ export interface It extends ItBase { export interface ItConcurrentBase { (testName: TestNameLike, testFn: ConcurrentTestFn, timeout?: number): void; each: Each; - failing(testName: TestNameLike, fn: ConcurrentTestFn, timeout?: number): void; + failing: Failing; } export interface ItConcurrentExtended extends ItConcurrentBase {