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 Nov 15, 2023
1 parent 0eb1033 commit d9cda50
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 10 deletions.
2 changes: 1 addition & 1 deletion packages/jest-circus/src/__mocks__/testUtils.ts
Expand Up @@ -36,7 +36,7 @@ export const runTest = (
global.afterAll = circus.afterAll;
const testEventHandler = require('${TEST_EVENT_HANDLER_PATH}').default;
const {addEventHandler, getState} = require('${CIRCUS_STATE_PATH}');
const {addEventHandler, removeEventHandler, getState} = require('${CIRCUS_STATE_PATH}');
getState().randomize = ${opts?.randomize};
getState().seed = ${opts?.seed ?? 0};
addEventHandler(testEventHandler);
Expand Down
25 changes: 25 additions & 0 deletions packages/jest-circus/src/__tests__/eventHandler.test.ts
@@ -0,0 +1,25 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// addEventHandler and removeEventHandler are provided in the ./index
import {addEventHandler, removeEventHandler} from '../index';
// dispatch comes from the ./state
import {dispatch} from '../state';

test('addEventHandler and removeEventHandler control handlers', async () => {
const spy: any = jest.fn();

addEventHandler(spy);
expect(spy).not.toHaveBeenCalledWith({name: 'unknown1'}, expect.anything());
await dispatch({name: 'unknown1' as any});
expect(spy).toHaveBeenCalledWith({name: 'unknown1'}, expect.anything());

removeEventHandler(spy);
expect(spy).not.toHaveBeenCalledWith({name: 'unknown2'}, expect.anything());
await dispatch({name: 'unknown2' as any});
expect(spy).not.toHaveBeenCalledWith({name: 'unknown2'}, expect.anything());
});
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, convertDescriptorToString, 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
26 changes: 18 additions & 8 deletions packages/jest-circus/src/state.ts
Expand Up @@ -8,13 +8,16 @@
import type {Circus, Global} 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> = [
eventHandler,
formatNodeAssertErrors,
];
/* eslint-disable no-restricted-globals */
const handlers: Array<Circus.EventHandler> = ((global as Global.Global)[
EVENT_HANDLERS
] = ((global as Global.Global)[
EVENT_HANDLERS
] as Array<Circus.EventHandler>) || [eventHandler, formatNodeAssertErrors]);
/* eslint-enable */

export const ROOT_DESCRIBE_BLOCK_NAME = 'ROOT_DESCRIBE_BLOCK';

Expand Down Expand Up @@ -52,17 +55,24 @@ export const setState = (state: Circus.State): Circus.State =>
/* eslint-enable */

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

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

export const addEventHandler = (handler: Circus.EventHandler): void => {
eventHandlers.push(handler);
handlers.push(handler);
};

export const removeEventHandler = (handler: Circus.EventHandler): void => {
const index = handlers.lastIndexOf(handler);
if (index !== -1) {
handlers.splice(index, 1);
}
};
1 change: 1 addition & 0 deletions packages/jest-circus/src/types.ts
Expand Up @@ -9,4 +9,5 @@ export const STATE_SYM = Symbol('JEST_STATE_SYMBOL');
export const RETRY_TIMES = Symbol.for('RETRY_TIMES');
// To pass this value from Runtime object to state we need to use global[sym]
export const TEST_TIMEOUT_SYMBOL = Symbol.for('TEST_TIMEOUT_SYMBOL');
export const EVENT_HANDLERS = Symbol.for('EVENT_HANDLERS');
export const LOG_ERRORS_BEFORE_RETRY = Symbol.for('LOG_ERRORS_BEFORE_RETRY');

0 comments on commit d9cda50

Please sign in to comment.