From b8a31cedf0445ac4b57da4babff1fd746b91f468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Sun, 27 Mar 2022 13:59:25 +0200 Subject: [PATCH 01/21] Add purposefully failing test case. --- .../__snapshots__/testPending.test.ts.snap | 32 +++++++++ e2e/__tests__/testPending.test.ts | 18 +++++ e2e/test-pending/__tests__/statuses.test.js | 28 ++++++++ e2e/test-pending/package.json | 5 ++ .../circusItPendingTestError.test.ts | 72 +++++++++++++++++++ packages/jest-circus/src/index.ts | 9 +++ packages/jest-circus/src/run.ts | 20 +++++- packages/jest-types/src/Circus.ts | 2 +- packages/jest-types/src/Global.ts | 1 + 9 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/testPending.test.ts.snap create mode 100644 e2e/__tests__/testPending.test.ts create mode 100644 e2e/test-pending/__tests__/statuses.test.js create mode 100644 e2e/test-pending/package.json create mode 100644 packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts diff --git a/e2e/__tests__/__snapshots__/testPending.test.ts.snap b/e2e/__tests__/__snapshots__/testPending.test.ts.snap new file mode 100644 index 000000000000..45d7ef7c0d7e --- /dev/null +++ b/e2e/__tests__/__snapshots__/testPending.test.ts.snap @@ -0,0 +1,32 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`works with all statuses 1`] = ` +"FAIL __tests__/statuses.test.js + ✓ passes + ✕ fails + ✓ pending failes = passes + ✕ pending passes = fails + ○ skipped skips + ✎ todo todo + + ● fails + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 11 | + 12 | it('fails', () => { + > 13 | expect(10).toBe(101); + | ^ + 14 | }); + 15 | + 16 | it.skip('skips', () => { + + at Object.toBe (__tests__/statuses.test.js:13:14) + + ● pending passes = fails + + Pending test passed even though it was supposed to fail. Remove \`.pending\` to remove error." +`; diff --git a/e2e/__tests__/testPending.test.ts b/e2e/__tests__/testPending.test.ts new file mode 100644 index 000000000000..5bc67bb3cab2 --- /dev/null +++ b/e2e/__tests__/testPending.test.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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 * as path from 'path'; +import {extractSummary} from '../Utils'; +import runJest from '../runJest'; +const dir = path.resolve(__dirname, '../test-pending'); + +test('works with all statuses', () => { + const result = runJest(dir, ['statuses.test.js']); + expect(result.exitCode).toBe(1); + const {rest} = extractSummary(result.stderr); + expect(rest).toMatchSnapshot(); +}); diff --git a/e2e/test-pending/__tests__/statuses.test.js b/e2e/test-pending/__tests__/statuses.test.js new file mode 100644 index 000000000000..aaf7b87b2dcf --- /dev/null +++ b/e2e/test-pending/__tests__/statuses.test.js @@ -0,0 +1,28 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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('passes', () => { + expect(10).toBe(10); +}); + +it('fails', () => { + expect(10).toBe(101); +}); + +it.skip('skips', () => { + expect(10).toBe(101); +}); + +it.todo('todo'); + +it.pending('pending failes = passes', () => { + expect(10).toBe(101); +}); + +it.pending('pending passes = fails', () => { + expect(10).toBe(10); +}); diff --git a/e2e/test-pending/package.json b/e2e/test-pending/package.json new file mode 100644 index 000000000000..148788b25446 --- /dev/null +++ b/e2e/test-pending/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "node" + } +} diff --git a/packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts b/packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts new file mode 100644 index 000000000000..a295ab26d661 --- /dev/null +++ b/packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts @@ -0,0 +1,72 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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 type {Global} from '@jest/types'; + +let circusIt: Global.It; +let circusTest: Global.It; + +// using jest-jasmine2's 'it' to test jest-circus's 'it'. Had to differentiate +// the two with this alias. + +const aliasCircusIt = () => { + const {it, test} = require('../'); + circusIt = it; + circusTest = test; +}; + +aliasCircusIt(); + +describe('test/it.pending error throwing', () => { + it("it doesn't throw an error with valid arguments", () => { + expect(() => { + circusIt.failing('test1', () => {}); + }).not.toThrowError(); + }); + it('it throws error with missing callback function', () => { + expect(() => { + circusIt.failing('test2'); + }).toThrowError( + 'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.', + ); + }); + it("it throws an error when first argument isn't valid", () => { + expect(() => { + circusIt.failing(() => {}); + }).toThrowError( + 'Invalid first argument, () => {}. It must be a named class, named function, number, or string.', + ); + }); + it('it throws an error when callback function is not a function', () => { + expect(() => { + circusIt.failing('test4', 'test4b'); + }).toThrowError( + 'Invalid second argument, test4b. It must be a callback function.', + ); + }); + it('test throws error with missing callback function', () => { + expect(() => { + circusTest.failing('test5'); + }).toThrowError( + 'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.', + ); + }); + it("test throws an error when first argument isn't a string", () => { + expect(() => { + circusTest.failing(() => {}); + }).toThrowError( + 'Invalid first argument, () => {}. It must be a named class, named function, number, or string.', + ); + }); + it('test throws an error when callback function is not a function', () => { + expect(() => { + circusTest.failing('test7', 'test8b'); + }).toThrowError( + 'Invalid second argument, test8b. It must be a callback function.', + ); + }); +}); diff --git a/packages/jest-circus/src/index.ts b/packages/jest-circus/src/index.ts index 33c4e43dec50..2727f6b59608 100644 --- a/packages/jest-circus/src/index.ts +++ b/packages/jest-circus/src/index.ts @@ -128,6 +128,11 @@ const test: Global.It = (() => { fn: Circus.TestFn, timeout?: number, ): void => _addTest(testName, 'only', fn, test.only, timeout); + const failing = ( + testName: Circus.TestNameLike, + fn?: Circus.TestFn, + timeout?: number, + ): void => _addTest(testName, 'failing', fn, failing, timeout); test.todo = (testName: Circus.TestNameLike, ...rest: Array): void => { if (rest.length > 0 || typeof testName !== 'string') { @@ -185,6 +190,10 @@ const test: Global.It = (() => { only.each = bindEach(only); skip.each = bindEach(skip); + only.failing = failing; + skip.failing = failing; + + test.failing = failing; test.only = only; test.skip = skip; diff --git a/packages/jest-circus/src/run.ts b/packages/jest-circus/src/run.ts index 9550629ecf5d..ae106f67fadd 100644 --- a/packages/jest-circus/src/run.ts +++ b/packages/jest-circus/src/run.ts @@ -6,6 +6,7 @@ */ import type {Circus} from '@jest/types'; +import {ErrorWithStack} from 'jest-util'; import {dispatch, getState} from './state'; import {RETRY_TIMES} from './types'; import { @@ -180,9 +181,24 @@ const _callCircusTest = async ( isHook: false, timeout, }); - await dispatch({name: 'test_fn_success', test}); + if (test.mode === 'failing') { + await dispatch({ + error: new ErrorWithStack( + 'Pending test passed even though it was supposed to fail. Remove `.pending` to remove error.', + test.fn, + ), + name: 'test_fn_failure', + test, + }); + } else { + await dispatch({name: 'test_fn_success', test}); + } } catch (error) { - await dispatch({error, name: 'test_fn_failure', test}); + if (test.mode === 'failing') { + await dispatch({name: 'test_fn_success', test}); + } else { + await dispatch({error, name: 'test_fn_failure', test}); + } } }; diff --git a/packages/jest-types/src/Circus.ts b/packages/jest-types/src/Circus.ts index 47d9d61a7623..6d64993a13f3 100644 --- a/packages/jest-types/src/Circus.ts +++ b/packages/jest-types/src/Circus.ts @@ -13,7 +13,7 @@ export type DoneFn = Global.DoneFn; export type BlockFn = Global.BlockFn; export type BlockName = Global.BlockName; export type BlockNameLike = Global.BlockNameLike; -export type BlockMode = void | 'skip' | 'only' | 'todo'; +export type BlockMode = void | 'skip' | 'only' | 'todo' | 'failing'; export type TestMode = BlockMode; export type TestName = Global.TestName; export type TestNameLike = Global.TestNameLike; diff --git a/packages/jest-types/src/Global.ts b/packages/jest-types/src/Global.ts index 486004f49bea..6def249d934d 100644 --- a/packages/jest-types/src/Global.ts +++ b/packages/jest-types/src/Global.ts @@ -75,6 +75,7 @@ export interface It extends ItBase { only: ItBase; skip: ItBase; todo: (testName: TestNameLike) => void; + failing: ItBase; } export interface ItConcurrentBase { From b48dc98f3fb1cfa94ab83986506fcb9e8bae7f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Sun, 27 Mar 2022 14:44:09 +0200 Subject: [PATCH 02/21] Handle failing with only and skipped --- .../__snapshots__/testFailing.test.ts.snap | 81 +++++++++++++++++++ .../__snapshots__/testPending.test.ts.snap | 32 -------- ...estPending.test.ts => testFailing.test.ts} | 16 +++- .../__tests__/statuses.test.js | 12 ++- .../__tests__/worksWithOnlyMode.test.js | 34 ++++++++ .../__tests__/worksWithSkipMode.test.js | 42 ++++++++++ .../package.json | 0 ...st.ts => circusItFailingTestError.test.ts} | 2 +- packages/jest-circus/src/eventHandler.ts | 3 +- packages/jest-circus/src/index.ts | 22 +++-- packages/jest-circus/src/run.ts | 6 +- packages/jest-circus/src/utils.ts | 2 + packages/jest-types/src/Circus.ts | 4 +- 13 files changed, 207 insertions(+), 49 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/testFailing.test.ts.snap delete mode 100644 e2e/__tests__/__snapshots__/testPending.test.ts.snap rename e2e/__tests__/{testPending.test.ts => testFailing.test.ts} (51%) rename e2e/{test-pending => test-failing}/__tests__/statuses.test.js (64%) create mode 100644 e2e/test-failing/__tests__/worksWithOnlyMode.test.js create mode 100644 e2e/test-failing/__tests__/worksWithSkipMode.test.js rename e2e/{test-pending => test-failing}/package.json (100%) rename packages/jest-circus/src/__tests__/{circusItPendingTestError.test.ts => circusItFailingTestError.test.ts} (97%) diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap new file mode 100644 index 000000000000..271aee186a03 --- /dev/null +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`works with all statuses 1`] = ` +"FAIL __tests__/statuses.test.js + ✓ passes + ✕ fails + ✓ failing failes = passes + ✕ failing passes = fails + ○ skipped skips + ○ skipped skipped failing 1 + ○ skipped skipped failing 2 + ✎ todo todo + + ● fails + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 11 | + 12 | it('fails', () => { + > 13 | expect(10).toBe(101); + | ^ + 14 | }); + 15 | + 16 | it.skip('skips', () => { + + at Object.toBe (__tests__/statuses.test.js:13:14) + + ● failing passes = fails + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." +`; + +exports[`works with only mode 1`] = ` +"FAIL __tests__/worksWithOnlyMode.test.js + block with only, should pass + ✓ failing failes = passes, should pass + ○ skipped failing test + ○ skipped passing test + block with only, should fail + ✕ failing passes = fails, should fail + ○ skipped failing test + ○ skipped passing test + + ● 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." +`; + +exports[`works with skip mode 1`] = ` +"FAIL __tests__/worksWithSkipMode.test.js + block with only, should pass + ✕ failing test + ✓ failing failes = passes + ○ skipped skipped failing failes = passes, should pass + ○ skipped passing test + block with only, should fail + ✓ passing test + ✓ failing passes = fails + ○ skipped failing passes = fails, should fail + ○ skipped failing test + + ● block with only, should pass › failing test + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 12 | + 13 | it('failing test', () => { + > 14 | expect(10).toBe(101); + | ^ + 15 | }); + 16 | + 17 | it.skip('passing test', () => { + + at Object.toBe (__tests__/worksWithSkipMode.test.js:14:16)" +`; diff --git a/e2e/__tests__/__snapshots__/testPending.test.ts.snap b/e2e/__tests__/__snapshots__/testPending.test.ts.snap deleted file mode 100644 index 45d7ef7c0d7e..000000000000 --- a/e2e/__tests__/__snapshots__/testPending.test.ts.snap +++ /dev/null @@ -1,32 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`works with all statuses 1`] = ` -"FAIL __tests__/statuses.test.js - ✓ passes - ✕ fails - ✓ pending failes = passes - ✕ pending passes = fails - ○ skipped skips - ✎ todo todo - - ● fails - - expect(received).toBe(expected) // Object.is equality - - Expected: 101 - Received: 10 - - 11 | - 12 | it('fails', () => { - > 13 | expect(10).toBe(101); - | ^ - 14 | }); - 15 | - 16 | it.skip('skips', () => { - - at Object.toBe (__tests__/statuses.test.js:13:14) - - ● pending passes = fails - - Pending test passed even though it was supposed to fail. Remove \`.pending\` to remove error." -`; diff --git a/e2e/__tests__/testPending.test.ts b/e2e/__tests__/testFailing.test.ts similarity index 51% rename from e2e/__tests__/testPending.test.ts rename to e2e/__tests__/testFailing.test.ts index 5bc67bb3cab2..783b2a599766 100644 --- a/e2e/__tests__/testPending.test.ts +++ b/e2e/__tests__/testFailing.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import {extractSummary} from '../Utils'; import runJest from '../runJest'; -const dir = path.resolve(__dirname, '../test-pending'); +const dir = path.resolve(__dirname, '../test-failing'); test('works with all statuses', () => { const result = runJest(dir, ['statuses.test.js']); @@ -16,3 +16,17 @@ test('works with all statuses', () => { const {rest} = extractSummary(result.stderr); expect(rest).toMatchSnapshot(); }); + +test('works with only mode', () => { + const result = runJest(dir, ['worksWithOnlyMode.test.js']); + expect(result.exitCode).toBe(1); + const {rest} = extractSummary(result.stderr); + expect(rest).toMatchSnapshot(); +}); + +test('works with skip mode', () => { + const result = runJest(dir, ['worksWithSkipMode.test.js']); + expect(result.exitCode).toBe(1); + const {rest} = extractSummary(result.stderr); + expect(rest).toMatchSnapshot(); +}); diff --git a/e2e/test-pending/__tests__/statuses.test.js b/e2e/test-failing/__tests__/statuses.test.js similarity index 64% rename from e2e/test-pending/__tests__/statuses.test.js rename to e2e/test-failing/__tests__/statuses.test.js index aaf7b87b2dcf..ac6c8489494d 100644 --- a/e2e/test-pending/__tests__/statuses.test.js +++ b/e2e/test-failing/__tests__/statuses.test.js @@ -19,10 +19,18 @@ it.skip('skips', () => { it.todo('todo'); -it.pending('pending failes = passes', () => { +it.failing('failing failes = passes', () => { expect(10).toBe(101); }); -it.pending('pending passes = fails', () => { +it.skip.failing('skipped failing 1', () => { + expect(10).toBe(10); +}); + +it.skip.failing('skipped failing 2', () => { + expect(10).toBe(101); +}); + +it.failing('failing passes = fails', () => { expect(10).toBe(10); }); diff --git a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js new file mode 100644 index 000000000000..adfb5b43521d --- /dev/null +++ b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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('block with only, should pass', () => { + it.only.failing('failing failes = passes, should pass', () => { + expect(10).toBe(101); + }); + + it('failing test', () => { + expect(10).toBe(101); + }); + + it('passing test', () => { + expect(10).toBe(10); + }); +}); + +describe('block with only, should fail', () => { + it.only.failing('failing passes = fails, should fail', () => { + expect(10).toBe(10); + }); + + it('failing test', () => { + expect(10).toBe(101); + }); + + it('passing test', () => { + expect(10).toBe(10); + }); +}); diff --git a/e2e/test-failing/__tests__/worksWithSkipMode.test.js b/e2e/test-failing/__tests__/worksWithSkipMode.test.js new file mode 100644 index 000000000000..850209b291ca --- /dev/null +++ b/e2e/test-failing/__tests__/worksWithSkipMode.test.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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('block with only, should pass', () => { + it.skip.failing('skipped failing failes = passes, should pass', () => { + expect(10).toBe(101); + }); + + it('failing test', () => { + expect(10).toBe(101); + }); + + it.skip('passing test', () => { + expect(10).toBe(10); + }); + + it.failing('failing failes = passes', () => { + expect(10).toBe(101); + }); +}); + +describe('block with only, should fail', () => { + it.skip.failing('failing passes = fails, should fail', () => { + expect(10).toBe(10); + }); + + it.skip('failing test', () => { + expect(10).toBe(101); + }); + + it('passing test', () => { + expect(10).toBe(10); + }); + + it.failing('failing passes = fails', () => { + expect(10).toBe(101); + }); +}); diff --git a/e2e/test-pending/package.json b/e2e/test-failing/package.json similarity index 100% rename from e2e/test-pending/package.json rename to e2e/test-failing/package.json diff --git a/packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts b/packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts similarity index 97% rename from packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts rename to packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts index a295ab26d661..d3a50a7dc145 100644 --- a/packages/jest-circus/src/__tests__/circusItPendingTestError.test.ts +++ b/packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts @@ -21,7 +21,7 @@ const aliasCircusIt = () => { aliasCircusIt(); -describe('test/it.pending error throwing', () => { +describe('test/it.failing error throwing', () => { it("it doesn't throw an error with valid arguments", () => { expect(() => { circusIt.failing('test1', () => {}); diff --git a/packages/jest-circus/src/eventHandler.ts b/packages/jest-circus/src/eventHandler.ts index 891399ac9ab1..02d02e3131f7 100644 --- a/packages/jest-circus/src/eventHandler.ts +++ b/packages/jest-circus/src/eventHandler.ts @@ -122,7 +122,7 @@ const eventHandler: Circus.EventHandler = (event, state) => { } case 'add_test': { const {currentDescribeBlock, currentlyRunningTest, hasStarted} = state; - const {asyncError, fn, mode, testName: name, timeout} = event; + const {asyncError, fn, mode, testName: name, timeout, failing} = event; if (currentlyRunningTest) { currentlyRunningTest.errors.push( @@ -147,6 +147,7 @@ const eventHandler: Circus.EventHandler = (event, state) => { currentDescribeBlock, timeout, asyncError, + failing, ); if (currentDescribeBlock.mode !== 'skip' && test.mode === 'only') { state.hasFocusedTests = true; diff --git a/packages/jest-circus/src/index.ts b/packages/jest-circus/src/index.ts index 2727f6b59608..7d1c0c01552c 100644 --- a/packages/jest-circus/src/index.ts +++ b/packages/jest-circus/src/index.ts @@ -128,11 +128,15 @@ const test: Global.It = (() => { fn: Circus.TestFn, timeout?: number, ): void => _addTest(testName, 'only', fn, test.only, timeout); - const failing = ( - testName: Circus.TestNameLike, - fn?: Circus.TestFn, - timeout?: number, - ): void => _addTest(testName, 'failing', fn, failing, timeout); + + const bindFailing = (mode: Circus.TestMode) => { + const failing = ( + testName: Circus.TestNameLike, + fn?: Circus.TestFn, + timeout?: number, + ): void => _addTest(testName, mode, fn, failing, timeout, true); + return failing; + }; test.todo = (testName: Circus.TestNameLike, ...rest: Array): void => { if (rest.length > 0 || typeof testName !== 'string') { @@ -154,6 +158,7 @@ const test: Global.It = (() => { timeout?: number, ) => void, timeout?: number, + failing?: boolean, ) => { const asyncError = new ErrorWithStack(undefined, testFn); @@ -178,6 +183,7 @@ const test: Global.It = (() => { return dispatchSync({ asyncError, + failing: failing === undefined ? false : failing, fn, mode, name: 'add_test', @@ -190,10 +196,10 @@ const test: Global.It = (() => { only.each = bindEach(only); skip.each = bindEach(skip); - only.failing = failing; - skip.failing = failing; + only.failing = bindFailing('only'); + skip.failing = bindFailing('skip'); - test.failing = failing; + test.failing = bindFailing(); test.only = only; test.skip = skip; diff --git a/packages/jest-circus/src/run.ts b/packages/jest-circus/src/run.ts index ae106f67fadd..f4255bedd79e 100644 --- a/packages/jest-circus/src/run.ts +++ b/packages/jest-circus/src/run.ts @@ -181,10 +181,10 @@ const _callCircusTest = async ( isHook: false, timeout, }); - if (test.mode === 'failing') { + if (test.failing) { await dispatch({ error: new ErrorWithStack( - 'Pending test passed even though it was supposed to fail. Remove `.pending` to remove error.', + 'Failing test passed even though it was supposed to fail. Remove `.failing` to remove error.', test.fn, ), name: 'test_fn_failure', @@ -194,7 +194,7 @@ const _callCircusTest = async ( await dispatch({name: 'test_fn_success', test}); } } catch (error) { - if (test.mode === 'failing') { + if (test.failing) { await dispatch({name: 'test_fn_success', test}); } else { await dispatch({error, name: 'test_fn_failure', test}); diff --git a/packages/jest-circus/src/utils.ts b/packages/jest-circus/src/utils.ts index 8dc4ffbea57d..61ded789218c 100644 --- a/packages/jest-circus/src/utils.ts +++ b/packages/jest-circus/src/utils.ts @@ -60,11 +60,13 @@ export const makeTest = ( parent: Circus.DescribeBlock, timeout: number | undefined, asyncError: Circus.Exception, + failing: boolean, ): Circus.TestEntry => ({ type: 'test', // eslint-disable-next-line sort-keys asyncError, duration: null, errors: [], + failing, fn, invocations: 0, mode, diff --git a/packages/jest-types/src/Circus.ts b/packages/jest-types/src/Circus.ts index 6d64993a13f3..2f319ce6f4a3 100644 --- a/packages/jest-types/src/Circus.ts +++ b/packages/jest-types/src/Circus.ts @@ -13,7 +13,7 @@ export type DoneFn = Global.DoneFn; export type BlockFn = Global.BlockFn; export type BlockName = Global.BlockName; export type BlockNameLike = Global.BlockNameLike; -export type BlockMode = void | 'skip' | 'only' | 'todo' | 'failing'; +export type BlockMode = void | 'skip' | 'only' | 'todo'; export type TestMode = BlockMode; export type TestName = Global.TestName; export type TestNameLike = Global.TestNameLike; @@ -72,6 +72,7 @@ export type SyncEvent = fn: TestFn; mode?: TestMode; timeout: number | undefined; + failing: boolean; } | { // Any unhandled error that happened outside of test/hooks (unless it is @@ -244,4 +245,5 @@ export type TestEntry = { seenDone: boolean; status?: TestStatus | null; // whether the test has been skipped or run already timeout?: number; + failing: boolean; }; From e5516b3016de96d657edafde6fd610367bc1442f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Sun, 27 Mar 2022 15:12:14 +0200 Subject: [PATCH 03/21] Add documentation about failing tests --- docs/GlobalAPI.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index 12f9f9a87c56..ae227c5e4571 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -878,3 +878,24 @@ const add = (a, b) => a + b; test.todo('add should be associative'); ``` + +### `test.failing(name, fn)` + +Also under the aliases: `it.failing(name, fn)`, `xtest.failing(name, fn)`, `xit.failing(name, fn)`, `it.skip.failing(name, fn)`, `it.only.failing(name, fn)` + +Use `test.failing` when you are writing a test and expecting it to fail. These tests will behave the other way normal tests do. If `failing` test will throw any errors then it will pass. If it does not throw it will fail. + +_Note_: You can use this type of tests i.e. when writing code in a BDD way. In that case the tests will not show up as failing until they pass. Then you can just remove the `failing` modifier to make them pass. + +Example: + +```js +test.failing('it is not equal', () => { + expect(5).toBe(6); // this test will pass +}); + +test.failing('it is equal', () => { + expect(10).toBe(10); // this test will fail +}); +``` + From 7547ebebed3f43bffd3285a67efb2aaf8f15026f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Tue, 26 Apr 2022 18:28:30 +0200 Subject: [PATCH 04/21] Add failing to types --- .../jest-types/__typetests__/globals.test.ts | 18 ++++++++++++++++++ packages/jest-types/src/Global.ts | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/jest-types/__typetests__/globals.test.ts b/packages/jest-types/__typetests__/globals.test.ts index fa8f3cf20940..0477e9c914ea 100644 --- a/packages/jest-types/__typetests__/globals.test.ts +++ b/packages/jest-types/__typetests__/globals.test.ts @@ -135,6 +135,24 @@ expectType(test.skip.each(list)(function named() {}, fn)); expectType(test.skip.each(list)(class {}, fn)); expectType(test.skip.each(list)(class Named {}, fn)); +expectType(test.failing(123, fn)); +expectType(test.failing(() => {}, fn)); +expectType(test.failing(function named() {}, fn)); +expectType(test.failing(class {}, fn)); +expectType(test.failing(class Named {}, fn)); + +expectType(test.skip.failing(123, fn)); +expectType(test.skip.failing(() => {}, fn)); +expectType(test.skip.failing(function named() {}, fn)); +expectType(test.skip.failing(class {}, fn)); +expectType(test.skip.failing(class Named {}, fn)); + +expectType(test.only.failing(123, fn)); +expectType(test.only.failing(() => {}, fn)); +expectType(test.only.failing(function named() {}, fn)); +expectType(test.only.failing(class {}, fn)); +expectType(test.only.failing(class Named {}, fn)); + expectType( test.each` a | b | expected diff --git a/packages/jest-types/src/Global.ts b/packages/jest-types/src/Global.ts index 6def249d934d..b115969bf9a5 100644 --- a/packages/jest-types/src/Global.ts +++ b/packages/jest-types/src/Global.ts @@ -69,13 +69,13 @@ export interface HookBase { export interface ItBase { (testName: TestNameLike, fn: TestFn, timeout?: number): void; each: Each; + failing: Omit; } export interface It extends ItBase { only: ItBase; skip: ItBase; todo: (testName: TestNameLike) => void; - failing: ItBase; } export interface ItConcurrentBase { From 159c4f83193d8eca7cb47dce68ce5bdef5a0f841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Tue, 26 Apr 2022 18:28:44 +0200 Subject: [PATCH 05/21] Add info about failing to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efa038f928b6..6388a59fd623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ - `[jest-watcher]` [**BREAKING**] Make `PatternPrompt` class to take `entityName` as third constructor parameter instead of `this._entityName` ([#12591](https://github.com/facebook/jest/pull/12591)) - `[jest-worker]` [**BREAKING**] Allow only absolute `workerPath` ([#12343](https://github.com/facebook/jest/pull/12343)) - `[pretty-format]` New `maxWidth` parameter ([#12402](https://github.com/facebook/jest/pull/12402)) +- `[jest-circus]` Add `failing` test modifier that inverts the behaviour of tests ([#12484](https://github.com/facebook/jest/pull/12484)) ### Fixes From 913623a9acc39e4f100b32d746964ea7fffcffd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Tue, 26 Apr 2022 19:14:35 +0200 Subject: [PATCH 06/21] Add missing specs and docs for skipping with different aliases --- docs/GlobalAPI.md | 76 ++++++++++++++----- .../__snapshots__/testFailing.test.ts.snap | 49 +++++++++++- e2e/test-failing/__tests__/statuses.test.js | 14 +++- .../__tests__/worksWithOnlyMode.test.js | 41 +++++++++- packages/jest-circus/src/eventHandler.ts | 10 ++- 5 files changed, 159 insertions(+), 31 deletions(-) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index ae227c5e4571..558bc5e8046b 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -731,6 +731,61 @@ test.each` }); ``` +### `test.failing(name, fn)` + +Also under the aliases: `it.failing(name, fn)` + +:::note + +This is only available with the default [jest-circus](https://github.com/facebook/jest/tree/main/packages/jest-circus) runner. + +::: + +Use `test.failing` when you are writing a test and expecting it to fail. These tests will behave the other way normal tests do. If `failing` test will throw any errors then it will pass. If it does not throw it will fail. + +:::tip + +You can use this type of tests i.e. when writing code in a BDD way. In that case the tests will not show up as failing until they pass. Then you can just remove the `failing` modifier to make them pass. + +::: + +Example: + +```js +test.failing('it is not equal', () => { + expect(5).toBe(6); // this test will pass +}); + +test.failing('it is equal', () => { + expect(10).toBe(10); // this test will fail +}); +``` + +### `test.only.failing(name, fn)` + +Also under the aliases: `it.only.failing(name, fn)`, `fit.failing(name, fn)` + +:::note + +This is only available with the default [jest-circus](https://github.com/facebook/jest/tree/main/packages/jest-circus) runner. + +::: + +Use `test.only.failing` if you want to only run a specific failing test. + + +### `test.skip.failing(name, fn)` + +Also under the aliases: `it.skip.failing(name, fn)`, `xit.failing(name, fn)`, `xtest.failing(name, fn)` + +:::note + +This is only available with the default [jest-circus](https://github.com/facebook/jest/tree/main/packages/jest-circus) runner. + +::: + +Use `test.skip.failing` if you want to skip running a specific failing test. + ### `test.only(name, fn, timeout)` Also under the aliases: `it.only(name, fn, timeout)`, and `fit(name, fn, timeout)` @@ -878,24 +933,3 @@ const add = (a, b) => a + b; test.todo('add should be associative'); ``` - -### `test.failing(name, fn)` - -Also under the aliases: `it.failing(name, fn)`, `xtest.failing(name, fn)`, `xit.failing(name, fn)`, `it.skip.failing(name, fn)`, `it.only.failing(name, fn)` - -Use `test.failing` when you are writing a test and expecting it to fail. These tests will behave the other way normal tests do. If `failing` test will throw any errors then it will pass. If it does not throw it will fail. - -_Note_: You can use this type of tests i.e. when writing code in a BDD way. In that case the tests will not show up as failing until they pass. Then you can just remove the `failing` modifier to make them pass. - -Example: - -```js -test.failing('it is not equal', () => { - expect(5).toBe(6); // this test will pass -}); - -test.failing('it is equal', () => { - expect(10).toBe(10); // this test will fail -}); -``` - diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap index 271aee186a03..3d18915de0d5 100644 --- a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -5,10 +5,13 @@ exports[`works with all statuses 1`] = ` ✓ passes ✕ fails ✓ failing failes = passes + ✓ failing failes = passes with test syntax ✕ failing passes = fails ○ skipped skips ○ skipped skipped failing 1 ○ skipped skipped failing 2 + ○ skipped skipped failing with different syntax + ○ skipped skipped failing with another different syntax ✎ todo todo ● fails @@ -37,15 +40,53 @@ exports[`works with only mode 1`] = ` "FAIL __tests__/worksWithOnlyMode.test.js block with only, should pass ✓ failing failes = passes, should pass - ○ skipped failing test - ○ skipped passing test + ○ skipped failing test but skipped + ○ skipped passing test but skipped block with only, should fail ✕ failing passes = fails, should fail - ○ skipped failing test - ○ skipped passing test + ○ skipped failing test but skipped + ○ skipped passing test but skipped + block with only in other it, should skip + ✕ failing test + ○ skipped failing passes = fails, should fail but skipped + ○ skipped passing test but skipped + block with only with different syntax, should fail + ✕ failing passes = fails, should fail 1 + ✕ failing passes = fails, should fail 2 + ○ skipped failing test but skipped + ○ skipped passing test but skipped ● 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. + + + + ● block with only in other it, should skip › failing test + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 41 | // eslint-disable-next-line jest/no-focused-tests + 42 | it.only('failing test', () => { + > 43 | expect(10).toBe(101); + | ^ + 44 | }); + 45 | + 46 | it('passing test but skipped', () => { + + at Object.toBe (__tests__/worksWithOnlyMode.test.js:43: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. + + + + ● 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." `; diff --git a/e2e/test-failing/__tests__/statuses.test.js b/e2e/test-failing/__tests__/statuses.test.js index ac6c8489494d..d197f14637be 100644 --- a/e2e/test-failing/__tests__/statuses.test.js +++ b/e2e/test-failing/__tests__/statuses.test.js @@ -23,14 +23,26 @@ it.failing('failing failes = passes', () => { expect(10).toBe(101); }); +test.failing('failing failes = passes with test syntax', () => { + expect(10).toBe(101); +}); + it.skip.failing('skipped failing 1', () => { expect(10).toBe(10); }); -it.skip.failing('skipped failing 2', () => { +test.skip.failing('skipped failing 2', () => { expect(10).toBe(101); }); it.failing('failing passes = fails', () => { expect(10).toBe(10); }); + +xit.failing('skipped failing with different syntax', () => { + expect(10).toBe(10); +}); + +xtest.failing('skipped failing with another different syntax', () => { + expect(10).toBe(10); +}); diff --git a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js index adfb5b43521d..4f41a13ed838 100644 --- a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js +++ b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js @@ -10,11 +10,11 @@ describe('block with only, should pass', () => { expect(10).toBe(101); }); - it('failing test', () => { + it('failing test but skipped', () => { expect(10).toBe(101); }); - it('passing test', () => { + it('passing test but skipped', () => { expect(10).toBe(10); }); }); @@ -24,11 +24,44 @@ describe('block with only, should fail', () => { expect(10).toBe(10); }); - it('failing test', () => { + it('failing test but skipped', () => { expect(10).toBe(101); }); - it('passing test', () => { + it('passing test but skipped', () => { + expect(10).toBe(10); + }); +}); + +describe('block with only in other it, should skip', () => { + it.failing('failing passes = fails, should fail but skipped', () => { + expect(10).toBe(10); + }); + + // eslint-disable-next-line jest/no-focused-tests + it.only('failing test', () => { + expect(10).toBe(101); + }); + + it('passing test but skipped', () => { + expect(10).toBe(10); + }); +}); + +describe('block with only with different syntax, should fail', () => { + fit.failing('failing passes = fails, should fail 1', () => { + expect(10).toBe(10); + }); + + test.only.failing('failing passes = fails, should fail 2', () => { + expect(10).toBe(10); + }); + + it('failing test but skipped', () => { + expect(10).toBe(101); + }); + + it('passing test but skipped', () => { expect(10).toBe(10); }); }); diff --git a/packages/jest-circus/src/eventHandler.ts b/packages/jest-circus/src/eventHandler.ts index 38aee07a563e..904ebd383d7a 100644 --- a/packages/jest-circus/src/eventHandler.ts +++ b/packages/jest-circus/src/eventHandler.ts @@ -122,7 +122,15 @@ const eventHandler: Circus.EventHandler = (event, state) => { } case 'add_test': { const {currentDescribeBlock, currentlyRunningTest, hasStarted} = state; - const {asyncError, fn, mode, testName: name, timeout, concurrent, failing} = event; + const { + asyncError, + fn, + mode, + testName: name, + timeout, + concurrent, + failing, + } = event; if (currentlyRunningTest) { currentlyRunningTest.errors.push( From a4cecd81aea8d5594de587a9a154571abc627af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Wed, 27 Apr 2022 14:53:53 +0200 Subject: [PATCH 07/21] Fix typos in README and specs --- docs/GlobalAPI.md | 3 +-- e2e/__tests__/__snapshots__/testFailing.test.ts.snap | 10 +++++----- e2e/test-failing/__tests__/statuses.test.js | 4 ++-- e2e/test-failing/__tests__/worksWithOnlyMode.test.js | 2 +- e2e/test-failing/__tests__/worksWithSkipMode.test.js | 4 ++-- .../src/__tests__/circusItFailingTestError.test.ts | 3 --- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index 558bc5e8046b..9c54de1f7f7a 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -733,7 +733,7 @@ test.each` ### `test.failing(name, fn)` -Also under the aliases: `it.failing(name, fn)` +Also under the alias: `it.failing(name, fn)` :::note @@ -773,7 +773,6 @@ This is only available with the default [jest-circus](https://github.com/faceboo Use `test.only.failing` if you want to only run a specific failing test. - ### `test.skip.failing(name, fn)` Also under the aliases: `it.skip.failing(name, fn)`, `xit.failing(name, fn)`, `xtest.failing(name, fn)` diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap index 3d18915de0d5..9dc981f75096 100644 --- a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -4,8 +4,8 @@ exports[`works with all statuses 1`] = ` "FAIL __tests__/statuses.test.js ✓ passes ✕ fails - ✓ failing failes = passes - ✓ failing failes = passes with test syntax + ✓ failing fails = passes + ✓ failing fails = passes with test syntax ✕ failing passes = fails ○ skipped skips ○ skipped skipped failing 1 @@ -39,7 +39,7 @@ exports[`works with all statuses 1`] = ` exports[`works with only mode 1`] = ` "FAIL __tests__/worksWithOnlyMode.test.js block with only, should pass - ✓ failing failes = passes, should pass + ✓ failing fails = passes, should pass ○ skipped failing test but skipped ○ skipped passing test but skipped block with only, should fail @@ -94,8 +94,8 @@ exports[`works with skip mode 1`] = ` "FAIL __tests__/worksWithSkipMode.test.js block with only, should pass ✕ failing test - ✓ failing failes = passes - ○ skipped skipped failing failes = passes, should pass + ✓ failing fails = passes + ○ skipped skipped failing fails = passes, should pass ○ skipped passing test block with only, should fail ✓ passing test diff --git a/e2e/test-failing/__tests__/statuses.test.js b/e2e/test-failing/__tests__/statuses.test.js index d197f14637be..a75235f1367b 100644 --- a/e2e/test-failing/__tests__/statuses.test.js +++ b/e2e/test-failing/__tests__/statuses.test.js @@ -19,11 +19,11 @@ it.skip('skips', () => { it.todo('todo'); -it.failing('failing failes = passes', () => { +it.failing('failing fails = passes', () => { expect(10).toBe(101); }); -test.failing('failing failes = passes with test syntax', () => { +test.failing('failing fails = passes with test syntax', () => { expect(10).toBe(101); }); diff --git a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js index 4f41a13ed838..47933f8c0234 100644 --- a/e2e/test-failing/__tests__/worksWithOnlyMode.test.js +++ b/e2e/test-failing/__tests__/worksWithOnlyMode.test.js @@ -6,7 +6,7 @@ */ describe('block with only, should pass', () => { - it.only.failing('failing failes = passes, should pass', () => { + it.only.failing('failing fails = passes, should pass', () => { expect(10).toBe(101); }); diff --git a/e2e/test-failing/__tests__/worksWithSkipMode.test.js b/e2e/test-failing/__tests__/worksWithSkipMode.test.js index 850209b291ca..36cb4d1e43bd 100644 --- a/e2e/test-failing/__tests__/worksWithSkipMode.test.js +++ b/e2e/test-failing/__tests__/worksWithSkipMode.test.js @@ -6,7 +6,7 @@ */ describe('block with only, should pass', () => { - it.skip.failing('skipped failing failes = passes, should pass', () => { + it.skip.failing('skipped failing fails = passes, should pass', () => { expect(10).toBe(101); }); @@ -18,7 +18,7 @@ describe('block with only, should pass', () => { expect(10).toBe(10); }); - it.failing('failing failes = passes', () => { + it.failing('failing fails = passes', () => { expect(10).toBe(101); }); }); diff --git a/packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts b/packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts index d3a50a7dc145..65322ba71184 100644 --- a/packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts +++ b/packages/jest-circus/src/__tests__/circusItFailingTestError.test.ts @@ -10,9 +10,6 @@ import type {Global} from '@jest/types'; let circusIt: Global.It; let circusTest: Global.It; -// using jest-jasmine2's 'it' to test jest-circus's 'it'. Had to differentiate -// the two with this alias. - const aliasCircusIt = () => { const {it, test} = require('../'); circusIt = it; From 57e8e5111029e42bfc4cd1b972f57076ae5f291c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Wed, 27 Apr 2022 16:50:55 +0200 Subject: [PATCH 08/21] Fix usage type in GlobalAPI.md --- docs/GlobalAPI.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index 9c54de1f7f7a..f044e2f81172 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -731,9 +731,9 @@ test.each` }); ``` -### `test.failing(name, fn)` +### `test.failing(name, fn, timeout)` -Also under the alias: `it.failing(name, fn)` +Also under the alias: `it.failing(name, fn, timeout)` :::note @@ -761,9 +761,9 @@ test.failing('it is equal', () => { }); ``` -### `test.only.failing(name, fn)` +### `test.only.failing(name, fn, timeout)` -Also under the aliases: `it.only.failing(name, fn)`, `fit.failing(name, fn)` +Also under the aliases: `it.only.failing(name, fn, timeout)`, `fit.failing(name, fn, timeout)` :::note @@ -773,9 +773,9 @@ This is only available with the default [jest-circus](https://github.com/faceboo Use `test.only.failing` if you want to only run a specific failing test. -### `test.skip.failing(name, fn)` +### `test.skip.failing(name, fn, timeout)` -Also under the aliases: `it.skip.failing(name, fn)`, `xit.failing(name, fn)`, `xtest.failing(name, fn)` +Also under the aliases: `it.skip.failing(name, fn, timeout)`, `xit.failing(name, fn, timeout)`, `xtest.failing(name, fn, timeout)` :::note From d9a5af84d651720fab9dfc381733e97fe656b996 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 30 Apr 2022 09:16:07 +0200 Subject: [PATCH 09/21] snapshot --- .../__snapshots__/circusDeclarationErrors.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap index fb8e6dd705be..d541ca6e6fbe 100644 --- a/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap +++ b/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap @@ -16,7 +16,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = ` 14 | }); 15 | }); - at eventHandler (../../packages/jest-circus/build/eventHandler.js:145:11) + at eventHandler (../../packages/jest-circus/build/eventHandler.js:153:11) at test (__tests__/asyncDefinition.test.js:12:5) ● Test suite failed to run @@ -46,7 +46,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = ` 20 | }); 21 | - at eventHandler (../../packages/jest-circus/build/eventHandler.js:145:11) + at eventHandler (../../packages/jest-circus/build/eventHandler.js:153:11) at test (__tests__/asyncDefinition.test.js:18:3) ● Test suite failed to run From a0df0bf719ba6182d5e53b0ba710a544f25f5b9e Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 30 Apr 2022 09:16:35 +0200 Subject: [PATCH 10/21] move changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b084ae9833c0..2c23ea9b43ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[jest-circus]` Add `failing` test modifier that inverts the behaviour of tests ([#12484](https://github.com/facebook/jest/pull/12484)) - `[jest-environment-node, jest-environment-jsdom]` Allow specifying `customExportConditions` ([#12774](https://github.com/facebook/jest/pull/12774)) ### Fixes @@ -38,7 +39,6 @@ ### Features - `[jest-resolve]` Expose `ResolverOptions` type ([#12736](https://github.com/facebook/jest/pull/12736)) -- `[jest-circus]` Add `failing` test modifier that inverts the behaviour of tests ([#12484](https://github.com/facebook/jest/pull/12484)) ### Fixes From fde999dc2857a2328bbc860a4c23168b84586b57 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 30 Apr 2022 09:18:22 +0200 Subject: [PATCH 11/21] correct changelog link --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c23ea9b43ba..376b8df56a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -- `[jest-circus]` Add `failing` test modifier that inverts the behaviour of tests ([#12484](https://github.com/facebook/jest/pull/12484)) +- `[jest-circus]` Add `failing` test modifier that inverts the behaviour of tests ([#12610](https://github.com/facebook/jest/pull/12610)) - `[jest-environment-node, jest-environment-jsdom]` Allow specifying `customExportConditions` ([#12774](https://github.com/facebook/jest/pull/12774)) ### Fixes From bf007fa5321c2f3c2c5fb1a06787373ddbd782da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Thu, 5 May 2022 10:35:37 +0200 Subject: [PATCH 12/21] Add another point to README for failing test. --- docs/GlobalAPI.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index f044e2f81172..42cdd9f9c872 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -747,6 +747,8 @@ Use `test.failing` when you are writing a test and expecting it to fail. These t You can use this type of tests i.e. when writing code in a BDD way. In that case the tests will not show up as failing until they pass. Then you can just remove the `failing` modifier to make them pass. +It can also be a nice way to contribute failing tests to a project, even if you don't know how to fix the bug. + ::: Example: From 874d45402cf06c7538d0821bc3c3191f6db8b9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Thu, 5 May 2022 10:46:41 +0200 Subject: [PATCH 13/21] Add skipping failing functionality with jasmine --- e2e/__tests__/testFailing.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/e2e/__tests__/testFailing.test.ts b/e2e/__tests__/testFailing.test.ts index 783b2a599766..539d309b9290 100644 --- a/e2e/__tests__/testFailing.test.ts +++ b/e2e/__tests__/testFailing.test.ts @@ -6,8 +6,12 @@ */ import * as path from 'path'; +import {skipSuiteOnJasmine} from '@jest/test-utils'; import {extractSummary} from '../Utils'; import runJest from '../runJest'; + +skipSuiteOnJasmine(); + const dir = path.resolve(__dirname, '../test-failing'); test('works with all statuses', () => { From 4ed39f606e0c66827828e7b5c637379287fe6c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Thu, 5 May 2022 12:54:10 +0200 Subject: [PATCH 14/21] Add skipping failing functionality to concurrent --- .../__snapshots__/testFailing.test.ts.snap | 43 +++++++++++++++++++ e2e/__tests__/testFailing.test.ts | 16 ++++++- .../__tests__/worksWithConcurrentMode.test.js | 24 +++++++++++ .../worksWithConcurrentOnlyMode.test.js | 24 +++++++++++ packages/jest-circus/src/index.ts | 2 + .../jest-jasmine2/src/jasmineAsyncInstall.ts | 2 + packages/jest-types/src/Global.ts | 1 + 7 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 e2e/test-failing/__tests__/worksWithConcurrentMode.test.js create mode 100644 e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap index 9dc981f75096..8d930174a7cf 100644 --- a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -36,6 +36,49 @@ exports[`works with all statuses 1`] = ` Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." `; +exports[`works with concurrent and only mode 1`] = ` +"FAIL __tests__/worksWithConcurrentOnlyMode.test.js + block with concurrent + ✕ failing passes = failes + ✓ failing fails = passes + ○ skipped skipped failing test + ○ skipped skipped failing fails + + ● block with concurrent › failing passes = failes + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." +`; + +exports[`works with concurrent mode 1`] = ` +"FAIL __tests__/worksWithConcurrentMode.test.js + block with concurrent + ✕ failing test + ✕ failing passes = failes + ✓ failing fails = passes + ○ skipped skipped failing fails + + ● block with concurrent › failing test + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 8 | describe('block with concurrent', () => { + 9 | it('failing test', () => { + > 10 | expect(10).toBe(101); + | ^ + 11 | }); + 12 | + 13 | it.concurrent.failing('failing passes = failes', () => { + + at Object.toBe (__tests__/worksWithConcurrentMode.test.js:10:16) + + ● block with concurrent › failing passes = failes + + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." +`; + exports[`works with only mode 1`] = ` "FAIL __tests__/worksWithOnlyMode.test.js block with only, should pass diff --git a/e2e/__tests__/testFailing.test.ts b/e2e/__tests__/testFailing.test.ts index 539d309b9290..da8584ba7b95 100644 --- a/e2e/__tests__/testFailing.test.ts +++ b/e2e/__tests__/testFailing.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import {skipSuiteOnJasmine} from '@jest/test-utils'; import {extractSummary} from '../Utils'; -import runJest from '../runJest'; +import runJest, {json as runWithJson} from '../runJest'; skipSuiteOnJasmine(); @@ -34,3 +34,17 @@ test('works with skip mode', () => { const {rest} = extractSummary(result.stderr); expect(rest).toMatchSnapshot(); }); + +test('works with concurrent mode', () => { + const result = runWithJson(dir, ['worksWithConcurrentMode.test.js']); + expect(result.exitCode).toBe(1); + const {rest} = extractSummary(result.stderr); + expect(rest).toMatchSnapshot(); +}); + +test('works with concurrent and only mode', () => { + const result = runWithJson(dir, ['worksWithConcurrentOnlyMode.test.js']); + expect(result.exitCode).toBe(1); + const {rest} = extractSummary(result.stderr); + expect(rest).toMatchSnapshot(); +}); diff --git a/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js b/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js new file mode 100644 index 000000000000..8e4433d75eba --- /dev/null +++ b/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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('block with concurrent', () => { + it('failing test', () => { + expect(10).toBe(101); + }); + + it.concurrent.failing('failing passes = failes', () => { + expect(10).toBe(10); + }); + + it.concurrent.failing('failing fails = passes', () => { + expect(10).toBe(101); + }); + + it.concurrent.skip.failing('skipped failing fails', () => { + expect(10).toBe(101); + }); +}); diff --git a/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js new file mode 100644 index 000000000000..9a80cfd56ab4 --- /dev/null +++ b/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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('block with concurrent', () => { + it('skipped failing test', () => { + expect(10).toBe(101); + }); + + it.concurrent.only.failing('failing passes = failes', () => { + expect(10).toBe(10); + }); + + it.concurrent.only.failing('failing fails = passes', () => { + expect(10).toBe(101); + }); + + it.concurrent.failing('skipped failing fails', () => { + expect(10).toBe(101); + }); +}); diff --git a/packages/jest-circus/src/index.ts b/packages/jest-circus/src/index.ts index 89a2b8b7fec7..7d49ba1ddc07 100644 --- a/packages/jest-circus/src/index.ts +++ b/packages/jest-circus/src/index.ts @@ -220,6 +220,8 @@ const test: Global.It = (() => { test.concurrent = concurrentTest; concurrentTest.only = concurrentOnly; concurrentTest.skip = skip; + concurrentTest.failing = bindFailing(true); + concurrentOnly.failing = bindFailing(true, 'only'); return test; })(); diff --git a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts index 836b0df29726..a630044beb6c 100644 --- a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts +++ b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts @@ -223,6 +223,8 @@ function makeConcurrent( }; // each is binded after the function is made concurrent, so for now it is made noop concurrentFn.each = () => () => {}; + // "failing" is not implemented in jasmine. It has to be defined because of TS types. + concurrentFn.failing = () => () => {}; return concurrentFn; } diff --git a/packages/jest-types/src/Global.ts b/packages/jest-types/src/Global.ts index 16dc1447141d..aa17a4c8f851 100644 --- a/packages/jest-types/src/Global.ts +++ b/packages/jest-types/src/Global.ts @@ -81,6 +81,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; } export interface ItConcurrentExtended extends ItConcurrentBase { From 60ffb4c7d2402335205a42ea82673f803803d693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Thu, 5 May 2022 13:11:23 +0200 Subject: [PATCH 15/21] Add type tests for concurrent functions --- .../jest-types/__typetests__/globals.test.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/jest-types/__typetests__/globals.test.ts b/packages/jest-types/__typetests__/globals.test.ts index 0477e9c914ea..e4bbd6fb6c6b 100644 --- a/packages/jest-types/__typetests__/globals.test.ts +++ b/packages/jest-types/__typetests__/globals.test.ts @@ -153,6 +153,24 @@ expectType(test.only.failing(function named() {}, fn)); expectType(test.only.failing(class {}, fn)); expectType(test.only.failing(class Named {}, fn)); +expectType(test.concurrent.failing(123, asyncFn)); +expectType(test.concurrent.failing(() => {}, asyncFn)); +expectType(test.concurrent.failing(function named() {}, asyncFn)); +expectType(test.concurrent.failing(class {}, asyncFn)); +expectType(test.concurrent.failing(class Named {}, asyncFn)); + +expectType(test.concurrent.skip.failing(123, asyncFn)); +expectType(test.concurrent.skip.failing(() => {}, asyncFn)); +expectType(test.concurrent.skip.failing(function named() {}, asyncFn)); +expectType(test.concurrent.skip.failing(class {}, asyncFn)); +expectType(test.concurrent.skip.failing(class Named {}, asyncFn)); + +expectType(test.concurrent.only.failing(123, asyncFn)); +expectType(test.concurrent.only.failing(() => {}, asyncFn)); +expectType(test.concurrent.only.failing(function named() {}, asyncFn)); +expectType(test.concurrent.only.failing(class {}, asyncFn)); +expectType(test.concurrent.only.failing(class Named {}, asyncFn)); + expectType( test.each` a | b | expected @@ -207,6 +225,9 @@ expectType( `(testName, fn, timeout), ); +expectType(test.concurrent(testName, asyncFn)); +expectType(test.concurrent(testName, asyncFn, timeout)); + expectType(test.concurrent.each(list)(testName, asyncFn)); expectType(test.concurrent.each(list)(testName, asyncFn, timeout)); expectType(test.concurrent.each(table)(testName, asyncFn)); From 3e70058719c9fbbf3c6b69cc7cfec5fbd07df2c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Thu, 5 May 2022 13:50:48 +0200 Subject: [PATCH 16/21] Fix typos in tests --- e2e/__tests__/__snapshots__/testFailing.test.ts.snap | 10 +++++----- .../__tests__/worksWithConcurrentMode.test.js | 2 +- .../__tests__/worksWithConcurrentOnlyMode.test.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap index 8d930174a7cf..05d8514a5d5f 100644 --- a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -39,12 +39,12 @@ exports[`works with all statuses 1`] = ` exports[`works with concurrent and only mode 1`] = ` "FAIL __tests__/worksWithConcurrentOnlyMode.test.js block with concurrent - ✕ failing passes = failes + ✕ failing passes = fails ✓ failing fails = passes ○ skipped skipped failing test ○ skipped skipped failing fails - ● block with concurrent › failing passes = failes + ● block with concurrent › failing passes = fails Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." `; @@ -53,7 +53,7 @@ exports[`works with concurrent mode 1`] = ` "FAIL __tests__/worksWithConcurrentMode.test.js block with concurrent ✕ failing test - ✕ failing passes = failes + ✕ failing passes = fails ✓ failing fails = passes ○ skipped skipped failing fails @@ -70,11 +70,11 @@ exports[`works with concurrent mode 1`] = ` | ^ 11 | }); 12 | - 13 | it.concurrent.failing('failing passes = failes', () => { + 13 | it.concurrent.failing('failing passes = fails', () => { at Object.toBe (__tests__/worksWithConcurrentMode.test.js:10:16) - ● block with concurrent › failing passes = failes + ● block with concurrent › failing passes = fails Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." `; diff --git a/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js b/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js index 8e4433d75eba..950b01c29d08 100644 --- a/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js +++ b/e2e/test-failing/__tests__/worksWithConcurrentMode.test.js @@ -10,7 +10,7 @@ describe('block with concurrent', () => { expect(10).toBe(101); }); - it.concurrent.failing('failing passes = failes', () => { + it.concurrent.failing('failing passes = fails', () => { expect(10).toBe(10); }); diff --git a/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js b/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js index 9a80cfd56ab4..93d8850d90ed 100644 --- a/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js +++ b/e2e/test-failing/__tests__/worksWithConcurrentOnlyMode.test.js @@ -10,7 +10,7 @@ describe('block with concurrent', () => { expect(10).toBe(101); }); - it.concurrent.only.failing('failing passes = failes', () => { + it.concurrent.only.failing('failing passes = fails', () => { expect(10).toBe(10); }); From 9faefc59dae26ebbf2e41bd084889b8dd9987c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Warda?= Date: Fri, 6 May 2022 11:32:30 +0200 Subject: [PATCH 17/21] Throw when trying to use `failing` in jasmine --- packages/jest-jasmine2/src/jasmineAsyncInstall.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts index a630044beb6c..4883344cf7e8 100644 --- a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts +++ b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts @@ -224,7 +224,11 @@ function makeConcurrent( // each is binded after the function is made concurrent, so for now it is made noop concurrentFn.each = () => () => {}; // "failing" is not implemented in jasmine. It has to be defined because of TS types. - concurrentFn.failing = () => () => {}; + concurrentFn.failing = () => () => { + throw new Error( + 'Jest: `failing` tests are only supported in `jest-circus`.', + ); + }; return concurrentFn; } From a804799291bc798aa6bc11fd5cddf31117055b27 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 6 May 2022 11:33:44 +0200 Subject: [PATCH 18/21] fix codeframe --- .../__snapshots__/testFailing.test.ts.snap | 69 +++++++++++++++++-- packages/jest-circus/src/run.ts | 8 +-- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap index 05d8514a5d5f..32a75730235d 100644 --- a/e2e/__tests__/__snapshots__/testFailing.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailing.test.ts.snap @@ -33,7 +33,17 @@ exports[`works with all statuses 1`] = ` ● failing passes = fails - Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 36 | }); + 37 | + > 38 | it.failing('failing passes = fails', () => { + | ^ + 39 | expect(10).toBe(10); + 40 | }); + 41 | + + at Object.failing (__tests__/statuses.test.js:38:4)" `; exports[`works with concurrent and only mode 1`] = ` @@ -46,7 +56,18 @@ exports[`works with concurrent and only mode 1`] = ` ● block with concurrent › failing passes = fails - Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 11 | }); + 12 | + > 13 | it.concurrent.only.failing('failing passes = fails', () => { + | ^ + 14 | expect(10).toBe(10); + 15 | }); + 16 | + + at failing (__tests__/worksWithConcurrentOnlyMode.test.js:13:22) + at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1)" `; exports[`works with concurrent mode 1`] = ` @@ -76,7 +97,18 @@ exports[`works with concurrent mode 1`] = ` ● block with concurrent › failing passes = fails - Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error." + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 11 | }); + 12 | + > 13 | it.concurrent.failing('failing passes = fails', () => { + | ^ + 14 | expect(10).toBe(10); + 15 | }); + 16 | + + at failing (__tests__/worksWithConcurrentMode.test.js:13:17) + at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1)" `; exports[`works with only mode 1`] = ` @@ -103,7 +135,16 @@ exports[`works with only mode 1`] = ` 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', () => { + | ^ + 24 | expect(10).toBe(10); + 25 | }); + 26 | + at failing (__tests__/worksWithOnlyMode.test.js:23:11) + at Object.describe (__tests__/worksWithOnlyMode.test.js:22:1) ● block with only in other it, should skip › failing test @@ -126,11 +167,31 @@ exports[`works with only mode 1`] = ` Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + 50 | + 51 | describe('block with only with different syntax, should fail', () => { + > 52 | fit.failing('failing passes = fails, should fail 1', () => { + | ^ + 53 | expect(10).toBe(10); + 54 | }); + 55 | + at failing (__tests__/worksWithOnlyMode.test.js:52:7) + at Object.describe (__tests__/worksWithOnlyMode.test.js:51: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." + Failing test passed even though it was supposed to fail. Remove \`.failing\` to remove error. + + 54 | }); + 55 | + > 56 | test.only.failing('failing passes = fails, should fail 2', () => { + | ^ + 57 | expect(10).toBe(10); + 58 | }); + 59 | + + at failing (__tests__/worksWithOnlyMode.test.js:56:13) + at Object.describe (__tests__/worksWithOnlyMode.test.js:51:1)" `; exports[`works with skip mode 1`] = ` diff --git a/packages/jest-circus/src/run.ts b/packages/jest-circus/src/run.ts index 9fde8e0451d5..4a944d186c2d 100644 --- a/packages/jest-circus/src/run.ts +++ b/packages/jest-circus/src/run.ts @@ -7,7 +7,6 @@ import throat from 'throat'; import type {Circus} from '@jest/types'; -import {ErrorWithStack} from 'jest-util'; import {dispatch, getState} from './state'; import {RETRY_TIMES} from './types'; import { @@ -226,11 +225,10 @@ const _callCircusTest = async ( timeout, }); if (test.failing) { + test.asyncError.message = + 'Failing test passed even though it was supposed to fail. Remove `.failing` to remove error.'; await dispatch({ - error: new ErrorWithStack( - 'Failing test passed even though it was supposed to fail. Remove `.failing` to remove error.', - test.fn, - ), + error: test.asyncError, name: 'test_fn_failure', test, }); From f8cc53dad4ab29feb7c88943deb2edb9f0efa43d Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 6 May 2022 11:53:08 +0200 Subject: [PATCH 19/21] throw error for failing in jasmine --- .../testFailingJasmine.test.ts.snap | 146 ++++++++++++++++++ e2e/__tests__/testFailingJasmine.test.ts | 22 +++ packages/jest-jasmine2/src/index.ts | 12 ++ 3 files changed, 180 insertions(+) create mode 100644 e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap create mode 100644 e2e/__tests__/testFailingJasmine.test.ts diff --git a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap new file mode 100644 index 000000000000..59eea8787c1f --- /dev/null +++ b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap @@ -0,0 +1,146 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`throws an error about unsupported modifier 1`] = ` +"FAIL __tests__/worksWithConcurrentMode.test.js + ● block with concurrent › failing test + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 8 | describe('block with concurrent', () => { + 9 | it('failing test', () => { + > 10 | expect(10).toBe(101); + | ^ + 11 | }); + 12 | + 13 | it.concurrent.failing('failing passes = fails', () => { + + at Object.toBe (__tests__/worksWithConcurrentMode.test.js:10:16) + +FAIL __tests__/worksWithOnlyMode.test.js + ● block with only, should pass › encountered a declaration exception + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 7 | + 8 | describe('block with only, should pass', () => { + > 9 | it.only.failing('failing fails = passes, should pass', () => { + | ^ + 10 | expect(10).toBe(101); + 11 | }); + 12 | + + at Suite.failing (__tests__/worksWithOnlyMode.test.js:9:11) + at Object.describe (__tests__/worksWithOnlyMode.test.js:8:1) + + ● block with only, should fail › encountered a declaration exception + + 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', () => { + | ^ + 24 | expect(10).toBe(10); + 25 | }); + 26 | + + at Suite.failing (__tests__/worksWithOnlyMode.test.js:23:11) + at Object.describe (__tests__/worksWithOnlyMode.test.js:22: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', () => { + | ^ + 38 | expect(10).toBe(10); + 39 | }); + 40 | + + at Suite.failing (__tests__/worksWithOnlyMode.test.js:37:6) + at Object.describe (__tests__/worksWithOnlyMode.test.js:36:1) + + ● block with only with different syntax, should fail › encountered a declaration exception + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 50 | + 51 | describe('block with only with different syntax, should fail', () => { + > 52 | fit.failing('failing passes = fails, should fail 1', () => { + | ^ + 53 | expect(10).toBe(10); + 54 | }); + 55 | + + at Suite.failing (__tests__/worksWithOnlyMode.test.js:52:7) + at Object.describe (__tests__/worksWithOnlyMode.test.js:51:1) + +FAIL __tests__/worksWithConcurrentOnlyMode.test.js + ● block with concurrent › skipped failing test + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 8 | describe('block with concurrent', () => { + 9 | it('skipped failing test', () => { + > 10 | expect(10).toBe(101); + | ^ + 11 | }); + 12 | + 13 | it.concurrent.only.failing('failing passes = fails', () => { + + at Object.toBe (__tests__/worksWithConcurrentOnlyMode.test.js:10:16) + +FAIL __tests__/worksWithSkipMode.test.js + ● block with only, should pass › encountered a declaration exception + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 7 | + 8 | describe('block with only, should pass', () => { + > 9 | it.skip.failing('skipped failing fails = passes, should pass', () => { + | ^ + 10 | expect(10).toBe(101); + 11 | }); + 12 | + + at Suite.failing (__tests__/worksWithSkipMode.test.js:9:11) + at Object.describe (__tests__/worksWithSkipMode.test.js:8:1) + + ● block with only, should fail › encountered a declaration exception + + 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', () => { + | ^ + 28 | expect(10).toBe(10); + 29 | }); + 30 | + + at Suite.failing (__tests__/worksWithSkipMode.test.js:27:11) + at Object.describe (__tests__/worksWithSkipMode.test.js:26:1) + +FAIL __tests__/statuses.test.js + ● Test suite failed to run + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 20 | it.todo('todo'); + 21 | + > 22 | it.failing('failing fails = passes', () => { + | ^ + 23 | expect(10).toBe(101); + 24 | }); + 25 | + + at Object.failing (__tests__/statuses.test.js:22:4)" +`; diff --git a/e2e/__tests__/testFailingJasmine.test.ts b/e2e/__tests__/testFailingJasmine.test.ts new file mode 100644 index 000000000000..c8f922843f66 --- /dev/null +++ b/e2e/__tests__/testFailingJasmine.test.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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 * as path from 'path'; +import {skipSuiteOnJestCircus} from '@jest/test-utils'; +import {extractSummary} from '../Utils'; +import runJest from '../runJest'; + +skipSuiteOnJestCircus(); + +const dir = path.resolve(__dirname, '../test-failing'); + +test('throws an error about unsupported modifier', () => { + const result = runJest(dir); + expect(result.exitCode).toBe(1); + const {rest} = extractSummary(result.stderr); + expect(rest).toMatchSnapshot(); +}); diff --git a/packages/jest-jasmine2/src/index.ts b/packages/jest-jasmine2/src/index.ts index cf7c8bf5b4b1..e09cbcc941cd 100644 --- a/packages/jest-jasmine2/src/index.ts +++ b/packages/jest-jasmine2/src/index.ts @@ -12,6 +12,7 @@ import type {AssertionResult, TestResult} from '@jest/test-result'; import type {Config, Global} from '@jest/types'; import type Runtime from 'jest-runtime'; import type {SnapshotState} from 'jest-snapshot'; +import {ErrorWithStack} from 'jest-util'; import installEach from './each'; import {installErrorOnPrivate} from './errorOnPrivate'; import type Spec from './jasmine/Spec'; @@ -80,6 +81,17 @@ export default async function jasmine2( installEach(environment); + const failing = () => { + throw new ErrorWithStack( + 'Jest: `failing` tests are only supported in `jest-circus`.', + failing, + ); + }; + + environment.global.it.failing = failing; + environment.global.fit.failing = failing; + environment.global.xit.failing = failing; + environment.global.test = environment.global.it; environment.global.it.only = environment.global.fit; environment.global.it.todo = env.todo; From a02b15925c14174c817e33fff2bfc6a06422cdce Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 6 May 2022 12:08:35 +0200 Subject: [PATCH 20/21] Update packages/jest-jasmine2/src/jasmineAsyncInstall.ts Co-authored-by: Tom Mrazauskas --- packages/jest-jasmine2/src/jasmineAsyncInstall.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts index 4883344cf7e8..5e0cb5288bc6 100644 --- a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts +++ b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts @@ -223,7 +223,6 @@ function makeConcurrent( }; // each is binded after the function is made concurrent, so for now it is made noop concurrentFn.each = () => () => {}; - // "failing" is not implemented in jasmine. It has to be defined because of TS types. concurrentFn.failing = () => () => { throw new Error( 'Jest: `failing` tests are only supported in `jest-circus`.', From 368eefd8637ff90f2eecc7238995776f586dcbbe Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 6 May 2022 12:11:08 +0200 Subject: [PATCH 21/21] sort --- .../testFailingJasmine.test.ts.snap | 70 +++++++++---------- e2e/__tests__/testFailingJasmine.test.ts | 4 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap index 59eea8787c1f..b4afcb588c50 100644 --- a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap @@ -1,7 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`throws an error about unsupported modifier 1`] = ` -"FAIL __tests__/worksWithConcurrentMode.test.js +"FAIL __tests__/statuses.test.js + ● Test suite failed to run + + Jest: \`failing\` tests are only supported in \`jest-circus\`. + + 20 | it.todo('todo'); + 21 | + > 22 | it.failing('failing fails = passes', () => { + | ^ + 23 | expect(10).toBe(101); + 24 | }); + 25 | + + at Object.failing (__tests__/statuses.test.js:22:4) + +FAIL __tests__/worksWithConcurrentMode.test.js ● block with concurrent › failing test expect(received).toBe(expected) // Object.is equality @@ -19,6 +34,24 @@ exports[`throws an error about unsupported modifier 1`] = ` at Object.toBe (__tests__/worksWithConcurrentMode.test.js:10:16) +FAIL __tests__/worksWithConcurrentOnlyMode.test.js + ● block with concurrent › skipped failing test + + expect(received).toBe(expected) // Object.is equality + + Expected: 101 + Received: 10 + + 8 | describe('block with concurrent', () => { + 9 | it('skipped failing test', () => { + > 10 | expect(10).toBe(101); + | ^ + 11 | }); + 12 | + 13 | it.concurrent.only.failing('failing passes = fails', () => { + + at Object.toBe (__tests__/worksWithConcurrentOnlyMode.test.js:10:16) + FAIL __tests__/worksWithOnlyMode.test.js ● block with only, should pass › encountered a declaration exception @@ -80,24 +113,6 @@ FAIL __tests__/worksWithOnlyMode.test.js at Suite.failing (__tests__/worksWithOnlyMode.test.js:52:7) at Object.describe (__tests__/worksWithOnlyMode.test.js:51:1) -FAIL __tests__/worksWithConcurrentOnlyMode.test.js - ● block with concurrent › skipped failing test - - expect(received).toBe(expected) // Object.is equality - - Expected: 101 - Received: 10 - - 8 | describe('block with concurrent', () => { - 9 | it('skipped failing test', () => { - > 10 | expect(10).toBe(101); - | ^ - 11 | }); - 12 | - 13 | it.concurrent.only.failing('failing passes = fails', () => { - - at Object.toBe (__tests__/worksWithConcurrentOnlyMode.test.js:10:16) - FAIL __tests__/worksWithSkipMode.test.js ● block with only, should pass › encountered a declaration exception @@ -127,20 +142,5 @@ FAIL __tests__/worksWithSkipMode.test.js 30 | at Suite.failing (__tests__/worksWithSkipMode.test.js:27:11) - at Object.describe (__tests__/worksWithSkipMode.test.js:26:1) - -FAIL __tests__/statuses.test.js - ● Test suite failed to run - - Jest: \`failing\` tests are only supported in \`jest-circus\`. - - 20 | it.todo('todo'); - 21 | - > 22 | it.failing('failing fails = passes', () => { - | ^ - 23 | expect(10).toBe(101); - 24 | }); - 25 | - - at Object.failing (__tests__/statuses.test.js:22:4)" + at Object.describe (__tests__/worksWithSkipMode.test.js:26:1)" `; diff --git a/e2e/__tests__/testFailingJasmine.test.ts b/e2e/__tests__/testFailingJasmine.test.ts index c8f922843f66..7c6aeecd2f9d 100644 --- a/e2e/__tests__/testFailingJasmine.test.ts +++ b/e2e/__tests__/testFailingJasmine.test.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import {skipSuiteOnJestCircus} from '@jest/test-utils'; -import {extractSummary} from '../Utils'; +import {extractSortedSummary} from '../Utils'; import runJest from '../runJest'; skipSuiteOnJestCircus(); @@ -17,6 +17,6 @@ const dir = path.resolve(__dirname, '../test-failing'); test('throws an error about unsupported modifier', () => { const result = runJest(dir); expect(result.exitCode).toBe(1); - const {rest} = extractSummary(result.stderr); + const {rest} = extractSortedSummary(result.stderr); expect(rest).toMatchSnapshot(); });