Skip to content

Commit

Permalink
fix: jest-circus shares events among imports #11483
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Jun 5, 2021
1 parent f628b45 commit 45ef491
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@

### Fixes

- `[jest-circus]` Shares events with event handlers among imports ([#11483](https://github.com/facebook/jest/pull/11483))
- `[jest-reporter]` Allow `node-notifier@10` as peer dependency ([#11523](https://github.com/facebook/jest/pull/11523))
- `[jest-reporter]` Update `v8-to-istanbul` ([#11523](https://github.com/facebook/jest/pull/11523))

Expand Down
1 change: 1 addition & 0 deletions packages/jest-circus/src/__mocks__/testUtils.ts
Expand Up @@ -46,6 +46,7 @@ export const runTest = (source: string) => {
const testEventHandler = require('${TEST_EVENT_HANDLER_PATH}').default;
const addEventHandler = require('${CIRCUS_STATE_PATH}').addEventHandler;
const removeEventHandler = require('${CIRCUS_STATE_PATH}').removeEventHandler;
addEventHandler(testEventHandler);
${source};
Expand Down
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`addEventHandler registers a callback with events 1`] = `
start_describe_definition: describe
add_test: receives events
finish_describe_definition: describe
run_start
run_describe_start: ROOT_DESCRIBE_BLOCK
run_describe_start: describe
test_start: receives events
test_fn_start: receives events
called true
test_fn_failure: receives events
test_done: receives events
run_describe_finish: describe
run_describe_finish: ROOT_DESCRIBE_BLOCK
run_finish
unhandledErrors: 0
`;

exports[`removeEventHandler unregisters a callback from events 1`] = `
start_describe_definition: describe
add_test: does not receive events
finish_describe_definition: describe
run_start
run_describe_start: ROOT_DESCRIBE_BLOCK
run_describe_start: describe
test_start: does not receive events
test_fn_start: does not receive events
called false
test_fn_failure: does not receive events
test_done: does not receive events
run_describe_finish: describe
run_describe_finish: ROOT_DESCRIBE_BLOCK
run_finish
unhandledErrors: 0
`;
44 changes: 44 additions & 0 deletions packages/jest-circus/src/__tests__/eventHandler.test.ts
@@ -0,0 +1,44 @@
/**
* 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 wrap from 'jest-snapshot-serializer-raw';
import {runTest} from '../__mocks__/testUtils';

test('addEventHandler registers a callback with events', () => {
const {stdout} = runTest(`
let called = false;
const callback = () => called = true;
addEventHandler(callback);
describe('describe', () => {
test('receives events', () => {
console.log('called', called);
expect(called).toEqual(true);
})
});
`);

expect(wrap(stdout)).toMatchSnapshot();
});

test('removeEventHandler unregisters a callback from events', () => {
const {stdout} = runTest(`
let called = false;
const callback = () => called = true;
addEventHandler(callback);
removeEventHandler(callback);
describe('describe', () => {
test('does not receive events', () => {
console.log('called', called);
expect(called).toEqual(false);
})
});
`);

expect(wrap(stdout)).toMatchSnapshot();
});
8 changes: 7 additions & 1 deletion packages/jest-circus/src/index.ts
Expand Up @@ -10,7 +10,13 @@ import {bind as bindEach} from 'jest-each';
import {ErrorWithStack, isPromise} from 'jest-util';
import {dispatchSync} from './state';

export {setState, getState, resetState} from './state';
export {
setState,
getState,
resetState,
addEventHandler,
removeEventHandler,
} from './state';
export {default as run} from './run';

type THook = (fn: Circus.HookFn, timeout?: number) => void;
Expand Down
17 changes: 12 additions & 5 deletions packages/jest-circus/src/state.ts
Expand Up @@ -8,10 +8,10 @@
import type {Circus} from '@jest/types';
import eventHandler from './eventHandler';
import formatNodeAssertErrors from './formatNodeAssertErrors';
import {STATE_SYM} from './types';
import {EVENT_HANDLERS, STATE_SYM} from './types';
import {makeDescribe} from './utils';

const eventHandlers: Array<Circus.EventHandler> = [
global[EVENT_HANDLERS] = global[EVENT_HANDLERS] || [
eventHandler,
formatNodeAssertErrors,
];
Expand Down Expand Up @@ -46,17 +46,24 @@ export const setState = (state: Circus.State): Circus.State =>
(global[STATE_SYM] = state);

export const dispatch = async (event: Circus.AsyncEvent): Promise<void> => {
for (const handler of eventHandlers) {
for (const handler of global[EVENT_HANDLERS]) {
await handler(event, getState());
}
};

export const dispatchSync = (event: Circus.SyncEvent): void => {
for (const handler of eventHandlers) {
for (const handler of global[EVENT_HANDLERS]) {
handler(event, getState());
}
};

export const addEventHandler = (handler: Circus.EventHandler): void => {
eventHandlers.push(handler);
global[EVENT_HANDLERS].push(handler);
};

export const removeEventHandler = (handler: Circus.EventHandler): void => {
const index = global[EVENT_HANDLERS].lastIndexOf(handler);
if (index !== -1) {
global[EVENT_HANDLERS].splice(index, 1);
}
};
4 changes: 4 additions & 0 deletions packages/jest-circus/src/types.ts
Expand Up @@ -19,13 +19,17 @@ export const RETRY_TIMES = Symbol.for(
export const TEST_TIMEOUT_SYMBOL = Symbol.for(
'TEST_TIMEOUT_SYMBOL',
) as unknown as 'TEST_TIMEOUT_SYMBOL';
export const EVENT_HANDLERS = Symbol.for(
'EVENT_HANDLERS',
) as unknown as 'EVENT_HANDLERS';

declare global {
module NodeJS {
interface Global {
STATE_SYM_SYMBOL: Circus.State;
RETRY_TIMES_SYMBOL: string;
TEST_TIMEOUT_SYMBOL: number;
EVENT_HANDLERS: Array<Circus.EventHandler>;
expect: typeof expect;
}
}
Expand Down

0 comments on commit 45ef491

Please sign in to comment.