From eca504464cc9bd1767e1a16a997368477b523592 Mon Sep 17 00:00:00 2001 From: satanTime Date: Sun, 8 May 2022 13:56:14 +0200 Subject: [PATCH] fix: jest-circus shares events among imports #11483 --- .../jest-circus/src/__mocks__/testUtils.ts | 1 + .../src/__tests__/eventHandler.test.ts | 25 +++++++++++++++++++ packages/jest-circus/src/index.ts | 8 +++++- packages/jest-circus/src/state.ts | 17 +++++++++---- packages/jest-circus/src/types.ts | 2 ++ 5 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 packages/jest-circus/src/__tests__/eventHandler.test.ts diff --git a/packages/jest-circus/src/__mocks__/testUtils.ts b/packages/jest-circus/src/__mocks__/testUtils.ts index 300159fd3e71..5d2aeadbdc89 100644 --- a/packages/jest-circus/src/__mocks__/testUtils.ts +++ b/packages/jest-circus/src/__mocks__/testUtils.ts @@ -49,6 +49,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}; diff --git a/packages/jest-circus/src/__tests__/eventHandler.test.ts b/packages/jest-circus/src/__tests__/eventHandler.test.ts new file mode 100644 index 000000000000..7915e7182ee7 --- /dev/null +++ b/packages/jest-circus/src/__tests__/eventHandler.test.ts @@ -0,0 +1,25 @@ +/** + * 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. + */ + +// 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 = 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()); +}); diff --git a/packages/jest-circus/src/index.ts b/packages/jest-circus/src/index.ts index cb885c6d6a5e..534920833dc1 100644 --- a/packages/jest-circus/src/index.ts +++ b/packages/jest-circus/src/index.ts @@ -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; diff --git a/packages/jest-circus/src/state.ts b/packages/jest-circus/src/state.ts index e9f0321e979f..1fef77d42ab3 100644 --- a/packages/jest-circus/src/state.ts +++ b/packages/jest-circus/src/state.ts @@ -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 = [ +global[EVENT_HANDLERS] = global[EVENT_HANDLERS] || [ eventHandler, formatNodeAssertErrors, ]; @@ -49,17 +49,24 @@ export const setState = (state: Circus.State): Circus.State => /* eslint-enable */ export const dispatch = async (event: Circus.AsyncEvent): Promise => { - 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); + } }; diff --git a/packages/jest-circus/src/types.ts b/packages/jest-circus/src/types.ts index 17a4019d3251..e35febacd81d 100644 --- a/packages/jest-circus/src/types.ts +++ b/packages/jest-circus/src/types.ts @@ -11,6 +11,7 @@ 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'); declare global { @@ -20,6 +21,7 @@ declare global { [STATE_SYM]: Circus.State; [RETRY_TIMES]: string; [TEST_TIMEOUT_SYMBOL]: number; + [EVENT_HANDLERS]: Array; [LOG_ERRORS_BEFORE_RETRY]: boolean; } }