diff --git a/packages/jest-runner/src/__tests__/helpers.test.ts b/packages/jest-runner/src/__tests__/helpers.test.ts new file mode 100644 index 000000000000..6b2441a2e634 --- /dev/null +++ b/packages/jest-runner/src/__tests__/helpers.test.ts @@ -0,0 +1,34 @@ +/** + * 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. + * + */ + +import {replaceFunctionsWithStringReferences} from '../helpers'; + +it('serialize functions inside the nested object', () => { + const obj = { + foo: () => {}, + nested: { + fn: function bar() { + return 0; + }, + }, + nestedArray: [{baz: function baz() {}}, () => {}], + }; + + expect(replaceFunctionsWithStringReferences(obj)).toEqual({ + foo: '[Function foo]', + nested: { + fn: '[Function bar]', + }, + nestedArray: [ + { + baz: '[Function baz]', + }, + '[Function anonymous]', + ], + }); +}); diff --git a/packages/jest-runner/src/helpers.ts b/packages/jest-runner/src/helpers.ts new file mode 100644 index 000000000000..ca77e354a34c --- /dev/null +++ b/packages/jest-runner/src/helpers.ts @@ -0,0 +1,29 @@ +/** + * 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. + */ + +export const replaceFunctionsWithStringReferences = (value: T): T => { + if (typeof value === 'function') { + return `[Function ${value.name || 'anonymous'}]` as unknown as T; + } + + if (Array.isArray(value)) { + return value.map(replaceFunctionsWithStringReferences) as T; + } + + const isObject = value !== null && typeof value === 'object'; + if (isObject) { + const oldObject = value as Record; + const newObject: Record = {}; + for (const key of Object.keys(value)) { + newObject[key] = replaceFunctionsWithStringReferences(oldObject[key]); + } + + return newObject as T; + } + + return value; +}; diff --git a/packages/jest-runner/src/testWorker.ts b/packages/jest-runner/src/testWorker.ts index 4d1ee811f8e5..3377b939134a 100644 --- a/packages/jest-runner/src/testWorker.ts +++ b/packages/jest-runner/src/testWorker.ts @@ -18,6 +18,7 @@ import {separateMessageFromStack} from 'jest-message-util'; import type Resolver from 'jest-resolve'; import Runtime from 'jest-runtime'; import {messageParent} from 'jest-worker'; +import {replaceFunctionsWithStringReferences} from './helpers'; import runTest from './runTest'; import type {ErrorWithCode, TestRunnerSerializedContext} from './types'; @@ -92,7 +93,7 @@ export async function worker({ context, }: WorkerData): Promise { try { - return await runTest( + const testResult = await runTest( path, globalConfig, config, @@ -106,7 +107,28 @@ export async function worker({ }, sendMessageToJest, ); + return makeSerializableTestResults(testResult); } catch (error: any) { throw formatError(error); } } + +function makeSerializableTestResults(result: TestResult): TestResult { + const {testResults} = result; + const serializableResults = testResults.map(resultItem => { + if (resultItem.failureDetails) { + return { + ...resultItem, + // Functions cause DataCloneError when passed between workers, + // therefore they are converted to string references + failureDetails: replaceFunctionsWithStringReferences( + resultItem.failureDetails, + ), + }; + } + + return resultItem; + }); + + return {...result, testResults: serializableResults}; +}