Set up comprehensive frontend testing infrastructure

- Install Jest for unit testing with React Testing Library
- Install Playwright for end-to-end testing
- Configure Jest with proper TypeScript support and module mapping
- Create test setup files and utilities for both unit and e2e tests

Components:
* Jest configuration with coverage thresholds
* Playwright configuration with browser automation
* Unit tests for LoginForm, AuthContext, and useSocketIO hook
* E2E tests for authentication, dashboard, and agents workflows
* GitHub Actions workflow for automated testing
* Mock data and API utilities for consistent testing
* Test documentation with best practices

Testing features:
- Unit tests with 70% coverage threshold
- E2E tests with API mocking and user journey testing
- CI/CD integration for automated test runs
- Cross-browser testing support with Playwright
- Authentication system testing end-to-end

🚀 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-07-11 14:06:34 +10:00
parent c6d69695a8
commit aacb45156b
6109 changed files with 777927 additions and 1 deletions

22
frontend/node_modules/jest-runner/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
MIT License
Copyright (c) Meta Platforms, Inc. and affiliates.
Copyright Contributors to the Jest project.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

55
frontend/node_modules/jest-runner/build/index.d.mts generated vendored Normal file
View File

@@ -0,0 +1,55 @@
import "jest-runtime";
import { SerializableError, Test, Test as Test$1, TestEvents, TestEvents as TestEvents$1, TestResult } from "@jest/test-result";
import { TestWatcher, TestWatcher as TestWatcher$1 } from "jest-watcher";
import { Config, Config as Config$1 } from "@jest/types";
//#region src/types.d.ts
type OnTestStart = (test: Test$1) => Promise<void>;
type OnTestFailure = (test: Test$1, serializableError: SerializableError) => Promise<void>;
type OnTestSuccess = (test: Test$1, testResult: TestResult) => Promise<void>;
type TestRunnerOptions = {
serial: boolean;
};
type TestRunnerContext = {
changedFiles?: Set<string>;
sourcesRelatedToTestsInChangedFiles?: Set<string>;
};
type UnsubscribeFn = () => void;
interface CallbackTestRunnerInterface {
readonly isSerial?: boolean;
readonly supportsEventEmitters?: boolean;
runTests(tests: Array<Test$1>, watcher: TestWatcher$1, onStart: OnTestStart, onResult: OnTestSuccess, onFailure: OnTestFailure, options: TestRunnerOptions): Promise<void>;
}
interface EmittingTestRunnerInterface {
readonly isSerial?: boolean;
readonly supportsEventEmitters: true;
runTests(tests: Array<Test$1>, watcher: TestWatcher$1, options: TestRunnerOptions): Promise<void>;
on<Name extends keyof TestEvents$1>(eventName: Name, listener: (eventData: TestEvents$1[Name]) => void | Promise<void>): UnsubscribeFn;
}
declare abstract class BaseTestRunner {
protected readonly _globalConfig: Config$1.GlobalConfig;
protected readonly _context: TestRunnerContext;
readonly isSerial?: boolean;
abstract readonly supportsEventEmitters: boolean;
constructor(_globalConfig: Config$1.GlobalConfig, _context: TestRunnerContext);
}
declare abstract class CallbackTestRunner extends BaseTestRunner implements CallbackTestRunnerInterface {
readonly supportsEventEmitters = false;
abstract runTests(tests: Array<Test$1>, watcher: TestWatcher$1, onStart: OnTestStart, onResult: OnTestSuccess, onFailure: OnTestFailure, options: TestRunnerOptions): Promise<void>;
}
declare abstract class EmittingTestRunner extends BaseTestRunner implements EmittingTestRunnerInterface {
readonly supportsEventEmitters = true;
abstract runTests(tests: Array<Test$1>, watcher: TestWatcher$1, options: TestRunnerOptions): Promise<void>;
abstract on<Name extends keyof TestEvents$1>(eventName: Name, listener: (eventData: TestEvents$1[Name]) => void | Promise<void>): UnsubscribeFn;
}
type JestTestRunner = CallbackTestRunner | EmittingTestRunner;
//#endregion
//#region src/index.d.ts
declare class TestRunner extends EmittingTestRunner {
#private;
runTests(tests: Array<Test$1>, watcher: TestWatcher$1, options: TestRunnerOptions): Promise<void>;
on<Name extends keyof TestEvents$1>(eventName: Name, listener: (eventData: TestEvents$1[Name]) => void | Promise<void>): UnsubscribeFn;
}
//#endregion
export { CallbackTestRunner, CallbackTestRunnerInterface, Config, EmittingTestRunner, EmittingTestRunnerInterface, JestTestRunner, OnTestFailure, OnTestStart, OnTestSuccess, Test, TestEvents, TestRunnerContext, TestRunnerOptions, TestWatcher, UnsubscribeFn, TestRunner as default };

