- 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>
194 lines
5.8 KiB
JavaScript
194 lines
5.8 KiB
JavaScript
/*!
|
|
* /**
|
|
* * 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_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;
|
|
function _fakeTimers() {
|
|
const data = require("@jest/fake-timers");
|
|
_fakeTimers = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _jestMock() {
|
|
const data = require("jest-mock");
|
|
_jestMock = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _jestUtil() {
|
|
const data = require("jest-util");
|
|
_jestUtil = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
/**
|
|
* 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.
|
|
*/
|
|
|
|
// The `Window` interface does not have an `Error.stackTraceLimit` property, but
|
|
// `JSDOMEnvironment` assumes it is there.
|
|
|
|
function isString(value) {
|
|
return typeof value === 'string';
|
|
}
|
|
class BaseJSDOMEnvironment {
|
|
dom;
|
|
fakeTimers;
|
|
fakeTimersModern;
|
|
global;
|
|
errorEventListener;
|
|
moduleMocker;
|
|
customExportConditions = ['browser'];
|
|
_configuredExportConditions;
|
|
constructor(config, context, jsdomModule) {
|
|
const {
|
|
projectConfig
|
|
} = config;
|
|
const {
|
|
JSDOM,
|
|
ResourceLoader,
|
|
VirtualConsole
|
|
} = jsdomModule;
|
|
const virtualConsole = new VirtualConsole();
|
|
virtualConsole.sendTo(context.console, {
|
|
omitJSDOMErrors: true
|
|
});
|
|
virtualConsole.on('jsdomError', error => {
|
|
context.console.error(error);
|
|
});
|
|
this.dom = new JSDOM(typeof projectConfig.testEnvironmentOptions.html === 'string' ? projectConfig.testEnvironmentOptions.html : '<!DOCTYPE html>', {
|
|
pretendToBeVisual: true,
|
|
resources: typeof projectConfig.testEnvironmentOptions.userAgent === 'string' ? new ResourceLoader({
|
|
userAgent: projectConfig.testEnvironmentOptions.userAgent
|
|
}) : undefined,
|
|
runScripts: 'dangerously',
|
|
url: 'http://localhost/',
|
|
virtualConsole,
|
|
...projectConfig.testEnvironmentOptions
|
|
});
|
|
const global = this.global = this.dom.window;
|
|
if (global == null) {
|
|
throw new Error('JSDOM did not return a Window object');
|
|
}
|
|
|
|
// TODO: remove at some point - for "universal" code (code should use `globalThis`)
|
|
global.global = global;
|
|
|
|
// Node's error-message stack size is limited at 10, but it's pretty useful
|
|
// to see more than that when a test fails.
|
|
this.global.Error.stackTraceLimit = 100;
|
|
(0, _jestUtil().installCommonGlobals)(global, projectConfig.globals);
|
|
|
|
// TODO: remove this ASAP, but it currently causes tests to run really slow
|
|
global.Buffer = Buffer;
|
|
|
|
// Report uncaught errors.
|
|
this.errorEventListener = event => {
|
|
if (userErrorListenerCount === 0 && event.error != null) {
|
|
process.emit('uncaughtException', event.error);
|
|
}
|
|
};
|
|
global.addEventListener('error', this.errorEventListener);
|
|
|
|
// However, don't report them as uncaught if the user listens to 'error' event.
|
|
// In that case, we assume the might have custom error handling logic.
|
|
const originalAddListener = global.addEventListener.bind(global);
|
|
const originalRemoveListener = global.removeEventListener.bind(global);
|
|
let userErrorListenerCount = 0;
|
|
global.addEventListener = function (...args) {
|
|
if (args[0] === 'error') {
|
|
userErrorListenerCount++;
|
|
}
|
|
return originalAddListener.apply(this, args);
|
|
};
|
|
global.removeEventListener = function (...args) {
|
|
if (args[0] === 'error') {
|
|
userErrorListenerCount--;
|
|
}
|
|
return originalRemoveListener.apply(this, args);
|
|
};
|
|
if ('customExportConditions' in projectConfig.testEnvironmentOptions) {
|
|
const {
|
|
customExportConditions
|
|
} = projectConfig.testEnvironmentOptions;
|
|
if (Array.isArray(customExportConditions) && customExportConditions.every(isString)) {
|
|
this._configuredExportConditions = customExportConditions;
|
|
} else {
|
|
throw new Error('Custom export conditions specified but they are not an array of strings');
|
|
}
|
|
}
|
|
this.moduleMocker = new (_jestMock().ModuleMocker)(global);
|
|
this.fakeTimers = new (_fakeTimers().LegacyFakeTimers)({
|
|
config: projectConfig,
|
|
global: global,
|
|
moduleMocker: this.moduleMocker,
|
|
timerConfig: {
|
|
idToRef: id => id,
|
|
refToId: ref => ref
|
|
}
|
|
});
|
|
this.fakeTimersModern = new (_fakeTimers().ModernFakeTimers)({
|
|
config: projectConfig,
|
|
global: global
|
|
});
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
async setup() {}
|
|
async teardown() {
|
|
if (this.fakeTimers) {
|
|
this.fakeTimers.dispose();
|
|
}
|
|
if (this.fakeTimersModern) {
|
|
this.fakeTimersModern.dispose();
|
|
}
|
|
if (this.global != null) {
|
|
if (this.errorEventListener) {
|
|
this.global.removeEventListener('error', this.errorEventListener);
|
|
}
|
|
this.global.close();
|
|
}
|
|
this.errorEventListener = null;
|
|
// @ts-expect-error: this.global not allowed to be `null`
|
|
this.global = null;
|
|
this.dom = null;
|
|
this.fakeTimers = null;
|
|
this.fakeTimersModern = null;
|
|
}
|
|
exportConditions() {
|
|
return this._configuredExportConditions ?? this.customExportConditions;
|
|
}
|
|
getVmContext() {
|
|
if (this.dom) {
|
|
return this.dom.getInternalVMContext();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
exports["default"] = BaseJSDOMEnvironment;
|
|
})();
|
|
|
|
module.exports = __webpack_exports__;
|
|
/******/ })()
|
|
; |