Skip to content

Commit

Permalink
jest-circus: throw if a test / hook is defined asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
jeysal committed Mar 9, 2019
1 parent 17ffcc9 commit c02488e
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 1 deletion.
68 changes: 68 additions & 0 deletions e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`defining tests and hooks asynchronously throws 1`] = `
"FAIL __tests__/asyncDefinition.test.js
● Test suite failed to run
Cannot add a test after tests have started running. Tests must be defined synchronously.
3 |
4 | Promise.resolve().then(() => {
> 5 | test('async definition inside describe', () => {});
| ^
6 | afterAll(() => {});
7 | });
8 | });
at test (__tests__/asyncDefinition.test.js:5:5)
● Test suite failed to run
Cannot add a hook after tests have started running. Hooks must be defined synchronously.
4 | Promise.resolve().then(() => {
5 | test('async definition inside describe', () => {});
> 6 | afterAll(() => {});
| ^
7 | });
8 | });
9 |
at afterAll (__tests__/asyncDefinition.test.js:6:5)
● Test suite failed to run
Cannot add a test after tests have started running. Tests must be defined synchronously.
9 |
10 | Promise.resolve().then(() => {
> 11 | test('async definition outside describe', () => {});
| ^
12 | afterAll(() => {});
13 | });
14 |
at test (__tests__/asyncDefinition.test.js:11:3)
● Test suite failed to run
Cannot add a hook after tests have started running. Hooks must be defined synchronously.
10 | Promise.resolve().then(() => {
11 | test('async definition outside describe', () => {});
> 12 | afterAll(() => {});
| ^
13 | });
14 |
at afterAll (__tests__/asyncDefinition.test.js:12:3)
Test Suites: 1 failed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.281s, estimated 1s
Ran all test suites matching /asyncDefinition.test.js/i.
"
`;
20 changes: 20 additions & 0 deletions e2e/__tests__/circusDeclarationErrors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* 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 {skipSuiteOnJasmine} from '@jest/test-utils';
import runJest from '../runJest';

skipSuiteOnJasmine();

it('defining tests and hooks asynchronously throws', () => {
const result = runJest('circus-declaration-errors', [
'asyncDefinition.test.js',
]);

expect(result.status).toBe(1);
expect(result.stderr).toMatchSnapshot();
});
13 changes: 13 additions & 0 deletions e2e/circus-declaration-errors/__tests__/asyncDefinition.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe('describe', () => {
test('correct test def', () => {});

Promise.resolve().then(() => {
test('async definition inside describe', () => {});
afterAll(() => {});
});
});

Promise.resolve().then(() => {
test('async definition outside describe', () => {});
afterAll(() => {});
});
5 changes: 5 additions & 0 deletions e2e/circus-declaration-errors/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "node"
}
}
17 changes: 17 additions & 0 deletions packages/jest-circus/src/eventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,28 @@ const eventHandler: EventHandler = (event, state): void => {
const {currentDescribeBlock} = state;
const {asyncError, fn, hookType: type, timeout} = event;
const parent = currentDescribeBlock;

if (state.hasStarted) {
asyncError.message =
'Cannot add a hook after tests have started running. Hooks must be defined synchronously.';
state.unhandledErrors.push(asyncError);
break;
}

currentDescribeBlock.hooks.push({asyncError, fn, parent, timeout, type});
break;
}
case 'add_test': {
const {currentDescribeBlock} = state;
const {asyncError, fn, mode, testName: name, timeout} = event;

if (state.hasStarted) {
asyncError.message =
'Cannot add a test after tests have started running. Tests must be defined synchronously.';
state.unhandledErrors.push(asyncError);
break;
}

const test = makeTest(
fn,
mode,
Expand Down Expand Up @@ -151,6 +167,7 @@ const eventHandler: EventHandler = (event, state): void => {
break;
}
case 'run_start': {
state.hasStarted = true;
global[TEST_TIMEOUT_SYMBOL] &&
(state.testTimeout = global[TEST_TIMEOUT_SYMBOL]);
break;
Expand Down
3 changes: 2 additions & 1 deletion packages/jest-circus/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const INITIAL_STATE: State = {
currentDescribeBlock: ROOT_DESCRIBE_BLOCK,
currentlyRunningTest: null,
expand: undefined,
hasFocusedTests: false, // whether .only has been used on any test/describe
hasFocusedTests: false,
hasStarted: false,
includeTestLocationInResult: false,
parentProcess: null,
rootDescribeBlock: ROOT_DESCRIBE_BLOCK,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-circus/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export type State = {
currentlyRunningTest: TestEntry | undefined | null; // including when hooks are being executed
expand?: boolean; // expand error messages
hasFocusedTests: boolean; // that are defined using test.only
hasStarted: boolean; // whether the rootDescribeBlock has started running
// Store process error handlers. During the run we inject our own
// handlers (so we could fail tests on unhandled errors) and later restore
// the original ones.
Expand Down

0 comments on commit c02488e

Please sign in to comment.