130
frontend/node_modules/jest-runner/build/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,130 @@
/**
* 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 {
SerializableError,
Test,
TestEvents,
TestResult,
} from '@jest/test-result';
import {Config} from '@jest/types';
import {TestWatcher} from 'jest-watcher';
declare abstract class BaseTestRunner {
protected readonly _globalConfig: Config.GlobalConfig;
protected readonly _context: TestRunnerContext;
readonly isSerial?: boolean;
abstract readonly supportsEventEmitters: boolean;
constructor(_globalConfig: Config.GlobalConfig, _context: TestRunnerContext);
}
export declare abstract class CallbackTestRunner
extends BaseTestRunner
implements CallbackTestRunnerInterface
{
readonly supportsEventEmitters = false;
abstract runTests(
tests: Array<Test>,
watcher: TestWatcher,
onStart: OnTestStart,
onResult: OnTestSuccess,
onFailure: OnTestFailure,
options: TestRunnerOptions,
): Promise<void>;
}
export declare interface CallbackTestRunnerInterface {
readonly isSerial?: boolean;
readonly supportsEventEmitters?: boolean;
runTests(
tests: Array<Test>,
watcher: TestWatcher,
onStart: OnTestStart,
onResult: OnTestSuccess,
onFailure: OnTestFailure,
options: TestRunnerOptions,
): Promise<void>;
}
export {Config};
export declare abstract class EmittingTestRunner
extends BaseTestRunner
implements EmittingTestRunnerInterface
{
readonly supportsEventEmitters = true;
abstract runTests(
tests: Array<Test>,
watcher: TestWatcher,
options: TestRunnerOptions,
): Promise<void>;
abstract on<Name extends keyof TestEvents>(
eventName: Name,
listener: (eventData: TestEvents[Name]) => void | Promise<void>,
): UnsubscribeFn;
}
export declare interface EmittingTestRunnerInterface {
readonly isSerial?: boolean;
readonly supportsEventEmitters: true;
runTests(
tests: Array<Test>,
watcher: TestWatcher,
options: TestRunnerOptions,
): Promise<void>;
on<Name extends keyof TestEvents>(
eventName: Name,
listener: (eventData: TestEvents[Name]) => void | Promise<void>,
): UnsubscribeFn;
}
export declare type JestTestRunner = CallbackTestRunner | EmittingTestRunner;
export declare type OnTestFailure = (
test: Test,
serializableError: SerializableError,
) => Promise<void>;
export declare type OnTestStart = (test: Test) => Promise<void>;
export declare type OnTestSuccess = (
test: Test,
testResult: TestResult,
) => Promise<void>;
export {Test};
export {TestEvents};
declare class TestRunner extends EmittingTestRunner {
#private;
runTests(
tests: Array<Test>,
watcher: TestWatcher,
options: TestRunnerOptions,
): Promise<void>;
on<Name extends keyof TestEvents>(
eventName: Name,
listener: (eventData: TestEvents[Name]) => void | Promise<void>,
): UnsubscribeFn;
}
export default TestRunner;
export declare type TestRunnerContext = {
changedFiles?: Set<string>;
sourcesRelatedToTestsInChangedFiles?: Set<string>;
};
export declare type TestRunnerOptions = {
serial: boolean;
};
export {TestWatcher};
export declare type UnsubscribeFn = () => void;
export {};

593
frontend/node_modules/jest-runner/build/index.js generated vendored Normal file
View File

@@ -0,0 +1,593 @@
/*!
* /**
* * 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.
* * /
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/runTest.ts":
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports["default"] = runTest;
function _nodeVm() {
const data = require("node:vm");
_nodeVm = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function fs() {
const data = _interopRequireWildcard(require("graceful-fs"));
fs = function () {
return data;
};
return data;
}
function sourcemapSupport() {
const data = _interopRequireWildcard(require("source-map-support"));
sourcemapSupport = function () {
return data;
};
return data;
}
function _console() {
const data = require("@jest/console");
_console = function () {
return data;
};
return data;
}
function _transform() {
const data = require("@jest/transform");
_transform = function () {
return data;
};
return data;
}
function docblock() {
const data = _interopRequireWildcard(require("jest-docblock"));
docblock = function () {
return data;
};
return data;
}
function _jestLeakDetector() {
const data = _interopRequireDefault(require("jest-leak-detector"));
_jestLeakDetector = function () {
return data;
};
return data;
}
function _jestMessageUtil() {
const data = require("jest-message-util");
_jestMessageUtil = function () {
return data;
};
return data;
}
function _jestResolve() {
const data = require("jest-resolve");
_jestResolve = function () {
return data;
};
return data;
}
function _jestUtil() {
const data = require("jest-util");
_jestUtil = function () {
return data;
};
return data;
}
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
function freezeConsole(testConsole, config) {
// @ts-expect-error: `_log` is `private` - we should figure out some proper API here
testConsole._log = function fakeConsolePush(_type, message) {
const error = new (_jestUtil().ErrorWithStack)(`${_chalk().default.red(`${_chalk().default.bold('Cannot log after tests are done.')} Did you forget to wait for something async in your test?`)}\nAttempted to log "${message}".`, fakeConsolePush);
const formattedError = (0, _jestMessageUtil().formatExecError)(error, config, {
noStackTrace: false
}, undefined, true);
process.stderr.write(`\n${formattedError}\n`);
process.exitCode = 1;
};
}
// Keeping the core of "runTest" as a separate function (as "runTestInternal")
// is key to be able to detect memory leaks. Since all variables are local to
// the function, when "runTestInternal" finishes its execution, they can all be
// freed, UNLESS something else is leaking them (and that's why we can detect
// the leak!).
//
// If we had all the code in a single function, we should manually nullify all
// references to verify if there is a leak, which is not maintainable and error
// prone. That's why "runTestInternal" CANNOT be inlined inside "runTest".
async function runTestInternal(path, globalConfig, projectConfig, resolver, context, sendMessageToJest) {
const testSource = fs().readFileSync(path, 'utf8');
const docblockPragmas = docblock().parse(docblock().extract(testSource));
const customEnvironment = docblockPragmas['jest-environment'];
const loadTestEnvironmentStart = Date.now();
let testEnvironment = projectConfig.testEnvironment;
if (customEnvironment) {
if (Array.isArray(customEnvironment)) {
throw new TypeError(`You can only define a single test environment through docblocks, got "${customEnvironment.join(', ')}"`);
}
testEnvironment = (0, _jestResolve().resolveTestEnvironment)({
...projectConfig,
// we wanna avoid webpack trying to be clever
requireResolveFunction: module => require.resolve(module),
testEnvironment: customEnvironment
});
}
const cacheFS = new Map([[path, testSource]]);
const transformer = await (0, _transform().createScriptTransformer)(projectConfig, cacheFS);
const TestEnvironment = await transformer.requireAndTranspileModule(testEnvironment);
const testFramework = await transformer.requireAndTranspileModule(process.env.JEST_JASMINE === '1' ? require.resolve('jest-jasmine2') : projectConfig.testRunner);
const Runtime = (0, _jestUtil().interopRequireDefault)(projectConfig.runtime ? require(projectConfig.runtime) : require('jest-runtime')).default;
const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
const consoleFormatter = (type, message) => (0, _console().getConsoleOutput)(
// 4 = the console call is buried 4 stack frames deep
_console().BufferedConsole.write([], type, message, 4), projectConfig, globalConfig);
let testConsole;
if (globalConfig.silent) {
testConsole = new (_console().NullConsole)(consoleOut, consoleOut, consoleFormatter);
} else if (globalConfig.verbose) {
testConsole = new (_console().CustomConsole)(consoleOut, consoleOut, consoleFormatter);
} else {
testConsole = new (_console().BufferedConsole)();
}
let extraTestEnvironmentOptions;
const docblockEnvironmentOptions = docblockPragmas['jest-environment-options'];
if (typeof docblockEnvironmentOptions === 'string') {
extraTestEnvironmentOptions = JSON.parse(docblockEnvironmentOptions);
}
const environment = new TestEnvironment({
globalConfig,
projectConfig: extraTestEnvironmentOptions ? {
...projectConfig,
testEnvironmentOptions: {
...projectConfig.testEnvironmentOptions,
...extraTestEnvironmentOptions
}
} : projectConfig
}, {
console: testConsole,
docblockPragmas,
testPath: path
});
const loadTestEnvironmentEnd = Date.now();
if (typeof environment.getVmContext !== 'function') {
console.error(`Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`);
process.exit(1);
}
const leakDetector = projectConfig.detectLeaks ? new (_jestLeakDetector().default)(environment) : null;
(0, _jestUtil().setGlobal)(environment.global, 'console', testConsole, 'retain');
const runtime = new Runtime(projectConfig, environment, resolver, transformer, cacheFS, {
changedFiles: context.changedFiles,
collectCoverage: globalConfig.collectCoverage,
collectCoverageFrom: globalConfig.collectCoverageFrom,
coverageProvider: globalConfig.coverageProvider,
sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles
}, path, globalConfig);
let isTornDown = false;
const tearDownEnv = async () => {
if (!isTornDown) {
runtime.teardown();
// source-map-support keeps memory leftovers in `Error.prepareStackTrace`
(0, _nodeVm().runInContext)("Error.prepareStackTrace = () => '';", environment.getVmContext());
sourcemapSupport().resetRetrieveHandlers();
await environment.teardown();
isTornDown = true;
}
};
const start = Date.now();
const setupFilesStart = Date.now();
for (const path of projectConfig.setupFiles) {
const esm = runtime.unstable_shouldLoadAsEsm(path);
if (esm) {
await runtime.unstable_importModule(path);
} else {
const setupFile = runtime.requireModule(path);
if (typeof setupFile === 'function') {
await setupFile();
}
}
}
const setupFilesEnd = Date.now();
const sourcemapOptions = {
environment: 'node',
handleUncaughtExceptions: false,
retrieveSourceMap: source => {
const sourceMapSource = runtime.getSourceMaps()?.get(source);
if (sourceMapSource) {
try {
return {
map: JSON.parse(fs().readFileSync(sourceMapSource, 'utf8')),
url: source
};
} catch {}
}
return null;
}
};
// For tests
runtime.requireInternalModule(require.resolve('source-map-support')).install(sourcemapOptions);
// For runtime errors
sourcemapSupport().install(sourcemapOptions);
if (environment.global && environment.global.process && environment.global.process.exit) {
const realExit = environment.global.process.exit;
environment.global.process.exit = function exit(...args) {
const error = new (_jestUtil().ErrorWithStack)(`process.exit called with "${args.join(', ')}"`, exit);
const formattedError = (0, _jestMessageUtil().formatExecError)(error, projectConfig, {
noStackTrace: false
}, undefined, true);
process.stderr.write(formattedError);
return realExit(...args);
};
}
// if we don't have `getVmContext` on the env skip coverage
const collectV8Coverage = globalConfig.collectCoverage && globalConfig.coverageProvider === 'v8' && typeof environment.getVmContext === 'function';
// Node's error-message stack size is limited at 10, but it's pretty useful
// to see more than that when a test fails.
Error.stackTraceLimit = 100;
try {
await environment.setup();
let result;
try {
if (collectV8Coverage) {
await runtime.collectV8Coverage();
}
result = await testFramework(globalConfig, projectConfig, environment, runtime, path, sendMessageToJest);
} catch (error) {
// Access all stacks before uninstalling sourcemaps
let e = error;
while (typeof e === 'object' && e !== null && 'stack' in e) {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
e.stack;
e = e?.cause;
}
throw error;
} finally {
if (collectV8Coverage) {
await runtime.stopCollectingV8Coverage();
}
}
freezeConsole(testConsole, projectConfig);
const testCount = result.numPassingTests + result.numFailingTests + result.numPendingTests + result.numTodoTests;
const end = Date.now();
const testRuntime = end - start;
result.perfStats = {
...result.perfStats,
end,
loadTestEnvironmentEnd,
loadTestEnvironmentStart,
runtime: testRuntime,
setupFilesEnd,
setupFilesStart,
slow: testRuntime / 1000 > projectConfig.slowTestThreshold,
start
};
result.testFilePath = path;
result.console = testConsole.getBuffer();
result.skipped = testCount === result.numPendingTests;
result.displayName = projectConfig.displayName;
const coverage = runtime.getAllCoverageInfoCopy();
if (coverage) {
const coverageKeys = Object.keys(coverage);
if (coverageKeys.length > 0) {
result.coverage = coverage;
}
}
if (collectV8Coverage) {
const v8Coverage = runtime.getAllV8CoverageInfoCopy();
if (v8Coverage && v8Coverage.length > 0) {
result.v8Coverage = v8Coverage;
}
}
if (globalConfig.logHeapUsage) {
globalThis.gc?.();
result.memoryUsage = process.memoryUsage().heapUsed;
}
await tearDownEnv();
// Delay the resolution to allow log messages to be output.
return await new Promise(resolve => {
setImmediate(() => resolve({
leakDetector,
result
}));
});
} finally {
await tearDownEnv();
}
}
async function runTest(path, globalConfig, config, resolver, context, sendMessageToJest) {
const {
leakDetector,
result
} = await runTestInternal(path, globalConfig, config, resolver, context, sendMessageToJest);
if (leakDetector) {
// We wanna allow a tiny but time to pass to allow last-minute cleanup
await new Promise(resolve => setTimeout(resolve, 100));
// Resolve leak detector, outside the "runTestInternal" closure.
result.leaks = await leakDetector.isLeaking();
} else {
result.leaks = false;
}
return result;
}
/***/ }),
/***/ "./src/types.ts":
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.EmittingTestRunner = exports.CallbackTestRunner = void 0;
/**
* 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.
*/
class BaseTestRunner {
isSerial;
constructor(_globalConfig, _context) {
this._globalConfig = _globalConfig;
this._context = _context;
}
}
class CallbackTestRunner extends BaseTestRunner {
supportsEventEmitters = false;
}
exports.CallbackTestRunner = CallbackTestRunner;
class EmittingTestRunner extends BaseTestRunner {
supportsEventEmitters = true;
}
exports.EmittingTestRunner = EmittingTestRunner;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
(() => {
var exports = __webpack_exports__;
Object.defineProperty(exports, "__esModule", ({
value: true
}));
Object.defineProperty(exports, "CallbackTestRunner", ({
enumerable: true,
get: function () {
return _types.CallbackTestRunner;
}
}));
Object.defineProperty(exports, "EmittingTestRunner", ({
enumerable: true,
get: function () {
return _types.EmittingTestRunner;
}
}));
exports["default"] = void 0;
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _emittery() {
const data = _interopRequireDefault(require("emittery"));
_emittery = function () {
return data;
};
return data;
}
function _pLimit() {
const data = _interopRequireDefault(require("p-limit"));
_pLimit = function () {
return data;
};
return data;
}
function _jestUtil() {
const data = require("jest-util");
_jestUtil = function () {
return data;
};
return data;
}
function _jestWorker() {
const data = require("jest-worker");
_jestWorker = function () {
return data;
};
return data;
}
var _runTest = _interopRequireDefault(__webpack_require__("./src/runTest.ts"));
var _types = __webpack_require__("./src/types.ts");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class TestRunner extends _types.EmittingTestRunner {
#eventEmitter = new (_emittery().default)();
async runTests(tests, watcher, options) {
return options.serial ? this.#createInBandTestRun(tests, watcher) : this.#createParallelTestRun(tests, watcher);
}
async #createInBandTestRun(tests, watcher) {
process.env.JEST_WORKER_ID = '1';
const mutex = (0, _pLimit().default)(1);
return tests.reduce((promise, test) => mutex(() => promise.then(async () => {
if (watcher.isInterrupted()) {
throw new CancelRun();
}
await this.#eventEmitter.emit('test-file-start', [test]);
return (0, _runTest.default)(test.path, this._globalConfig, test.context.config, test.context.resolver, this._context, this.#sendMessageToJest);
}).then(result => this.#eventEmitter.emit('test-file-success', [test, result]), error => this.#eventEmitter.emit('test-file-failure', [test, error]))), Promise.resolve());
}
async #createParallelTestRun(tests, watcher) {
const resolvers = new Map();
for (const test of tests) {
if (!resolvers.has(test.context.config.id)) {
resolvers.set(test.context.config.id, {
config: test.context.config,
serializableModuleMap: test.context.moduleMap.toJSON()
});
}
}
const worker = new (_jestWorker().Worker)(require.resolve('./testWorker'), {
enableWorkerThreads: this._globalConfig.workerThreads,
exposedMethods: ['worker'],
forkOptions: {
serialization: 'json',
stdio: 'pipe'
},
// The workerIdleMemoryLimit should've been converted to a number during
// the normalization phase.
idleMemoryLimit: typeof this._globalConfig.workerIdleMemoryLimit === 'number' ? this._globalConfig.workerIdleMemoryLimit : undefined,
maxRetries: 3,
numWorkers: this._globalConfig.maxWorkers,
setupArgs: [{
serializableResolvers: [...resolvers.values()]
}]
});
if (worker.getStdout()) worker.getStdout().pipe(process.stdout);
if (worker.getStderr()) worker.getStderr().pipe(process.stderr);
const mutex = (0, _pLimit().default)(this._globalConfig.maxWorkers);
// Send test suites to workers continuously instead of all at once to track
// the start time of individual tests.
const runTestInWorker = test => mutex(async () => {
if (watcher.isInterrupted()) {
// eslint-disable-next-line unicorn/error-message
throw new Error();
}
await this.#eventEmitter.emit('test-file-start', [test]);
const promise = worker.worker({
config: test.context.config,
context: {
...this._context,
changedFiles: this._context.changedFiles && [...this._context.changedFiles],
sourcesRelatedToTestsInChangedFiles: this._context.sourcesRelatedToTestsInChangedFiles && [...this._context.sourcesRelatedToTestsInChangedFiles]
},
globalConfig: this._globalConfig,
path: test.path
});
if (promise.UNSTABLE_onCustomMessage) {
// TODO: Get appropriate type for `onCustomMessage`
promise.UNSTABLE_onCustomMessage(([event, payload]) => this.#eventEmitter.emit(event, payload));
}
return promise;
});
const onInterrupt = new Promise((_resolve, reject) => {
watcher.on('change', state => {
if (state.interrupted) {
reject(new CancelRun());
}
});
});
const runAllTests = Promise.all(tests.map(test => runTestInWorker(test).then(result => this.#eventEmitter.emit('test-file-success', [test, result]), error => this.#eventEmitter.emit('test-file-failure', [test, error]))));
const cleanup = async () => {
const {
forceExited
} = await worker.end();
if (forceExited) {
console.error(_chalk().default.yellow('A worker process has failed to exit gracefully and has been force exited. ' + 'This is likely caused by tests leaking due to improper teardown. ' + 'Try running with --detectOpenHandles to find leaks. ' + 'Active timers can also cause this, ensure that .unref() was called on them.'));
}
};
return Promise.race([runAllTests, onInterrupt]).then(cleanup, cleanup);
}
on(eventName, listener) {
return this.#eventEmitter.on(eventName, listener);
}
#sendMessageToJest = async (eventName, args) => {
await this.#eventEmitter.emit(eventName,
// `deepCyclicCopy` used here to avoid mem-leak
(0, _jestUtil().deepCyclicCopy)(args, {
keepPrototype: false
}));
};
}
exports["default"] = TestRunner;
class CancelRun extends Error {
constructor(message) {
super(message);
this.name = 'CancelRun';
}
}
})();
module.exports = __webpack_exports__;
/******/ })()
;

5
frontend/node_modules/jest-runner/build/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import cjsModule from './index.js';
export const CallbackTestRunner = cjsModule.CallbackTestRunner;
export const EmittingTestRunner = cjsModule.EmittingTestRunner;
export default cjsModule.default;

View File

@@ -0,0 +1,36 @@
import { SerializableModuleMap } from "jest-haste-map";
import Runtime from "jest-runtime";
import { TestResult } from "@jest/test-result";
import { Config } from "@jest/types";
//#region src/types.d.ts
type TestRunnerContext = {
changedFiles?: Set<string>;
sourcesRelatedToTestsInChangedFiles?: Set<string>;
};
type SerializeSet<T> = T extends Set<infer U> ? Array<U> : T;
type TestRunnerSerializedContext = { [K in keyof TestRunnerContext]: SerializeSet<TestRunnerContext[K]> };
//#endregion
//#region src/testWorker.d.ts
type SerializableResolver = {
config: Config.ProjectConfig;
serializableModuleMap: SerializableModuleMap;
};
type WorkerData = {
config: Config.ProjectConfig;
globalConfig: Config.GlobalConfig;
path: string;
context: TestRunnerSerializedContext;
};
declare function setup(setupData: {
serializableResolvers: Array<SerializableResolver>;
}): void;
declare function worker({
config,
globalConfig,
path,
context
}: WorkerData): Promise<TestResult>;
//#endregion
export { SerializableResolver, setup, worker };

507
frontend/node_modules/jest-runner/build/testWorker.js generated vendored Normal file
View File

@@ -0,0 +1,507 @@
/*!
* /**
* * 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.
* * /
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/runTest.ts":
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports["default"] = runTest;
function _nodeVm() {
const data = require("node:vm");
_nodeVm = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function fs() {
const data = _interopRequireWildcard(require("graceful-fs"));
fs = function () {
return data;
};
return data;
}
function sourcemapSupport() {
const data = _interopRequireWildcard(require("source-map-support"));
sourcemapSupport = function () {
return data;
};
return data;
}
function _console() {
const data = require("@jest/console");
_console = function () {
return data;
};
return data;
}
function _transform() {
const data = require("@jest/transform");
_transform = function () {
return data;
};
return data;
}
function docblock() {
const data = _interopRequireWildcard(require("jest-docblock"));
docblock = function () {
return data;
};
return data;
}
function _jestLeakDetector() {
const data = _interopRequireDefault(require("jest-leak-detector"));
_jestLeakDetector = function () {
return data;
};
return data;
}
function _jestMessageUtil() {
const data = require("jest-message-util");
_jestMessageUtil = function () {
return data;
};
return data;
}
function _jestResolve() {
const data = require("jest-resolve");
_jestResolve = function () {
return data;
};
return data;
}
function _jestUtil() {
const data = require("jest-util");
_jestUtil = function () {
return data;
};
return data;
}
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
function freezeConsole(testConsole, config) {
// @ts-expect-error: `_log` is `private` - we should figure out some proper API here
testConsole._log = function fakeConsolePush(_type, message) {
const error = new (_jestUtil().ErrorWithStack)(`${_chalk().default.red(`${_chalk().default.bold('Cannot log after tests are done.')} Did you forget to wait for something async in your test?`)}\nAttempted to log "${message}".`, fakeConsolePush);
const formattedError = (0, _jestMessageUtil().formatExecError)(error, config, {
noStackTrace: false
}, undefined, true);
process.stderr.write(`\n${formattedError}\n`);
process.exitCode = 1;
};
}
// Keeping the core of "runTest" as a separate function (as "runTestInternal")
// is key to be able to detect memory leaks. Since all variables are local to
// the function, when "runTestInternal" finishes its execution, they can all be
// freed, UNLESS something else is leaking them (and that's why we can detect
// the leak!).
//
// If we had all the code in a single function, we should manually nullify all
// references to verify if there is a leak, which is not maintainable and error
// prone. That's why "runTestInternal" CANNOT be inlined inside "runTest".
async function runTestInternal(path, globalConfig, projectConfig, resolver, context, sendMessageToJest) {
const testSource = fs().readFileSync(path, 'utf8');
const docblockPragmas = docblock().parse(docblock().extract(testSource));
const customEnvironment = docblockPragmas['jest-environment'];
const loadTestEnvironmentStart = Date.now();
let testEnvironment = projectConfig.testEnvironment;
if (customEnvironment) {
if (Array.isArray(customEnvironment)) {
throw new TypeError(`You can only define a single test environment through docblocks, got "${customEnvironment.join(', ')}"`);
}
testEnvironment = (0, _jestResolve().resolveTestEnvironment)({
...projectConfig,
// we wanna avoid webpack trying to be clever
requireResolveFunction: module => require.resolve(module),
testEnvironment: customEnvironment
});
}
const cacheFS = new Map([[path, testSource]]);
const transformer = await (0, _transform().createScriptTransformer)(projectConfig, cacheFS);
const TestEnvironment = await transformer.requireAndTranspileModule(testEnvironment);
const testFramework = await transformer.requireAndTranspileModule(process.env.JEST_JASMINE === '1' ? require.resolve('jest-jasmine2') : projectConfig.testRunner);
const Runtime = (0, _jestUtil().interopRequireDefault)(projectConfig.runtime ? require(projectConfig.runtime) : require('jest-runtime')).default;
const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
const consoleFormatter = (type, message) => (0, _console().getConsoleOutput)(
// 4 = the console call is buried 4 stack frames deep
_console().BufferedConsole.write([], type, message, 4), projectConfig, globalConfig);
let testConsole;
if (globalConfig.silent) {
testConsole = new (_console().NullConsole)(consoleOut, consoleOut, consoleFormatter);
} else if (globalConfig.verbose) {
testConsole = new (_console().CustomConsole)(consoleOut, consoleOut, consoleFormatter);
} else {
testConsole = new (_console().BufferedConsole)();
}
let extraTestEnvironmentOptions;
const docblockEnvironmentOptions = docblockPragmas['jest-environment-options'];
if (typeof docblockEnvironmentOptions === 'string') {
extraTestEnvironmentOptions = JSON.parse(docblockEnvironmentOptions);
}
const environment = new TestEnvironment({
globalConfig,
projectConfig: extraTestEnvironmentOptions ? {
...projectConfig,
testEnvironmentOptions: {
...projectConfig.testEnvironmentOptions,
...extraTestEnvironmentOptions
}
} : projectConfig
}, {
console: testConsole,
docblockPragmas,
testPath: path
});
const loadTestEnvironmentEnd = Date.now();
if (typeof environment.getVmContext !== 'function') {
console.error(`Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`);
process.exit(1);
}
const leakDetector = projectConfig.detectLeaks ? new (_jestLeakDetector().default)(environment) : null;
(0, _jestUtil().setGlobal)(environment.global, 'console', testConsole, 'retain');
const runtime = new Runtime(projectConfig, environment, resolver, transformer, cacheFS, {
changedFiles: context.changedFiles,
collectCoverage: globalConfig.collectCoverage,
collectCoverageFrom: globalConfig.collectCoverageFrom,
coverageProvider: globalConfig.coverageProvider,
sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles
}, path, globalConfig);
let isTornDown = false;
const tearDownEnv = async () => {
if (!isTornDown) {
runtime.teardown();
// source-map-support keeps memory leftovers in `Error.prepareStackTrace`
(0, _nodeVm().runInContext)("Error.prepareStackTrace = () => '';", environment.getVmContext());
sourcemapSupport().resetRetrieveHandlers();
await environment.teardown();
isTornDown = true;
}
};
const start = Date.now();
const setupFilesStart = Date.now();
for (const path of projectConfig.setupFiles) {
const esm = runtime.unstable_shouldLoadAsEsm(path);
if (esm) {
await runtime.unstable_importModule(path);
} else {
const setupFile = runtime.requireModule(path);
if (typeof setupFile === 'function') {
await setupFile();
}
}
}
const setupFilesEnd = Date.now();
const sourcemapOptions = {
environment: 'node',
handleUncaughtExceptions: false,
retrieveSourceMap: source => {
const sourceMapSource = runtime.getSourceMaps()?.get(source);
if (sourceMapSource) {
try {
return {
map: JSON.parse(fs().readFileSync(sourceMapSource, 'utf8')),
url: source
};
} catch {}
}
return null;
}
};
// For tests
runtime.requireInternalModule(require.resolve('source-map-support')).install(sourcemapOptions);
// For runtime errors
sourcemapSupport().install(sourcemapOptions);
if (environment.global && environment.global.process && environment.global.process.exit) {
const realExit = environment.global.process.exit;
environment.global.process.exit = function exit(...args) {
const error = new (_jestUtil().ErrorWithStack)(`process.exit called with "${args.join(', ')}"`, exit);
const formattedError = (0, _jestMessageUtil().formatExecError)(error, projectConfig, {
noStackTrace: false
}, undefined, true);
process.stderr.write(formattedError);
return realExit(...args);
};
}
// if we don't have `getVmContext` on the env skip coverage
const collectV8Coverage = globalConfig.collectCoverage && globalConfig.coverageProvider === 'v8' && typeof environment.getVmContext === 'function';
// Node's error-message stack size is limited at 10, but it's pretty useful
// to see more than that when a test fails.
Error.stackTraceLimit = 100;
try {
await environment.setup();
let result;
try {
if (collectV8Coverage) {
await runtime.collectV8Coverage();
}
result = await testFramework(globalConfig, projectConfig, environment, runtime, path, sendMessageToJest);
} catch (error) {
// Access all stacks before uninstalling sourcemaps
let e = error;
while (typeof e === 'object' && e !== null && 'stack' in e) {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
e.stack;
e = e?.cause;
}
throw error;
} finally {
if (collectV8Coverage) {
await runtime.stopCollectingV8Coverage();
}
}
freezeConsole(testConsole, projectConfig);
const testCount = result.numPassingTests + result.numFailingTests + result.numPendingTests + result.numTodoTests;
const end = Date.now();
const testRuntime = end - start;
result.perfStats = {
...result.perfStats,
end,
loadTestEnvironmentEnd,
loadTestEnvironmentStart,
runtime: testRuntime,
setupFilesEnd,
setupFilesStart,
slow: testRuntime / 1000 > projectConfig.slowTestThreshold,
start
};
result.testFilePath = path;
result.console = testConsole.getBuffer();
result.skipped = testCount === result.numPendingTests;
result.displayName = projectConfig.displayName;
const coverage = runtime.getAllCoverageInfoCopy();
if (coverage) {
const coverageKeys = Object.keys(coverage);
if (coverageKeys.length > 0) {
result.coverage = coverage;
}
}
if (collectV8Coverage) {
const v8Coverage = runtime.getAllV8CoverageInfoCopy();
if (v8Coverage && v8Coverage.length > 0) {
result.v8Coverage = v8Coverage;
}
}
if (globalConfig.logHeapUsage) {
globalThis.gc?.();
result.memoryUsage = process.memoryUsage().heapUsed;
}
await tearDownEnv();
// Delay the resolution to allow log messages to be output.
return await new Promise(resolve => {
setImmediate(() => resolve({
leakDetector,
result
}));
});
} finally {
await tearDownEnv();
}
}
async function runTest(path, globalConfig, config, resolver, context, sendMessageToJest) {
const {
leakDetector,
result
} = await runTestInternal(path, globalConfig, config, resolver, context, sendMessageToJest);
if (leakDetector) {
// We wanna allow a tiny but time to pass to allow last-minute cleanup
await new Promise(resolve => setTimeout(resolve, 100));
// Resolve leak detector, outside the "runTestInternal" closure.
result.leaks = await leakDetector.isLeaking();
} else {
result.leaks = false;
}
return result;
}
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
(() => {
var exports = __webpack_exports__;
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.setup = setup;
exports.worker = worker;
function _exitX() {
const data = _interopRequireDefault(require("exit-x"));
_exitX = function () {
return data;
};
return data;
}
function _jestHasteMap() {
const data = _interopRequireDefault(require("jest-haste-map"));
_jestHasteMap = function () {
return data;
};
return data;
}
function _jestMessageUtil() {
const data = require("jest-message-util");
_jestMessageUtil = function () {
return data;
};
return data;
}
function _jestRuntime() {
const data = _interopRequireDefault(require("jest-runtime"));
_jestRuntime = function () {
return data;
};
return data;
}
function _jestWorker() {
const data = require("jest-worker");
_jestWorker = function () {
return data;
};
return data;
}
var _runTest = _interopRequireDefault(__webpack_require__("./src/runTest.ts"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*
*/
// Make sure uncaught errors are logged before we exit.
process.on('uncaughtException', err => {
if (err.stack) {
console.error(err.stack);
} else {
console.error(err);
}
(0, _exitX().default)(1);
});
const formatError = error => {
if (typeof error === 'string') {
const {
message,
stack
} = (0, _jestMessageUtil().separateMessageFromStack)(error);
return {
message,
stack,
type: 'Error'
};
}
return {
code: error.code || undefined,
message: error.message,
stack: error.stack,
type: 'Error'
};
};
const resolvers = new Map();
const getResolver = config => {
const resolver = resolvers.get(config.id);
if (!resolver) {
throw new Error(`Cannot find resolver for: ${config.id}`);
}
return resolver;
};
function setup(setupData) {
// Module maps that will be needed for the test runs are passed.
for (const {
config,
serializableModuleMap
} of setupData.serializableResolvers) {
const moduleMap = _jestHasteMap().default.getStatic(config).getModuleMapFromJSON(serializableModuleMap);
resolvers.set(config.id, _jestRuntime().default.createResolver(config, moduleMap));
}
}
const sendMessageToJest = (eventName, args) => {
(0, _jestWorker().messageParent)([eventName, args]);
};
async function worker({
config,
globalConfig,
path,
context
}) {
try {
return await (0, _runTest.default)(path, globalConfig, config, getResolver(config), {
...context,
changedFiles: context.changedFiles && new Set(context.changedFiles),
sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles && new Set(context.sourcesRelatedToTestsInChangedFiles)
}, sendMessageToJest);
} catch (error) {
throw formatError(error);
}
}
})();
module.exports = __webpack_exports__;
/******/ })()
;

