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:
76
frontend/node_modules/jest-circus/build/index.d.ts
generated
vendored
Normal file
76
frontend/node_modules/jest-circus/build/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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 {Circus, Global as Global_2} from '@jest/types';
|
||||
|
||||
export declare const addEventHandler: (handler: Circus.EventHandler) => void;
|
||||
|
||||
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: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
|
||||
each: Global_2.EachTestFn<any>;
|
||||
only: {
|
||||
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
|
||||
each: Global_2.EachTestFn<any>;
|
||||
};
|
||||
skip: {
|
||||
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
|
||||
each: Global_2.EachTestFn<any>;
|
||||
};
|
||||
};
|
||||
it: Global_2.It;
|
||||
test: Global_2.It;
|
||||
};
|
||||
export default _default;
|
||||
|
||||
export declare const describe: {
|
||||
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
|
||||
each: Global_2.EachTestFn<any>;
|
||||
only: {
|
||||
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
|
||||
each: Global_2.EachTestFn<any>;
|
||||
};
|
||||
skip: {
|
||||
(blockName: Circus.BlockNameLike, blockFn: Circus.BlockFn): void;
|
||||
each: Global_2.EachTestFn<any>;
|
||||
};
|
||||
};
|
||||
|
||||
declare type Event_2 = Circus.Event;
|
||||
export {Event_2 as Event};
|
||||
|
||||
export declare const getState: () => Circus.State;
|
||||
|
||||
export declare const it: Global_2.It;
|
||||
|
||||
export declare const removeEventHandler: (handler: Circus.EventHandler) => void;
|
||||
|
||||
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_2.It;
|
||||
|
||||
declare type THook = (fn: Circus.HookFn, timeout?: number) => void;
|
||||
|
||||
export {};
|
||||
1672
frontend/node_modules/jest-circus/build/index.js
generated
vendored
Normal file
1672
frontend/node_modules/jest-circus/build/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
frontend/node_modules/jest-circus/build/index.mjs
generated
vendored
Normal file
16
frontend/node_modules/jest-circus/build/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const addEventHandler = cjsModule.addEventHandler;
|
||||
export const afterAll = cjsModule.afterAll;
|
||||
export const afterEach = cjsModule.afterEach;
|
||||
export const beforeAll = cjsModule.beforeAll;
|
||||
export const beforeEach = cjsModule.beforeEach;
|
||||
export const describe = cjsModule.describe;
|
||||
export const getState = cjsModule.getState;
|
||||
export const it = cjsModule.it;
|
||||
export const removeEventHandler = cjsModule.removeEventHandler;
|
||||
export const resetState = cjsModule.resetState;
|
||||
export const run = cjsModule.run;
|
||||
export const setState = cjsModule.setState;
|
||||
export const test = cjsModule.test;
|
||||
export default cjsModule.default;
|
||||
51
frontend/node_modules/jest-circus/build/jestAdapterInit.d.mts
generated
vendored
Normal file
51
frontend/node_modules/jest-circus/build/jestAdapterInit.d.mts
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import { JestExpect } from "@jest/expect";
|
||||
import { TestFileEvent, TestResult } from "@jest/test-result";
|
||||
import { SnapshotState } from "jest-snapshot";
|
||||
import * as Process from "process";
|
||||
import { JestEnvironment } from "@jest/environment";
|
||||
import { Circus, Config, Global } from "@jest/types";
|
||||
import Runtime from "jest-runtime";
|
||||
|
||||
//#region src/legacy-code-todo-rewrite/jestAdapterInit.d.ts
|
||||
|
||||
interface RuntimeGlobals extends Global.TestFrameworkGlobals {
|
||||
expect: JestExpect;
|
||||
}
|
||||
declare const initialize: ({
|
||||
config,
|
||||
environment,
|
||||
runtime,
|
||||
globalConfig,
|
||||
localRequire,
|
||||
parentProcess,
|
||||
sendMessageToJest,
|
||||
setGlobalsForRuntime,
|
||||
testPath
|
||||
}: {
|
||||
config: Config.ProjectConfig;
|
||||
environment: JestEnvironment;
|
||||
runtime: Runtime;
|
||||
globalConfig: Config.GlobalConfig;
|
||||
localRequire: <T = unknown>(path: string) => T;
|
||||
testPath: string;
|
||||
parentProcess: typeof Process;
|
||||
sendMessageToJest?: TestFileEvent;
|
||||
setGlobalsForRuntime: (globals: RuntimeGlobals) => void;
|
||||
}) => Promise<{
|
||||
globals: Global.TestFrameworkGlobals;
|
||||
snapshotState: SnapshotState;
|
||||
}>;
|
||||
declare const runAndTransformResultsToJestFormat: ({
|
||||
config,
|
||||
globalConfig,
|
||||
setupAfterEnvPerfStats,
|
||||
testPath
|
||||
}: {
|
||||
config: Config.ProjectConfig;
|
||||
globalConfig: Config.GlobalConfig;
|
||||
testPath: string;
|
||||
setupAfterEnvPerfStats: Config.SetupAfterEnvPerfStats;
|
||||
}) => Promise<TestResult>;
|
||||
declare const eventHandler: (event: Circus.Event) => Promise<void>;
|
||||
//#endregion
|
||||
export { eventHandler, initialize, runAndTransformResultsToJestFormat };
|
||||
2051
frontend/node_modules/jest-circus/build/jestAdapterInit.js
generated
vendored
Normal file
2051
frontend/node_modules/jest-circus/build/jestAdapterInit.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1249
frontend/node_modules/jest-circus/build/jestAdapterInit.mjs
generated
vendored
Normal file
1249
frontend/node_modules/jest-circus/build/jestAdapterInit.mjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10
frontend/node_modules/jest-circus/build/runner.d.mts
generated
vendored
Normal file
10
frontend/node_modules/jest-circus/build/runner.d.mts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import { JestEnvironment } from "@jest/environment";
|
||||
import { TestFileEvent, TestResult } from "@jest/test-result";
|
||||
import { Config } from "@jest/types";
|
||||
import Runtime from "jest-runtime";
|
||||
|
||||
//#region src/legacy-code-todo-rewrite/jestAdapter.d.ts
|
||||
|
||||
declare const jestAdapter: (globalConfig: Config.GlobalConfig, config: Config.ProjectConfig, environment: JestEnvironment, runtime: Runtime, testPath: string, sendMessageToJest?: TestFileEvent) => Promise<TestResult>;
|
||||
//#endregion
|
||||
export { jestAdapter as default };
|
||||
200
frontend/node_modules/jest-circus/build/runner.js
generated
vendored
Normal file
200
frontend/node_modules/jest-circus/build/runner.js
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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/legacy-code-todo-rewrite/jestAdapter.ts":
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = void 0;
|
||||
var _jestUtil = require("jest-util");
|
||||
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 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,
|
||||
runtime,
|
||||
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();
|
||||
}
|
||||
});
|
||||
const setupAfterEnvStart = jestNow();
|
||||
for (const path of config.setupFilesAfterEnv) {
|
||||
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 setupAfterEnvEnd = jestNow();
|
||||
const esm = runtime.unstable_shouldLoadAsEsm(testPath);
|
||||
if (esm) {
|
||||
await runtime.unstable_importModule(testPath);
|
||||
} else {
|
||||
runtime.requireModule(testPath);
|
||||
}
|
||||
const setupAfterEnvPerfStats = {
|
||||
setupAfterEnvEnd,
|
||||
setupAfterEnvStart
|
||||
};
|
||||
const results = await runAndTransformResultsToJestFormat({
|
||||
config,
|
||||
globalConfig,
|
||||
setupAfterEnvPerfStats,
|
||||
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) => {
|
||||
for (const {
|
||||
fullName,
|
||||
status,
|
||||
failing
|
||||
} of results.testResults) {
|
||||
if (status === 'pending' || status === 'failed' || failing && status === 'passed') {
|
||||
// If test is skipped or failed, we don't want to mark
|
||||
// its snapshots as obsolete.
|
||||
// When tests called with test.failing pass, they've thrown an exception,
|
||||
// so maintain any snapshots after the error.
|
||||
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 ? 0 : uncheckedCount;
|
||||
// Copy the array to prevent memory leaks
|
||||
results.snapshot.uncheckedKeys = [...uncheckedKeys];
|
||||
};
|
||||
var _default = exports["default"] = jestAdapter;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // 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["default"] = void 0;
|
||||
var _jestAdapter = _interopRequireDefault(__webpack_require__("./src/legacy-code-todo-rewrite/jestAdapter.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.
|
||||
*/
|
||||
// Allow people to use `jest-circus/runner` as a runner.
|
||||
var _default = exports["default"] = _jestAdapter.default;
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
81
frontend/node_modules/jest-circus/build/runner.mjs
generated
vendored
Normal file
81
frontend/node_modules/jest-circus/build/runner.mjs
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { deepCyclicCopy } from "jest-util";
|
||||
|
||||
//#region rolldown:runtime
|
||||
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
||||
|
||||
//#endregion
|
||||
//#region src/legacy-code-todo-rewrite/jestAdapter.ts
|
||||
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,
|
||||
runtime,
|
||||
sendMessageToJest,
|
||||
setGlobalsForRuntime: runtime.setGlobalsForRuntime.bind(runtime),
|
||||
testPath
|
||||
});
|
||||
if (config.fakeTimers.enableGlobally) if (config.fakeTimers.legacyFakeTimers) 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) environment.fakeTimers.useFakeTimers();
|
||||
}
|
||||
if (config.restoreMocks) runtime.restoreAllMocks();
|
||||
});
|
||||
const setupAfterEnvStart = Date.now();
|
||||
for (const path of config.setupFilesAfterEnv) {
|
||||
const esm$1 = runtime.unstable_shouldLoadAsEsm(path);
|
||||
if (esm$1) await runtime.unstable_importModule(path);
|
||||
else {
|
||||
const setupFile = runtime.requireModule(path);
|
||||
if (typeof setupFile === "function") await setupFile();
|
||||
}
|
||||
}
|
||||
const setupAfterEnvEnd = Date.now();
|
||||
const esm = runtime.unstable_shouldLoadAsEsm(testPath);
|
||||
if (esm) await runtime.unstable_importModule(testPath);
|
||||
else runtime.requireModule(testPath);
|
||||
const setupAfterEnvPerfStats = {
|
||||
setupAfterEnvEnd,
|
||||
setupAfterEnvStart
|
||||
};
|
||||
const results = await runAndTransformResultsToJestFormat({
|
||||
config,
|
||||
globalConfig,
|
||||
setupAfterEnvPerfStats,
|
||||
testPath
|
||||
});
|
||||
_addSnapshotData(results, snapshotState);
|
||||
return deepCyclicCopy(results, { keepPrototype: false });
|
||||
};
|
||||
const _addSnapshotData = (results, snapshotState) => {
|
||||
for (const { fullName, status: status$1, failing } of results.testResults) if (status$1 === "pending" || status$1 === "failed" || failing && status$1 === "passed") 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 ? 0 : uncheckedCount;
|
||||
results.snapshot.uncheckedKeys = [...uncheckedKeys];
|
||||
};
|
||||
var jestAdapter_default = jestAdapter;
|
||||
|
||||
//#endregion
|
||||
//#region src/runner.ts
|
||||
var runner_default = jestAdapter_default;
|
||||
|
||||
//#endregion
|
||||
export { runner_default as default };
|
||||
Reference in New Issue
Block a user