Change endpoint from persons to people

This commit is contained in:
xfarrow
2025-03-23 21:00:08 +01:00
parent 4ae263662c
commit d005193f63
7158 changed files with 700476 additions and 735 deletions

View File

@ -0,0 +1,281 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _jestUtil = require('jest-util');
var _globalErrorHandlers = require('./globalErrorHandlers');
var _types = require('./types');
var _utils = require('./utils');
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
var jestNow = globalThis[Symbol.for('jest-native-now')] || globalThis.Date.now;
/**
* 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.
*/
const eventHandler = (event, state) => {
switch (event.name) {
case 'include_test_location_in_result': {
state.includeTestLocationInResult = true;
break;
}
case 'hook_start': {
event.hook.seenDone = false;
break;
}
case 'start_describe_definition': {
const {blockName, mode} = event;
const {currentDescribeBlock, currentlyRunningTest} = state;
if (currentlyRunningTest) {
currentlyRunningTest.errors.push(
new Error(
`Cannot nest a describe inside a test. Describe block "${blockName}" cannot run because it is nested within "${currentlyRunningTest.name}".`
)
);
break;
}
const describeBlock = (0, _utils.makeDescribe)(
blockName,
currentDescribeBlock,
mode
);
currentDescribeBlock.children.push(describeBlock);
state.currentDescribeBlock = describeBlock;
break;
}
case 'finish_describe_definition': {
const {currentDescribeBlock} = state;
(0, _jestUtil.invariant)(
currentDescribeBlock,
'currentDescribeBlock must be there'
);
if (!(0, _utils.describeBlockHasTests)(currentDescribeBlock)) {
currentDescribeBlock.hooks.forEach(hook => {
hook.asyncError.message = `Invalid: ${hook.type}() may not be used in a describe block containing no tests.`;
state.unhandledErrors.push(hook.asyncError);
});
}
// pass mode of currentDescribeBlock to tests
// but do not when there is already a single test with "only" mode
const shouldPassMode = !(
currentDescribeBlock.mode === 'only' &&
currentDescribeBlock.children.some(
child => child.type === 'test' && child.mode === 'only'
)
);
if (shouldPassMode) {
currentDescribeBlock.children.forEach(child => {
if (child.type === 'test' && !child.mode) {
child.mode = currentDescribeBlock.mode;
}
});
}
if (
!state.hasFocusedTests &&
currentDescribeBlock.mode !== 'skip' &&
currentDescribeBlock.children.some(
child => child.type === 'test' && child.mode === 'only'
)
) {
state.hasFocusedTests = true;
}
if (currentDescribeBlock.parent) {
state.currentDescribeBlock = currentDescribeBlock.parent;
}
break;
}
case 'add_hook': {
const {currentDescribeBlock, currentlyRunningTest, hasStarted} = state;
const {asyncError, fn, hookType: type, timeout} = event;
if (currentlyRunningTest) {
currentlyRunningTest.errors.push(
new Error(
`Hooks cannot be defined inside tests. Hook of type "${type}" is nested within "${currentlyRunningTest.name}".`
)
);
break;
} else if (hasStarted) {
state.unhandledErrors.push(
new Error(
'Cannot add a hook after tests have started running. Hooks must be defined synchronously.'
)
);
break;
}
const parent = currentDescribeBlock;
currentDescribeBlock.hooks.push({
asyncError,
fn,
parent,
seenDone: false,
timeout,
type
});
break;
}
case 'add_test': {
const {currentDescribeBlock, currentlyRunningTest, hasStarted} = state;
const {
asyncError,
fn,
mode,
testName: name,
timeout,
concurrent,
failing
} = event;
if (currentlyRunningTest) {
currentlyRunningTest.errors.push(
new Error(
`Tests cannot be nested. Test "${name}" cannot run because it is nested within "${currentlyRunningTest.name}".`
)
);
break;
} else if (hasStarted) {
state.unhandledErrors.push(
new Error(
'Cannot add a test after tests have started running. Tests must be defined synchronously.'
)
);
break;
}
const test = (0, _utils.makeTest)(
fn,
mode,
concurrent,
name,
currentDescribeBlock,
timeout,
asyncError,
failing
);
if (currentDescribeBlock.mode !== 'skip' && test.mode === 'only') {
state.hasFocusedTests = true;
}
currentDescribeBlock.children.push(test);
currentDescribeBlock.tests.push(test);
break;
}
case 'hook_failure': {
const {test, describeBlock, error, hook} = event;
const {asyncError, type} = hook;
if (type === 'beforeAll') {
(0, _jestUtil.invariant)(
describeBlock,
'always present for `*All` hooks'
);
(0, _utils.addErrorToEachTestUnderDescribe)(
describeBlock,
error,
asyncError
);
} else if (type === 'afterAll') {
// Attaching `afterAll` errors to each test makes execution flow
// too complicated, so we'll consider them to be global.
state.unhandledErrors.push([error, asyncError]);
} else {
(0, _jestUtil.invariant)(test, 'always present for `*Each` hooks');
test.errors.push([error, asyncError]);
}
break;
}
case 'test_skip': {
event.test.status = 'skip';
break;
}
case 'test_todo': {
event.test.status = 'todo';
break;
}
case 'test_done': {
event.test.duration = (0, _utils.getTestDuration)(event.test);
event.test.status = 'done';
state.currentlyRunningTest = null;
break;
}
case 'test_start': {
state.currentlyRunningTest = event.test;
event.test.startedAt = jestNow();
event.test.invocations += 1;
break;
}
case 'test_fn_start': {
event.test.seenDone = false;
break;
}
case 'test_fn_failure': {
const {
error,
test: {asyncError}
} = event;
event.test.errors.push([error, asyncError]);
break;
}
case 'test_retry': {
const logErrorsBeforeRetry =
// eslint-disable-next-line no-restricted-globals
global[_types.LOG_ERRORS_BEFORE_RETRY] || false;
if (logErrorsBeforeRetry) {
event.test.retryReasons.push(...event.test.errors);
}
event.test.errors = [];
break;
}
case 'run_start': {
state.hasStarted = true;
/* eslint-disable no-restricted-globals */
global[_types.TEST_TIMEOUT_SYMBOL] &&
(state.testTimeout = global[_types.TEST_TIMEOUT_SYMBOL]);
/* eslint-enable */
break;
}
case 'run_finish': {
break;
}
case 'setup': {
// Uncaught exception handlers should be defined on the parent process
// object. If defined on the VM's process object they just no op and let
// the parent process crash. It might make sense to return a `dispatch`
// function to the parent process and register handlers there instead, but
// i'm not sure if this is works. For now i just replicated whatever
// jasmine was doing -- dabramov
state.parentProcess = event.parentProcess;
(0, _jestUtil.invariant)(state.parentProcess);
state.originalGlobalErrorHandlers = (0,
_globalErrorHandlers.injectGlobalErrorHandlers)(state.parentProcess);
if (event.testNamePattern) {
state.testNamePattern = new RegExp(event.testNamePattern, 'i');
}
break;
}
case 'teardown': {
(0, _jestUtil.invariant)(state.originalGlobalErrorHandlers);
(0, _jestUtil.invariant)(state.parentProcess);
(0, _globalErrorHandlers.restoreGlobalErrorHandlers)(
state.parentProcess,
state.originalGlobalErrorHandlers
);
break;
}
case 'error': {
// It's very likely for long-running async tests to throw errors. In this
// case we want to catch them and fail the current test. At the same time
// there's a possibility that one test sets a long timeout, that will
// eventually throw after this test finishes but during some other test
// execution, which will result in one test's error failing another test.
// In any way, it should be possible to track where the error was thrown
// from.
state.currentlyRunningTest
? state.currentlyRunningTest.errors.push(event.error)
: state.unhandledErrors.push(event.error);
break;
}
}
};
var _default = eventHandler;
exports.default = _default;