254
frontend/node_modules/jest-runner/build/testWorker.mjs generated vendored Normal file
View File

@@ -0,0 +1,254 @@
import { createRequire } from "node:module";
import exit from "exit-x";
import HasteMap from "jest-haste-map";
import { formatExecError, separateMessageFromStack } from "jest-message-util";
import Runtime from "jest-runtime";
import { messageParent } from "jest-worker";
import { runInContext } from "node:vm";
import chalk from "chalk";
import * as fs from "graceful-fs";
import * as sourcemapSupport from "source-map-support";
import { BufferedConsole, CustomConsole, NullConsole, getConsoleOutput } from "@jest/console";
import { createScriptTransformer } from "@jest/transform";
import * as docblock from "jest-docblock";
import LeakDetector from "jest-leak-detector";
import { resolveTestEnvironment } from "jest-resolve";
import { ErrorWithStack, interopRequireDefault, setGlobal } from "jest-util";
//#region rolldown:runtime
var __require = /* @__PURE__ */ createRequire(import.meta.url);
//#endregion
//#region src/runTest.ts
function freezeConsole(testConsole, config) {
testConsole._log = function fakeConsolePush(_type, message) {
const error = new ErrorWithStack(`${chalk.red(`${chalk.bold("Cannot log after tests are done.")} Did you forget to wait for something async in your test?`)}\nAttempted to log "${message}".`, fakeConsolePush);
const formattedError = formatExecError(error, config, { noStackTrace: false }, void 0, true);
process.stderr.write(`\n${formattedError}\n`);
process.exitCode = 1;
};
}
async function runTestInternal(path, globalConfig, projectConfig, resolver, context, sendMessageToJest$1) {
const testSource = fs.readFileSync(path, "utf8");
const docblockPragmas = docblock.parse(docblock.extract(testSource));
const customEnvironment = docblockPragmas["jest-environment"];
const loadTestEnvironmentStart = Date.now();
let testEnvironment = projectConfig.testEnvironment;
if (customEnvironment) {
if (Array.isArray(customEnvironment)) throw new TypeError(`You can only define a single test environment through docblocks, got "${customEnvironment.join(", ")}"`);
testEnvironment = resolveTestEnvironment({
...projectConfig,
requireResolveFunction: (module) => __require.resolve(module),
testEnvironment: customEnvironment
});
}
const cacheFS = new Map([[path, testSource]]);
const transformer = await createScriptTransformer(projectConfig, cacheFS);
const TestEnvironment = await transformer.requireAndTranspileModule(testEnvironment);
const testFramework = await transformer.requireAndTranspileModule(process.env.JEST_JASMINE === "1" ? __require.resolve("jest-jasmine2") : projectConfig.testRunner);
const Runtime$1 = interopRequireDefault(projectConfig.runtime ? __require(projectConfig.runtime) : __require("jest-runtime")).default;
const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
const consoleFormatter = (type, message) => getConsoleOutput(BufferedConsole.write([], type, message, 4), projectConfig, globalConfig);
let testConsole;
if (globalConfig.silent) testConsole = new NullConsole(consoleOut, consoleOut, consoleFormatter);
else if (globalConfig.verbose) testConsole = new CustomConsole(consoleOut, consoleOut, consoleFormatter);
else testConsole = new BufferedConsole();
let extraTestEnvironmentOptions;
const docblockEnvironmentOptions = docblockPragmas["jest-environment-options"];
if (typeof docblockEnvironmentOptions === "string") extraTestEnvironmentOptions = JSON.parse(docblockEnvironmentOptions);
const environment = new TestEnvironment({
globalConfig,
projectConfig: extraTestEnvironmentOptions ? {
...projectConfig,
testEnvironmentOptions: {
...projectConfig.testEnvironmentOptions,
...extraTestEnvironmentOptions
}
} : projectConfig
}, {
console: testConsole,
docblockPragmas,
testPath: path
});
const loadTestEnvironmentEnd = Date.now();
if (typeof environment.getVmContext !== "function") {
console.error(`Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`);
process.exit(1);
}
const leakDetector = projectConfig.detectLeaks ? new LeakDetector(environment) : null;
setGlobal(environment.global, "console", testConsole, "retain");
const runtime = new Runtime$1(projectConfig, environment, resolver, transformer, cacheFS, {
changedFiles: context.changedFiles,
collectCoverage: globalConfig.collectCoverage,
collectCoverageFrom: globalConfig.collectCoverageFrom,
coverageProvider: globalConfig.coverageProvider,
sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles
}, path, globalConfig);
let isTornDown = false;
const tearDownEnv = async () => {
if (!isTornDown) {
runtime.teardown();
runInContext("Error.prepareStackTrace = () => '';", environment.getVmContext());
sourcemapSupport.resetRetrieveHandlers();
await environment.teardown();
isTornDown = true;
}
};
const start = Date.now();
const setupFilesStart = Date.now();
for (const path$1 of projectConfig.setupFiles) {
const esm = runtime.unstable_shouldLoadAsEsm(path$1);
if (esm) await runtime.unstable_importModule(path$1);
else {
const setupFile = runtime.requireModule(path$1);
if (typeof setupFile === "function") await setupFile();
}
}
const setupFilesEnd = Date.now();
const sourcemapOptions = {
environment: "node",
handleUncaughtExceptions: false,
retrieveSourceMap: (source) => {
const sourceMapSource = runtime.getSourceMaps()?.get(source);
if (sourceMapSource) try {
return {
map: JSON.parse(fs.readFileSync(sourceMapSource, "utf8")),
url: source
};
} catch {}
return null;
}
};
runtime.requireInternalModule(__require.resolve("source-map-support")).install(sourcemapOptions);
sourcemapSupport.install(sourcemapOptions);
if (environment.global && environment.global.process && environment.global.process.exit) {
const realExit = environment.global.process.exit;
environment.global.process.exit = function exit$1(...args) {
const error = new ErrorWithStack(`process.exit called with "${args.join(", ")}"`, exit$1);
const formattedError = formatExecError(error, projectConfig, { noStackTrace: false }, void 0, true);
process.stderr.write(formattedError);
return realExit(...args);
};
}
const collectV8Coverage = globalConfig.collectCoverage && globalConfig.coverageProvider === "v8" && typeof environment.getVmContext === "function";
Error.stackTraceLimit = 100;
try {
await environment.setup();
let result;
try {
if (collectV8Coverage) await runtime.collectV8Coverage();
result = await testFramework(globalConfig, projectConfig, environment, runtime, path, sendMessageToJest$1);
} catch (error) {
let e = error;
while (typeof e === "object" && e !== null && "stack" in e) {
e.stack;
e = e?.cause;
}
throw error;
} finally {
if (collectV8Coverage) await runtime.stopCollectingV8Coverage();
}
freezeConsole(testConsole, projectConfig);
const testCount = result.numPassingTests + result.numFailingTests + result.numPendingTests + result.numTodoTests;
const end = Date.now();
const testRuntime = end - start;
result.perfStats = {
...result.perfStats,
end,
loadTestEnvironmentEnd,
loadTestEnvironmentStart,
runtime: testRuntime,
setupFilesEnd,
setupFilesStart,
slow: testRuntime / 1e3 > projectConfig.slowTestThreshold,
start
};
result.testFilePath = path;
result.console = testConsole.getBuffer();
result.skipped = testCount === result.numPendingTests;
result.displayName = projectConfig.displayName;
const coverage = runtime.getAllCoverageInfoCopy();
if (coverage) {
const coverageKeys = Object.keys(coverage);
if (coverageKeys.length > 0) result.coverage = coverage;
}
if (collectV8Coverage) {
const v8Coverage = runtime.getAllV8CoverageInfoCopy();
if (v8Coverage && v8Coverage.length > 0) result.v8Coverage = v8Coverage;
}
if (globalConfig.logHeapUsage) {
globalThis.gc?.();
result.memoryUsage = process.memoryUsage().heapUsed;
}
await tearDownEnv();
return await new Promise((resolve) => {
setImmediate(() => resolve({
leakDetector,
result
}));
});
} finally {
await tearDownEnv();
}
}
async function runTest(path, globalConfig, config, resolver, context, sendMessageToJest$1) {
const { leakDetector, result } = await runTestInternal(path, globalConfig, config, resolver, context, sendMessageToJest$1);
if (leakDetector) {
await new Promise((resolve) => setTimeout(resolve, 100));
result.leaks = await leakDetector.isLeaking();
} else result.leaks = false;
return result;
}
//#endregion
//#region src/testWorker.ts
process.on("uncaughtException", (err) => {
if (err.stack) console.error(err.stack);
else console.error(err);
exit(1);
});
const formatError = (error) => {
if (typeof error === "string") {
const { message, stack } = separateMessageFromStack(error);
return {
message,
stack,
type: "Error"
};
}
return {
code: error.code || void 0,
message: error.message,
stack: error.stack,
type: "Error"
};
};
const resolvers = /* @__PURE__ */ new Map();
const getResolver = (config) => {
const resolver = resolvers.get(config.id);
if (!resolver) throw new Error(`Cannot find resolver for: ${config.id}`);
return resolver;
};
function setup(setupData) {
for (const { config, serializableModuleMap } of setupData.serializableResolvers) {
const moduleMap = HasteMap.getStatic(config).getModuleMapFromJSON(serializableModuleMap);
resolvers.set(config.id, Runtime.createResolver(config, moduleMap));
}
}
const sendMessageToJest = (eventName, args) => {
messageParent([eventName, args]);
};
async function worker({ config, globalConfig, path, context }) {
try {
return await runTest(path, globalConfig, config, getResolver(config), {
...context,
changedFiles: context.changedFiles && new Set(context.changedFiles),
sourcesRelatedToTestsInChangedFiles: context.sourcesRelatedToTestsInChangedFiles && new Set(context.sourcesRelatedToTestsInChangedFiles)
}, sendMessageToJest);
} catch (error) {
throw formatError(error);
}
}
//#endregion
export { setup, worker };

