@rstest/core
Version:
The Rsbuild-based test tool.
848 lines (834 loc) • 39.9 kB
JavaScript
import 'module';
/*#__PURE__*/ import.meta.url;
export const __webpack_ids__ = [
"854"
];
export const __webpack_modules__ = {
"./src/core/rsbuild.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
__webpack_require__.d(__webpack_exports__, {
r: ()=>createRsbuildServer,
z: ()=>prepareRsbuild
});
var core_ = __webpack_require__("@rsbuild/core");
var external_pathe_ = __webpack_require__("pathe");
var utils = __webpack_require__("./src/utils/index.ts");
const pluginBasic = (context)=>({
name: 'rstest:basic',
setup: (api)=>{
api.modifyRsbuildConfig(async (config)=>{
config.environments = {
[context.normalizedConfig.name]: {
output: {
target: 'node'
}
}
};
});
api.modifyEnvironmentConfig(async (config, { mergeEnvironmentConfig })=>mergeEnvironmentConfig(config, {
source: {
define: {
'import.meta.rstest': "global['@rstest/core']"
}
},
output: {
manifest: true,
sourceMap: {
js: 'source-map'
},
distPath: {
root: utils.Nk
}
},
tools: {
rspack: (config, { isProd, rspack })=>{
config.mode = isProd ? 'production' : 'development';
config.output ??= {};
config.output.iife = false;
config.output.importFunctionName = '__rstest_dynamic_import__';
config.output.devtoolModuleFilenameTemplate = '[absolute-resource-path]';
config.plugins.push(new rspack.experiments.RstestPlugin({
injectModulePathName: true,
importMetaPathName: true,
hoistMockModule: true,
manualMockRoot: external_pathe_["default"].resolve(context.rootPath, '__mocks__')
}));
config.module.parser ??= {};
config.module.parser.javascript = {
importDynamic: false,
requireDynamic: false,
requireAsExpression: false,
requireResolve: false,
...config.module.parser.javascript || {}
};
config.resolve ??= {};
config.resolve.extensions ??= [];
config.resolve.extensions.push('.cjs');
config.resolve.extensionAlias ??= {};
config.resolve.extensionAlias['.js'] = [
'.js',
'.ts',
'.tsx'
];
config.resolve.extensionAlias['.jsx'] = [
'.jsx',
'.tsx'
];
if ('node' === context.normalizedConfig.testEnvironment) config.resolve.mainFields = config.resolve.mainFields?.filter((filed)=>'module' !== filed) || [
'main'
];
config.resolve.byDependency ??= {};
config.resolve.byDependency.commonjs ??= {};
config.resolve.byDependency.commonjs.mainFields = [
'main',
'...'
];
config.optimization = {
moduleIds: 'named',
chunkIds: 'named',
nodeEnv: false,
...config.optimization || {},
runtimeChunk: {
name: 'runtime'
}
};
}
}
}));
}
});
var external_node_path_ = __webpack_require__("node:path");
var external_node_url_ = __webpack_require__("node:url");
const PLUGIN_CSS_FILTER = 'rstest:css-filter';
const css_filter_dirname = external_node_path_["default"].dirname((0, external_node_url_.fileURLToPath)(import.meta.url));
const pluginCSSFilter = ()=>({
name: PLUGIN_CSS_FILTER,
setup (api) {
api.modifyBundlerChain({
order: 'post',
handler: async (chain, { target, CHAIN_ID, environment })=>{
const emitCss = environment.config.output.emitCss ?? 'web' === target;
if (!emitCss) {
const ruleIds = [
CHAIN_ID.RULE.CSS,
CHAIN_ID.RULE.SASS,
CHAIN_ID.RULE.LESS,
CHAIN_ID.RULE.STYLUS
];
for (const ruleId of ruleIds){
if (!chain.module.rules.has(ruleId)) continue;
const rule = chain.module.rule(ruleId);
if (!rule.uses.has(CHAIN_ID.USE.CSS)) continue;
const cssLoaderOptions = rule.use(CHAIN_ID.USE.CSS).get('options');
if (cssLoaderOptions.modules && ('object' != typeof cssLoaderOptions.modules || false !== cssLoaderOptions.modules.auto)) rule.use('rstest-css-pre-filter').loader(external_node_path_["default"].join(css_filter_dirname, 'cssFilterLoader.mjs')).options({
modules: cssLoaderOptions.modules
}).after(ruleId);
}
}
}
});
}
});
class TestFileWatchPlugin {
contextToWatch = null;
constructor(contextToWatch){
this.contextToWatch = contextToWatch;
}
apply(compiler) {
compiler.hooks.afterCompile.tap('Rstest:TestFileWatchPlugin', (compilation)=>{
if (null === this.contextToWatch) return;
const contextDep = compilation.contextDependencies;
if (!contextDep.has(this.contextToWatch)) contextDep.add(this.contextToWatch);
});
}
}
const pluginEntryWatch = ({ isWatch, globTestSourceEntries, setupFiles })=>({
name: 'rstest:entry-watch',
setup: (api)=>{
api.modifyRspackConfig(async (config)=>{
if (isWatch) {
config.plugins.push(new TestFileWatchPlugin(api.context.rootPath));
config.entry = async ()=>{
const sourceEntries = await globTestSourceEntries();
return {
...sourceEntries,
...setupFiles
};
};
config.watchOptions ??= {};
config.watchOptions.ignored = (0, utils.XQ)(config.watchOptions.ignored || []);
if (0 === config.watchOptions.ignored.length) config.watchOptions.ignored.push('**/.git', '**/node_modules');
config.watchOptions.ignored.push(utils.f1);
} else {
config.watch = false;
config.watchOptions ??= {};
config.watchOptions.ignored = '**/**';
const sourceEntries = await globTestSourceEntries();
config.entry = {
...setupFiles,
...sourceEntries
};
}
});
}
});
const autoExternalNodeModules = ({ context, request, dependencyType, getResolve }, callback)=>{
if (!request) return callback();
if (request.startsWith('@swc/helpers/')) return callback();
const doExternal = (externalPath = request)=>{
callback(void 0, externalPath, 'commonjs' === dependencyType ? 'commonjs' : 'import');
};
const resolver = getResolve?.();
if (!resolver) return callback();
resolver(context, request, (err, resolvePath)=>{
if (err) return callback();
if (resolvePath && /node_modules/.test(resolvePath)) return doExternal(resolvePath);
return callback();
});
};
function autoExternalNodeBuiltin({ request, dependencyType }, callback) {
if (!request) return void callback();
const isNodeBuiltin = utils.Tn.some((builtin)=>{
if ('string' == typeof builtin) return builtin === request;
return builtin.test(request);
});
if (isNodeBuiltin) callback(void 0, request, 'commonjs' === dependencyType ? 'commonjs' : 'module-import');
else callback();
}
const pluginExternal = (testEnvironment)=>({
name: 'rstest:external',
setup: (api)=>{
api.modifyRsbuildConfig(async (config, { mergeRsbuildConfig })=>mergeRsbuildConfig(config, {
output: {
externals: 'node' === testEnvironment ? [
autoExternalNodeModules
] : void 0
},
tools: {
rspack: (config)=>{
config.externals = (0, utils.XQ)(config.externals) || [];
config.externals.unshift({
'@rstest/core': 'global @rstest/core'
});
config.externalsPresets ??= {};
config.externalsPresets.node = false;
config.externals.push(autoExternalNodeBuiltin);
}
}
}));
}
});
class IgnoreModuleNotFoundErrorPlugin {
apply(compiler) {
compiler.hooks.done.tap('Rstest:IgnoreModuleNotFoundPlugin', (stats)=>{
for(let i = stats.compilation.errors.length - 1; i >= 0; i--)if (/Module not found/.test(stats.compilation.errors[i].message)) stats.compilation.errors.splice(i, 1);
});
}
}
const pluginIgnoreResolveError = {
name: 'rstest:ignore-resolve-error',
setup: (api)=>{
api.modifyRspackConfig(async (config)=>{
config.plugins.push(new IgnoreModuleNotFoundErrorPlugin());
config.optimization ??= {};
config.optimization.emitOnErrors = true;
config.ignoreWarnings ??= [];
config.ignoreWarnings.push(/Module not found/);
});
}
};
var external_node_inspector_ = __webpack_require__("node:inspector");
const enable = void 0 !== external_node_inspector_["default"].url();
const pluginInspect = ()=>enable ? {
name: 'rstest:inspect',
setup: (api)=>{
api.modifyRspackConfig(async (config)=>{
config.devtool = 'inline-source-map';
config.optimization ??= {};
config.optimization.splitChunks = {
...config.optimization.splitChunks || {},
maxSize: 1048576,
chunks: 'all'
};
});
}
} : null;
class MockRuntimeRspackPlugin {
apply(compiler) {
const { RuntimeModule } = compiler.webpack;
class RetestImportRuntimeModule extends RuntimeModule {
constructor(){
super('rstest runtime');
}
generate() {
return `
if (typeof __webpack_require__ === 'undefined') {
return;
}
const originalRequire = __webpack_require__;
__webpack_require__ = function(...args) {
try {
return originalRequire(...args);
} catch (e) {
const errMsg = e.message ?? e.toString();
if (errMsg.includes('__webpack_modules__[moduleId] is not a function')) {
throw new Error(\`Cannot find module '\${args[0]}'\`)
}
throw e;
}
};
Object.keys(originalRequire).forEach(key => {
__webpack_require__[key] = originalRequire[key];
});
__webpack_require__.rstest_original_modules = {};
__webpack_require__.rstest_reset_modules = () => {
const mockedIds = Object.keys(__webpack_require__.rstest_original_modules)
Object.keys(__webpack_module_cache__).forEach(id => {
// Do not reset mocks registry.
if (!mockedIds.includes(id)) {
delete __webpack_module_cache__[id];
}
});
}
__webpack_require__.rstest_unmock = (id) => {
delete __webpack_module_cache__[id]
}
__webpack_require__.rstest_require_actual = __webpack_require__.rstest_import_actual = (id) => {
const originalModule = __webpack_require__.rstest_original_modules[id];
// Use fallback module if the module is not mocked.
const fallbackMod = __webpack_require__(id);
return originalModule ? originalModule : fallbackMod;
}
__webpack_require__.rstest_exec = async (id, modFactory) => {
if (__webpack_module_cache__) {
let asyncFactory = __webpack_module_cache__[id];
if (asyncFactory && asyncFactory.constructor.name === 'AsyncFunction') {
await asyncFactory();
}
}
};
__webpack_require__.rstest_mock = (id, modFactory) => {
let requiredModule = undefined
try {
requiredModule = __webpack_require__(id);
} catch {
// TODO: non-resolved module
} finally {
__webpack_require__.rstest_original_modules[id] = requiredModule;
}
if (typeof modFactory === 'string' || typeof modFactory === 'number') {
__webpack_module_cache__[id] = { exports: __webpack_require__(modFactory) };
} else if (typeof modFactory === 'function') {
if (modFactory.constructor.name === 'AsyncFunction') {
__webpack_module_cache__[id] = async () => {
const exports = await modFactory();
__webpack_require__.r(exports);
__webpack_module_cache__[id] = { exports, id, loaded: true };
}
} else {
const exports = modFactory();
__webpack_require__.r(exports);
__webpack_module_cache__[id] = { exports, id, loaded: true };
}
}
};
__webpack_require__.rstest_do_mock = (id, modFactory) => {
let requiredModule = undefined
try {
requiredModule = __webpack_require__(id);
} catch {
// TODO: non-resolved module
} finally {
__webpack_require__.rstest_original_modules[id] = requiredModule;
}
if (typeof modFactory === 'string' || typeof modFactory === 'number') {
__webpack_module_cache__[id] = { exports: __webpack_require__(modFactory) };
} else if (typeof modFactory === 'function') {
const exports = modFactory();
__webpack_require__.r(exports);
__webpack_module_cache__[id] = { exports, id, loaded: true };
}
};
`;
}
}
compiler.hooks.thisCompilation.tap('CustomPlugin', (compilation)=>{
compilation.hooks.additionalTreeRuntimeRequirements.tap('CustomPlugin', (chunk)=>{
compilation.addRuntimeModule(chunk, new RetestImportRuntimeModule());
});
});
}
}
const pluginMockRuntime = {
name: 'rstest:mock-runtime',
setup: (api)=>{
api.modifyRspackConfig(async (config)=>{
config.plugins.push(new MockRuntimeRspackPlugin());
});
}
};
class RstestCacheControlPlugin {
apply(compiler) {
const { RuntimeModule } = compiler.webpack;
class RetestCacheControlModule extends RuntimeModule {
constructor(){
super('rstest_cache_control');
}
generate() {
return `
global.setupIds = [];
function __rstest_clean_core_cache__() {
if (typeof __webpack_require__ === 'undefined') {
return;
}
delete __webpack_module_cache__['@rstest/core'];
global.setupIds.forEach((id) => {
delete __webpack_module_cache__[id];
});
}
global.__rstest_clean_core_cache__ = __rstest_clean_core_cache__;
`;
}
}
compiler.hooks.thisCompilation.tap('CustomPlugin', (compilation)=>{
compilation.hooks.additionalTreeRuntimeRequirements.tap('CustomPlugin', (chunk)=>{
compilation.addRuntimeModule(chunk, new RetestCacheControlModule());
});
});
}
}
const pluginCacheControl = (setupFiles)=>({
name: 'rstest:cache-control',
setup: (api)=>{
api.transform({
test: setupFiles
}, ({ code })=>({
code: `
${code}
if (global.setupIds && __webpack_module__.id) {
global.setupIds.push(__webpack_module__.id);
}
`
}));
api.modifyRspackConfig(async (config)=>{
config.plugins.push(new RstestCacheControlPlugin());
});
}
});
function parseInlineSourceMap(code) {
const inlineSourceMapRegex = /\/\/# sourceMappingURL=data:application\/json(?:;charset=utf-8)?;base64,(.+)\s*$/m;
const match = code.match(inlineSourceMapRegex);
if (!match || !match[1]) return null;
try {
const base64Data = match[1];
const decodedStr = Buffer.from(base64Data, 'base64').toString('utf-8');
const sourceMap = JSON.parse(decodedStr);
return sourceMap;
} catch (_error) {
return null;
}
}
const isMultiCompiler = (compiler)=>'compilers' in compiler && Array.isArray(compiler.compilers);
const prepareRsbuild = async (context, globTestSourceEntries, setupFiles)=>{
const { command, normalizedConfig: { isolate, plugins, resolve, source, output, tools, testEnvironment, performance, dev = {} } } = context;
const debugMode = (0, utils.L1)();
core_.logger.level = debugMode ? 'verbose' : 'error';
const writeToDisk = dev.writeToDisk || debugMode;
const rsbuildInstance = await (0, core_.createRsbuild)({
callerName: 'rstest',
rsbuildConfig: {
tools,
resolve,
source,
output,
server: {
printUrls: false,
strictPort: false,
middlewareMode: true,
compress: false,
cors: false,
publicDir: false
},
dev: {
hmr: false,
writeToDisk
},
performance,
plugins: [
...plugins || [],
pluginBasic(context),
pluginIgnoreResolveError,
pluginMockRuntime,
pluginCSSFilter(),
pluginEntryWatch({
globTestSourceEntries,
setupFiles,
isWatch: 'watch' === command
}),
pluginExternal(testEnvironment),
!isolate ? pluginCacheControl(Object.values(setupFiles)) : null,
pluginInspect()
].filter(Boolean)
}
});
return rsbuildInstance;
};
const createRsbuildServer = async ({ name, globTestSourceEntries, setupFiles, rsbuildInstance, normalizedConfig })=>{
let rspackCompiler;
const rstestCompilerPlugin = {
name: 'rstest:compiler',
setup: (api)=>{
api.onAfterCreateCompiler(({ compiler })=>{
rspackCompiler = compiler;
});
}
};
rsbuildInstance.addPlugins([
rstestCompilerPlugin
]);
const devServer = await rsbuildInstance.createDevServer({
getPortSilently: true
});
if ((0, utils.L1)()) await rsbuildInstance.inspectConfig({
writeToDisk: true,
extraConfigs: {
rstest: normalizedConfig
}
});
if (!rspackCompiler) throw new Error('rspackCompiler was not initialized');
const outputFileSystem = isMultiCompiler(rspackCompiler) ? rspackCompiler.compilers[0].outputFileSystem : rspackCompiler.outputFileSystem;
if (!outputFileSystem) throw new Error(`Expect outputFileSystem to be defined, but got ${outputFileSystem}`);
const getRsbuildStats = async ({ fileFilters } = {})=>{
const stats = await devServer.environments[name].getStats();
const manifest = devServer.environments[name].context.manifest;
const { entrypoints, outputPath, assets, hash, time: buildTime } = stats.toJson({
all: false,
hash: true,
entrypoints: true,
outputPath: true,
assets: true,
relatedAssets: true,
cachedAssets: true,
timings: true
});
const readFile = async (fileName)=>new Promise((resolve, reject)=>{
outputFileSystem.readFile(fileName, (err, data)=>{
if (err) reject(err);
resolve('string' == typeof data ? data : data.toString());
});
});
const getEntryFiles = async ()=>{
const entryFiles = {};
const entries = Object.keys(manifest.entries);
for (const entry of entries){
const data = manifest.entries[entry];
entryFiles[entry] = ((data?.initial?.js || []).concat(data?.async?.js || []) || []).map((file)=>external_pathe_["default"].join(outputPath, file));
}
return entryFiles;
};
const entryFiles = await getEntryFiles();
const entries = [];
const setupEntries = [];
const sourceEntries = await globTestSourceEntries();
for (const entry of Object.keys(entrypoints)){
const e = entrypoints[entry];
const distPath = external_pathe_["default"].join(outputPath, e.assets[e.assets.length - 1].name);
if (setupFiles[entry]) setupEntries.push({
distPath,
testPath: setupFiles[entry],
files: entryFiles[entry]
});
else if (sourceEntries[entry]) {
if (fileFilters?.length && !fileFilters.includes(sourceEntries[entry])) continue;
entries.push({
distPath,
testPath: sourceEntries[entry],
files: entryFiles[entry]
});
}
}
const inlineSourceMap = 'inline-source-map' === stats.compilation.options.devtool;
const sourceMaps = Object.fromEntries((await Promise.all(assets.map(async (asset)=>{
const assetFilePath = external_pathe_["default"].join(outputPath, asset.name);
if (inlineSourceMap) {
const content = await readFile(assetFilePath);
return [
assetFilePath,
parseInlineSourceMap(content)
];
}
const sourceMapPath = asset?.info.related?.sourceMap?.[0];
if (sourceMapPath) {
const filePath = external_pathe_["default"].join(outputPath, sourceMapPath);
const sourceMap = await readFile(filePath);
return [
assetFilePath,
JSON.parse(sourceMap)
];
}
return [
assetFilePath,
null
];
}))).filter((asset)=>null !== asset[1]));
return {
hash,
entries,
setupEntries,
buildTime: buildTime,
assetFiles: Object.fromEntries(await Promise.all(assets.map(async (a)=>{
const filePath = external_pathe_["default"].join(outputPath, a.name);
return [
filePath,
await readFile(filePath)
];
}))),
sourceMaps,
getSourcemap: (sourcePath)=>sourceMaps[sourcePath] || null
};
};
return {
closeServer: devServer.close,
getRsbuildStats
};
};
},
"./src/pool/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
__webpack_require__.d(__webpack_exports__, {
K: ()=>createPool
});
var external_node_os_ = __webpack_require__("node:os");
var utils = __webpack_require__("./src/utils/index.ts");
var external_node_events_ = __webpack_require__("node:events");
var external_node_url_ = __webpack_require__("node:url");
var external_node_v8_ = __webpack_require__("node:v8");
var external_birpc_ = __webpack_require__("birpc");
var external_pathe_ = __webpack_require__("pathe");
var external_tinypool_ = __webpack_require__("tinypool");
const forks_filename = (0, external_node_url_.fileURLToPath)(import.meta.url);
const forks_dirname = (0, external_pathe_.dirname)(forks_filename);
function createChannel(rpcMethods) {
const emitter = new external_node_events_["default"]();
const cleanup = ()=>emitter.removeAllListeners();
const events = {
message: 'message',
response: 'response'
};
const channel = {
onMessage: (callback)=>{
emitter.on(events.message, callback);
},
postMessage: (message)=>{
emitter.emit(events.response, message);
}
};
(0, external_birpc_.createBirpc)(rpcMethods, {
serialize: external_node_v8_["default"].serialize,
deserialize: (v)=>external_node_v8_["default"].deserialize(Buffer.from(v)),
post (v) {
emitter.emit(events.message, v);
},
on (fn) {
emitter.on(events.response, fn);
}
});
return {
channel,
cleanup
};
}
const createForksPool = (poolOptions)=>{
const { maxWorkers: maxThreads, minWorkers: minThreads, env, execArgv = [], isolate = true } = poolOptions;
const options = {
runtime: 'child_process',
filename: (0, external_pathe_.resolve)(forks_dirname, './worker.js'),
env,
execArgv,
maxThreads,
minThreads,
concurrentTasksPerWorker: 1,
isolateWorkers: isolate
};
const pool = new external_tinypool_.Tinypool(options);
return {
name: 'forks',
runTest: async ({ options, rpcMethods })=>{
const { channel, cleanup } = createChannel(rpcMethods);
try {
return await pool.run(options, {
channel
});
} finally{
cleanup();
}
},
collectTests: async ({ options, rpcMethods })=>{
const { channel, cleanup } = createChannel(rpcMethods);
try {
return await pool.run(options, {
channel
});
} finally{
cleanup();
}
},
close: ()=>pool.destroy()
};
};
const getNumCpus = ()=>external_node_os_["default"].availableParallelism?.() ?? external_node_os_["default"].cpus().length;
const parseWorkers = (maxWorkers)=>{
const parsed = Number.parseInt(maxWorkers.toString(), 10);
if ('string' == typeof maxWorkers && maxWorkers.trim().endsWith('%')) {
const numCpus = getNumCpus();
const workers = Math.floor(parsed / 100 * numCpus);
return Math.max(workers, 1);
}
return parsed > 0 ? parsed : 1;
};
const getRuntimeConfig = (context)=>{
const { testNamePattern, testTimeout, passWithNoTests, retry, globals, clearMocks, resetMocks, restoreMocks, unstubEnvs, unstubGlobals, maxConcurrency, printConsoleTrace, disableConsoleIntercept, testEnvironment, hookTimeout, isolate } = context.normalizedConfig;
return {
testNamePattern,
testTimeout,
hookTimeout,
passWithNoTests,
retry,
globals,
clearMocks,
resetMocks,
restoreMocks,
unstubEnvs,
unstubGlobals,
maxConcurrency,
printConsoleTrace,
disableConsoleIntercept,
testEnvironment,
isolate
};
};
const filterAssetsByEntry = (entryInfo, assetFiles, setupAssets, sourceMaps, entryLength)=>{
const neededFiles = entryLength > 1 && entryInfo.files ? Object.fromEntries(Object.entries(assetFiles).filter(([key])=>entryInfo.files.includes(key) || setupAssets.includes(key))) : assetFiles;
const neededSourceMaps = entryLength > 1 ? Object.fromEntries(Object.entries(sourceMaps).filter(([key])=>neededFiles[key])) : sourceMaps;
return {
assetFiles: neededFiles,
sourceMaps: neededSourceMaps
};
};
const createPool = async ({ context, recommendWorkerCount = 1 / 0 })=>{
const execArgv = process.execArgv.filter((execArg)=>execArg.startsWith('--perf') || execArg.startsWith('--cpu-prof') || execArg.startsWith('--heap-prof') || execArg.startsWith('--diagnostic-dir'));
const numCpus = getNumCpus();
const { normalizedConfig: { pool: poolOptions, isolate }, reporters } = context;
const threadsCount = 'watch' === context.command ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
const recommendCount = 'watch' === context.command ? threadsCount : Math.min(recommendWorkerCount, threadsCount);
const maxWorkers = poolOptions.maxWorkers ? parseWorkers(poolOptions.maxWorkers) : recommendCount;
const minWorkers = poolOptions.minWorkers ? parseWorkers(poolOptions.minWorkers) : maxWorkers < recommendCount ? maxWorkers : recommendCount;
if (maxWorkers < minWorkers) throw `Invalid pool configuration: maxWorkers(${maxWorkers}) cannot be less than minWorkers(${minWorkers}).`;
const pool = createForksPool({
...poolOptions,
isolate,
maxWorkers,
minWorkers,
execArgv: [
...poolOptions?.execArgv ?? [],
...execArgv,
'--experimental-vm-modules',
'--experimental-import-meta-resolve',
'--no-warnings',
(0, utils.PA)() ? '--experimental-detect-module' : void 0
].filter(Boolean),
env: {
NODE_ENV: 'test',
FORCE_COLOR: '1',
...process.env
}
});
const runtimeConfig = getRuntimeConfig(context);
const rpcMethods = {
onTestCaseResult: async (result)=>{
await Promise.all(reporters.map((reporter)=>reporter.onTestCaseResult?.(result)));
},
onConsoleLog: async (log)=>{
await Promise.all(reporters.map((reporter)=>reporter.onUserConsoleLog?.(log)));
},
onTestFileStart: async (test)=>{
await Promise.all(reporters.map((reporter)=>reporter.onTestFileStart?.(test)));
},
onTestFileResult: async (test)=>{
await Promise.all(reporters.map((reporter)=>reporter.onTestFileResult?.(test)));
}
};
return {
runTests: async ({ entries, assetFiles, setupEntries, sourceMaps, updateSnapshot })=>{
const setupAssets = setupEntries.flatMap((entry)=>entry.files || []);
const entryLength = Object.keys(entries).length;
const results = await Promise.all(entries.map((entryInfo)=>{
const { assetFiles: neededFiles, sourceMaps: neededSourceMaps } = filterAssetsByEntry(entryInfo, assetFiles, setupAssets, sourceMaps, entryLength);
return pool.runTest({
options: {
entryInfo,
assetFiles: neededFiles,
context: {
rootPath: context.rootPath,
runtimeConfig: (0, utils.v8)(runtimeConfig)
},
type: 'run',
sourceMaps: neededSourceMaps,
setupEntries,
updateSnapshot
},
rpcMethods
}).catch((err)=>{
err.fullStack = true;
return {
testPath: entryInfo.testPath,
status: 'fail',
name: '',
results: [],
errors: [
err
]
};
});
}));
for (const result of results)if (result.snapshotResult) context.snapshotManager.add(result.snapshotResult);
const testResults = results.flatMap((r)=>r.results);
return {
results,
testResults
};
},
collectTests: async ({ entries, assetFiles, setupEntries, sourceMaps, updateSnapshot })=>{
const setupAssets = setupEntries.flatMap((entry)=>entry.files || []);
const entryLength = Object.keys(entries).length;
return Promise.all(entries.map((entryInfo)=>{
const { assetFiles: neededFiles, sourceMaps: neededSourceMaps } = filterAssetsByEntry(entryInfo, assetFiles, setupAssets, sourceMaps, entryLength);
return pool.collectTests({
options: {
entryInfo,
assetFiles: neededFiles,
context: {
rootPath: context.rootPath,
runtimeConfig: (0, utils.v8)(runtimeConfig)
},
type: 'collect',
sourceMaps: neededSourceMaps,
setupEntries,
updateSnapshot
},
rpcMethods
}).catch((err)=>{
err.fullStack = true;
return {
testPath: entryInfo.testPath,
tests: [],
errors: [
err
]
};
});
}));
},
close: ()=>pool.close()
};
};
}
};