View File

@ -0,0 +1,186 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _assert = require('assert');
var _chalk = _interopRequireDefault(require('chalk'));
var _jestMatcherUtils = require('jest-matcher-utils');
var _prettyFormat = require('pretty-format');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* 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.
*/
const assertOperatorsMap = {
'!=': 'notEqual',
'!==': 'notStrictEqual',
'==': 'equal',
'===': 'strictEqual'
};
const humanReadableOperators = {
deepEqual: 'to deeply equal',
deepStrictEqual: 'to deeply and strictly equal',
equal: 'to be equal',
notDeepEqual: 'not to deeply equal',
notDeepStrictEqual: 'not to deeply and strictly equal',
notEqual: 'to not be equal',
notStrictEqual: 'not be strictly equal',
strictEqual: 'to strictly be equal'
};
const formatNodeAssertErrors = (event, state) => {
if (event.name === 'test_done') {
event.test.errors = event.test.errors.map(errors => {
let error;
if (Array.isArray(errors)) {
const [originalError, asyncError] = errors;
if (originalError == null) {
error = asyncError;
} else if (!originalError.stack) {
error = asyncError;
error.message = originalError.message
? originalError.message
: `thrown: ${(0, _prettyFormat.format)(originalError, {
maxDepth: 3
})}`;
} else {
error = originalError;
}
} else {
error = errors;
}
return isAssertionError(error)
? {
message: assertionErrorMessage(error, {
expand: state.expand
})
}
: errors;
});
}
};
const getOperatorName = (operator, stack) => {
if (typeof operator === 'string') {
return assertOperatorsMap[operator] || operator;
}
if (stack.match('.doesNotThrow')) {
return 'doesNotThrow';
}
if (stack.match('.throws')) {
return 'throws';
}
return '';
};
const operatorMessage = operator => {
const niceOperatorName = getOperatorName(operator, '');
const humanReadableOperator = humanReadableOperators[niceOperatorName];
return typeof operator === 'string'
? `${humanReadableOperator || niceOperatorName} to:\n`
: '';
};
const assertThrowingMatcherHint = operatorName =>
operatorName
? _chalk.default.dim('assert') +
_chalk.default.dim(`.${operatorName}(`) +
_chalk.default.red('function') +
_chalk.default.dim(')')
: '';
const assertMatcherHint = (operator, operatorName, expected) => {
let message = '';
if (operator === '==' && expected === true) {
message =
_chalk.default.dim('assert') +
_chalk.default.dim('(') +
_chalk.default.red('received') +
_chalk.default.dim(')');
} else if (operatorName) {
message =
_chalk.default.dim('assert') +
_chalk.default.dim(`.${operatorName}(`) +
_chalk.default.red('received') +
_chalk.default.dim(', ') +
_chalk.default.green('expected') +
_chalk.default.dim(')');
}
return message;
};
function assertionErrorMessage(error, options) {
const {expected, actual, generatedMessage, message, operator, stack} = error;
const diffString = (0, _jestMatcherUtils.diff)(expected, actual, options);
const hasCustomMessage = !generatedMessage;
const operatorName = getOperatorName(operator, stack);
const trimmedStack = stack
.replace(message, '')
.replace(/AssertionError(.*)/g, '');
if (operatorName === 'doesNotThrow') {
return (
// eslint-disable-next-line prefer-template
buildHintString(assertThrowingMatcherHint(operatorName)) +
_chalk.default.reset('Expected the function not to throw an error.\n') +
_chalk.default.reset('Instead, it threw:\n') +
` ${(0, _jestMatcherUtils.printReceived)(actual)}` +
_chalk.default.reset(
hasCustomMessage ? `\n\nMessage:\n ${message}` : ''
) +
trimmedStack
);
}
if (operatorName === 'throws') {
if (error.generatedMessage) {
return (
buildHintString(assertThrowingMatcherHint(operatorName)) +
_chalk.default.reset(error.message) +
_chalk.default.reset(
hasCustomMessage ? `\n\nMessage:\n ${message}` : ''
) +
trimmedStack
);
}
return (
buildHintString(assertThrowingMatcherHint(operatorName)) +
_chalk.default.reset('Expected the function to throw an error.\n') +
_chalk.default.reset("But it didn't throw anything.") +
_chalk.default.reset(
hasCustomMessage ? `\n\nMessage:\n ${message}` : ''
) +
trimmedStack
);
}
if (operatorName === 'fail') {
return (
buildHintString(assertMatcherHint(operator, operatorName, expected)) +
_chalk.default.reset(hasCustomMessage ? `Message:\n ${message}` : '') +
trimmedStack
);
}
return (
// eslint-disable-next-line prefer-template
buildHintString(assertMatcherHint(operator, operatorName, expected)) +
_chalk.default.reset(`Expected value ${operatorMessage(operator)}`) +
` ${(0, _jestMatcherUtils.printExpected)(expected)}\n` +
_chalk.default.reset('Received:\n') +
` ${(0, _jestMatcherUtils.printReceived)(actual)}` +
_chalk.default.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') +
(diffString ? `\n\nDifference:\n\n${diffString}` : '') +
trimmedStack
);
}
function isAssertionError(error) {
return (
error &&
(error instanceof _assert.AssertionError ||
error.name === _assert.AssertionError.name ||
error.code === 'ERR_ASSERTION')
);
}
function buildHintString(hint) {
return hint ? `${hint}\n\n` : '';
}
var _default = formatNodeAssertErrors;
exports.default = _default;

View File

@ -0,0 +1,44 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.restoreGlobalErrorHandlers = exports.injectGlobalErrorHandlers = void 0;
var _state = require('./state');
/**
* 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.
*/
const uncaught = error => {
(0, _state.dispatchSync)({
error,
name: 'error'
});
};
const injectGlobalErrorHandlers = parentProcess => {
const uncaughtException = process.listeners('uncaughtException').slice();
const unhandledRejection = process.listeners('unhandledRejection').slice();
parentProcess.removeAllListeners('uncaughtException');
parentProcess.removeAllListeners('unhandledRejection');
parentProcess.on('uncaughtException', uncaught);
parentProcess.on('unhandledRejection', uncaught);
return {
uncaughtException,
unhandledRejection
};
};
exports.injectGlobalErrorHandlers = injectGlobalErrorHandlers;
const restoreGlobalErrorHandlers = (parentProcess, originalErrorHandlers) => {
parentProcess.removeListener('uncaughtException', uncaught);
parentProcess.removeListener('unhandledRejection', uncaught);
for (const listener of originalErrorHandlers.uncaughtException) {
parentProcess.on('uncaughtException', listener);
}
for (const listener of originalErrorHandlers.unhandledRejection) {
parentProcess.on('unhandledRejection', listener);
}
};
exports.restoreGlobalErrorHandlers = restoreGlobalErrorHandlers;