58
frontend/node_modules/jest-runner/package.json generated vendored Normal file
View File

@@ -0,0 +1,58 @@
{
"name": "jest-runner",
"version": "30.0.4",
"repository": {
"type": "git",
"url": "https://github.com/jestjs/jest.git",
"directory": "packages/jest-runner"
},
"license": "MIT",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"exports": {
".": {
"types": "./build/index.d.ts",
"require": "./build/index.js",
"import": "./build/index.mjs",
"default": "./build/index.js"
},
"./package.json": "./package.json"
},
"dependencies": {
"@jest/console": "30.0.4",
"@jest/environment": "30.0.4",
"@jest/test-result": "30.0.4",
"@jest/transform": "30.0.4",
"@jest/types": "30.0.1",
"@types/node": "*",
"chalk": "^4.1.2",
"emittery": "^0.13.1",
"exit-x": "^0.2.2",
"graceful-fs": "^4.2.11",
"jest-docblock": "30.0.1",
"jest-environment-node": "30.0.4",
"jest-haste-map": "30.0.2",
"jest-leak-detector": "30.0.2",
"jest-message-util": "30.0.2",
"jest-resolve": "30.0.2",
"jest-runtime": "30.0.4",
"jest-util": "30.0.2",
"jest-watcher": "30.0.4",
"jest-worker": "30.0.2",
"p-limit": "^3.1.0",
"source-map-support": "0.5.13"
},
"devDependencies": {
"@jest/test-utils": "30.0.4",
"@types/graceful-fs": "^4.1.9",
"@types/source-map-support": "^0.5.10",
"jest-jasmine2": "30.0.4"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
},
"publishConfig": {
"access": "public"
},
"gitHead": "f4296d2bc85c1405f84ddf613a25d0bc3766b7e5"
}