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:
8
frontend/node_modules/ts-jest/dist/legacy/compiler/compiler-utils.d.ts
generated
vendored
Normal file
8
frontend/node_modules/ts-jest/dist/legacy/compiler/compiler-utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Rely on TypeScript compiled output generation which contains this prefix to point to sourcemap location.
|
||||
*/
|
||||
export declare const SOURCE_MAPPING_PREFIX = "sourceMappingURL=";
|
||||
/**
|
||||
* Update the output remapping the source map.
|
||||
*/
|
||||
export declare function updateOutput(outputText: string, normalizedFileName: string, sourceMap?: string): string;
|
||||
32
frontend/node_modules/ts-jest/dist/legacy/compiler/compiler-utils.js
generated
vendored
Normal file
32
frontend/node_modules/ts-jest/dist/legacy/compiler/compiler-utils.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SOURCE_MAPPING_PREFIX = void 0;
|
||||
exports.updateOutput = updateOutput;
|
||||
const utils_1 = require("../../utils");
|
||||
/**
|
||||
* Rely on TypeScript compiled output generation which contains this prefix to point to sourcemap location.
|
||||
*/
|
||||
exports.SOURCE_MAPPING_PREFIX = 'sourceMappingURL=';
|
||||
/**
|
||||
* Update the output remapping the source map.
|
||||
*/
|
||||
function updateOutput(outputText, normalizedFileName, sourceMap) {
|
||||
if (sourceMap) {
|
||||
const base64Map = Buffer.from(updateSourceMap(sourceMap, normalizedFileName), 'utf8').toString('base64');
|
||||
const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}`;
|
||||
// sourceMappingURL= prefix is always at the end of compiledOutput, using lastIndexOf should be the safest way to substring
|
||||
return (outputText.slice(0, outputText.lastIndexOf(exports.SOURCE_MAPPING_PREFIX) + exports.SOURCE_MAPPING_PREFIX.length) +
|
||||
sourceMapContent);
|
||||
}
|
||||
return outputText;
|
||||
}
|
||||
/**
|
||||
* Update the source map contents for improved output.
|
||||
*/
|
||||
const updateSourceMap = (sourceMapText, normalizedFileName) => {
|
||||
const sourceMap = JSON.parse(sourceMapText);
|
||||
sourceMap.file = normalizedFileName;
|
||||
sourceMap.sources = [normalizedFileName];
|
||||
delete sourceMap.sourceRoot;
|
||||
return (0, utils_1.stringify)(sourceMap);
|
||||
};
|
||||
2
frontend/node_modules/ts-jest/dist/legacy/compiler/index.d.ts
generated
vendored
Normal file
2
frontend/node_modules/ts-jest/dist/legacy/compiler/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './ts-compiler';
|
||||
export * from './ts-jest-compiler';
|
||||
18
frontend/node_modules/ts-jest/dist/legacy/compiler/index.js
generated
vendored
Normal file
18
frontend/node_modules/ts-jest/dist/legacy/compiler/index.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./ts-compiler"), exports);
|
||||
__exportStar(require("./ts-jest-compiler"), exports);
|
||||
27
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-compiler.d.ts
generated
vendored
Normal file
27
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-compiler.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Logger } from 'bs-logger';
|
||||
import { CompilerOptions, CustomTransformers, Program, TranspileOutput } from 'typescript';
|
||||
import type { StringMap, TsCompilerInstance, TsJestAstTransformer, TsJestCompileOptions, TTypeScript, CompiledOutput } from '../../types';
|
||||
import type { ConfigSet } from '../config/config-set';
|
||||
export declare class TsCompiler implements TsCompilerInstance {
|
||||
readonly configSet: ConfigSet;
|
||||
readonly runtimeCacheFS: StringMap;
|
||||
protected readonly _logger: Logger;
|
||||
protected readonly _ts: TTypeScript;
|
||||
protected readonly _initialCompilerOptions: CompilerOptions;
|
||||
protected _compilerOptions: CompilerOptions;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private _runtimeCacheFS;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private _fileContentCache;
|
||||
program: Program | undefined;
|
||||
constructor(configSet: ConfigSet, runtimeCacheFS: StringMap);
|
||||
getResolvedModules(fileContent: string, fileName: string, runtimeCacheFS: StringMap): string[];
|
||||
private fixupCompilerOptionsForModuleKind;
|
||||
getCompiledOutput(fileContent: string, fileName: string, options: TsJestCompileOptions): CompiledOutput;
|
||||
protected _transpileOutput(fileContent: string, fileName: string): TranspileOutput;
|
||||
protected _makeTransformers(customTransformers: TsJestAstTransformer): CustomTransformers;
|
||||
}
|
||||
425
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-compiler.js
generated
vendored
Normal file
425
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-compiler.js
generated
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TsCompiler = void 0;
|
||||
const path_1 = require("path");
|
||||
const bs_logger_1 = require("bs-logger");
|
||||
const lodash_memoize_1 = __importDefault(require("lodash.memoize"));
|
||||
const typescript_1 = __importDefault(require("typescript"));
|
||||
const constants_1 = require("../../constants");
|
||||
const transpile_module_1 = require("../../transpilers/typescript/transpile-module");
|
||||
const utils_1 = require("../../utils");
|
||||
const messages_1 = require("../../utils/messages");
|
||||
const compiler_utils_1 = require("./compiler-utils");
|
||||
const assertCompilerOptionsWithJestTransformMode = (compilerOptions, isEsmMode, logger) => {
|
||||
if (isEsmMode && compilerOptions.module === typescript_1.default.ModuleKind.CommonJS) {
|
||||
logger.error("The current compiler option \"module\" value is not suitable for Jest ESM mode. Please either use ES module kinds or Node16/NodeNext module kinds with \"type: module\" in package.json" /* Errors.InvalidModuleKindForEsm */);
|
||||
}
|
||||
};
|
||||
class TsCompiler {
|
||||
configSet;
|
||||
runtimeCacheFS;
|
||||
_logger;
|
||||
_ts;
|
||||
_initialCompilerOptions;
|
||||
_compilerOptions;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_runtimeCacheFS;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_fileContentCache;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_parsedTsConfig;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_fileVersionCache;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_cachedReadFile;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_projectVersion = 1;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_languageService;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_moduleResolutionHost;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_moduleResolutionCache;
|
||||
program;
|
||||
constructor(configSet, runtimeCacheFS) {
|
||||
this.configSet = configSet;
|
||||
this.runtimeCacheFS = runtimeCacheFS;
|
||||
this._ts = configSet.compilerModule;
|
||||
this._logger = utils_1.rootLogger.child({ namespace: 'ts-compiler' });
|
||||
this._parsedTsConfig = this.configSet.parsedTsConfig;
|
||||
this._initialCompilerOptions = { ...this._parsedTsConfig.options };
|
||||
this._compilerOptions = { ...this._initialCompilerOptions };
|
||||
this._runtimeCacheFS = runtimeCacheFS;
|
||||
if (!this.configSet.isolatedModules) {
|
||||
this._fileContentCache = new Map();
|
||||
this._fileVersionCache = new Map();
|
||||
this._cachedReadFile = this._logger.wrap({
|
||||
namespace: 'ts:serviceHost',
|
||||
call: null,
|
||||
[bs_logger_1.LogContexts.logLevel]: bs_logger_1.LogLevels.trace,
|
||||
}, 'readFile', (0, lodash_memoize_1.default)(this._ts.sys.readFile));
|
||||
/* istanbul ignore next */
|
||||
this._moduleResolutionHost = {
|
||||
fileExists: (0, lodash_memoize_1.default)(this._ts.sys.fileExists),
|
||||
readFile: this._cachedReadFile,
|
||||
directoryExists: (0, lodash_memoize_1.default)(this._ts.sys.directoryExists),
|
||||
getCurrentDirectory: () => this.configSet.cwd,
|
||||
realpath: this._ts.sys.realpath && (0, lodash_memoize_1.default)(this._ts.sys.realpath),
|
||||
getDirectories: (0, lodash_memoize_1.default)(this._ts.sys.getDirectories),
|
||||
useCaseSensitiveFileNames: () => this._ts.sys.useCaseSensitiveFileNames,
|
||||
};
|
||||
this._moduleResolutionCache = this._ts.createModuleResolutionCache(this.configSet.cwd, this._ts.sys.useCaseSensitiveFileNames ? (x) => x : (x) => x.toLowerCase(), this._compilerOptions);
|
||||
this._createLanguageService();
|
||||
}
|
||||
}
|
||||
getResolvedModules(fileContent, fileName, runtimeCacheFS) {
|
||||
// In watch mode, it is possible that the initial cacheFS becomes empty
|
||||
if (!this.runtimeCacheFS.size) {
|
||||
this._runtimeCacheFS = runtimeCacheFS;
|
||||
}
|
||||
this._logger.debug({ fileName }, 'getResolvedModules(): resolve direct imported module paths');
|
||||
const importedModulePaths = Array.from(new Set(this._getImportedModulePaths(fileContent, fileName)));
|
||||
this._logger.debug({ fileName }, 'getResolvedModules(): resolve nested imported module paths from directed imported module paths');
|
||||
importedModulePaths.forEach((importedModulePath) => {
|
||||
const resolvedFileContent = this._getFileContentFromCache(importedModulePath);
|
||||
importedModulePaths.push(...this._getImportedModulePaths(resolvedFileContent, importedModulePath).filter((modulePath) => !importedModulePaths.includes(modulePath)));
|
||||
});
|
||||
return importedModulePaths;
|
||||
}
|
||||
fixupCompilerOptionsForModuleKind(compilerOptions, isEsm) {
|
||||
const moduleResolution = this._ts.ModuleResolutionKind.Node10 ?? this._ts.ModuleResolutionKind.NodeJs;
|
||||
if (!isEsm) {
|
||||
return {
|
||||
...compilerOptions,
|
||||
module: this._ts.ModuleKind.CommonJS,
|
||||
moduleResolution,
|
||||
/**
|
||||
* This option is only supported in `Node16`/`NodeNext` and `Bundler` module, see https://www.typescriptlang.org/tsconfig/#customConditions
|
||||
*/
|
||||
customConditions: undefined,
|
||||
};
|
||||
}
|
||||
let moduleKind = compilerOptions.module ?? this._ts.ModuleKind.ESNext;
|
||||
let esModuleInterop = compilerOptions.esModuleInterop;
|
||||
if ((0, transpile_module_1.isModernNodeModuleKind)(moduleKind)) {
|
||||
esModuleInterop = true;
|
||||
moduleKind = this._ts.ModuleKind.ESNext;
|
||||
}
|
||||
return {
|
||||
...compilerOptions,
|
||||
module: moduleKind,
|
||||
esModuleInterop,
|
||||
moduleResolution,
|
||||
/**
|
||||
* This option is only supported in `Node16`/`NodeNext` and `Bundler` module, see https://www.typescriptlang.org/tsconfig/#customConditions
|
||||
*/
|
||||
customConditions: undefined,
|
||||
};
|
||||
}
|
||||
getCompiledOutput(fileContent, fileName, options) {
|
||||
const isEsmMode = this.configSet.useESM && options.supportsStaticESM;
|
||||
this._compilerOptions = this.fixupCompilerOptionsForModuleKind(this._initialCompilerOptions, isEsmMode);
|
||||
if (!this._initialCompilerOptions.isolatedModules && (0, transpile_module_1.isModernNodeModuleKind)(this._initialCompilerOptions.module)) {
|
||||
this._logger.warn("Using hybrid module kind (Node16/18/Next) is only supported in \"isolatedModules: true\". Please set \"isolatedModules: true\" in your tsconfig.json." /* Helps.UsingModernNodeResolution */);
|
||||
}
|
||||
const moduleKind = this._initialCompilerOptions.module;
|
||||
const currentModuleKind = this._compilerOptions.module;
|
||||
if (this._languageService) {
|
||||
if (constants_1.JS_JSX_REGEX.test(fileName) && !this._compilerOptions.allowJs) {
|
||||
this._logger.warn({ fileName: fileName }, (0, messages_1.interpolate)("Got a `.js` file to compile while `allowJs` option is not set to `true` (file: {{path}}). To fix this:\n - if you want TypeScript to process JS files, set `allowJs` to `true` in your TypeScript config (usually tsconfig.json)\n - if you do not want TypeScript to process your `.js` files, in your Jest config change the `transform` key which value is `ts-jest` so that it does not match `.js` files anymore" /* Errors.GotJsFileButAllowJsFalse */, { path: fileName }));
|
||||
return {
|
||||
code: fileContent,
|
||||
};
|
||||
}
|
||||
this._logger.debug({ fileName }, 'getCompiledOutput(): compiling using language service');
|
||||
// Must set memory cache before attempting to compile
|
||||
this._updateMemoryCache(fileContent, fileName, currentModuleKind === moduleKind);
|
||||
const output = this._languageService.getEmitOutput(fileName);
|
||||
const diagnostics = this.getDiagnostics(fileName);
|
||||
if (!isEsmMode && diagnostics.length) {
|
||||
this.configSet.raiseDiagnostics(diagnostics, fileName, this._logger);
|
||||
if (options.watchMode) {
|
||||
this._logger.debug({ fileName }, '_doTypeChecking(): starting watch mode computing diagnostics');
|
||||
for (const entry of options.depGraphs.entries()) {
|
||||
const normalizedModuleNames = entry[1].resolvedModuleNames.map((moduleName) => (0, path_1.normalize)(moduleName));
|
||||
const fileToReTypeCheck = entry[0];
|
||||
if (normalizedModuleNames.includes(fileName) && this.configSet.shouldReportDiagnostics(fileToReTypeCheck)) {
|
||||
this._logger.debug({ fileToReTypeCheck }, '_doTypeChecking(): computing diagnostics using language service');
|
||||
this._updateMemoryCache(this._getFileContentFromCache(fileToReTypeCheck), fileToReTypeCheck);
|
||||
const importedModulesDiagnostics = [
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...this._languageService.getSemanticDiagnostics(fileToReTypeCheck),
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...this._languageService.getSyntacticDiagnostics(fileToReTypeCheck),
|
||||
];
|
||||
// will raise or just warn diagnostics depending on config
|
||||
this.configSet.raiseDiagnostics(importedModulesDiagnostics, fileName, this._logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (output.emitSkipped) {
|
||||
if (constants_1.TS_TSX_REGEX.test(fileName)) {
|
||||
throw new Error((0, messages_1.interpolate)("Unable to process '{{file}}', please make sure that `outDir` in your tsconfig is neither `''` or `'.'`. You can also configure Jest config option `transformIgnorePatterns` to inform `ts-jest` to transform {{file}}" /* Errors.CannotProcessFile */, { file: fileName }));
|
||||
}
|
||||
else {
|
||||
this._logger.warn((0, messages_1.interpolate)("Unable to process '{{file}}', falling back to original file content. You can also configure Jest config option `transformIgnorePatterns` to ignore {{file}} from transformation or make sure that `outDir` in your tsconfig is neither `''` or `'.'`" /* Errors.CannotProcessFileReturnOriginal */, { file: fileName }));
|
||||
return {
|
||||
code: fileContent,
|
||||
};
|
||||
}
|
||||
}
|
||||
// Throw an error when requiring `.d.ts` files.
|
||||
if (!output.outputFiles.length) {
|
||||
throw new TypeError((0, messages_1.interpolate)("Unable to require `.d.ts` file for file: {{file}}.\nThis is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or another executable extension available alongside `{{file}}`." /* Errors.UnableToRequireDefinitionFile */, {
|
||||
file: (0, path_1.basename)(fileName),
|
||||
}));
|
||||
}
|
||||
const { outputFiles } = output;
|
||||
return this._compilerOptions.sourceMap
|
||||
? {
|
||||
code: (0, compiler_utils_1.updateOutput)(outputFiles[1].text, fileName, outputFiles[0].text),
|
||||
diagnostics,
|
||||
}
|
||||
: {
|
||||
code: (0, compiler_utils_1.updateOutput)(outputFiles[0].text, fileName),
|
||||
diagnostics,
|
||||
};
|
||||
}
|
||||
else {
|
||||
this._logger.debug({ fileName }, 'getCompiledOutput(): compiling as isolated module');
|
||||
assertCompilerOptionsWithJestTransformMode(this._initialCompilerOptions, isEsmMode, this._logger);
|
||||
const result = this._transpileOutput(fileContent, fileName);
|
||||
if (result.diagnostics && this.configSet.shouldReportDiagnostics(fileName)) {
|
||||
this.configSet.raiseDiagnostics(result.diagnostics, fileName, this._logger);
|
||||
}
|
||||
return {
|
||||
code: (0, compiler_utils_1.updateOutput)(result.outputText, fileName, result.sourceMapText),
|
||||
};
|
||||
}
|
||||
}
|
||||
_transpileOutput(fileContent, fileName) {
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* This code path should be removed in the next major version to benefit from checking on compiler options
|
||||
*/
|
||||
if (!(0, transpile_module_1.isModernNodeModuleKind)(this._initialCompilerOptions.module)) {
|
||||
return this._ts.transpileModule(fileContent, {
|
||||
fileName,
|
||||
transformers: this._makeTransformers(this.configSet.resolvedTransformers),
|
||||
compilerOptions: this._compilerOptions,
|
||||
reportDiagnostics: this.configSet.shouldReportDiagnostics(fileName),
|
||||
});
|
||||
}
|
||||
return (0, transpile_module_1.tsTranspileModule)(fileContent, {
|
||||
fileName,
|
||||
transformers: (program) => {
|
||||
this.program = program;
|
||||
return this._makeTransformers(this.configSet.resolvedTransformers);
|
||||
},
|
||||
compilerOptions: this._initialCompilerOptions,
|
||||
reportDiagnostics: fileName ? this.configSet.shouldReportDiagnostics(fileName) : false,
|
||||
});
|
||||
}
|
||||
_makeTransformers(customTransformers) {
|
||||
return {
|
||||
before: customTransformers.before.map((beforeTransformer) => beforeTransformer.factory(this, beforeTransformer.options)),
|
||||
after: customTransformers.after.map((afterTransformer) => afterTransformer.factory(this, afterTransformer.options)),
|
||||
afterDeclarations: customTransformers.afterDeclarations.map((afterDeclarations) => afterDeclarations.factory(this, afterDeclarations.options)),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_createLanguageService() {
|
||||
// Initialize memory cache for typescript compiler
|
||||
this._parsedTsConfig.fileNames
|
||||
.filter((fileName) => constants_1.TS_TSX_REGEX.test(fileName) && !this.configSet.isTestFile(fileName))
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
.forEach((fileName) => this._fileVersionCache.set(fileName, 0));
|
||||
/* istanbul ignore next */
|
||||
const serviceHost = {
|
||||
useCaseSensitiveFileNames: () => this._ts.sys.useCaseSensitiveFileNames,
|
||||
getProjectVersion: () => String(this._projectVersion),
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
getScriptFileNames: () => [...this._fileVersionCache.keys()],
|
||||
getScriptVersion: (fileName) => {
|
||||
const normalizedFileName = (0, path_1.normalize)(fileName);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const version = this._fileVersionCache.get(normalizedFileName);
|
||||
// We need to return `undefined` and not a string here because TypeScript will use
|
||||
// `getScriptVersion` and compare against their own version - which can be `undefined`.
|
||||
// If we don't return `undefined` it results in `undefined === "undefined"` and run
|
||||
// `createProgram` again (which is very slow). Using a `string` assertion here to avoid
|
||||
// TypeScript errors from the function signature (expects `(x: string) => string`).
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return version === undefined ? undefined : String(version);
|
||||
},
|
||||
getScriptSnapshot: (fileName) => {
|
||||
const normalizedFileName = (0, path_1.normalize)(fileName);
|
||||
const hit = this._isFileInCache(normalizedFileName);
|
||||
this._logger.trace({ normalizedFileName, cacheHit: hit }, 'getScriptSnapshot():', 'cache', hit ? 'hit' : 'miss');
|
||||
// Read file content from either memory cache or Jest runtime cache or fallback to file system read
|
||||
if (!hit) {
|
||||
const fileContent =
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileContentCache.get(normalizedFileName) ??
|
||||
this._runtimeCacheFS.get(normalizedFileName) ??
|
||||
this._cachedReadFile?.(normalizedFileName) ??
|
||||
undefined;
|
||||
if (fileContent !== undefined) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileContentCache.set(normalizedFileName, fileContent);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileVersionCache.set(normalizedFileName, 1);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const contents = this._fileContentCache.get(normalizedFileName);
|
||||
if (contents === undefined)
|
||||
return;
|
||||
return this._ts.ScriptSnapshot.fromString(contents);
|
||||
},
|
||||
fileExists: (0, lodash_memoize_1.default)(this._ts.sys.fileExists),
|
||||
readFile: this._cachedReadFile ?? this._ts.sys.readFile,
|
||||
readDirectory: (0, lodash_memoize_1.default)(this._ts.sys.readDirectory),
|
||||
getDirectories: (0, lodash_memoize_1.default)(this._ts.sys.getDirectories),
|
||||
directoryExists: (0, lodash_memoize_1.default)(this._ts.sys.directoryExists),
|
||||
realpath: this._ts.sys.realpath && (0, lodash_memoize_1.default)(this._ts.sys.realpath),
|
||||
getNewLine: () => constants_1.LINE_FEED,
|
||||
getCurrentDirectory: () => this.configSet.cwd,
|
||||
getCompilationSettings: () => this._compilerOptions,
|
||||
getDefaultLibFileName: () => this._ts.getDefaultLibFilePath(this._compilerOptions),
|
||||
getCustomTransformers: () => this._makeTransformers(this.configSet.resolvedTransformers),
|
||||
resolveModuleNames: (moduleNames, containingFile) => moduleNames.map((moduleName) => this._resolveModuleName(moduleName, containingFile).resolvedModule),
|
||||
};
|
||||
this._logger.debug('created language service');
|
||||
this._languageService = this._ts.createLanguageService(serviceHost, this._ts.createDocumentRegistry(this._ts.sys.useCaseSensitiveFileNames, this.configSet.cwd));
|
||||
this.program = this._languageService.getProgram();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getFileContentFromCache(filePath) {
|
||||
const normalizedFilePath = (0, path_1.normalize)(filePath);
|
||||
let resolvedFileContent = this._runtimeCacheFS.get(normalizedFilePath);
|
||||
if (!resolvedFileContent) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
resolvedFileContent = this._moduleResolutionHost.readFile(normalizedFilePath);
|
||||
this._runtimeCacheFS.set(normalizedFilePath, resolvedFileContent);
|
||||
}
|
||||
return resolvedFileContent;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getImportedModulePaths(resolvedFileContent, containingFile) {
|
||||
return this._ts
|
||||
.preProcessFile(resolvedFileContent, true, true)
|
||||
.importedFiles.map((importedFile) => {
|
||||
const { resolvedModule } = this._resolveModuleName(importedFile.fileName, containingFile);
|
||||
/* istanbul ignore next already covered */
|
||||
const resolvedFileName = resolvedModule?.resolvedFileName;
|
||||
/* istanbul ignore next already covered */
|
||||
return resolvedFileName && !resolvedModule?.isExternalLibraryImport ? resolvedFileName : '';
|
||||
})
|
||||
.filter((resolveFileName) => !!resolveFileName);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_resolveModuleName(moduleNameToResolve, containingFile) {
|
||||
return this._ts.resolveModuleName(moduleNameToResolve, containingFile, this._compilerOptions,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._moduleResolutionHost,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._moduleResolutionCache);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_isFileInCache(fileName) {
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileContentCache.has(fileName) &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileVersionCache.has(fileName) &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileVersionCache.get(fileName) !== 0);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_updateMemoryCache(contents, fileName, isModuleKindTheSame = true) {
|
||||
this._logger.debug({ fileName }, 'updateMemoryCache: update memory cache for language service');
|
||||
let shouldIncrementProjectVersion = false;
|
||||
const hit = this._isFileInCache(fileName);
|
||||
if (!hit) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileVersionCache.set(fileName, 1);
|
||||
shouldIncrementProjectVersion = true;
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const prevVersion = this._fileVersionCache.get(fileName);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const previousContents = this._fileContentCache.get(fileName);
|
||||
// Avoid incrementing cache when nothing has changed.
|
||||
if (previousContents !== contents) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileVersionCache.set(fileName, prevVersion + 1);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this._fileContentCache.set(fileName, contents);
|
||||
shouldIncrementProjectVersion = true;
|
||||
}
|
||||
/**
|
||||
* When a file is from node_modules or referenced to a referenced project and jest wants to transform it, we need
|
||||
* to make sure that the Program is updated with this information
|
||||
*/
|
||||
if (!this._parsedTsConfig.fileNames.includes(fileName) || !isModuleKindTheSame) {
|
||||
shouldIncrementProjectVersion = true;
|
||||
}
|
||||
}
|
||||
if (shouldIncrementProjectVersion)
|
||||
this._projectVersion++;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getDiagnostics(fileName) {
|
||||
const diagnostics = [];
|
||||
if (this.configSet.shouldReportDiagnostics(fileName)) {
|
||||
this._logger.debug({ fileName }, '_doTypeChecking(): computing diagnostics using language service');
|
||||
// Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`.
|
||||
diagnostics.push(
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...this._languageService.getSemanticDiagnostics(fileName),
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
...this._languageService.getSyntacticDiagnostics(fileName));
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
exports.TsCompiler = TsCompiler;
|
||||
8
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-jest-compiler.d.ts
generated
vendored
Normal file
8
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-jest-compiler.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { CompilerInstance, CompiledOutput, StringMap, TsJestCompileOptions } from '../../types';
|
||||
import type { ConfigSet } from '../config/config-set';
|
||||
export declare class TsJestCompiler implements CompilerInstance {
|
||||
private readonly _compilerInstance;
|
||||
constructor(configSet: ConfigSet, runtimeCacheFS: StringMap);
|
||||
getResolvedModules(fileContent: string, fileName: string, runtimeCacheFS: StringMap): string[];
|
||||
getCompiledOutput(fileContent: string, fileName: string, options: TsJestCompileOptions): CompiledOutput;
|
||||
}
|
||||
18
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-jest-compiler.js
generated
vendored
Normal file
18
frontend/node_modules/ts-jest/dist/legacy/compiler/ts-jest-compiler.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TsJestCompiler = void 0;
|
||||
const ts_compiler_1 = require("./ts-compiler");
|
||||
class TsJestCompiler {
|
||||
_compilerInstance;
|
||||
constructor(configSet, runtimeCacheFS) {
|
||||
// Later we can add swc/esbuild or other typescript compiler instance here
|
||||
this._compilerInstance = new ts_compiler_1.TsCompiler(configSet, runtimeCacheFS);
|
||||
}
|
||||
getResolvedModules(fileContent, fileName, runtimeCacheFS) {
|
||||
return this._compilerInstance.getResolvedModules(fileContent, fileName, runtimeCacheFS);
|
||||
}
|
||||
getCompiledOutput(fileContent, fileName, options) {
|
||||
return this._compilerInstance.getCompiledOutput(fileContent, fileName, options);
|
||||
}
|
||||
}
|
||||
exports.TsJestCompiler = TsJestCompiler;
|
||||
36
frontend/node_modules/ts-jest/dist/legacy/config/config-set.d.ts
generated
vendored
Normal file
36
frontend/node_modules/ts-jest/dist/legacy/config/config-set.d.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Logger } from 'bs-logger';
|
||||
import type * as ts from 'typescript';
|
||||
import type { TsConfigCompilerOptionsJson } from '../../config/types';
|
||||
import type { RawCompilerOptions } from '../../raw-compiler-options';
|
||||
import type { TsJestAstTransformer, TsJestTransformOptions, TTypeScript } from '../../types';
|
||||
export declare class ConfigSet {
|
||||
readonly parentLogger?: Logger | undefined;
|
||||
/**
|
||||
* Use by e2e, don't mark as internal
|
||||
*/
|
||||
readonly tsJestDigest: string;
|
||||
readonly logger: Logger;
|
||||
readonly compilerModule: TTypeScript;
|
||||
readonly isolatedModules: boolean;
|
||||
readonly cwd: string;
|
||||
readonly rootDir: string;
|
||||
cacheSuffix: string;
|
||||
tsCacheDir: string | undefined;
|
||||
parsedTsConfig: ts.ParsedCommandLine | Record<string, any>;
|
||||
resolvedTransformers: TsJestAstTransformer;
|
||||
useESM: boolean;
|
||||
constructor(jestConfig: TsJestTransformOptions['config'] | undefined, parentLogger?: Logger | undefined);
|
||||
/**
|
||||
* Load TypeScript configuration. Returns the parsed TypeScript config and any `tsconfig` options specified in ts-jest
|
||||
* Subclasses which extend `ConfigSet` can override the default behavior
|
||||
*/
|
||||
protected _resolveTsConfig(compilerOptions?: RawCompilerOptions | TsConfigCompilerOptionsJson, resolvedConfigFile?: string): Record<string, any>;
|
||||
isTestFile(fileName: string): boolean;
|
||||
shouldStringifyContent(filePath: string): boolean;
|
||||
raiseDiagnostics(diagnostics: ts.Diagnostic[], filePath?: string, logger?: Logger): void;
|
||||
shouldReportDiagnostics(filePath: string): boolean;
|
||||
resolvePath(inputPath: string, { throwIfMissing, nodeResolve }?: {
|
||||
throwIfMissing?: boolean;
|
||||
nodeResolve?: boolean;
|
||||
}): string;
|
||||
}
|
||||
622
frontend/node_modules/ts-jest/dist/legacy/config/config-set.js
generated
vendored
Normal file
622
frontend/node_modules/ts-jest/dist/legacy/config/config-set.js
generated
vendored
Normal file
@@ -0,0 +1,622 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ConfigSet = exports.TS_JEST_OUT_DIR = exports.IGNORE_DIAGNOSTIC_CODES = exports.MY_DIGEST = void 0;
|
||||
/**
|
||||
* This is the core of settings and so ts-jest.
|
||||
* Since configuration are used to create a good cache key, everything
|
||||
* depending on it is here. Fast jest relies on correct cache keys
|
||||
* depending on all settings that could affect the generated output.
|
||||
*
|
||||
* The big issue is that jest calls first `getCacheKey()` with stringified
|
||||
* version of the `jest.ProjectConfig`, and then later it calls `process()`
|
||||
* with the complete, object version of it.
|
||||
*/
|
||||
const fs_1 = require("fs");
|
||||
const module_1 = __importDefault(require("module"));
|
||||
const path_1 = require("path");
|
||||
const bs_logger_1 = require("bs-logger");
|
||||
const jest_util_1 = require("jest-util");
|
||||
const json5_1 = __importDefault(require("json5"));
|
||||
const constants_1 = require("../../constants");
|
||||
const hoistJestTransformer = __importStar(require("../../transformers/hoist-jest"));
|
||||
const utils_1 = require("../../utils");
|
||||
const backports_1 = require("../../utils/backports");
|
||||
const importer_1 = require("../../utils/importer");
|
||||
const messages_1 = require("../../utils/messages");
|
||||
const normalize_slashes_1 = require("../../utils/normalize-slashes");
|
||||
const sha1_1 = require("../../utils/sha1");
|
||||
const ts_error_1 = require("../../utils/ts-error");
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
exports.MY_DIGEST = (0, fs_1.readFileSync)((0, path_1.resolve)(__dirname, '../../../.ts-jest-digest'), 'utf8');
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
exports.IGNORE_DIAGNOSTIC_CODES = [
|
||||
6059, // "'rootDir' is expected to contain all source files."
|
||||
18002, // "The 'files' list in config file is empty."
|
||||
18003, // "No inputs were found in config file."
|
||||
];
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
exports.TS_JEST_OUT_DIR = '$$ts-jest$$';
|
||||
const normalizeRegex = (pattern) => pattern ? (typeof pattern === 'string' ? pattern : pattern.source) : undefined;
|
||||
const toDiagnosticCode = (code) => code ? parseInt(`${code}`.trim().replace(/^TS/, ''), 10) ?? undefined : undefined;
|
||||
const toDiagnosticCodeList = (items, into = []) => {
|
||||
for (let item of items) {
|
||||
if (typeof item === 'string') {
|
||||
const children = item.trim().split(/\s*,\s*/g);
|
||||
if (children.length > 1) {
|
||||
toDiagnosticCodeList(children, into);
|
||||
continue;
|
||||
}
|
||||
item = children[0];
|
||||
}
|
||||
if (!item)
|
||||
continue;
|
||||
const code = toDiagnosticCode(item);
|
||||
if (code && !into.includes(code))
|
||||
into.push(code);
|
||||
}
|
||||
return into;
|
||||
};
|
||||
const requireFromString = (code, fileName) => {
|
||||
// @ts-expect-error `_nodeModulePaths` is not exposed in typing
|
||||
const paths = module_1.default._nodeModulePaths((0, path_1.dirname)(fileName));
|
||||
const parent = module.parent;
|
||||
const m = new module_1.default(fileName, parent);
|
||||
m.filename = fileName;
|
||||
m.paths = [].concat(paths);
|
||||
// @ts-expect-error `_compile` is not exposed in typing
|
||||
m._compile(code, fileName);
|
||||
const exports = m.exports;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
parent && parent.children && parent.children.splice(parent.children.indexOf(m), 1);
|
||||
return exports;
|
||||
};
|
||||
class ConfigSet {
|
||||
parentLogger;
|
||||
/**
|
||||
* Use by e2e, don't mark as internal
|
||||
*/
|
||||
tsJestDigest = exports.MY_DIGEST;
|
||||
logger;
|
||||
compilerModule;
|
||||
isolatedModules;
|
||||
cwd;
|
||||
rootDir;
|
||||
cacheSuffix;
|
||||
tsCacheDir;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
parsedTsConfig;
|
||||
resolvedTransformers = {
|
||||
before: [],
|
||||
after: [],
|
||||
afterDeclarations: [],
|
||||
};
|
||||
useESM = false;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
babelConfig;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
babelJestTransformer;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_jestCfg;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_diagnostics;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_stringifyContentRegExp;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_matchablePatterns;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_matchTestFilePath;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_shouldIgnoreDiagnosticsForFile;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_overriddenCompilerOptions = {
|
||||
inlineSourceMap: false,
|
||||
declaration: false, // we don't want to create declaration files
|
||||
isolatedDeclarations: false, // we don't want to create declaration files
|
||||
noEmit: false, // set to true will make compiler API not emit any compiled results.
|
||||
// else istanbul related will be dropped
|
||||
removeComments: false,
|
||||
// to clear out else it's buggy
|
||||
out: undefined,
|
||||
outFile: undefined,
|
||||
composite: undefined, // see https://github.com/TypeStrong/ts-node/pull/657/files
|
||||
declarationDir: undefined,
|
||||
declarationMap: undefined,
|
||||
emitDeclarationOnly: undefined,
|
||||
sourceRoot: undefined,
|
||||
tsBuildInfoFile: undefined,
|
||||
rewriteRelativeImportExtensions: false,
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
tsconfigFilePath;
|
||||
constructor(jestConfig, parentLogger) {
|
||||
this.parentLogger = parentLogger;
|
||||
this.logger = this.parentLogger
|
||||
? this.parentLogger.child({ [bs_logger_1.LogContexts.namespace]: 'config' })
|
||||
: utils_1.rootLogger.child({ namespace: 'config' });
|
||||
this._backportJestCfg(jestConfig ?? Object.create(null));
|
||||
this.cwd = (0, path_1.normalize)(this._jestCfg.cwd ?? process.cwd());
|
||||
this.rootDir = (0, path_1.normalize)(this._jestCfg.rootDir ?? this.cwd);
|
||||
const tsJestCfg = this._jestCfg.globals && this._jestCfg.globals['ts-jest'];
|
||||
const options = tsJestCfg ?? Object.create(null);
|
||||
// compiler module
|
||||
this.compilerModule = importer_1.importer.typescript("Using \"ts-jest\" requires this package to be installed." /* ImportReasons.TsJest */, options.compiler ?? 'typescript');
|
||||
this.logger.debug({ compilerModule: this.compilerModule }, 'normalized compiler module config via ts-jest option');
|
||||
this._setupConfigSet(options);
|
||||
this._matchablePatterns = [...this._jestCfg.testMatch, ...this._jestCfg.testRegex].filter((pattern) =>
|
||||
/**
|
||||
* jest config testRegex doesn't always deliver the correct RegExp object
|
||||
* See https://github.com/facebook/jest/issues/9778
|
||||
*/
|
||||
pattern instanceof RegExp || typeof pattern === 'string');
|
||||
if (!this._matchablePatterns.length) {
|
||||
this._matchablePatterns.push(...constants_1.DEFAULT_JEST_TEST_MATCH);
|
||||
}
|
||||
this._matchTestFilePath = (0, jest_util_1.globsToMatcher)(this._matchablePatterns.filter((pattern) => typeof pattern === 'string'));
|
||||
// isolatedModules
|
||||
if (options.isolatedModules) {
|
||||
this.parsedTsConfig.options.isolatedModules = true;
|
||||
if (this.tsconfigFilePath) {
|
||||
this.logger.warn((0, messages_1.interpolate)("\n The \"ts-jest\" config option \"isolatedModules\" is deprecated and will be removed in v30.0.0. Please use \"isolatedModules: true\" in {{tsconfigFilePath}} instead, see https://www.typescriptlang.org/tsconfig/#isolatedModules\n " /* Deprecations.IsolatedModulesWithTsconfigPath */, {
|
||||
tsconfigFilePath: this.tsconfigFilePath,
|
||||
}));
|
||||
}
|
||||
else {
|
||||
this.logger.warn("\n The \"ts-jest\" config option \"isolatedModules\" is deprecated and will be removed in v30.0.0. Please use \"isolatedModules: true\", see https://www.typescriptlang.org/tsconfig/#isolatedModules\n " /* Deprecations.IsolatedModulesWithoutTsconfigPath */);
|
||||
}
|
||||
}
|
||||
this.isolatedModules = this.parsedTsConfig.options.isolatedModules ?? false;
|
||||
this._resolveTsCacheDir();
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_backportJestCfg(jestCfg) {
|
||||
const config = (0, backports_1.backportJestConfig)(this.logger, jestCfg);
|
||||
this.logger.debug({ jestConfig: config }, 'normalized jest config');
|
||||
this._jestCfg = {
|
||||
...config,
|
||||
testMatch: config.testMatch ?? constants_1.DEFAULT_JEST_TEST_MATCH,
|
||||
testRegex: config.testRegex ?? [],
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_setupConfigSet(options) {
|
||||
// useESM
|
||||
this.useESM = options.useESM ?? false;
|
||||
// babel config (for babel-jest) default is undefined so we don't need to have fallback like tsConfig
|
||||
if (!options.babelConfig) {
|
||||
this.logger.debug('babel is disabled');
|
||||
}
|
||||
else {
|
||||
const baseBabelCfg = { cwd: this.cwd };
|
||||
if (typeof options.babelConfig === 'string') {
|
||||
const babelCfgPath = this.resolvePath(options.babelConfig);
|
||||
const babelFileExtName = (0, path_1.extname)(options.babelConfig);
|
||||
if (babelFileExtName === '.js' || babelFileExtName === '.cjs') {
|
||||
this.babelConfig = {
|
||||
...baseBabelCfg,
|
||||
...require(babelCfgPath),
|
||||
};
|
||||
}
|
||||
else {
|
||||
this.babelConfig = {
|
||||
...baseBabelCfg,
|
||||
...json5_1.default.parse((0, fs_1.readFileSync)(babelCfgPath, 'utf-8')),
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (typeof options.babelConfig === 'object') {
|
||||
this.babelConfig = {
|
||||
...baseBabelCfg,
|
||||
...options.babelConfig,
|
||||
};
|
||||
}
|
||||
else {
|
||||
this.babelConfig = baseBabelCfg;
|
||||
}
|
||||
this.logger.debug({ babelConfig: this.babelConfig }, 'normalized babel config via ts-jest option');
|
||||
this.babelJestTransformer = importer_1.importer
|
||||
.babelJest("Using \"babel-jest\" requires this package to be installed." /* ImportReasons.BabelJest */)
|
||||
.createTransformer(this.babelConfig);
|
||||
this.logger.debug('created babel-jest transformer');
|
||||
}
|
||||
// diagnostics
|
||||
const diagnosticsOpt = options.diagnostics ?? true;
|
||||
const ignoreList = [...exports.IGNORE_DIAGNOSTIC_CODES];
|
||||
if (typeof diagnosticsOpt === 'object') {
|
||||
const { ignoreCodes } = diagnosticsOpt;
|
||||
if (ignoreCodes) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
Array.isArray(ignoreCodes) ? ignoreList.push(...ignoreCodes) : ignoreList.push(ignoreCodes);
|
||||
}
|
||||
this._diagnostics = {
|
||||
pretty: diagnosticsOpt.pretty ?? true,
|
||||
exclude: diagnosticsOpt.exclude ?? [],
|
||||
ignoreCodes: toDiagnosticCodeList(ignoreList),
|
||||
throws: !diagnosticsOpt.warnOnly,
|
||||
};
|
||||
}
|
||||
else {
|
||||
this._diagnostics = {
|
||||
ignoreCodes: diagnosticsOpt ? toDiagnosticCodeList(ignoreList) : [],
|
||||
exclude: [],
|
||||
pretty: true,
|
||||
throws: diagnosticsOpt,
|
||||
};
|
||||
}
|
||||
if (diagnosticsOpt) {
|
||||
this._shouldIgnoreDiagnosticsForFile = this._diagnostics.exclude.length
|
||||
? (0, jest_util_1.globsToMatcher)(this._diagnostics.exclude)
|
||||
: () => false;
|
||||
}
|
||||
else {
|
||||
this._shouldIgnoreDiagnosticsForFile = () => true;
|
||||
}
|
||||
this.logger.debug({ diagnostics: this._diagnostics }, 'normalized diagnostics config via ts-jest option');
|
||||
// tsconfig
|
||||
const tsconfigOpt = options.tsconfig;
|
||||
const configFilePath = typeof tsconfigOpt === 'string' ? this.resolvePath(tsconfigOpt) : undefined;
|
||||
this.parsedTsConfig = this._getAndResolveTsConfig(typeof tsconfigOpt === 'object' ? tsconfigOpt : undefined, configFilePath);
|
||||
// throw errors if any matching wanted diagnostics
|
||||
this.raiseDiagnostics(this.parsedTsConfig.errors, configFilePath);
|
||||
this.logger.debug({ tsconfig: this.parsedTsConfig }, 'normalized typescript config via ts-jest option');
|
||||
// transformers
|
||||
this.resolvedTransformers.before = [
|
||||
{
|
||||
factory: hoistJestTransformer.factory,
|
||||
name: hoistJestTransformer.name,
|
||||
version: hoistJestTransformer.version,
|
||||
},
|
||||
];
|
||||
const { astTransformers } = options;
|
||||
if (astTransformers) {
|
||||
const resolveTransformerFunc = (transformerPath) => {
|
||||
let transformerFunc;
|
||||
if ((0, path_1.extname)(transformerPath) === '.ts') {
|
||||
const compiledTransformer = importer_1.importer
|
||||
.esBuild("Using \"esbuild\" requires this package to be installed." /* ImportReasons.EsBuild */)
|
||||
.transformSync((0, fs_1.readFileSync)(transformerPath, 'utf-8'), {
|
||||
loader: 'ts',
|
||||
format: 'cjs',
|
||||
target: 'es2015',
|
||||
}).code;
|
||||
transformerFunc = requireFromString(compiledTransformer, transformerPath.replace('.ts', '.js'));
|
||||
}
|
||||
else {
|
||||
transformerFunc = require(transformerPath);
|
||||
}
|
||||
if (!transformerFunc.version) {
|
||||
this.logger.warn("The AST transformer {{file}} must have an `export const version = <your_transformer_version>`" /* Errors.MissingTransformerVersion */, { file: transformerPath });
|
||||
}
|
||||
if (!transformerFunc.name) {
|
||||
this.logger.warn("The AST transformer {{file}} must have an `export const name = <your_transformer_name>`" /* Errors.MissingTransformerName */, { file: transformerPath });
|
||||
}
|
||||
return transformerFunc;
|
||||
};
|
||||
const resolveTransformers = (transformers) => transformers.map((transformer) => {
|
||||
if (typeof transformer === 'string') {
|
||||
return resolveTransformerFunc(this.resolvePath(transformer, { nodeResolve: true }));
|
||||
}
|
||||
else {
|
||||
return {
|
||||
...resolveTransformerFunc(this.resolvePath(transformer.path, { nodeResolve: true })),
|
||||
options: transformer.options,
|
||||
};
|
||||
}
|
||||
});
|
||||
if (astTransformers.before) {
|
||||
/* istanbul ignore next (already covered in unit test) */
|
||||
this.resolvedTransformers.before?.push(...resolveTransformers(astTransformers.before));
|
||||
}
|
||||
if (astTransformers.after) {
|
||||
this.resolvedTransformers = {
|
||||
...this.resolvedTransformers,
|
||||
after: resolveTransformers(astTransformers.after),
|
||||
};
|
||||
}
|
||||
if (astTransformers.afterDeclarations) {
|
||||
this.resolvedTransformers = {
|
||||
...this.resolvedTransformers,
|
||||
afterDeclarations: resolveTransformers(astTransformers.afterDeclarations),
|
||||
};
|
||||
}
|
||||
}
|
||||
this.logger.debug({ customTransformers: this.resolvedTransformers }, 'normalized custom AST transformers via ts-jest option');
|
||||
// stringifyContentPathRegex
|
||||
if (options.stringifyContentPathRegex) {
|
||||
this._stringifyContentRegExp =
|
||||
typeof options.stringifyContentPathRegex === 'string'
|
||||
? new RegExp(normalizeRegex(options.stringifyContentPathRegex)) // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
||||
: options.stringifyContentPathRegex;
|
||||
this.logger.debug({ stringifyContentPathRegex: this._stringifyContentRegExp }, 'normalized stringifyContentPathRegex config via ts-jest option');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_resolveTsCacheDir() {
|
||||
this.cacheSuffix = (0, sha1_1.sha1)((0, utils_1.stringify)({
|
||||
version: this.compilerModule.version,
|
||||
digest: this.tsJestDigest,
|
||||
babelConfig: this.babelConfig,
|
||||
tsconfig: {
|
||||
options: this.parsedTsConfig.options,
|
||||
raw: this.parsedTsConfig.raw,
|
||||
},
|
||||
isolatedModules: this.isolatedModules,
|
||||
diagnostics: this._diagnostics,
|
||||
transformers: Object.values(this.resolvedTransformers)
|
||||
.reduce((prevVal, currentVal) => [...prevVal, currentVal])
|
||||
.map((transformer) => `${transformer.name}-${transformer.version}`),
|
||||
}));
|
||||
if (!this._jestCfg.cache) {
|
||||
this.logger.debug('file caching disabled');
|
||||
}
|
||||
else {
|
||||
const res = (0, path_1.join)(this._jestCfg.cacheDirectory, 'ts-jest', this.cacheSuffix.substr(0, 2), this.cacheSuffix.substr(2));
|
||||
this.logger.debug({ cacheDirectory: res }, 'will use file caching');
|
||||
this.tsCacheDir = res;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getAndResolveTsConfig(compilerOptions, resolvedConfigFile) {
|
||||
const result = this._resolveTsConfig(compilerOptions, resolvedConfigFile);
|
||||
const { _overriddenCompilerOptions: forcedOptions } = this;
|
||||
const finalOptions = result.options;
|
||||
// Target ES2015 output by default (instead of ES3).
|
||||
if (finalOptions.target === undefined) {
|
||||
finalOptions.target = this.compilerModule.ScriptTarget.ES2015;
|
||||
}
|
||||
// check the module interoperability
|
||||
const target = finalOptions.target;
|
||||
// compute the default if not set
|
||||
const defaultModule = [this.compilerModule.ScriptTarget.ES3, this.compilerModule.ScriptTarget.ES5].includes(target)
|
||||
? this.compilerModule.ModuleKind.CommonJS
|
||||
: this.compilerModule.ModuleKind.ESNext;
|
||||
const moduleValue = finalOptions.module ?? defaultModule;
|
||||
const warningModulesForEsmInterop = [
|
||||
this.compilerModule.ModuleKind.CommonJS,
|
||||
this.compilerModule.ModuleKind.Node16,
|
||||
this.compilerModule.ModuleKind.NodeNext,
|
||||
];
|
||||
if (!this.babelConfig &&
|
||||
!warningModulesForEsmInterop.includes(moduleValue) &&
|
||||
!(finalOptions.esModuleInterop || finalOptions.allowSyntheticDefaultImports)) {
|
||||
result.errors.push({
|
||||
code: messages_1.TsJestDiagnosticCodes.ConfigModuleOption,
|
||||
messageText: "If you have issues related to imports, you should consider setting `esModuleInterop` to `true` in your TypeScript configuration file (usually `tsconfig.json`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information." /* Errors.ConfigNoModuleInterop */,
|
||||
category: this.compilerModule.DiagnosticCategory.Message,
|
||||
file: undefined,
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
});
|
||||
}
|
||||
// Make sure when allowJs is enabled, outDir is required to have when using allowJs: true
|
||||
if (finalOptions.allowJs && !finalOptions.outDir) {
|
||||
finalOptions.outDir = exports.TS_JEST_OUT_DIR;
|
||||
}
|
||||
// ensure undefined are removed and other values are overridden
|
||||
for (const key of Object.keys(forcedOptions)) {
|
||||
const val = forcedOptions[key];
|
||||
if (val === undefined) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete finalOptions[key];
|
||||
}
|
||||
else {
|
||||
finalOptions[key] = val;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* See https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping
|
||||
* Every time this page is updated, we also need to update here. Here we only show warning message for Node LTS versions
|
||||
*/
|
||||
const nodeJsVer = process.version;
|
||||
const compilationTarget = result.options.target;
|
||||
const TARGET_TO_VERSION_MAPPING = {
|
||||
[this.compilerModule.ScriptTarget.ES2018]: 'es2018',
|
||||
[this.compilerModule.ScriptTarget.ES2019]: 'es2019',
|
||||
[this.compilerModule.ScriptTarget.ES2020]: 'es2020',
|
||||
[this.compilerModule.ScriptTarget.ESNext]: 'ESNext',
|
||||
};
|
||||
/* istanbul ignore next (cover by e2e) */
|
||||
if (compilationTarget &&
|
||||
!this.babelConfig &&
|
||||
nodeJsVer.startsWith('v12') &&
|
||||
compilationTarget > this.compilerModule.ScriptTarget.ES2019) {
|
||||
const message = (0, messages_1.interpolate)("There is a mismatch between your NodeJs version {{nodeJsVer}} and your TypeScript target {{compilationTarget}}. This might lead to some unexpected errors when running tests with `ts-jest`. To fix this, you can check https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping" /* Errors.MismatchNodeTargetMapping */, {
|
||||
nodeJsVer: process.version,
|
||||
compilationTarget: TARGET_TO_VERSION_MAPPING[compilationTarget],
|
||||
});
|
||||
this.logger.warn(message);
|
||||
}
|
||||
const resultOptions = result.options;
|
||||
const sourceMap = resultOptions.sourceMap ?? true;
|
||||
return {
|
||||
...result,
|
||||
options: {
|
||||
...resultOptions,
|
||||
sourceMap,
|
||||
inlineSources: sourceMap,
|
||||
module: resultOptions.module ?? this.compilerModule.ModuleKind.CommonJS,
|
||||
},
|
||||
};
|
||||
}
|
||||
_resolveTsConfig(compilerOptions, resolvedConfigFile) {
|
||||
let config = { compilerOptions: Object.create(null) };
|
||||
let basePath = (0, normalize_slashes_1.normalizeSlashes)(this.rootDir);
|
||||
const ts = this.compilerModule;
|
||||
// Read project configuration when available.
|
||||
this.tsconfigFilePath = resolvedConfigFile
|
||||
? (0, normalize_slashes_1.normalizeSlashes)(resolvedConfigFile)
|
||||
: ts.findConfigFile((0, normalize_slashes_1.normalizeSlashes)(this.rootDir), ts.sys.fileExists);
|
||||
if (this.tsconfigFilePath) {
|
||||
this.logger.debug({ tsConfigFileName: this.tsconfigFilePath }, 'readTsConfig(): reading', this.tsconfigFilePath);
|
||||
const result = ts.readConfigFile(this.tsconfigFilePath, ts.sys.readFile);
|
||||
// Return diagnostics.
|
||||
if (result.error) {
|
||||
return { errors: [result.error], fileNames: [], options: {} };
|
||||
}
|
||||
config = result.config;
|
||||
basePath = (0, normalize_slashes_1.normalizeSlashes)((0, path_1.dirname)(this.tsconfigFilePath));
|
||||
}
|
||||
// Override default configuration options `ts-jest` requires.
|
||||
config.compilerOptions = {
|
||||
...config.compilerOptions,
|
||||
...compilerOptions,
|
||||
};
|
||||
// parse json, merge config extending others, ...
|
||||
return ts.parseJsonConfigFileContent(config, ts.sys, basePath, undefined, this.tsconfigFilePath);
|
||||
}
|
||||
isTestFile(fileName) {
|
||||
return this._matchablePatterns.some((pattern) => typeof pattern === 'string' ? this._matchTestFilePath(fileName) : pattern.test(fileName));
|
||||
}
|
||||
shouldStringifyContent(filePath) {
|
||||
return this._stringifyContentRegExp ? this._stringifyContentRegExp.test(filePath) : false;
|
||||
}
|
||||
raiseDiagnostics(diagnostics, filePath, logger = this.logger) {
|
||||
const { ignoreCodes } = this._diagnostics;
|
||||
const { DiagnosticCategory } = this.compilerModule;
|
||||
const filteredDiagnostics = filePath && !this.shouldReportDiagnostics(filePath)
|
||||
? []
|
||||
: diagnostics.filter((diagnostic) => {
|
||||
if (diagnostic.file?.fileName && !this.shouldReportDiagnostics(diagnostic.file.fileName)) {
|
||||
return false;
|
||||
}
|
||||
return !ignoreCodes.includes(diagnostic.code);
|
||||
});
|
||||
if (!filteredDiagnostics.length)
|
||||
return;
|
||||
const error = this.createTsError(filteredDiagnostics);
|
||||
// only throw if `warnOnly` and it is a warning or error
|
||||
const importantCategories = [DiagnosticCategory.Warning, DiagnosticCategory.Error];
|
||||
if (this._diagnostics.throws && filteredDiagnostics.some((d) => importantCategories.includes(d.category))) {
|
||||
throw error;
|
||||
}
|
||||
logger.warn({ error }, error.message);
|
||||
}
|
||||
shouldReportDiagnostics(filePath) {
|
||||
const fileExtension = (0, path_1.extname)(filePath);
|
||||
return constants_1.JS_JSX_EXTENSIONS.includes(fileExtension)
|
||||
? this.parsedTsConfig.options.checkJs && !this._shouldIgnoreDiagnosticsForFile(filePath)
|
||||
: !this._shouldIgnoreDiagnosticsForFile(filePath);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
createTsError(diagnostics) {
|
||||
const formatDiagnostics = this._diagnostics.pretty
|
||||
? this.compilerModule.formatDiagnosticsWithColorAndContext
|
||||
: this.compilerModule.formatDiagnostics;
|
||||
/* istanbul ignore next (not possible to cover) */
|
||||
const diagnosticHost = {
|
||||
getNewLine: () => '\n',
|
||||
getCurrentDirectory: () => this.cwd,
|
||||
getCanonicalFileName: (path) => path,
|
||||
};
|
||||
const diagnosticText = formatDiagnostics(diagnostics, diagnosticHost);
|
||||
const diagnosticCodes = diagnostics.map((x) => x.code);
|
||||
return new ts_error_1.TSError(diagnosticText, diagnosticCodes);
|
||||
}
|
||||
resolvePath(inputPath, { throwIfMissing = true, nodeResolve = false } = {}) {
|
||||
let path = inputPath;
|
||||
let nodeResolved = false;
|
||||
if (path.startsWith('<rootDir>')) {
|
||||
path = (0, path_1.resolve)((0, path_1.join)(this.rootDir, path.substr(9)));
|
||||
}
|
||||
else if (!(0, path_1.isAbsolute)(path)) {
|
||||
if (!path.startsWith('.') && nodeResolve) {
|
||||
try {
|
||||
path = require.resolve(path);
|
||||
nodeResolved = true;
|
||||
}
|
||||
catch {
|
||||
this.logger.debug({ path }, 'failed to resolve path', path);
|
||||
}
|
||||
}
|
||||
if (!nodeResolved) {
|
||||
path = (0, path_1.resolve)(this.cwd, path);
|
||||
}
|
||||
}
|
||||
if (!nodeResolved && nodeResolve) {
|
||||
try {
|
||||
path = require.resolve(path);
|
||||
nodeResolved = true;
|
||||
}
|
||||
catch {
|
||||
this.logger.debug({ path }, 'failed to resolve path', path);
|
||||
}
|
||||
}
|
||||
if (throwIfMissing && !(0, fs_1.existsSync)(path)) {
|
||||
throw new Error((0, messages_1.interpolate)("File not found: {{inputPath}} (resolved as: {{resolvedPath}})" /* Errors.FileNotFound */, { inputPath, resolvedPath: path }));
|
||||
}
|
||||
this.logger.debug({ fromPath: inputPath, toPath: path }, 'resolved path from', inputPath, 'to', path);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
exports.ConfigSet = ConfigSet;
|
||||
6
frontend/node_modules/ts-jest/dist/legacy/index.d.ts
generated
vendored
Normal file
6
frontend/node_modules/ts-jest/dist/legacy/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { TsJestTransformerOptions } from '../types';
|
||||
import { TsJestTransformer } from './ts-jest-transformer';
|
||||
declare const _default: {
|
||||
createTransformer: (tsJestConfig?: TsJestTransformerOptions) => TsJestTransformer;
|
||||
};
|
||||
export default _default;
|
||||
6
frontend/node_modules/ts-jest/dist/legacy/index.js
generated
vendored
Normal file
6
frontend/node_modules/ts-jest/dist/legacy/index.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const ts_jest_transformer_1 = require("./ts-jest-transformer");
|
||||
exports.default = {
|
||||
createTransformer: (tsJestConfig) => new ts_jest_transformer_1.TsJestTransformer(tsJestConfig),
|
||||
};
|
||||
28
frontend/node_modules/ts-jest/dist/legacy/ts-jest-transformer.d.ts
generated
vendored
Normal file
28
frontend/node_modules/ts-jest/dist/legacy/ts-jest-transformer.d.ts
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { SyncTransformer, TransformedSource } from '@jest/transform';
|
||||
import type { CompilerInstance, TsJestTransformerOptions, TsJestTransformOptions } from '../types';
|
||||
import { ConfigSet } from './config/config-set';
|
||||
export declare class TsJestTransformer implements SyncTransformer<TsJestTransformerOptions> {
|
||||
private readonly transformerOptions?;
|
||||
private readonly _logger;
|
||||
protected _compiler: CompilerInstance;
|
||||
private _transformCfgStr;
|
||||
private _depGraphs;
|
||||
private _watchMode;
|
||||
constructor(transformerOptions?: TsJestTransformerOptions | undefined);
|
||||
private _configsFor;
|
||||
protected _createConfigSet(config: TsJestTransformOptions['config'] | undefined): ConfigSet;
|
||||
protected _createCompiler(configSet: ConfigSet, cacheFS: Map<string, string>): void;
|
||||
process(sourceText: string, sourcePath: string, transformOptions: TsJestTransformOptions): TransformedSource;
|
||||
processAsync(sourceText: string, sourcePath: string, transformOptions: TsJestTransformOptions): Promise<TransformedSource>;
|
||||
private processWithTs;
|
||||
private runTsJestHook;
|
||||
/**
|
||||
* Jest uses this to cache the compiled version of a file
|
||||
*
|
||||
* @see https://github.com/facebook/jest/blob/v23.5.0/packages/jest-runtime/src/script_transformer.js#L61-L90
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
getCacheKey(fileContent: string, filePath: string, transformOptions: TsJestTransformOptions): string;
|
||||
getCacheKeyAsync(sourceText: string, sourcePath: string, transformOptions: TsJestTransformOptions): Promise<string>;
|
||||
}
|
||||
293
frontend/node_modules/ts-jest/dist/legacy/ts-jest-transformer.js
generated
vendored
Normal file
293
frontend/node_modules/ts-jest/dist/legacy/ts-jest-transformer.js
generated
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TsJestTransformer = exports.CACHE_KEY_EL_SEPARATOR = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const typescript_1 = __importDefault(require("typescript"));
|
||||
const constants_1 = require("../constants");
|
||||
const utils_1 = require("../utils");
|
||||
const importer_1 = require("../utils/importer");
|
||||
const messages_1 = require("../utils/messages");
|
||||
const sha1_1 = require("../utils/sha1");
|
||||
const compiler_1 = require("./compiler");
|
||||
const compiler_utils_1 = require("./compiler/compiler-utils");
|
||||
const config_set_1 = require("./config/config-set");
|
||||
const isNodeModule = (filePath) => {
|
||||
return path_1.default.normalize(filePath).split(path_1.default.sep).includes('node_modules');
|
||||
};
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
exports.CACHE_KEY_EL_SEPARATOR = '\x00';
|
||||
class TsJestTransformer {
|
||||
transformerOptions;
|
||||
/**
|
||||
* cache ConfigSet between test runs
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static _cachedConfigSets = [];
|
||||
_logger;
|
||||
_compiler;
|
||||
_transformCfgStr;
|
||||
_depGraphs = new Map();
|
||||
_watchMode = false;
|
||||
constructor(transformerOptions) {
|
||||
this.transformerOptions = transformerOptions;
|
||||
this._logger = utils_1.rootLogger.child({ namespace: 'ts-jest-transformer' });
|
||||
/**
|
||||
* For some unknown reasons, `this` is undefined in `getCacheKey` and `process`
|
||||
* when running Jest in ESM mode
|
||||
*/
|
||||
this.getCacheKey = this.getCacheKey.bind(this);
|
||||
this.getCacheKeyAsync = this.getCacheKeyAsync.bind(this);
|
||||
this.process = this.process.bind(this);
|
||||
this.processAsync = this.processAsync.bind(this);
|
||||
this._logger.debug('created new transformer');
|
||||
process.env.TS_JEST = '1';
|
||||
}
|
||||
_configsFor(transformOptions) {
|
||||
const { config, cacheFS } = transformOptions;
|
||||
const ccs = TsJestTransformer._cachedConfigSets.find((cs) => cs.jestConfig.value === config);
|
||||
let configSet;
|
||||
if (ccs) {
|
||||
this._transformCfgStr = ccs.transformerCfgStr;
|
||||
this._compiler = ccs.compiler;
|
||||
this._depGraphs = ccs.depGraphs;
|
||||
this._watchMode = ccs.watchMode;
|
||||
configSet = ccs.configSet;
|
||||
}
|
||||
else {
|
||||
// try to look-it up by stringified version
|
||||
const serializedJestCfg = (0, utils_1.stringify)(config);
|
||||
const serializedCcs = TsJestTransformer._cachedConfigSets.find((cs) => cs.jestConfig.serialized === serializedJestCfg);
|
||||
if (serializedCcs) {
|
||||
// update the object so that we can find it later
|
||||
// this happens because jest first calls getCacheKey with stringified version of
|
||||
// the config, and then it calls the transformer with the proper object
|
||||
serializedCcs.jestConfig.value = config;
|
||||
this._transformCfgStr = serializedCcs.transformerCfgStr;
|
||||
this._compiler = serializedCcs.compiler;
|
||||
this._depGraphs = serializedCcs.depGraphs;
|
||||
this._watchMode = serializedCcs.watchMode;
|
||||
configSet = serializedCcs.configSet;
|
||||
}
|
||||
else {
|
||||
// create the new record in the index
|
||||
this._logger.info('no matching config-set found, creating a new one');
|
||||
if (config.globals?.['ts-jest']) {
|
||||
this._logger.warn("Define `ts-jest` config under `globals` is deprecated. Please do\ntransform: {\n <transform_regex>: ['ts-jest', { /* ts-jest config goes here in Jest */ }],\n},\nSee more at https://kulshekhar.github.io/ts-jest/docs/getting-started/presets#advanced" /* Deprecations.GlobalsTsJestConfigOption */);
|
||||
}
|
||||
const jestGlobalsConfig = config.globals ?? {};
|
||||
const tsJestGlobalsConfig = jestGlobalsConfig['ts-jest'] ?? {};
|
||||
const migratedConfig = this.transformerOptions
|
||||
? {
|
||||
...config,
|
||||
globals: {
|
||||
...jestGlobalsConfig,
|
||||
'ts-jest': {
|
||||
...tsJestGlobalsConfig,
|
||||
...this.transformerOptions,
|
||||
},
|
||||
},
|
||||
}
|
||||
: config;
|
||||
configSet = this._createConfigSet(migratedConfig);
|
||||
const jest = { ...migratedConfig };
|
||||
// we need to remove some stuff from jest config
|
||||
// this which does not depend on config
|
||||
jest.cacheDirectory = undefined; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
this._transformCfgStr = `${new utils_1.JsonableValue(jest).serialized}${configSet.cacheSuffix}`;
|
||||
this._createCompiler(configSet, cacheFS);
|
||||
this._watchMode = process.argv.includes('--watch');
|
||||
TsJestTransformer._cachedConfigSets.push({
|
||||
jestConfig: new utils_1.JsonableValue(config),
|
||||
configSet,
|
||||
transformerCfgStr: this._transformCfgStr,
|
||||
compiler: this._compiler,
|
||||
depGraphs: this._depGraphs,
|
||||
watchMode: this._watchMode,
|
||||
});
|
||||
}
|
||||
}
|
||||
return configSet;
|
||||
}
|
||||
_createConfigSet(config) {
|
||||
return new config_set_1.ConfigSet(config);
|
||||
}
|
||||
_createCompiler(configSet, cacheFS) {
|
||||
this._compiler = new compiler_1.TsJestCompiler(configSet, cacheFS);
|
||||
}
|
||||
process(sourceText, sourcePath, transformOptions) {
|
||||
this._logger.debug({ fileName: sourcePath, transformOptions }, 'processing', sourcePath);
|
||||
const configs = this._configsFor(transformOptions);
|
||||
const shouldStringifyContent = configs.shouldStringifyContent(sourcePath);
|
||||
const babelJest = shouldStringifyContent ? undefined : configs.babelJestTransformer;
|
||||
let result = {
|
||||
code: this.processWithTs(sourceText, sourcePath, transformOptions).code,
|
||||
};
|
||||
if (babelJest) {
|
||||
this._logger.debug({ fileName: sourcePath }, 'calling babel-jest processor');
|
||||
// do not instrument here, jest will do it anyway afterwards
|
||||
result = babelJest.process(result.code, sourcePath, {
|
||||
...transformOptions,
|
||||
instrument: false,
|
||||
});
|
||||
}
|
||||
result = this.runTsJestHook(sourcePath, sourceText, transformOptions, result);
|
||||
return result;
|
||||
}
|
||||
async processAsync(sourceText, sourcePath, transformOptions) {
|
||||
this._logger.debug({ fileName: sourcePath, transformOptions }, 'processing', sourcePath);
|
||||
const configs = this._configsFor(transformOptions);
|
||||
const shouldStringifyContent = configs.shouldStringifyContent(sourcePath);
|
||||
const babelJest = shouldStringifyContent ? undefined : configs.babelJestTransformer;
|
||||
let result;
|
||||
const processWithTsResult = this.processWithTs(sourceText, sourcePath, transformOptions);
|
||||
result = {
|
||||
code: processWithTsResult.code,
|
||||
};
|
||||
if (processWithTsResult.diagnostics?.length) {
|
||||
throw configs.createTsError(processWithTsResult.diagnostics);
|
||||
}
|
||||
if (babelJest) {
|
||||
this._logger.debug({ fileName: sourcePath }, 'calling babel-jest processor');
|
||||
// do not instrument here, jest will do it anyway afterwards
|
||||
result = await babelJest.processAsync(result.code, sourcePath, {
|
||||
...transformOptions,
|
||||
instrument: false,
|
||||
});
|
||||
}
|
||||
result = this.runTsJestHook(sourcePath, sourceText, transformOptions, result);
|
||||
return result;
|
||||
}
|
||||
processWithTs(sourceText, sourcePath, transformOptions) {
|
||||
let result;
|
||||
const configs = this._configsFor(transformOptions);
|
||||
const shouldStringifyContent = configs.shouldStringifyContent(sourcePath);
|
||||
const babelJest = shouldStringifyContent ? undefined : configs.babelJestTransformer;
|
||||
const isDefinitionFile = sourcePath.endsWith(constants_1.DECLARATION_TYPE_EXT);
|
||||
const isJsFile = constants_1.JS_JSX_REGEX.test(sourcePath);
|
||||
const isTsFile = !isDefinitionFile && constants_1.TS_TSX_REGEX.test(sourcePath);
|
||||
if (shouldStringifyContent) {
|
||||
// handles here what we should simply stringify
|
||||
result = {
|
||||
code: `module.exports=${(0, utils_1.stringify)(sourceText)}`,
|
||||
};
|
||||
}
|
||||
else if (isDefinitionFile) {
|
||||
// do not try to compile declaration files
|
||||
result = {
|
||||
code: '',
|
||||
};
|
||||
}
|
||||
else if (isJsFile || isTsFile) {
|
||||
if (isJsFile && isNodeModule(sourcePath)) {
|
||||
const transpiledResult = typescript_1.default.transpileModule(sourceText, {
|
||||
compilerOptions: {
|
||||
...configs.parsedTsConfig.options,
|
||||
module: transformOptions.supportsStaticESM && transformOptions.transformerConfig.useESM
|
||||
? typescript_1.default.ModuleKind.ESNext
|
||||
: typescript_1.default.ModuleKind.CommonJS,
|
||||
},
|
||||
fileName: sourcePath,
|
||||
});
|
||||
result = {
|
||||
code: (0, compiler_utils_1.updateOutput)(transpiledResult.outputText, sourcePath, transpiledResult.sourceMapText),
|
||||
};
|
||||
}
|
||||
else {
|
||||
// transpile TS code (source maps are included)
|
||||
result = this._compiler.getCompiledOutput(sourceText, sourcePath, {
|
||||
depGraphs: this._depGraphs,
|
||||
supportsStaticESM: transformOptions.supportsStaticESM,
|
||||
watchMode: this._watchMode,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we should not get called for files with other extension than js[x], ts[x] and d.ts,
|
||||
// TypeScript will bail if we try to compile, and if it was to call babel, users can
|
||||
// define the transform value with `babel-jest` for this extension instead
|
||||
const message = babelJest ? "Got a unknown file type to compile (file: {{path}}). To fix this, in your Jest config change the `transform` key which value is `ts-jest` so that it does not match this kind of files anymore. If you still want Babel to process it, add another entry to the `transform` option with value `babel-jest` which key matches this type of files." /* Errors.GotUnknownFileTypeWithBabel */ : "Got a unknown file type to compile (file: {{path}}). To fix this, in your Jest config change the `transform` key which value is `ts-jest` so that it does not match this kind of files anymore." /* Errors.GotUnknownFileTypeWithoutBabel */;
|
||||
this._logger.warn({ fileName: sourcePath }, (0, messages_1.interpolate)(message, { path: sourcePath }));
|
||||
result = {
|
||||
code: sourceText,
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
runTsJestHook(sourcePath, sourceText, transformOptions, compiledOutput) {
|
||||
let hooksFile = process.env.TS_JEST_HOOKS;
|
||||
let hooks;
|
||||
/* istanbul ignore next (cover by e2e) */
|
||||
if (hooksFile) {
|
||||
hooksFile = path_1.default.resolve(this._configsFor(transformOptions).cwd, hooksFile);
|
||||
hooks = importer_1.importer.tryTheseOr(hooksFile, {});
|
||||
}
|
||||
// This is not supposed to be a public API but we keep it as some people use it
|
||||
if (hooks?.afterProcess) {
|
||||
this._logger.debug({ fileName: sourcePath, hookName: 'afterProcess' }, 'calling afterProcess hook');
|
||||
const newResult = hooks.afterProcess([sourceText, sourcePath, transformOptions.config, transformOptions], compiledOutput);
|
||||
if (newResult) {
|
||||
return newResult;
|
||||
}
|
||||
}
|
||||
return compiledOutput;
|
||||
}
|
||||
/**
|
||||
* Jest uses this to cache the compiled version of a file
|
||||
*
|
||||
* @see https://github.com/facebook/jest/blob/v23.5.0/packages/jest-runtime/src/script_transformer.js#L61-L90
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
getCacheKey(fileContent, filePath, transformOptions) {
|
||||
const configs = this._configsFor(transformOptions);
|
||||
this._logger.debug({ fileName: filePath, transformOptions }, 'computing cache key for', filePath);
|
||||
// we do not instrument, ensure it is false all the time
|
||||
const { supportsStaticESM, instrument = false } = transformOptions;
|
||||
const constructingCacheKeyElements = [
|
||||
this._transformCfgStr,
|
||||
exports.CACHE_KEY_EL_SEPARATOR,
|
||||
configs.rootDir,
|
||||
exports.CACHE_KEY_EL_SEPARATOR,
|
||||
`instrument:${instrument ? 'on' : 'off'}`,
|
||||
exports.CACHE_KEY_EL_SEPARATOR,
|
||||
`supportsStaticESM:${supportsStaticESM ? 'on' : 'off'}`,
|
||||
exports.CACHE_KEY_EL_SEPARATOR,
|
||||
fileContent,
|
||||
exports.CACHE_KEY_EL_SEPARATOR,
|
||||
filePath,
|
||||
];
|
||||
if (!configs.isolatedModules && configs.tsCacheDir) {
|
||||
let resolvedModuleNames;
|
||||
if (this._depGraphs.get(filePath)?.fileContent === fileContent) {
|
||||
this._logger.debug({ fileName: filePath, transformOptions }, 'getting resolved modules from disk caching or memory caching for', filePath);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
resolvedModuleNames = this._depGraphs
|
||||
.get(filePath)
|
||||
.resolvedModuleNames.filter((moduleName) => (0, fs_1.existsSync)(moduleName));
|
||||
}
|
||||
else {
|
||||
this._logger.debug({ fileName: filePath, transformOptions }, 'getting resolved modules from TypeScript API for', filePath);
|
||||
resolvedModuleNames = this._compiler.getResolvedModules(fileContent, filePath, transformOptions.cacheFS);
|
||||
this._depGraphs.set(filePath, {
|
||||
fileContent,
|
||||
resolvedModuleNames,
|
||||
});
|
||||
}
|
||||
resolvedModuleNames.forEach((moduleName) => {
|
||||
constructingCacheKeyElements.push(exports.CACHE_KEY_EL_SEPARATOR, moduleName, exports.CACHE_KEY_EL_SEPARATOR, (0, fs_1.statSync)(moduleName).mtimeMs.toString());
|
||||
});
|
||||
}
|
||||
return (0, sha1_1.sha1)(...constructingCacheKeyElements);
|
||||
}
|
||||
async getCacheKeyAsync(sourceText, sourcePath, transformOptions) {
|
||||
return Promise.resolve(this.getCacheKey(sourceText, sourcePath, transformOptions));
|
||||
}
|
||||
}
|
||||
exports.TsJestTransformer = TsJestTransformer;
|
||||
Reference in New Issue
Block a user