View File

@ -0,0 +1,72 @@
/**
* 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 type {Circus} from '@jest/types';
import type {Global} from '@jest/types';
export declare const afterAll: THook;
export declare const afterEach: THook;
export declare const beforeAll: THook;
export declare const beforeEach: THook;
declare const _default: {
afterAll: THook;
afterEach: THook;
beforeAll: THook;
beforeEach: THook;
describe: {
(blockName: Global.BlockNameLike, blockFn: Global.BlockFn): void;
each: Global.EachTestFn<any>;
only: {
(blockName: Global.BlockNameLike, blockFn: Global.BlockFn): void;
each: Global.EachTestFn<any>;
};
skip: {
(blockName: Global.BlockNameLike, blockFn: Global.BlockFn): void;
each: Global.EachTestFn<any>;
};
};
it: Global.It;
test: Global.It;
};
export default _default;
export declare const describe: {
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
each: Global.EachTestFn<any>;
only: {
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
each: Global.EachTestFn<any>;
};
skip: {
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
each: Global.EachTestFn<any>;
};
};
declare type Event_2 = Circus.Event;
export {Event_2 as Event};
export declare const getState: () => Circus.State;
export declare const it: Global.It;
export declare const resetState: () => void;
export declare const run: () => Promise<Circus.RunResult>;
export declare const setState: (state: Circus.State) => Circus.State;
export declare type State = Circus.State;
export declare const test: Global.It;
declare type THook = (fn: Circus.HookFn, timeout?: number) => void;
export {};

View File

@ -0,0 +1,238 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.describe =
exports.default =
exports.beforeEach =
exports.beforeAll =
exports.afterEach =
exports.afterAll =
void 0;
Object.defineProperty(exports, 'getState', {
enumerable: true,
get: function () {
return _state.getState;
}
});
exports.it = void 0;
Object.defineProperty(exports, 'resetState', {
enumerable: true,
get: function () {
return _state.resetState;
}
});
Object.defineProperty(exports, 'run', {
enumerable: true,
get: function () {
return _run.default;
}
});
Object.defineProperty(exports, 'setState', {
enumerable: true,
get: function () {
return _state.setState;
}
});
exports.test = void 0;
var _jestEach = require('jest-each');
var _jestUtil = require('jest-util');
var _state = require('./state');
var _run = _interopRequireDefault(require('./run'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* 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.
*/
const describe = (() => {
const describe = (blockName, blockFn) =>
_dispatchDescribe(blockFn, blockName, describe);
const only = (blockName, blockFn) =>
_dispatchDescribe(blockFn, blockName, only, 'only');
const skip = (blockName, blockFn) =>
_dispatchDescribe(blockFn, blockName, skip, 'skip');
describe.each = (0, _jestEach.bind)(describe, false);
only.each = (0, _jestEach.bind)(only, false);
skip.each = (0, _jestEach.bind)(skip, false);
describe.only = only;
describe.skip = skip;
return describe;
})();
exports.describe = describe;
const _dispatchDescribe = (blockFn, blockName, describeFn, mode) => {
const asyncError = new _jestUtil.ErrorWithStack(undefined, describeFn);
if (blockFn === undefined) {
asyncError.message =
'Missing second argument. It must be a callback function.';
throw asyncError;
}
if (typeof blockFn !== 'function') {
asyncError.message = `Invalid second argument, ${blockFn}. It must be a callback function.`;
throw asyncError;
}
try {
blockName = (0, _jestUtil.convertDescriptorToString)(blockName);
} catch (error) {
asyncError.message = error.message;
throw asyncError;
}
(0, _state.dispatchSync)({
asyncError,
blockName,
mode,
name: 'start_describe_definition'
});
const describeReturn = blockFn();
if ((0, _jestUtil.isPromise)(describeReturn)) {
throw new _jestUtil.ErrorWithStack(
'Returning a Promise from "describe" is not supported. Tests must be defined synchronously.',
describeFn
);
} else if (describeReturn !== undefined) {
throw new _jestUtil.ErrorWithStack(
'A "describe" callback must not return a value.',
describeFn
);
}
(0, _state.dispatchSync)({
blockName,
mode,
name: 'finish_describe_definition'
});
};
const _addHook = (fn, hookType, hookFn, timeout) => {
const asyncError = new _jestUtil.ErrorWithStack(undefined, hookFn);
if (typeof fn !== 'function') {
asyncError.message =
'Invalid first argument. It must be a callback function.';
throw asyncError;
}
(0, _state.dispatchSync)({
asyncError,
fn,
hookType,
name: 'add_hook',
timeout
});
};
// Hooks have to pass themselves to the HOF in order for us to trim stack traces.
const beforeEach = (fn, timeout) =>
_addHook(fn, 'beforeEach', beforeEach, timeout);
exports.beforeEach = beforeEach;
const beforeAll = (fn, timeout) =>
_addHook(fn, 'beforeAll', beforeAll, timeout);
exports.beforeAll = beforeAll;
const afterEach = (fn, timeout) =>
_addHook(fn, 'afterEach', afterEach, timeout);
exports.afterEach = afterEach;
const afterAll = (fn, timeout) => _addHook(fn, 'afterAll', afterAll, timeout);
exports.afterAll = afterAll;
const test = (() => {
const test = (testName, fn, timeout) =>
_addTest(testName, undefined, false, fn, test, timeout);
const skip = (testName, fn, timeout) =>
_addTest(testName, 'skip', false, fn, skip, timeout);
const only = (testName, fn, timeout) =>
_addTest(testName, 'only', false, fn, test.only, timeout);
const concurrentTest = (testName, fn, timeout) =>
_addTest(testName, undefined, true, fn, concurrentTest, timeout);
const concurrentOnly = (testName, fn, timeout) =>
_addTest(testName, 'only', true, fn, concurrentOnly, timeout);
const bindFailing = (concurrent, mode) => {
const failing = (testName, fn, timeout, eachError) =>
_addTest(
testName,
mode,
concurrent,
fn,
failing,
timeout,
true,
eachError
);
failing.each = (0, _jestEach.bind)(failing, false, true);
return failing;
};
test.todo = (testName, ...rest) => {
if (rest.length > 0 || typeof testName !== 'string') {
throw new _jestUtil.ErrorWithStack(
'Todo must be called with only a description.',
test.todo
);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
return _addTest(testName, 'todo', false, () => {}, test.todo);
};
const _addTest = (
testName,
mode,
concurrent,
fn,
testFn,
timeout,
failing,
asyncError = new _jestUtil.ErrorWithStack(undefined, testFn)
) => {
try {
testName = (0, _jestUtil.convertDescriptorToString)(testName);
} catch (error) {
asyncError.message = error.message;
throw asyncError;
}
if (fn === undefined) {
asyncError.message =
'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.';
throw asyncError;
}
if (typeof fn !== 'function') {
asyncError.message = `Invalid second argument, ${fn}. It must be a callback function.`;
throw asyncError;
}
return (0, _state.dispatchSync)({
asyncError,
concurrent,
failing: failing === undefined ? false : failing,
fn,
mode,
name: 'add_test',
testName,
timeout
});
};
test.each = (0, _jestEach.bind)(test);
only.each = (0, _jestEach.bind)(only);
skip.each = (0, _jestEach.bind)(skip);
concurrentTest.each = (0, _jestEach.bind)(concurrentTest, false);
concurrentOnly.each = (0, _jestEach.bind)(concurrentOnly, false);
only.failing = bindFailing(false, 'only');
skip.failing = bindFailing(false, 'skip');
test.failing = bindFailing(false);
test.only = only;
test.skip = skip;
test.concurrent = concurrentTest;
concurrentTest.only = concurrentOnly;
concurrentTest.skip = skip;
concurrentTest.failing = bindFailing(true);
concurrentOnly.failing = bindFailing(true, 'only');
return test;
})();
exports.test = test;
const it = test;
exports.it = it;
var _default = {
afterAll,
afterEach,
beforeAll,
beforeEach,
describe,
it,
test
};
exports.default = _default;

View File

@ -0,0 +1,117 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _jestUtil = require('jest-util');
/**
* 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.
*/
const FRAMEWORK_INITIALIZER = require.resolve('./jestAdapterInit');
const jestAdapter = async (
globalConfig,
config,
environment,
runtime,
testPath,
sendMessageToJest
) => {
const {initialize, runAndTransformResultsToJestFormat} =
runtime.requireInternalModule(FRAMEWORK_INITIALIZER);
const {globals, snapshotState} = await initialize({
config,
environment,
globalConfig,
localRequire: runtime.requireModule.bind(runtime),
parentProcess: process,
sendMessageToJest,
setGlobalsForRuntime: runtime.setGlobalsForRuntime.bind(runtime),
testPath
});
if (config.fakeTimers.enableGlobally) {
if (config.fakeTimers.legacyFakeTimers) {
// during setup, this cannot be null (and it's fine to explode if it is)
environment.fakeTimers.useFakeTimers();
} else {
environment.fakeTimersModern.useFakeTimers();
}
}
globals.beforeEach(() => {
if (config.resetModules) {
runtime.resetModules();
}
if (config.clearMocks) {
runtime.clearAllMocks();
}
if (config.resetMocks) {
runtime.resetAllMocks();
if (
config.fakeTimers.enableGlobally &&
config.fakeTimers.legacyFakeTimers
) {
// during setup, this cannot be null (and it's fine to explode if it is)
environment.fakeTimers.useFakeTimers();
}
}
if (config.restoreMocks) {
runtime.restoreAllMocks();
}
});
for (const path of config.setupFilesAfterEnv) {
const esm = runtime.unstable_shouldLoadAsEsm(path);
if (esm) {
await runtime.unstable_importModule(path);
} else {
runtime.requireModule(path);
}
}
const esm = runtime.unstable_shouldLoadAsEsm(testPath);
if (esm) {
await runtime.unstable_importModule(testPath);
} else {
runtime.requireModule(testPath);
}
const results = await runAndTransformResultsToJestFormat({
config,
globalConfig,
testPath
});
_addSnapshotData(results, snapshotState);
// We need to copy the results object to ensure we don't leaks the prototypes
// from the VM. Jasmine creates the result objects in the parent process, we
// should consider doing that for circus as well.
return (0, _jestUtil.deepCyclicCopy)(results, {
keepPrototype: false
});
};
const _addSnapshotData = (results, snapshotState) => {
results.testResults.forEach(({fullName, status}) => {
if (status === 'pending' || status === 'failed') {
// if test is skipped or failed, we don't want to mark
// its snapshots as obsolete.
snapshotState.markSnapshotsAsCheckedForTest(fullName);
}
});
const uncheckedCount = snapshotState.getUncheckedCount();
const uncheckedKeys = snapshotState.getUncheckedKeys();
if (uncheckedCount) {
snapshotState.removeUncheckedKeys();
}
const status = snapshotState.save();
results.snapshot.fileDeleted = status.deleted;
results.snapshot.added = snapshotState.added;
results.snapshot.matched = snapshotState.matched;
results.snapshot.unmatched = snapshotState.unmatched;
results.snapshot.updated = snapshotState.updated;
results.snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
// Copy the array to prevent memory leaks
results.snapshot.uncheckedKeys = Array.from(uncheckedKeys);
};
var _default = jestAdapter;
exports.default = _default;

View File

@ -0,0 +1,240 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.runAndTransformResultsToJestFormat = exports.initialize = void 0;
var _expect = require('@jest/expect');
var _testResult = require('@jest/test-result');
var _jestMessageUtil = require('jest-message-util');
var _jestSnapshot = require('jest-snapshot');
var _ = _interopRequireDefault(require('..'));
var _run = _interopRequireDefault(require('../run'));
var _state = require('../state');
var _testCaseReportHandler = _interopRequireDefault(
require('../testCaseReportHandler')
);
var _utils = require('../utils');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* 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.
*/
const initialize = async ({
config,
environment,
globalConfig,
localRequire,
parentProcess,
sendMessageToJest,
setGlobalsForRuntime,
testPath
}) => {
if (globalConfig.testTimeout) {
(0, _state.getState)().testTimeout = globalConfig.testTimeout;
}
(0, _state.getState)().maxConcurrency = globalConfig.maxConcurrency;
(0, _state.getState)().randomize = globalConfig.randomize;
(0, _state.getState)().seed = globalConfig.seed;
// @ts-expect-error: missing `concurrent` which is added later
const globalsObject = {
..._.default,
fdescribe: _.default.describe.only,
fit: _.default.it.only,
xdescribe: _.default.describe.skip,
xit: _.default.it.skip,
xtest: _.default.it.skip
};
(0, _state.addEventHandler)(eventHandler);
if (environment.handleTestEvent) {
(0, _state.addEventHandler)(environment.handleTestEvent.bind(environment));
}
_expect.jestExpect.setState({
expand: globalConfig.expand
});
const runtimeGlobals = {
...globalsObject,
expect: _expect.jestExpect
};
setGlobalsForRuntime(runtimeGlobals);
if (config.injectGlobals) {
Object.assign(environment.global, runtimeGlobals);
}
await (0, _state.dispatch)({
name: 'setup',
parentProcess,
runtimeGlobals,
testNamePattern: globalConfig.testNamePattern
});
if (config.testLocationInResults) {
await (0, _state.dispatch)({
name: 'include_test_location_in_result'
});
}
// Jest tests snapshotSerializers in order preceding built-in serializers.
// Therefore, add in reverse because the last added is the first tested.
config.snapshotSerializers
.concat()
.reverse()
.forEach(path => (0, _jestSnapshot.addSerializer)(localRequire(path)));
const snapshotResolver = await (0, _jestSnapshot.buildSnapshotResolver)(
config,
localRequire
);
const snapshotPath = snapshotResolver.resolveSnapshotPath(testPath);
const snapshotState = new _jestSnapshot.SnapshotState(snapshotPath, {
expand: globalConfig.expand,
prettierPath: config.prettierPath,
rootDir: config.rootDir,
snapshotFormat: config.snapshotFormat,
updateSnapshot: globalConfig.updateSnapshot
});
_expect.jestExpect.setState({
snapshotState,
testPath
});
(0, _state.addEventHandler)(handleSnapshotStateAfterRetry(snapshotState));
if (sendMessageToJest) {
(0, _state.addEventHandler)(
(0, _testCaseReportHandler.default)(testPath, sendMessageToJest)
);
}
// Return it back to the outer scope (test runner outside the VM).
return {
globals: globalsObject,
snapshotState
};
};
exports.initialize = initialize;
const runAndTransformResultsToJestFormat = async ({
config,
globalConfig,
testPath
}) => {
const runResult = await (0, _run.default)();
let numFailingTests = 0;
let numPassingTests = 0;
let numPendingTests = 0;
let numTodoTests = 0;
const assertionResults = runResult.testResults.map(testResult => {
let status;
if (testResult.status === 'skip') {
status = 'pending';
numPendingTests += 1;
} else if (testResult.status === 'todo') {
status = 'todo';
numTodoTests += 1;
} else if (testResult.errors.length) {
status = 'failed';
numFailingTests += 1;
} else {
status = 'passed';
numPassingTests += 1;
}
const ancestorTitles = testResult.testPath.filter(
name => name !== _state.ROOT_DESCRIBE_BLOCK_NAME
);
const title = ancestorTitles.pop();
return {
ancestorTitles,
duration: testResult.duration,
failureDetails: testResult.errorsDetailed,
failureMessages: testResult.errors,
fullName: title
? ancestorTitles.concat(title).join(' ')
: ancestorTitles.join(' '),
invocations: testResult.invocations,
location: testResult.location,
numPassingAsserts: testResult.numPassingAsserts,
retryReasons: testResult.retryReasons,
status,
title: testResult.testPath[testResult.testPath.length - 1]
};
});
let failureMessage = (0, _jestMessageUtil.formatResultsErrors)(
assertionResults,
config,
globalConfig,
testPath
);
let testExecError;
if (runResult.unhandledErrors.length) {
testExecError = {
message: '',
stack: runResult.unhandledErrors.join('\n')
};
failureMessage = `${failureMessage || ''}\n\n${runResult.unhandledErrors
.map(err =>
(0, _jestMessageUtil.formatExecError)(err, config, globalConfig)
)
.join('\n')}`;
}
await (0, _state.dispatch)({
name: 'teardown'
});
return {
...(0, _testResult.createEmptyTestResult)(),
console: undefined,
displayName: config.displayName,
failureMessage,
numFailingTests,
numPassingTests,
numPendingTests,
numTodoTests,
testExecError,
testFilePath: testPath,
testResults: assertionResults
};
};
exports.runAndTransformResultsToJestFormat = runAndTransformResultsToJestFormat;
const handleSnapshotStateAfterRetry = snapshotState => event => {
switch (event.name) {
case 'test_retry': {
// Clear any snapshot data that occurred in previous test run
snapshotState.clear();
}
}
};
const eventHandler = async event => {
switch (event.name) {
case 'test_start': {
_expect.jestExpect.setState({
currentTestName: (0, _utils.getTestID)(event.test)
});
break;
}
case 'test_done': {
event.test.numPassingAsserts =
_expect.jestExpect.getState().numPassingAsserts;
_addSuppressedErrors(event.test);
_addExpectedAssertionErrors(event.test);
break;
}
}
};
const _addExpectedAssertionErrors = test => {
const failures = _expect.jestExpect.extractExpectedAssertionsErrors();
const errors = failures.map(failure => failure.error);
test.errors = test.errors.concat(errors);
};
// Get suppressed errors from ``jest-matchers`` that weren't throw during
// test execution and add them to the test result, potentially failing
// a passing test.
const _addSuppressedErrors = test => {
const {suppressedErrors} = _expect.jestExpect.getState();
_expect.jestExpect.setState({
suppressedErrors: []
});
if (suppressedErrors.length) {
test.errors = test.errors.concat(suppressedErrors);
}
};

View File

@ -0,0 +1,350 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _async_hooks = require('async_hooks');
var _pLimit = _interopRequireDefault(require('p-limit'));
var _expect = require('@jest/expect');
var _jestUtil = require('jest-util');
var _shuffleArray = _interopRequireWildcard(require('./shuffleArray'));
var _state = require('./state');
var _types = require('./types');
var _utils = require('./utils');
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* 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.
*/
const run = async () => {
const {rootDescribeBlock, seed, randomize} = (0, _state.getState)();
const rng = randomize ? (0, _shuffleArray.rngBuilder)(seed) : undefined;
await (0, _state.dispatch)({
name: 'run_start'
});
await _runTestsForDescribeBlock(rootDescribeBlock, rng, true);
await (0, _state.dispatch)({
name: 'run_finish'
});
return (0, _utils.makeRunResult)(
(0, _state.getState)().rootDescribeBlock,
(0, _state.getState)().unhandledErrors
);
};
const _runTestsForDescribeBlock = async (
describeBlock,
rng,
isRootBlock = false
) => {
await (0, _state.dispatch)({
describeBlock,
name: 'run_describe_start'
});
const {beforeAll, afterAll} = (0, _utils.getAllHooksForDescribe)(
describeBlock
);
const isSkipped = describeBlock.mode === 'skip';
if (!isSkipped) {
for (const hook of beforeAll) {
await _callCircusHook({
describeBlock,
hook
});
}
}
if (isRootBlock) {
const concurrentTests = collectConcurrentTests(describeBlock);
if (concurrentTests.length > 0) {
startTestsConcurrently(concurrentTests);
}
}
// Tests that fail and are retried we run after other tests
// eslint-disable-next-line no-restricted-globals
const retryTimes = parseInt(global[_types.RETRY_TIMES], 10) || 0;
const deferredRetryTests = [];
if (rng) {
describeBlock.children = (0, _shuffleArray.default)(
describeBlock.children,
rng
);
}
for (const child of describeBlock.children) {
switch (child.type) {
case 'describeBlock': {
await _runTestsForDescribeBlock(child, rng);
break;
}
case 'test': {
const hasErrorsBeforeTestRun = child.errors.length > 0;
await _runTest(child, isSkipped);
if (
hasErrorsBeforeTestRun === false &&
retryTimes > 0 &&
child.errors.length > 0
) {
deferredRetryTests.push(child);
}
break;
}
}
}
// Re-run failed tests n-times if configured
for (const test of deferredRetryTests) {
let numRetriesAvailable = retryTimes;
while (numRetriesAvailable > 0 && test.errors.length > 0) {
// Clear errors so retries occur
await (0, _state.dispatch)({
name: 'test_retry',
test
});
await _runTest(test, isSkipped);
numRetriesAvailable--;
}
}
if (!isSkipped) {
for (const hook of afterAll) {
await _callCircusHook({
describeBlock,
hook
});
}
}
await (0, _state.dispatch)({
describeBlock,
name: 'run_describe_finish'
});
};
function collectConcurrentTests(describeBlock) {
if (describeBlock.mode === 'skip') {
return [];
}
const {hasFocusedTests, testNamePattern} = (0, _state.getState)();
return describeBlock.children.flatMap(child => {
switch (child.type) {
case 'describeBlock':
return collectConcurrentTests(child);
case 'test':
const skip =
!child.concurrent ||
child.mode === 'skip' ||
(hasFocusedTests && child.mode !== 'only') ||
(testNamePattern &&
!testNamePattern.test((0, _utils.getTestID)(child)));
return skip ? [] : [child];
}
});
}
function startTestsConcurrently(concurrentTests) {
const mutex = (0, _pLimit.default)((0, _state.getState)().maxConcurrency);
const testNameStorage = new _async_hooks.AsyncLocalStorage();
_expect.jestExpect.setState({
currentConcurrentTestName: () => testNameStorage.getStore()
});
for (const test of concurrentTests) {
try {
const testFn = test.fn;
const promise = mutex(() =>
testNameStorage.run((0, _utils.getTestID)(test), testFn)
);
// Avoid triggering the uncaught promise rejection handler in case the
// test fails before being awaited on.
// eslint-disable-next-line @typescript-eslint/no-empty-function
promise.catch(() => {});
test.fn = () => promise;
} catch (err) {
test.fn = () => {
throw err;
};
}
}
}
const _runTest = async (test, parentSkipped) => {
await (0, _state.dispatch)({
name: 'test_start',
test
});
const testContext = Object.create(null);
const {hasFocusedTests, testNamePattern} = (0, _state.getState)();
const isSkipped =
parentSkipped ||
test.mode === 'skip' ||
(hasFocusedTests && test.mode === undefined) ||
(testNamePattern && !testNamePattern.test((0, _utils.getTestID)(test)));
if (isSkipped) {
await (0, _state.dispatch)({
name: 'test_skip',
test
});
return;
}
if (test.mode === 'todo') {
await (0, _state.dispatch)({
name: 'test_todo',
test
});
return;
}
await (0, _state.dispatch)({
name: 'test_started',
test
});
const {afterEach, beforeEach} = (0, _utils.getEachHooksForTest)(test);
for (const hook of beforeEach) {
if (test.errors.length) {
// If any of the before hooks failed already, we don't run any
// hooks after that.
break;
}
await _callCircusHook({
hook,
test,
testContext
});
}
await _callCircusTest(test, testContext);
for (const hook of afterEach) {
await _callCircusHook({
hook,
test,
testContext
});
}
// `afterAll` hooks should not affect test status (pass or fail), because if
// we had a global `afterAll` hook it would block all existing tests until
// this hook is executed. So we dispatch `test_done` right away.
await (0, _state.dispatch)({
name: 'test_done',
test
});
};
const _callCircusHook = async ({
hook,
test,
describeBlock,
testContext = {}
}) => {
await (0, _state.dispatch)({
hook,
name: 'hook_start'
});
const timeout = hook.timeout || (0, _state.getState)().testTimeout;
try {
await (0, _utils.callAsyncCircusFn)(hook, testContext, {
isHook: true,
timeout
});
await (0, _state.dispatch)({
describeBlock,
hook,
name: 'hook_success',
test
});
} catch (error) {
await (0, _state.dispatch)({
describeBlock,
error,
hook,
name: 'hook_failure',
test
});
}
};
const _callCircusTest = async (test, testContext) => {
await (0, _state.dispatch)({
name: 'test_fn_start',
test
});
const timeout = test.timeout || (0, _state.getState)().testTimeout;
(0, _jestUtil.invariant)(
test.fn,
"Tests with no 'fn' should have 'mode' set to 'skipped'"
);
if (test.errors.length) {
return; // We don't run the test if there's already an error in before hooks.
}
try {
await (0, _utils.callAsyncCircusFn)(test, testContext, {
isHook: false,
timeout
});
if (test.failing) {
test.asyncError.message =
'Failing test passed even though it was supposed to fail. Remove `.failing` to remove error.';
await (0, _state.dispatch)({
error: test.asyncError,
name: 'test_fn_failure',
test
});
} else {
await (0, _state.dispatch)({
name: 'test_fn_success',
test
});
}
} catch (error) {
if (test.failing) {
await (0, _state.dispatch)({
name: 'test_fn_success',
test
});
} else {
await (0, _state.dispatch)({
error,
name: 'test_fn_failure',
test
});
}
}
};
var _default = run;
exports.default = _default;

View File

@ -0,0 +1,41 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = shuffleArray;
exports.rngBuilder = void 0;
var _pureRand = require('pure-rand');
/**
* 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.
*/
// Generates [from, to] inclusive
const rngBuilder = seed => {
const gen = (0, _pureRand.xoroshiro128plus)(seed);
return {
next: (from, to) =>
(0, _pureRand.unsafeUniformIntDistribution)(from, to, gen)
};
};
// Fisher-Yates shuffle
// This is performed in-place
exports.rngBuilder = rngBuilder;
function shuffleArray(array, random) {
const length = array.length;
if (length === 0) {
return [];
}
for (let i = 0; i < length; i++) {
const n = random.next(i, length - 1);
const value = array[i];
array[i] = array[n];
array[n] = value;
}
return array;
}

View File

@ -0,0 +1,80 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.setState =
exports.resetState =
exports.getState =
exports.dispatchSync =
exports.dispatch =
exports.addEventHandler =
exports.ROOT_DESCRIBE_BLOCK_NAME =
void 0;
var _eventHandler = _interopRequireDefault(require('./eventHandler'));
var _formatNodeAssertErrors = _interopRequireDefault(
require('./formatNodeAssertErrors')
);
var _types = require('./types');
var _utils = require('./utils');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* 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.
*/
const eventHandlers = [_eventHandler.default, _formatNodeAssertErrors.default];
const ROOT_DESCRIBE_BLOCK_NAME = 'ROOT_DESCRIBE_BLOCK';
exports.ROOT_DESCRIBE_BLOCK_NAME = ROOT_DESCRIBE_BLOCK_NAME;
const createState = () => {
const ROOT_DESCRIBE_BLOCK = (0, _utils.makeDescribe)(
ROOT_DESCRIBE_BLOCK_NAME
);
return {
currentDescribeBlock: ROOT_DESCRIBE_BLOCK,
currentlyRunningTest: null,
expand: undefined,
hasFocusedTests: false,
hasStarted: false,
includeTestLocationInResult: false,
maxConcurrency: 5,
parentProcess: null,
rootDescribeBlock: ROOT_DESCRIBE_BLOCK,
seed: 0,
testNamePattern: null,
testTimeout: 5000,
unhandledErrors: []
};
};
/* eslint-disable no-restricted-globals */
const resetState = () => {
global[_types.STATE_SYM] = createState();
};
exports.resetState = resetState;
resetState();
const getState = () => global[_types.STATE_SYM];
exports.getState = getState;
const setState = state => (global[_types.STATE_SYM] = state);
/* eslint-enable */
exports.setState = setState;
const dispatch = async event => {
for (const handler of eventHandlers) {
await handler(event, getState());
}
};
exports.dispatch = dispatch;
const dispatchSync = event => {
for (const handler of eventHandlers) {
handler(event, getState());
}
};
exports.dispatchSync = dispatchSync;
const addEventHandler = handler => {
eventHandlers.push(handler);
};
exports.addEventHandler = addEventHandler;

View File

@ -0,0 +1,32 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _utils = require('./utils');
/**
* 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.
*/
const testCaseReportHandler = (testPath, sendMessageToJest) => event => {
switch (event.name) {
case 'test_started': {
const testCaseStartInfo = (0, _utils.createTestCaseStartInfo)(event.test);
sendMessageToJest('test-case-start', [testPath, testCaseStartInfo]);
break;
}
case 'test_todo':
case 'test_done': {
const testResult = (0, _utils.makeSingleTestResult)(event.test);
const testCaseResult = (0, _utils.parseSingleTestResult)(testResult);
sendMessageToJest('test-case-result', [testPath, testCaseResult]);
break;
}
}
};
var _default = testCaseReportHandler;
exports.default = _default;

View File

@ -0,0 +1,27 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.TEST_TIMEOUT_SYMBOL =
exports.STATE_SYM =
exports.RETRY_TIMES =
exports.LOG_ERRORS_BEFORE_RETRY =
void 0;
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
/**
* 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.
*/
const STATE_SYM = Symbol('JEST_STATE_SYMBOL');
exports.STATE_SYM = STATE_SYM;
const RETRY_TIMES = Symbol.for('RETRY_TIMES');
// To pass this value from Runtime object to state we need to use global[sym]
exports.RETRY_TIMES = RETRY_TIMES;
const TEST_TIMEOUT_SYMBOL = Symbol.for('TEST_TIMEOUT_SYMBOL');
exports.TEST_TIMEOUT_SYMBOL = TEST_TIMEOUT_SYMBOL;
const LOG_ERRORS_BEFORE_RETRY = Symbol.for('LOG_ERRORS_BEFORE_RETRY');
exports.LOG_ERRORS_BEFORE_RETRY = LOG_ERRORS_BEFORE_RETRY;

View File

@ -0,0 +1,511 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.parseSingleTestResult =
exports.makeTest =
exports.makeSingleTestResult =
exports.makeRunResult =
exports.makeDescribe =
exports.getTestID =
exports.getTestDuration =
exports.getEachHooksForTest =
exports.getAllHooksForDescribe =
exports.describeBlockHasTests =
exports.createTestCaseStartInfo =
exports.callAsyncCircusFn =
exports.addErrorToEachTestUnderDescribe =
void 0;
var path = _interopRequireWildcard(require('path'));
var _co = _interopRequireDefault(require('co'));
var _dedent = _interopRequireDefault(require('dedent'));
var _isGeneratorFn = _interopRequireDefault(require('is-generator-fn'));
var _slash = _interopRequireDefault(require('slash'));
var _stackUtils = _interopRequireDefault(require('stack-utils'));
var _jestUtil = require('jest-util');
var _prettyFormat = require('pretty-format');
var _state = require('./state');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
var jestNow = globalThis[Symbol.for('jest-native-now')] || globalThis.Date.now;
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
var Promise =
globalThis[Symbol.for('jest-native-promise')] || globalThis.Promise;
/**
* 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.
*/
const stackUtils = new _stackUtils.default({
cwd: 'A path that does not exist'
});
const jestEachBuildDir = (0, _slash.default)(
path.dirname(require.resolve('jest-each'))
);
function takesDoneCallback(fn) {
return fn.length > 0;
}
function isGeneratorFunction(fn) {
return (0, _isGeneratorFn.default)(fn);
}
const makeDescribe = (name, parent, mode) => {
let _mode = mode;
if (parent && !mode) {
// If not set explicitly, inherit from the parent describe.
_mode = parent.mode;
}
return {
type: 'describeBlock',
// eslint-disable-next-line sort-keys
children: [],
hooks: [],
mode: _mode,
name: (0, _jestUtil.convertDescriptorToString)(name),
parent,
tests: []
};
};
exports.makeDescribe = makeDescribe;
const makeTest = (
fn,
mode,
concurrent,
name,
parent,
timeout,
asyncError,
failing
) => ({
type: 'test',
// eslint-disable-next-line sort-keys
asyncError,
concurrent,
duration: null,
errors: [],
failing,
fn,
invocations: 0,
mode,
name: (0, _jestUtil.convertDescriptorToString)(name),
numPassingAsserts: 0,
parent,
retryReasons: [],
seenDone: false,
startedAt: null,
status: null,
timeout
});
// Traverse the tree of describe blocks and return true if at least one describe
// block has an enabled test.
exports.makeTest = makeTest;
const hasEnabledTest = describeBlock => {
const {hasFocusedTests, testNamePattern} = (0, _state.getState)();
return describeBlock.children.some(child =>
child.type === 'describeBlock'
? hasEnabledTest(child)
: !(
child.mode === 'skip' ||
(hasFocusedTests && child.mode !== 'only') ||
(testNamePattern && !testNamePattern.test(getTestID(child)))
)
);
};
const getAllHooksForDescribe = describe => {
const result = {
afterAll: [],
beforeAll: []
};
if (hasEnabledTest(describe)) {
for (const hook of describe.hooks) {
switch (hook.type) {
case 'beforeAll':
result.beforeAll.push(hook);
break;
case 'afterAll':
result.afterAll.push(hook);
break;
}
}
}
return result;
};
exports.getAllHooksForDescribe = getAllHooksForDescribe;
const getEachHooksForTest = test => {
const result = {
afterEach: [],
beforeEach: []
};
if (test.concurrent) {
// *Each hooks are not run for concurrent tests
return result;
}
let block = test.parent;
do {
const beforeEachForCurrentBlock = [];
for (const hook of block.hooks) {
switch (hook.type) {
case 'beforeEach':
beforeEachForCurrentBlock.push(hook);
break;
case 'afterEach':
result.afterEach.push(hook);
break;
}
}
// 'beforeEach' hooks are executed from top to bottom, the opposite of the
// way we traversed it.
result.beforeEach = [...beforeEachForCurrentBlock, ...result.beforeEach];
} while ((block = block.parent));
return result;
};
exports.getEachHooksForTest = getEachHooksForTest;
const describeBlockHasTests = describe =>
describe.children.some(
child => child.type === 'test' || describeBlockHasTests(child)
);
exports.describeBlockHasTests = describeBlockHasTests;
const _makeTimeoutMessage = (timeout, isHook, takesDoneCallback) =>
`Exceeded timeout of ${(0, _jestUtil.formatTime)(timeout)} for a ${
isHook ? 'hook' : 'test'
}${
takesDoneCallback ? ' while waiting for `done()` to be called' : ''
}.\nAdd a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout.`;
// Global values can be overwritten by mocks or tests. We'll capture
// the original values in the variables before we require any files.
const {setTimeout, clearTimeout} = globalThis;
function checkIsError(error) {
return !!(error && error.message && error.stack);
}
const callAsyncCircusFn = (testOrHook, testContext, {isHook, timeout}) => {
let timeoutID;
let completed = false;
const {fn, asyncError} = testOrHook;
const doneCallback = takesDoneCallback(fn);
return new Promise((resolve, reject) => {
timeoutID = setTimeout(
() => reject(_makeTimeoutMessage(timeout, isHook, doneCallback)),
timeout
);
// If this fn accepts `done` callback we return a promise that fulfills as
// soon as `done` called.
if (doneCallback) {
let returnedValue = undefined;
const done = reason => {
// We need to keep a stack here before the promise tick
const errorAtDone = new _jestUtil.ErrorWithStack(undefined, done);
if (!completed && testOrHook.seenDone) {
errorAtDone.message =
'Expected done to be called once, but it was called multiple times.';
if (reason) {
errorAtDone.message += ` Reason: ${(0, _prettyFormat.format)(
reason,
{
maxDepth: 3
}
)}`;
}
reject(errorAtDone);
throw errorAtDone;
} else {
testOrHook.seenDone = true;
}
// Use `Promise.resolve` to allow the event loop to go a single tick in case `done` is called synchronously
Promise.resolve().then(() => {
if (returnedValue !== undefined) {
asyncError.message = (0, _dedent.default)`
Test functions cannot both take a 'done' callback and return something. Either use a 'done' callback, or return a promise.
Returned value: ${(0, _prettyFormat.format)(returnedValue, {
maxDepth: 3
})}
`;
return reject(asyncError);
}
let errorAsErrorObject;
if (checkIsError(reason)) {
errorAsErrorObject = reason;
} else {
errorAsErrorObject = errorAtDone;
errorAtDone.message = `Failed: ${(0, _prettyFormat.format)(reason, {
maxDepth: 3
})}`;
}
// Consider always throwing, regardless if `reason` is set or not
if (completed && reason) {
errorAsErrorObject.message = `Caught error after test environment was torn down\n\n${errorAsErrorObject.message}`;
throw errorAsErrorObject;
}
return reason ? reject(errorAsErrorObject) : resolve();
});
};
returnedValue = fn.call(testContext, done);
return;
}
let returnedValue;
if (isGeneratorFunction(fn)) {
returnedValue = _co.default.wrap(fn).call({});
} else {
try {
returnedValue = fn.call(testContext);
} catch (error) {
reject(error);
return;
}
}
if ((0, _jestUtil.isPromise)(returnedValue)) {
returnedValue.then(() => resolve(), reject);
return;
}
if (!isHook && returnedValue !== undefined) {
reject(
new Error((0, _dedent.default)`
test functions can only return Promise or undefined.
Returned value: ${(0, _prettyFormat.format)(returnedValue, {
maxDepth: 3
})}
`)
);
return;
}
// Otherwise this test is synchronous, and if it didn't throw it means
// it passed.
resolve();
})
.then(() => {
completed = true;
// If timeout is not cleared/unrefed the node process won't exit until
// it's resolved.
timeoutID.unref?.();
clearTimeout(timeoutID);
})
.catch(error => {
completed = true;
timeoutID.unref?.();
clearTimeout(timeoutID);
throw error;
});
};
exports.callAsyncCircusFn = callAsyncCircusFn;
const getTestDuration = test => {
const {startedAt} = test;
return typeof startedAt === 'number' ? jestNow() - startedAt : null;
};
exports.getTestDuration = getTestDuration;
const makeRunResult = (describeBlock, unhandledErrors) => ({
testResults: makeTestResults(describeBlock),
unhandledErrors: unhandledErrors.map(_getError).map(getErrorStack)
});
exports.makeRunResult = makeRunResult;
const getTestNamesPath = test => {
const titles = [];
let parent = test;
do {
titles.unshift(parent.name);
} while ((parent = parent.parent));
return titles;
};
const makeSingleTestResult = test => {
const {includeTestLocationInResult} = (0, _state.getState)();
const {status} = test;
(0, _jestUtil.invariant)(
status,
'Status should be present after tests are run.'
);
const testPath = getTestNamesPath(test);
let location = null;
if (includeTestLocationInResult) {
const stackLines = test.asyncError.stack.split('\n');
const stackLine = stackLines[1];
let parsedLine = stackUtils.parseLine(stackLine);
if (parsedLine?.file?.startsWith(jestEachBuildDir)) {
const stackLine = stackLines[4];
parsedLine = stackUtils.parseLine(stackLine);
}
if (
parsedLine &&
typeof parsedLine.column === 'number' &&
typeof parsedLine.line === 'number'
) {
location = {
column: parsedLine.column,
line: parsedLine.line
};
}
}
const errorsDetailed = test.errors.map(_getError);
return {
duration: test.duration,
errors: errorsDetailed.map(getErrorStack),
errorsDetailed,
invocations: test.invocations,
location,
numPassingAsserts: test.numPassingAsserts,
retryReasons: test.retryReasons.map(_getError).map(getErrorStack),
status,
testPath: Array.from(testPath)
};
};
exports.makeSingleTestResult = makeSingleTestResult;
const makeTestResults = describeBlock => {
const testResults = [];
for (const child of describeBlock.children) {
switch (child.type) {
case 'describeBlock': {
testResults.push(...makeTestResults(child));
break;
}
case 'test': {
testResults.push(makeSingleTestResult(child));
break;
}
}
}
return testResults;
};
// Return a string that identifies the test (concat of parent describe block
// names + test title)
const getTestID = test => {
const testNamesPath = getTestNamesPath(test);
testNamesPath.shift(); // remove TOP_DESCRIBE_BLOCK_NAME
return testNamesPath.join(' ');
};
exports.getTestID = getTestID;
const _getError = errors => {
let error;
let asyncError;
if (Array.isArray(errors)) {
error = errors[0];
asyncError = errors[1];
} else {
error = errors;
asyncError = new Error();
}
if (error && (typeof error.stack === 'string' || error.message)) {
return error;
}
asyncError.message = `thrown: ${(0, _prettyFormat.format)(error, {
maxDepth: 3
})}`;
return asyncError;
};
const getErrorStack = error =>
typeof error.stack === 'string' ? error.stack : error.message;
const addErrorToEachTestUnderDescribe = (describeBlock, error, asyncError) => {
for (const child of describeBlock.children) {
switch (child.type) {
case 'describeBlock':
addErrorToEachTestUnderDescribe(child, error, asyncError);
break;
case 'test':
child.errors.push([error, asyncError]);
break;
}
}
};
exports.addErrorToEachTestUnderDescribe = addErrorToEachTestUnderDescribe;
const resolveTestCaseStartInfo = testNamesPath => {
const ancestorTitles = testNamesPath.filter(
name => name !== _state.ROOT_DESCRIBE_BLOCK_NAME
);
const fullName = ancestorTitles.join(' ');
const title = testNamesPath[testNamesPath.length - 1];
// remove title
ancestorTitles.pop();
return {
ancestorTitles,
fullName,
title
};
};
const parseSingleTestResult = testResult => {
let status;
if (testResult.status === 'skip') {
status = 'pending';
} else if (testResult.status === 'todo') {
status = 'todo';
} else if (testResult.errors.length > 0) {
status = 'failed';
} else {
status = 'passed';
}
const {ancestorTitles, fullName, title} = resolveTestCaseStartInfo(
testResult.testPath
);
return {
ancestorTitles,
duration: testResult.duration,
failureDetails: testResult.errorsDetailed,
failureMessages: Array.from(testResult.errors),
fullName,
invocations: testResult.invocations,
location: testResult.location,
numPassingAsserts: testResult.numPassingAsserts,
retryReasons: Array.from(testResult.retryReasons),
status,
title
};
};
exports.parseSingleTestResult = parseSingleTestResult;
const createTestCaseStartInfo = test => {
const testPath = getTestNamesPath(test);
const {ancestorTitles, fullName, title} = resolveTestCaseStartInfo(testPath);
return {
ancestorTitles,
fullName,
mode: test.mode,
startedAt: test.startedAt,
title
};
};
exports.createTestCaseStartInfo = createTestCaseStartInfo;