vitest 4.0.0-beta.5 → 4.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +2 -2
- package/dist/chunks/{base.DMfOuRWD.js → base.BXI97p6t.js} +7 -16
- package/dist/chunks/{benchmark.CtuRzf-i.js → benchmark.UW6Ezvxy.js} +4 -9
- package/dist/chunks/{browser.d.Cawq_X_N.d.ts → browser.d.DOMmqJQx.d.ts} +1 -1
- package/dist/chunks/{cac.CKnbxhn2.js → cac.Dsn7ixFt.js} +38 -113
- package/dist/chunks/{cli-api.COn58yrl.js → cli-api.DfGJyldU.js} +829 -1232
- package/dist/chunks/{config.d.CKNVOKm0.d.ts → config.d._GBBbReY.d.ts} +1 -0
- package/dist/chunks/{console.Duv2dVIC.js → console.B0quX7yH.js} +32 -68
- package/dist/chunks/{coverage.B6cReEn1.js → coverage.Dvxug1RM.js} +210 -579
- package/dist/chunks/{creator.DUVZ6rfm.js → creator.KEg6n5IC.js} +28 -74
- package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
- package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
- package/dist/chunks/{globals.CJQ63oO0.js → globals.lgsmH00r.js} +5 -5
- package/dist/chunks/{index.QZr3S3vQ.js → index.AR8aAkCC.js} +2 -2
- package/dist/chunks/{index.DQhAfQQU.js → index.C3EbxYwt.js} +276 -607
- package/dist/chunks/{index.oWRWx-nj.js → index.CsFXYRkW.js} +17 -36
- package/dist/chunks/{index.DgN0Zk9a.js → index.D2B6d2vv.js} +14 -24
- package/dist/chunks/{index.BRtIe7r8.js → index.DfviD7lX.js} +55 -110
- package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
- package/dist/chunks/{moduleRunner.d.mmOmOGrW.d.ts → moduleRunner.d.CX4DuqOx.d.ts} +2 -2
- package/dist/chunks/{node.4JV5OXkt.js → node.BOqcT2jW.js} +1 -1
- package/dist/chunks/{plugin.d.CvOlgjxK.d.ts → plugin.d.vcD4xbMS.d.ts} +1 -1
- package/dist/chunks/{reporters.d.CYE9sT5z.d.ts → reporters.d.BC86JJdB.d.ts} +799 -758
- package/dist/chunks/{resolver.D5bG4zy5.js → resolver.Bx6lE0iq.js} +21 -64
- package/dist/chunks/{rpc.DGoW_Vl-.js → rpc.RpPylpp0.js} +7 -21
- package/dist/chunks/{runBaseTests.B3KcKqlF.js → runBaseTests.D6sfuWBM.js} +25 -54
- package/dist/chunks/{setup-common.lgPs-bYv.js → setup-common.hLGRxhC8.js} +9 -22
- package/dist/chunks/{startModuleRunner.C8FtT_BY.js → startModuleRunner.C8TW8zTN.js} +83 -205
- package/dist/chunks/{typechecker.BgoW4nTA.js → typechecker.DSo_maXz.js} +97 -209
- package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
- package/dist/chunks/{utils.B9FY3b73.js → utils.C7__0Iv5.js} +5 -14
- package/dist/chunks/{vi.DGAfBY4R.js → vi.BfdOiD4j.js} +110 -267
- package/dist/chunks/{vm.BKfKvaKl.js → vm.BHBje7cC.js} +73 -177
- package/dist/chunks/{worker.d.Db-UVmXc.d.ts → worker.d.BKu8cnnX.d.ts} +1 -1
- package/dist/chunks/{worker.d.D9QWnzAe.d.ts → worker.d.DYlqbejz.d.ts} +1 -1
- package/dist/cli.js +3 -3
- package/dist/config.d.ts +7 -7
- package/dist/coverage.d.ts +4 -4
- package/dist/coverage.js +2 -2
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +5 -5
- package/dist/module-evaluator.d.ts +3 -3
- package/dist/module-evaluator.js +33 -84
- package/dist/module-runner.js +2 -2
- package/dist/node.d.ts +11 -9
- package/dist/node.js +16 -27
- package/dist/reporters.d.ts +5 -5
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +23 -51
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +18 -34
- package/dist/workers/forks.js +4 -4
- package/dist/workers/runVmTests.js +19 -37
- package/dist/workers/threads.js +4 -4
- package/dist/workers/vmForks.js +7 -7
- package/dist/workers/vmThreads.js +7 -7
- package/dist/workers.d.ts +3 -3
- package/dist/workers.js +11 -11
- package/package.json +11 -11
|
@@ -23,7 +23,7 @@ import { isatty } from 'node:tty';
|
|
|
23
23
|
import EventEmitter from 'node:events';
|
|
24
24
|
import { c as createBirpc } from './index.Bgo3tNWt.js';
|
|
25
25
|
import Tinypool$1, { Tinypool } from 'tinypool';
|
|
26
|
-
import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.
|
|
26
|
+
import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.DSo_maXz.js';
|
|
27
27
|
import { MessageChannel } from 'node:worker_threads';
|
|
28
28
|
import { hasFailed } from '@vitest/runner/utils';
|
|
29
29
|
import { rootDir } from '../path.js';
|
|
@@ -33,9 +33,7 @@ import { r as resolveCoverageProviderModule } from './coverage.D_JHT54q.js';
|
|
|
33
33
|
function groupBy(collection, iteratee) {
|
|
34
34
|
return collection.reduce((acc, item) => {
|
|
35
35
|
const key = iteratee(item);
|
|
36
|
-
acc[key] ||= [];
|
|
37
|
-
acc[key].push(item);
|
|
38
|
-
return acc;
|
|
36
|
+
return acc[key] ||= [], acc[key].push(item), acc;
|
|
39
37
|
}, {});
|
|
40
38
|
}
|
|
41
39
|
function stdout() {
|
|
@@ -2384,8 +2382,7 @@ const isPackageListed = quansync(function* (name, cwd) {
|
|
|
2384
2382
|
isPackageListed.sync;
|
|
2385
2383
|
|
|
2386
2384
|
function getWorkersCountByPercentage(percent) {
|
|
2387
|
-
const maxWorkersCount = nodeos__default.availableParallelism?.() ?? nodeos__default.cpus().length;
|
|
2388
|
-
const workersCountByPercentage = Math.round(Number.parseInt(percent) / 100 * maxWorkersCount);
|
|
2385
|
+
const maxWorkersCount = nodeos__default.availableParallelism?.() ?? nodeos__default.cpus().length, workersCountByPercentage = Math.round(Number.parseInt(percent) / 100 * maxWorkersCount);
|
|
2389
2386
|
return Math.max(1, Math.min(maxWorkersCount, workersCountByPercentage));
|
|
2390
2387
|
}
|
|
2391
2388
|
|
|
@@ -2406,9 +2403,7 @@ async function groupFilesByEnv(files) {
|
|
|
2406
2403
|
if (envOptionsJson?.endsWith("*/"))
|
|
2407
2404
|
// Trim closing Docblock characters the above regex might have captured
|
|
2408
2405
|
envOptionsJson = envOptionsJson.slice(0, -2);
|
|
2409
|
-
const envOptions = JSON.parse(envOptionsJson || "null")
|
|
2410
|
-
const envKey = env === "happy-dom" ? "happyDOM" : env;
|
|
2411
|
-
const environment = {
|
|
2406
|
+
const envOptions = JSON.parse(envOptionsJson || "null"), envKey = env === "happy-dom" ? "happyDOM" : env, environment = {
|
|
2412
2407
|
name: env,
|
|
2413
2408
|
options: envOptions ? { [envKey]: envOptions } : null
|
|
2414
2409
|
};
|
|
@@ -2424,8 +2419,7 @@ async function groupFilesByEnv(files) {
|
|
|
2424
2419
|
return groupBy(filesWithEnv, ({ environment }) => environment.name);
|
|
2425
2420
|
}
|
|
2426
2421
|
|
|
2427
|
-
const created = /* @__PURE__ */ new Set();
|
|
2428
|
-
const promises = /* @__PURE__ */ new Map();
|
|
2422
|
+
const created = /* @__PURE__ */ new Set(), promises = /* @__PURE__ */ new Map();
|
|
2429
2423
|
function createFetchModuleFunction(resolver, cacheFs = false, tmpDir = join$1(tmpdir(), nanoid())) {
|
|
2430
2424
|
const cachedFsResults = /* @__PURE__ */ new Map();
|
|
2431
2425
|
return async (url, importer, environment, options) => {
|
|
@@ -2451,8 +2445,7 @@ function createFetchModuleFunction(resolver, cacheFs = false, tmpDir = join$1(tm
|
|
|
2451
2445
|
// so we do this first to resolve the module and check its `id`. The next call of
|
|
2452
2446
|
// `ensureEntryFromUrl` inside `fetchModule` is cached and should take no time
|
|
2453
2447
|
// This also makes it so externalized modules are inside the module graph.
|
|
2454
|
-
const moduleGraphModule = await environment.moduleGraph.ensureEntryFromUrl(unwrapId(url));
|
|
2455
|
-
const cached = !!moduleGraphModule.transformResult;
|
|
2448
|
+
const moduleGraphModule = await environment.moduleGraph.ensureEntryFromUrl(unwrapId(url)), cached = !!moduleGraphModule.transformResult;
|
|
2456
2449
|
// if url is already cached, we can just confirm it's also cached on the server
|
|
2457
2450
|
if (options?.cached && cached) return { cache: true };
|
|
2458
2451
|
if (moduleGraphModule.id) {
|
|
@@ -2465,29 +2458,15 @@ function createFetchModuleFunction(resolver, cacheFs = false, tmpDir = join$1(tm
|
|
|
2465
2458
|
const moduleRunnerModule = await fetchModule(environment, url, importer, {
|
|
2466
2459
|
...options,
|
|
2467
2460
|
inlineSourceMap: false
|
|
2468
|
-
}).catch(handleRollupError);
|
|
2469
|
-
const result = processResultSource(environment, moduleRunnerModule);
|
|
2461
|
+
}).catch(handleRollupError), result = processResultSource(environment, moduleRunnerModule);
|
|
2470
2462
|
if (!cacheFs || !("code" in result)) return result;
|
|
2471
2463
|
const code = result.code;
|
|
2472
2464
|
// to avoid serialising large chunks of code,
|
|
2473
2465
|
// we store them in a tmp file and read in the test thread
|
|
2474
2466
|
if (cachedFsResults.has(result.id)) return getCachedResult(result, cachedFsResults);
|
|
2475
|
-
const dir = join$1(tmpDir, environment.name);
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
if (!created.has(dir)) {
|
|
2479
|
-
mkdirSync(dir, { recursive: true });
|
|
2480
|
-
created.add(dir);
|
|
2481
|
-
}
|
|
2482
|
-
if (promises.has(tmp)) {
|
|
2483
|
-
await promises.get(tmp);
|
|
2484
|
-
cachedFsResults.set(result.id, tmp);
|
|
2485
|
-
return getCachedResult(result, cachedFsResults);
|
|
2486
|
-
}
|
|
2487
|
-
promises.set(tmp, atomicWriteFile(tmp, code).catch(() => writeFile(tmp, code, "utf-8")).finally(() => promises.delete(tmp)));
|
|
2488
|
-
await promises.get(tmp);
|
|
2489
|
-
cachedFsResults.set(result.id, tmp);
|
|
2490
|
-
return getCachedResult(result, cachedFsResults);
|
|
2467
|
+
const dir = join$1(tmpDir, environment.name), name = hash("sha1", result.id, "hex"), tmp = join$1(dir, name);
|
|
2468
|
+
if (!created.has(dir)) mkdirSync(dir, { recursive: true }), created.add(dir);
|
|
2469
|
+
return promises.has(tmp) ? (await promises.get(tmp), cachedFsResults.set(result.id, tmp), getCachedResult(result, cachedFsResults)) : (promises.set(tmp, atomicWriteFile(tmp, code).catch(() => writeFile(tmp, code, "utf-8")).finally(() => promises.delete(tmp))), await promises.get(tmp), cachedFsResults.set(result.id, tmp), getCachedResult(result, cachedFsResults));
|
|
2491
2470
|
};
|
|
2492
2471
|
}
|
|
2493
2472
|
let SOURCEMAPPING_URL = "sourceMa";
|
|
@@ -2514,15 +2493,12 @@ function inlineSourceMap(result) {
|
|
|
2514
2493
|
const map = result.map;
|
|
2515
2494
|
let code = result.code;
|
|
2516
2495
|
if (!map || !("version" in map) || code.includes(MODULE_RUNNER_SOURCEMAPPING_SOURCE)) return result;
|
|
2517
|
-
|
|
2518
|
-
OTHER_SOURCE_MAP_REGEXP.lastIndex = 0;
|
|
2519
|
-
if (OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
|
|
2496
|
+
if (OTHER_SOURCE_MAP_REGEXP.lastIndex = 0, OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
|
|
2520
2497
|
const sourceMap = { ...map };
|
|
2521
2498
|
// If the first line is not present on source maps, add simple 1:1 mapping ([0,0,0,0], [1,0,0,0])
|
|
2522
2499
|
// so that debuggers can be set to break on first line
|
|
2523
2500
|
if (sourceMap.mappings.startsWith(";")) sourceMap.mappings = `AAAA,CAAA${sourceMap.mappings}`;
|
|
2524
|
-
result.code = `${code.trimEnd()}\n${MODULE_RUNNER_SOURCEMAPPING_SOURCE}\n//# ${SOURCEMAPPING_URL}=${genSourceMapUrl(sourceMap)}\n
|
|
2525
|
-
return result;
|
|
2501
|
+
return result.code = `${code.trimEnd()}\n${MODULE_RUNNER_SOURCEMAPPING_SOURCE}\n//# ${SOURCEMAPPING_URL}=${genSourceMapUrl(sourceMap)}\n`, result;
|
|
2526
2502
|
}
|
|
2527
2503
|
function genSourceMapUrl(map) {
|
|
2528
2504
|
if (typeof map !== "string") map = JSON.stringify(map);
|
|
@@ -2542,9 +2518,7 @@ function getCachedResult(result, cachedFsResults) {
|
|
|
2542
2518
|
}
|
|
2543
2519
|
// serialize rollup error on server to preserve details as a test error
|
|
2544
2520
|
function handleRollupError(e) {
|
|
2545
|
-
|
|
2546
|
-
// eslint-disable-next-line no-throw-literal
|
|
2547
|
-
throw {
|
|
2521
|
+
throw e instanceof Error && ("plugin" in e || "frame" in e || "id" in e) ? {
|
|
2548
2522
|
name: e.name,
|
|
2549
2523
|
message: e.message,
|
|
2550
2524
|
stack: e.stack,
|
|
@@ -2555,8 +2529,7 @@ function handleRollupError(e) {
|
|
|
2555
2529
|
loc: e.loc,
|
|
2556
2530
|
frame: e.frame
|
|
2557
2531
|
}
|
|
2558
|
-
};
|
|
2559
|
-
throw e;
|
|
2532
|
+
} : e;
|
|
2560
2533
|
}
|
|
2561
2534
|
/**
|
|
2562
2535
|
* Performs an atomic write operation using the write-then-rename pattern.
|
|
@@ -2573,11 +2546,9 @@ function handleRollupError(e) {
|
|
|
2573
2546
|
* Added in https://github.com/vitest-dev/vitest/pull/7531
|
|
2574
2547
|
*/
|
|
2575
2548
|
async function atomicWriteFile(realFilePath, data) {
|
|
2576
|
-
const dir = dirname$1(realFilePath);
|
|
2577
|
-
const tmpFilePath = join$1(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
2549
|
+
const dir = dirname$1(realFilePath), tmpFilePath = join$1(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
2578
2550
|
try {
|
|
2579
|
-
await writeFile(tmpFilePath, data, "utf-8");
|
|
2580
|
-
await rename(tmpFilePath, realFilePath);
|
|
2551
|
+
await writeFile(tmpFilePath, data, "utf-8"), await rename(tmpFilePath, realFilePath);
|
|
2581
2552
|
} finally {
|
|
2582
2553
|
try {
|
|
2583
2554
|
if (await stat(tmpFilePath)) await unlink(tmpFilePath);
|
|
@@ -2587,8 +2558,7 @@ async function atomicWriteFile(realFilePath, data) {
|
|
|
2587
2558
|
|
|
2588
2559
|
// this is copy pasted from vite
|
|
2589
2560
|
function normalizeResolvedIdToUrl(environment, resolvedId) {
|
|
2590
|
-
const root = environment.config.root;
|
|
2591
|
-
const depsOptimizer = environment.depsOptimizer;
|
|
2561
|
+
const root = environment.config.root, depsOptimizer = environment.depsOptimizer;
|
|
2592
2562
|
let url;
|
|
2593
2563
|
// normalize all imports into resolved URLs
|
|
2594
2564
|
// e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`
|
|
@@ -2608,9 +2578,7 @@ function normalizeResolvedIdToUrl(environment, resolvedId) {
|
|
|
2608
2578
|
}
|
|
2609
2579
|
|
|
2610
2580
|
function createMethodsRPC(project, options = {}) {
|
|
2611
|
-
const ctx = project.vitest;
|
|
2612
|
-
const cacheFs = options.cacheFs ?? false;
|
|
2613
|
-
const fetch = createFetchModuleFunction(project._resolver, cacheFs, project.tmpDir);
|
|
2581
|
+
const ctx = project.vitest, cacheFs = options.cacheFs ?? false, fetch = createFetchModuleFunction(project._resolver, cacheFs, project.tmpDir);
|
|
2614
2582
|
return {
|
|
2615
2583
|
async fetch(url, importer, environmentName, options) {
|
|
2616
2584
|
const environment = project.vite.environments[environmentName];
|
|
@@ -2626,12 +2594,11 @@ function createMethodsRPC(project, options = {}) {
|
|
|
2626
2594
|
const environment = project.vite.environments[environmentName];
|
|
2627
2595
|
if (!environment) throw new Error(`The environment ${environmentName} was not defined in the Vite config.`);
|
|
2628
2596
|
const resolved = await environment.pluginContainer.resolveId(id, importer);
|
|
2629
|
-
|
|
2630
|
-
return {
|
|
2597
|
+
return resolved ? {
|
|
2631
2598
|
file: cleanUrl(resolved.id),
|
|
2632
2599
|
url: normalizeResolvedIdToUrl(environment, resolved.id),
|
|
2633
2600
|
id: resolved.id
|
|
2634
|
-
};
|
|
2601
|
+
} : null;
|
|
2635
2602
|
},
|
|
2636
2603
|
snapshotSaved(snapshot) {
|
|
2637
2604
|
ctx.snapshot.add(snapshot);
|
|
@@ -2642,8 +2609,7 @@ function createMethodsRPC(project, options = {}) {
|
|
|
2642
2609
|
async transform(id) {
|
|
2643
2610
|
const environment = project.vite.environments.__vitest_vm__;
|
|
2644
2611
|
if (!environment) throw new Error(`The VM environment was not defined in the Vite config. This is a bug in Vitest. Please, open a new issue with reproduction.`);
|
|
2645
|
-
const url = normalizeResolvedIdToUrl(environment, fileURLToPath$1(id));
|
|
2646
|
-
const result = await environment.transformRequest(url).catch(handleRollupError);
|
|
2612
|
+
const url = normalizeResolvedIdToUrl(environment, fileURLToPath$1(id)), result = await environment.transformRequest(url).catch(handleRollupError);
|
|
2647
2613
|
return { code: result?.code };
|
|
2648
2614
|
},
|
|
2649
2615
|
async onQueued(file) {
|
|
@@ -2681,12 +2647,10 @@ function createMethodsRPC(project, options = {}) {
|
|
|
2681
2647
|
}
|
|
2682
2648
|
|
|
2683
2649
|
function createChildProcessChannel$1(project, collect = false) {
|
|
2684
|
-
const emitter = new EventEmitter()
|
|
2685
|
-
const events = {
|
|
2650
|
+
const emitter = new EventEmitter(), events = {
|
|
2686
2651
|
message: "message",
|
|
2687
2652
|
response: "response"
|
|
2688
|
-
}
|
|
2689
|
-
const rpc = createBirpc(createMethodsRPC(project, {
|
|
2653
|
+
}, rpc = createBirpc(createMethodsRPC(project, {
|
|
2690
2654
|
cacheFs: true,
|
|
2691
2655
|
collect
|
|
2692
2656
|
}), {
|
|
@@ -2716,20 +2680,13 @@ function createChildProcessChannel$1(project, collect = false) {
|
|
|
2716
2680
|
onMessage: (callback) => emitter.on(events.message, callback),
|
|
2717
2681
|
postMessage: (message) => emitter.emit(events.response, message),
|
|
2718
2682
|
onClose: () => {
|
|
2719
|
-
emitter.removeAllListeners();
|
|
2720
|
-
rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
2683
|
+
emitter.removeAllListeners(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
2721
2684
|
}
|
|
2722
2685
|
};
|
|
2723
2686
|
return channel;
|
|
2724
2687
|
}
|
|
2725
2688
|
function createForksPool(vitest, { execArgv, env }) {
|
|
2726
|
-
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length
|
|
2727
|
-
const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
|
|
2728
|
-
const poolOptions = vitest.config.poolOptions?.forks ?? {};
|
|
2729
|
-
const maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount;
|
|
2730
|
-
const minThreads = poolOptions.minForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
|
|
2731
|
-
const worker = resolve(vitest.distPath, "workers/forks.js");
|
|
2732
|
-
const options = {
|
|
2689
|
+
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.forks ?? {}, maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.minForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/forks.js"), options = {
|
|
2733
2690
|
runtime: "child_process",
|
|
2734
2691
|
filename: resolve(vitest.distPath, "worker.js"),
|
|
2735
2692
|
teardown: "teardown",
|
|
@@ -2739,22 +2696,15 @@ function createForksPool(vitest, { execArgv, env }) {
|
|
|
2739
2696
|
execArgv: [...poolOptions.execArgv ?? [], ...execArgv],
|
|
2740
2697
|
terminateTimeout: vitest.config.teardownTimeout,
|
|
2741
2698
|
concurrentTasksPerWorker: 1
|
|
2742
|
-
};
|
|
2743
|
-
const isolated = poolOptions.isolate ?? true;
|
|
2699
|
+
}, isolated = poolOptions.isolate ?? true;
|
|
2744
2700
|
if (isolated) options.isolateWorkers = true;
|
|
2745
|
-
if (poolOptions.singleFork || !vitest.config.fileParallelism)
|
|
2746
|
-
|
|
2747
|
-
options.minThreads = 1;
|
|
2748
|
-
}
|
|
2749
|
-
const pool = new Tinypool(options);
|
|
2750
|
-
const runWithFiles = (name) => {
|
|
2701
|
+
if (poolOptions.singleFork || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
|
|
2702
|
+
const pool = new Tinypool(options), runWithFiles = (name) => {
|
|
2751
2703
|
let id = 0;
|
|
2752
2704
|
async function runFiles(project, config, files, environment, invalidates = []) {
|
|
2753
2705
|
const paths = files.map((f) => f.filepath);
|
|
2754
2706
|
vitest.state.clearFiles(project, paths);
|
|
2755
|
-
const channel = createChildProcessChannel$1(project, name === "collect")
|
|
2756
|
-
const workerId = ++id;
|
|
2757
|
-
const data = {
|
|
2707
|
+
const channel = createChildProcessChannel$1(project, name === "collect"), workerId = ++id, data = {
|
|
2758
2708
|
pool: "forks",
|
|
2759
2709
|
worker,
|
|
2760
2710
|
config,
|
|
@@ -2780,40 +2730,25 @@ function createForksPool(vitest, { execArgv, env }) {
|
|
|
2780
2730
|
return async (specs, invalidates) => {
|
|
2781
2731
|
// Cancel pending tasks from pool when possible
|
|
2782
2732
|
vitest.onCancel(() => pool.cancelPendingTasks());
|
|
2783
|
-
const configs = /* @__PURE__ */ new WeakMap()
|
|
2784
|
-
const getConfig = (project) => {
|
|
2733
|
+
const configs = /* @__PURE__ */ new WeakMap(), getConfig = (project) => {
|
|
2785
2734
|
if (configs.has(project)) return configs.get(project);
|
|
2786
|
-
const _config = project.getSerializableConfig();
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
return config;
|
|
2790
|
-
};
|
|
2791
|
-
const singleFork = specs.filter((spec) => spec.project.config.poolOptions?.forks?.singleFork);
|
|
2792
|
-
const multipleForks = specs.filter((spec) => !spec.project.config.poolOptions?.forks?.singleFork);
|
|
2735
|
+
const _config = project.getSerializableConfig(), config = wrapSerializableConfig(_config);
|
|
2736
|
+
return configs.set(project, config), config;
|
|
2737
|
+
}, singleFork = specs.filter((spec) => spec.project.config.poolOptions?.forks?.singleFork), multipleForks = specs.filter((spec) => !spec.project.config.poolOptions?.forks?.singleFork);
|
|
2793
2738
|
if (multipleForks.length) {
|
|
2794
|
-
const filesByEnv = await groupFilesByEnv(multipleForks);
|
|
2795
|
-
const files = Object.values(filesByEnv).flat();
|
|
2796
|
-
const results = [];
|
|
2739
|
+
const filesByEnv = await groupFilesByEnv(multipleForks), files = Object.values(filesByEnv).flat(), results = [];
|
|
2797
2740
|
if (isolated) results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
|
|
2798
2741
|
else {
|
|
2799
2742
|
// When isolation is disabled, we still need to isolate environments and workspace projects from each other.
|
|
2800
2743
|
// Tasks are still running parallel but environments are isolated between tasks.
|
|
2801
2744
|
const grouped = groupBy(files, ({ project, environment }) => project.name + environment.name + JSON.stringify(environment.options));
|
|
2802
|
-
for (const group of Object.values(grouped)) {
|
|
2803
|
-
// Push all files to pool's queue
|
|
2804
|
-
results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
|
|
2805
|
-
// Once all tasks are running or finished, recycle worker for isolation.
|
|
2806
|
-
// On-going workers will run in the previous environment.
|
|
2807
|
-
await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve));
|
|
2808
|
-
await pool.recycleWorkers();
|
|
2809
|
-
}
|
|
2745
|
+
for (const group of Object.values(grouped)) results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)))), await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve)), await pool.recycleWorkers();
|
|
2810
2746
|
}
|
|
2811
2747
|
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
2812
2748
|
if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
|
|
2813
2749
|
}
|
|
2814
2750
|
if (singleFork.length) {
|
|
2815
|
-
const filesByEnv = await groupFilesByEnv(singleFork);
|
|
2816
|
-
const envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
|
|
2751
|
+
const filesByEnv = await groupFilesByEnv(singleFork), envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
|
|
2817
2752
|
for (const env of envs) {
|
|
2818
2753
|
const files = filesByEnv[env];
|
|
2819
2754
|
if (!files?.length) continue;
|
|
@@ -2837,10 +2772,7 @@ function createForksPool(vitest, { execArgv, env }) {
|
|
|
2837
2772
|
}
|
|
2838
2773
|
|
|
2839
2774
|
function createWorkerChannel$1(project, collect) {
|
|
2840
|
-
const channel = new MessageChannel()
|
|
2841
|
-
const port = channel.port2;
|
|
2842
|
-
const workerPort = channel.port1;
|
|
2843
|
-
const rpc = createBirpc(createMethodsRPC(project, { collect }), {
|
|
2775
|
+
const channel = new MessageChannel(), port = channel.port2, workerPort = channel.port1, rpc = createBirpc(createMethodsRPC(project, { collect }), {
|
|
2844
2776
|
eventNames: ["onCancel"],
|
|
2845
2777
|
post(v) {
|
|
2846
2778
|
port.postMessage(v);
|
|
@@ -2852,9 +2784,7 @@ function createWorkerChannel$1(project, collect) {
|
|
|
2852
2784
|
});
|
|
2853
2785
|
project.vitest.onCancel((reason) => rpc.onCancel(reason));
|
|
2854
2786
|
const onClose = () => {
|
|
2855
|
-
port.close();
|
|
2856
|
-
workerPort.close();
|
|
2857
|
-
rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
2787
|
+
port.close(), workerPort.close(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
2858
2788
|
};
|
|
2859
2789
|
return {
|
|
2860
2790
|
workerPort,
|
|
@@ -2863,13 +2793,7 @@ function createWorkerChannel$1(project, collect) {
|
|
|
2863
2793
|
};
|
|
2864
2794
|
}
|
|
2865
2795
|
function createThreadsPool(vitest, { execArgv, env }) {
|
|
2866
|
-
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length
|
|
2867
|
-
const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
|
|
2868
|
-
const poolOptions = vitest.config.poolOptions?.threads ?? {};
|
|
2869
|
-
const maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount;
|
|
2870
|
-
const minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
|
|
2871
|
-
const worker = resolve(vitest.distPath, "workers/threads.js");
|
|
2872
|
-
const options = {
|
|
2796
|
+
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.threads ?? {}, maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/threads.js"), options = {
|
|
2873
2797
|
filename: resolve(vitest.distPath, "worker.js"),
|
|
2874
2798
|
teardown: "teardown",
|
|
2875
2799
|
useAtomics: poolOptions.useAtomics ?? false,
|
|
@@ -2879,22 +2803,15 @@ function createThreadsPool(vitest, { execArgv, env }) {
|
|
|
2879
2803
|
execArgv: [...poolOptions.execArgv ?? [], ...execArgv],
|
|
2880
2804
|
terminateTimeout: vitest.config.teardownTimeout,
|
|
2881
2805
|
concurrentTasksPerWorker: 1
|
|
2882
|
-
};
|
|
2883
|
-
const isolated = poolOptions.isolate ?? true;
|
|
2806
|
+
}, isolated = poolOptions.isolate ?? true;
|
|
2884
2807
|
if (isolated) options.isolateWorkers = true;
|
|
2885
|
-
if (poolOptions.singleThread || !vitest.config.fileParallelism)
|
|
2886
|
-
|
|
2887
|
-
options.minThreads = 1;
|
|
2888
|
-
}
|
|
2889
|
-
const pool = new Tinypool$1(options);
|
|
2890
|
-
const runWithFiles = (name) => {
|
|
2808
|
+
if (poolOptions.singleThread || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
|
|
2809
|
+
const pool = new Tinypool$1(options), runWithFiles = (name) => {
|
|
2891
2810
|
let id = 0;
|
|
2892
2811
|
async function runFiles(project, config, files, environment, invalidates = []) {
|
|
2893
2812
|
const paths = files.map((f) => f.filepath);
|
|
2894
2813
|
vitest.state.clearFiles(project, paths);
|
|
2895
|
-
const { workerPort, onClose } = createWorkerChannel$1(project, name === "collect")
|
|
2896
|
-
const workerId = ++id;
|
|
2897
|
-
const data = {
|
|
2814
|
+
const { workerPort, onClose } = createWorkerChannel$1(project, name === "collect"), workerId = ++id, data = {
|
|
2898
2815
|
pool: "threads",
|
|
2899
2816
|
worker,
|
|
2900
2817
|
port: workerPort,
|
|
@@ -2922,39 +2839,25 @@ function createThreadsPool(vitest, { execArgv, env }) {
|
|
|
2922
2839
|
return async (specs, invalidates) => {
|
|
2923
2840
|
// Cancel pending tasks from pool when possible
|
|
2924
2841
|
vitest.onCancel(() => pool.cancelPendingTasks());
|
|
2925
|
-
const configs = /* @__PURE__ */ new WeakMap()
|
|
2926
|
-
const getConfig = (project) => {
|
|
2842
|
+
const configs = /* @__PURE__ */ new WeakMap(), getConfig = (project) => {
|
|
2927
2843
|
if (configs.has(project)) return configs.get(project);
|
|
2928
2844
|
const config = project.serializedConfig;
|
|
2929
|
-
configs.set(project, config);
|
|
2930
|
-
|
|
2931
|
-
};
|
|
2932
|
-
const singleThreads = specs.filter((spec) => spec.project.config.poolOptions?.threads?.singleThread);
|
|
2933
|
-
const multipleThreads = specs.filter((spec) => !spec.project.config.poolOptions?.threads?.singleThread);
|
|
2845
|
+
return configs.set(project, config), config;
|
|
2846
|
+
}, singleThreads = specs.filter((spec) => spec.project.config.poolOptions?.threads?.singleThread), multipleThreads = specs.filter((spec) => !spec.project.config.poolOptions?.threads?.singleThread);
|
|
2934
2847
|
if (multipleThreads.length) {
|
|
2935
|
-
const filesByEnv = await groupFilesByEnv(multipleThreads);
|
|
2936
|
-
const files = Object.values(filesByEnv).flat();
|
|
2937
|
-
const results = [];
|
|
2848
|
+
const filesByEnv = await groupFilesByEnv(multipleThreads), files = Object.values(filesByEnv).flat(), results = [];
|
|
2938
2849
|
if (isolated) results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
|
|
2939
2850
|
else {
|
|
2940
2851
|
// When isolation is disabled, we still need to isolate environments and workspace projects from each other.
|
|
2941
2852
|
// Tasks are still running parallel but environments are isolated between tasks.
|
|
2942
2853
|
const grouped = groupBy(files, ({ project, environment }) => project.name + environment.name + JSON.stringify(environment.options));
|
|
2943
|
-
for (const group of Object.values(grouped)) {
|
|
2944
|
-
// Push all files to pool's queue
|
|
2945
|
-
results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
|
|
2946
|
-
// Once all tasks are running or finished, recycle worker for isolation.
|
|
2947
|
-
// On-going workers will run in the previous environment.
|
|
2948
|
-
await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve));
|
|
2949
|
-
await pool.recycleWorkers();
|
|
2950
|
-
}
|
|
2854
|
+
for (const group of Object.values(grouped)) results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)))), await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve)), await pool.recycleWorkers();
|
|
2951
2855
|
}
|
|
2952
2856
|
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
2953
2857
|
if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
|
|
2954
2858
|
}
|
|
2955
2859
|
if (singleThreads.length) {
|
|
2956
|
-
const filesByEnv = await groupFilesByEnv(singleThreads);
|
|
2957
|
-
const envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
|
|
2860
|
+
const filesByEnv = await groupFilesByEnv(singleThreads), envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
|
|
2958
2861
|
for (const env of envs) {
|
|
2959
2862
|
const files = filesByEnv[env];
|
|
2960
2863
|
if (!files?.length) continue;
|
|
@@ -2978,102 +2881,69 @@ function createThreadsPool(vitest, { execArgv, env }) {
|
|
|
2978
2881
|
}
|
|
2979
2882
|
|
|
2980
2883
|
function createTypecheckPool(vitest) {
|
|
2981
|
-
const promisesMap = /* @__PURE__ */ new WeakMap();
|
|
2982
|
-
const rerunTriggered = /* @__PURE__ */ new WeakSet();
|
|
2884
|
+
const promisesMap = /* @__PURE__ */ new WeakMap(), rerunTriggered = /* @__PURE__ */ new WeakSet();
|
|
2983
2885
|
async function onParseEnd(project, { files, sourceErrors }) {
|
|
2984
|
-
const checker = project.typechecker;
|
|
2985
|
-
|
|
2986
|
-
await vitest._testRun.updated(packs, events);
|
|
2987
|
-
if (!project.config.typecheck.ignoreSourceErrors) sourceErrors.forEach((error) => vitest.state.catchError(error, "Unhandled Source Error"));
|
|
2886
|
+
const checker = project.typechecker, { packs, events } = checker.getTestPacksAndEvents();
|
|
2887
|
+
if (await vitest._testRun.updated(packs, events), !project.config.typecheck.ignoreSourceErrors) sourceErrors.forEach((error) => vitest.state.catchError(error, "Unhandled Source Error"));
|
|
2988
2888
|
const processError = !hasFailed(files) && !sourceErrors.length && checker.getExitCode();
|
|
2989
2889
|
if (processError) {
|
|
2990
2890
|
const error = new Error(checker.getOutput());
|
|
2991
|
-
error.stack = "";
|
|
2992
|
-
vitest.state.catchError(error, "Typecheck Error");
|
|
2891
|
+
error.stack = "", vitest.state.catchError(error, "Typecheck Error");
|
|
2993
2892
|
}
|
|
2994
|
-
promisesMap.get(project)?.resolve();
|
|
2995
|
-
rerunTriggered.delete(project);
|
|
2996
2893
|
// triggered by TSC watcher, not Vitest watcher, so we need to emulate what Vitest does in this case
|
|
2997
|
-
if (vitest.config.watch && !vitest.runningPromise) {
|
|
2998
|
-
|
|
2999
|
-
await vitest.report("onWatcherStart", files, [...project.config.typecheck.ignoreSourceErrors ? [] : sourceErrors, ...vitest.state.getUnhandledErrors()]);
|
|
2894
|
+
if (promisesMap.get(project)?.resolve(), rerunTriggered.delete(project), vitest.config.watch && !vitest.runningPromise) {
|
|
2895
|
+
const modules = files.map((file) => vitest.state.getReportedEntity(file)).filter((e) => e?.type === "module"), state = vitest.isCancelling ? "interrupted" : modules.some((m) => !m.ok()) ? "failed" : "passed";
|
|
2896
|
+
await vitest.report("onTestRunEnd", modules, [], state), await vitest.report("onWatcherStart", files, [...project.config.typecheck.ignoreSourceErrors ? [] : sourceErrors, ...vitest.state.getUnhandledErrors()]);
|
|
3000
2897
|
}
|
|
3001
2898
|
}
|
|
3002
2899
|
async function createWorkspaceTypechecker(project, files) {
|
|
3003
2900
|
const checker = project.typechecker ?? new Typechecker(project);
|
|
3004
|
-
|
|
3005
|
-
project.typechecker = checker;
|
|
3006
|
-
checker.setFiles(files);
|
|
3007
|
-
checker.onParseStart(async () => {
|
|
2901
|
+
return project.typechecker ? checker : (project.typechecker = checker, checker.setFiles(files), checker.onParseStart(async () => {
|
|
3008
2902
|
const files = checker.getTestFiles();
|
|
3009
2903
|
for (const file of files) await vitest._testRun.enqueued(project, file);
|
|
3010
2904
|
await vitest._testRun.collected(project, files);
|
|
3011
|
-
})
|
|
3012
|
-
|
|
3013
|
-
checker.onWatcherRerun(async () => {
|
|
3014
|
-
rerunTriggered.add(project);
|
|
3015
|
-
if (!vitest.runningPromise) {
|
|
3016
|
-
vitest.state.clearErrors();
|
|
3017
|
-
await vitest.report("onWatcherRerun", files, "File change detected. Triggering rerun.");
|
|
3018
|
-
}
|
|
2905
|
+
}), checker.onParseEnd((result) => onParseEnd(project, result)), checker.onWatcherRerun(async () => {
|
|
2906
|
+
if (rerunTriggered.add(project), !vitest.runningPromise) vitest.state.clearErrors(), await vitest.report("onWatcherRerun", files, "File change detected. Triggering rerun.");
|
|
3019
2907
|
await checker.collectTests();
|
|
3020
2908
|
const testFiles = checker.getTestFiles();
|
|
3021
2909
|
for (const file of testFiles) await vitest._testRun.enqueued(project, file);
|
|
3022
2910
|
await vitest._testRun.collected(project, testFiles);
|
|
3023
2911
|
const { packs, events } = checker.getTestPacksAndEvents();
|
|
3024
2912
|
await vitest._testRun.updated(packs, events);
|
|
3025
|
-
});
|
|
3026
|
-
return checker;
|
|
2913
|
+
}), checker);
|
|
3027
2914
|
}
|
|
3028
2915
|
async function startTypechecker(project, files) {
|
|
3029
2916
|
if (project.typechecker) return;
|
|
3030
2917
|
const checker = await createWorkspaceTypechecker(project, files);
|
|
3031
|
-
await checker.collectTests();
|
|
3032
|
-
await checker.start();
|
|
2918
|
+
await checker.collectTests(), await checker.start();
|
|
3033
2919
|
}
|
|
3034
2920
|
async function collectTests(specs) {
|
|
3035
2921
|
const specsByProject = groupBy(specs, (spec) => spec.project.name);
|
|
3036
2922
|
for (const name in specsByProject) {
|
|
3037
|
-
const project = specsByProject[name][0].project;
|
|
3038
|
-
|
|
3039
|
-
const checker = await createWorkspaceTypechecker(project, files);
|
|
3040
|
-
checker.setFiles(files);
|
|
3041
|
-
await checker.collectTests();
|
|
2923
|
+
const project = specsByProject[name][0].project, files = specsByProject[name].map((spec) => spec.moduleId), checker = await createWorkspaceTypechecker(project, files);
|
|
2924
|
+
checker.setFiles(files), await checker.collectTests();
|
|
3042
2925
|
const testFiles = checker.getTestFiles();
|
|
3043
2926
|
vitest.state.collectFiles(project, testFiles);
|
|
3044
2927
|
}
|
|
3045
2928
|
}
|
|
3046
2929
|
async function runTests(specs) {
|
|
3047
|
-
const specsByProject = groupBy(specs, (spec) => spec.project.name);
|
|
3048
|
-
const promises = [];
|
|
2930
|
+
const specsByProject = groupBy(specs, (spec) => spec.project.name), promises = [];
|
|
3049
2931
|
for (const name in specsByProject) {
|
|
3050
|
-
const project = specsByProject[name][0].project
|
|
3051
|
-
const files = specsByProject[name].map((spec) => spec.moduleId);
|
|
3052
|
-
const promise = createDefer();
|
|
3053
|
-
// check that watcher actually triggered rerun
|
|
3054
|
-
const _p = new Promise((resolve) => {
|
|
2932
|
+
const project = specsByProject[name][0].project, files = specsByProject[name].map((spec) => spec.moduleId), promise = createDefer(), _p = new Promise((resolve) => {
|
|
3055
2933
|
const _i = setInterval(() => {
|
|
3056
|
-
if (!project.typechecker || rerunTriggered.has(project))
|
|
3057
|
-
resolve(true);
|
|
3058
|
-
clearInterval(_i);
|
|
3059
|
-
}
|
|
2934
|
+
if (!project.typechecker || rerunTriggered.has(project)) resolve(true), clearInterval(_i);
|
|
3060
2935
|
});
|
|
3061
2936
|
setTimeout(() => {
|
|
3062
|
-
resolve(false);
|
|
3063
|
-
clearInterval(_i);
|
|
2937
|
+
resolve(false), clearInterval(_i);
|
|
3064
2938
|
}, 500).unref();
|
|
3065
|
-
});
|
|
3066
|
-
const triggered = await _p;
|
|
2939
|
+
}), triggered = await _p;
|
|
3067
2940
|
if (project.typechecker && !triggered) {
|
|
3068
2941
|
const testFiles = project.typechecker.getTestFiles();
|
|
3069
2942
|
for (const file of testFiles) await vitest._testRun.enqueued(project, file);
|
|
3070
|
-
await vitest._testRun.collected(project, testFiles);
|
|
3071
|
-
await onParseEnd(project, project.typechecker.getResult());
|
|
2943
|
+
await vitest._testRun.collected(project, testFiles), await onParseEnd(project, project.typechecker.getResult());
|
|
3072
2944
|
continue;
|
|
3073
2945
|
}
|
|
3074
|
-
promises.push(promise);
|
|
3075
|
-
promisesMap.set(project, promise);
|
|
3076
|
-
promises.push(startTypechecker(project, files));
|
|
2946
|
+
promises.push(promise), promisesMap.set(project, promise), promises.push(startTypechecker(project, files));
|
|
3077
2947
|
}
|
|
3078
2948
|
await Promise.all(promises);
|
|
3079
2949
|
}
|
|
@@ -3117,8 +2987,7 @@ function stringToBytes(input, percentageReference) {
|
|
|
3117
2987
|
let [, numericString, trailingChars] = input.match(/(.*?)([^0-9.-]+)$/) || [];
|
|
3118
2988
|
if (trailingChars && numericString) {
|
|
3119
2989
|
const numericValue = Number.parseFloat(numericString);
|
|
3120
|
-
trailingChars = trailingChars.toLowerCase()
|
|
3121
|
-
switch (trailingChars) {
|
|
2990
|
+
switch (trailingChars = trailingChars.toLowerCase(), trailingChars) {
|
|
3122
2991
|
case "%":
|
|
3123
2992
|
input = numericValue / 100;
|
|
3124
2993
|
break;
|
|
@@ -3134,21 +3003,20 @@ function stringToBytes(input, percentageReference) {
|
|
|
3134
3003
|
}
|
|
3135
3004
|
}
|
|
3136
3005
|
} else input = Number.parseFloat(input);
|
|
3137
|
-
if (typeof input === "number") if (input <= 1 && input > 0)
|
|
3138
|
-
|
|
3139
|
-
|
|
3006
|
+
if (typeof input === "number") if (input <= 1 && input > 0) {
|
|
3007
|
+
if (percentageReference) return Math.floor(input * percentageReference);
|
|
3008
|
+
throw new Error("For a percentage based memory limit a percentageReference must be supplied");
|
|
3009
|
+
} else if (input > 1) return Math.floor(input);
|
|
3140
3010
|
else throw new Error("Unexpected numerical input for \"memoryLimit\"");
|
|
3141
3011
|
return null;
|
|
3142
3012
|
}
|
|
3143
3013
|
|
|
3144
3014
|
const suppressWarningsPath$1 = resolve(rootDir, "./suppress-warnings.cjs");
|
|
3145
3015
|
function createChildProcessChannel(project, collect) {
|
|
3146
|
-
const emitter = new EventEmitter()
|
|
3147
|
-
const events = {
|
|
3016
|
+
const emitter = new EventEmitter(), events = {
|
|
3148
3017
|
message: "message",
|
|
3149
3018
|
response: "response"
|
|
3150
|
-
}
|
|
3151
|
-
const rpc = createBirpc(createMethodsRPC(project, {
|
|
3019
|
+
}, rpc = createBirpc(createMethodsRPC(project, {
|
|
3152
3020
|
cacheFs: true,
|
|
3153
3021
|
collect
|
|
3154
3022
|
}), {
|
|
@@ -3178,20 +3046,13 @@ function createChildProcessChannel(project, collect) {
|
|
|
3178
3046
|
onMessage: (callback) => emitter.on(events.message, callback),
|
|
3179
3047
|
postMessage: (message) => emitter.emit(events.response, message),
|
|
3180
3048
|
onClose: () => {
|
|
3181
|
-
emitter.removeAllListeners();
|
|
3182
|
-
rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
3049
|
+
emitter.removeAllListeners(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
3183
3050
|
}
|
|
3184
3051
|
};
|
|
3185
3052
|
return { channel };
|
|
3186
3053
|
}
|
|
3187
3054
|
function createVmForksPool(vitest, { execArgv, env }) {
|
|
3188
|
-
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length
|
|
3189
|
-
const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
|
|
3190
|
-
const poolOptions = vitest.config.poolOptions?.vmForks ?? {};
|
|
3191
|
-
const maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount;
|
|
3192
|
-
const minThreads = poolOptions.maxForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
|
|
3193
|
-
const worker = resolve(vitest.distPath, "workers/vmForks.js");
|
|
3194
|
-
const options = {
|
|
3055
|
+
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.vmForks ?? {}, maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.maxForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/vmForks.js"), options = {
|
|
3195
3056
|
runtime: "child_process",
|
|
3196
3057
|
filename: resolve(vitest.distPath, "worker.js"),
|
|
3197
3058
|
maxThreads,
|
|
@@ -3209,19 +3070,13 @@ function createVmForksPool(vitest, { execArgv, env }) {
|
|
|
3209
3070
|
concurrentTasksPerWorker: 1,
|
|
3210
3071
|
maxMemoryLimitBeforeRecycle: getMemoryLimit$1(vitest.config) || void 0
|
|
3211
3072
|
};
|
|
3212
|
-
if (poolOptions.singleFork || !vitest.config.fileParallelism)
|
|
3213
|
-
|
|
3214
|
-
options.minThreads = 1;
|
|
3215
|
-
}
|
|
3216
|
-
const pool = new Tinypool$1(options);
|
|
3217
|
-
const runWithFiles = (name) => {
|
|
3073
|
+
if (poolOptions.singleFork || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
|
|
3074
|
+
const pool = new Tinypool$1(options), runWithFiles = (name) => {
|
|
3218
3075
|
let id = 0;
|
|
3219
3076
|
async function runFiles(project, config, files, environment, invalidates = []) {
|
|
3220
3077
|
const paths = files.map((f) => f.filepath);
|
|
3221
3078
|
vitest.state.clearFiles(project, paths);
|
|
3222
|
-
const { channel } = createChildProcessChannel(project, name === "collect")
|
|
3223
|
-
const workerId = ++id;
|
|
3224
|
-
const data = {
|
|
3079
|
+
const { channel } = createChildProcessChannel(project, name === "collect"), workerId = ++id, data = {
|
|
3225
3080
|
pool: "forks",
|
|
3226
3081
|
worker,
|
|
3227
3082
|
config,
|
|
@@ -3249,18 +3104,11 @@ function createVmForksPool(vitest, { execArgv, env }) {
|
|
|
3249
3104
|
return async (specs, invalidates) => {
|
|
3250
3105
|
// Cancel pending tasks from pool when possible
|
|
3251
3106
|
vitest.onCancel(() => pool.cancelPendingTasks());
|
|
3252
|
-
const configs = /* @__PURE__ */ new Map()
|
|
3253
|
-
const getConfig = (project) => {
|
|
3107
|
+
const configs = /* @__PURE__ */ new Map(), getConfig = (project) => {
|
|
3254
3108
|
if (configs.has(project)) return configs.get(project);
|
|
3255
|
-
const _config = project.serializedConfig;
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
return config;
|
|
3259
|
-
};
|
|
3260
|
-
const filesByEnv = await groupFilesByEnv(specs);
|
|
3261
|
-
const promises = Object.values(filesByEnv).flat();
|
|
3262
|
-
const results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)));
|
|
3263
|
-
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3109
|
+
const _config = project.serializedConfig, config = wrapSerializableConfig(_config);
|
|
3110
|
+
return configs.set(project, config), config;
|
|
3111
|
+
}, filesByEnv = await groupFilesByEnv(specs), promises = Object.values(filesByEnv).flat(), results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))), errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3264
3112
|
if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
|
|
3265
3113
|
};
|
|
3266
3114
|
};
|
|
@@ -3272,21 +3120,14 @@ function createVmForksPool(vitest, { execArgv, env }) {
|
|
|
3272
3120
|
};
|
|
3273
3121
|
}
|
|
3274
3122
|
function getMemoryLimit$1(config) {
|
|
3275
|
-
const memory = nodeos.totalmem();
|
|
3276
|
-
const limit = getWorkerMemoryLimit(config, "vmForks");
|
|
3277
|
-
if (typeof memory === "number") return stringToBytes(limit, config.watch ? memory / 2 : memory);
|
|
3278
|
-
// If totalmem is not supported we cannot resolve percentage based values like 0.5, "50%"
|
|
3279
|
-
if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") return stringToBytes(limit);
|
|
3123
|
+
const memory = nodeos.totalmem(), limit = getWorkerMemoryLimit(config, "vmForks");
|
|
3280
3124
|
// just ignore "memoryLimit" value because we cannot detect memory limit
|
|
3281
|
-
return null;
|
|
3125
|
+
return typeof memory === "number" ? stringToBytes(limit, config.watch ? memory / 2 : memory) : typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%" ? stringToBytes(limit) : null;
|
|
3282
3126
|
}
|
|
3283
3127
|
|
|
3284
3128
|
const suppressWarningsPath = resolve(rootDir, "./suppress-warnings.cjs");
|
|
3285
3129
|
function createWorkerChannel(project, collect) {
|
|
3286
|
-
const channel = new MessageChannel()
|
|
3287
|
-
const port = channel.port2;
|
|
3288
|
-
const workerPort = channel.port1;
|
|
3289
|
-
const rpc = createBirpc(createMethodsRPC(project, { collect }), {
|
|
3130
|
+
const channel = new MessageChannel(), port = channel.port2, workerPort = channel.port1, rpc = createBirpc(createMethodsRPC(project, { collect }), {
|
|
3290
3131
|
eventNames: ["onCancel"],
|
|
3291
3132
|
post(v) {
|
|
3292
3133
|
port.postMessage(v);
|
|
@@ -3298,9 +3139,7 @@ function createWorkerChannel(project, collect) {
|
|
|
3298
3139
|
});
|
|
3299
3140
|
project.vitest.onCancel((reason) => rpc.onCancel(reason));
|
|
3300
3141
|
function onClose() {
|
|
3301
|
-
workerPort.close();
|
|
3302
|
-
port.close();
|
|
3303
|
-
rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
3142
|
+
workerPort.close(), port.close(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
|
|
3304
3143
|
}
|
|
3305
3144
|
return {
|
|
3306
3145
|
workerPort,
|
|
@@ -3308,13 +3147,7 @@ function createWorkerChannel(project, collect) {
|
|
|
3308
3147
|
};
|
|
3309
3148
|
}
|
|
3310
3149
|
function createVmThreadsPool(vitest, { execArgv, env }) {
|
|
3311
|
-
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length
|
|
3312
|
-
const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
|
|
3313
|
-
const poolOptions = vitest.config.poolOptions?.vmThreads ?? {};
|
|
3314
|
-
const maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount;
|
|
3315
|
-
const minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
|
|
3316
|
-
const worker = resolve(vitest.distPath, "workers/vmThreads.js");
|
|
3317
|
-
const options = {
|
|
3150
|
+
const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.vmThreads ?? {}, maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/vmThreads.js"), options = {
|
|
3318
3151
|
filename: resolve(vitest.distPath, "worker.js"),
|
|
3319
3152
|
useAtomics: poolOptions.useAtomics ?? false,
|
|
3320
3153
|
maxThreads,
|
|
@@ -3332,19 +3165,13 @@ function createVmThreadsPool(vitest, { execArgv, env }) {
|
|
|
3332
3165
|
concurrentTasksPerWorker: 1,
|
|
3333
3166
|
maxMemoryLimitBeforeRecycle: getMemoryLimit(vitest.config) || void 0
|
|
3334
3167
|
};
|
|
3335
|
-
if (poolOptions.singleThread || !vitest.config.fileParallelism)
|
|
3336
|
-
|
|
3337
|
-
options.minThreads = 1;
|
|
3338
|
-
}
|
|
3339
|
-
const pool = new Tinypool$1(options);
|
|
3340
|
-
const runWithFiles = (name) => {
|
|
3168
|
+
if (poolOptions.singleThread || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
|
|
3169
|
+
const pool = new Tinypool$1(options), runWithFiles = (name) => {
|
|
3341
3170
|
let id = 0;
|
|
3342
3171
|
async function runFiles(project, config, files, environment, invalidates = []) {
|
|
3343
3172
|
const paths = files.map((f) => f.filepath);
|
|
3344
3173
|
vitest.state.clearFiles(project, paths);
|
|
3345
|
-
const { workerPort, onClose } = createWorkerChannel(project, name === "collect")
|
|
3346
|
-
const workerId = ++id;
|
|
3347
|
-
const data = {
|
|
3174
|
+
const { workerPort, onClose } = createWorkerChannel(project, name === "collect"), workerId = ++id, data = {
|
|
3348
3175
|
pool: "vmThreads",
|
|
3349
3176
|
worker,
|
|
3350
3177
|
port: workerPort,
|
|
@@ -3373,17 +3200,11 @@ function createVmThreadsPool(vitest, { execArgv, env }) {
|
|
|
3373
3200
|
return async (specs, invalidates) => {
|
|
3374
3201
|
// Cancel pending tasks from pool when possible
|
|
3375
3202
|
vitest.onCancel(() => pool.cancelPendingTasks());
|
|
3376
|
-
const configs = /* @__PURE__ */ new Map()
|
|
3377
|
-
const getConfig = (project) => {
|
|
3203
|
+
const configs = /* @__PURE__ */ new Map(), getConfig = (project) => {
|
|
3378
3204
|
if (configs.has(project)) return configs.get(project);
|
|
3379
3205
|
const config = project.serializedConfig;
|
|
3380
|
-
configs.set(project, config);
|
|
3381
|
-
|
|
3382
|
-
};
|
|
3383
|
-
const filesByEnv = await groupFilesByEnv(specs);
|
|
3384
|
-
const promises = Object.values(filesByEnv).flat();
|
|
3385
|
-
const results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)));
|
|
3386
|
-
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3206
|
+
return configs.set(project, config), config;
|
|
3207
|
+
}, filesByEnv = await groupFilesByEnv(specs), promises = Object.values(filesByEnv).flat(), results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))), errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
3387
3208
|
if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
|
|
3388
3209
|
};
|
|
3389
3210
|
};
|
|
@@ -3395,13 +3216,9 @@ function createVmThreadsPool(vitest, { execArgv, env }) {
|
|
|
3395
3216
|
};
|
|
3396
3217
|
}
|
|
3397
3218
|
function getMemoryLimit(config) {
|
|
3398
|
-
const memory = nodeos.totalmem();
|
|
3399
|
-
const limit = getWorkerMemoryLimit(config, "vmThreads");
|
|
3400
|
-
if (typeof memory === "number") return stringToBytes(limit, config.watch ? memory / 2 : memory);
|
|
3401
|
-
// If totalmem is not supported we cannot resolve percentage based values like 0.5, "50%"
|
|
3402
|
-
if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") return stringToBytes(limit);
|
|
3219
|
+
const memory = nodeos.totalmem(), limit = getWorkerMemoryLimit(config, "vmThreads");
|
|
3403
3220
|
// just ignore "memoryLimit" value because we cannot detect memory limit
|
|
3404
|
-
return null;
|
|
3221
|
+
return typeof memory === "number" ? stringToBytes(limit, config.watch ? memory / 2 : memory) : typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%" ? stringToBytes(limit) : null;
|
|
3405
3222
|
}
|
|
3406
3223
|
|
|
3407
3224
|
const builtinPools = [
|
|
@@ -3413,8 +3230,7 @@ const builtinPools = [
|
|
|
3413
3230
|
"typescript"
|
|
3414
3231
|
];
|
|
3415
3232
|
function getDefaultPoolName(project) {
|
|
3416
|
-
|
|
3417
|
-
return project.config.pool;
|
|
3233
|
+
return project.config.browser.enabled ? "browser" : project.config.pool;
|
|
3418
3234
|
}
|
|
3419
3235
|
function getFilePoolName(project) {
|
|
3420
3236
|
return getDefaultPoolName(project);
|
|
@@ -3427,26 +3243,15 @@ function createPool(ctx) {
|
|
|
3427
3243
|
vmThreads: null,
|
|
3428
3244
|
vmForks: null,
|
|
3429
3245
|
typescript: null
|
|
3430
|
-
}
|
|
3431
|
-
// in addition to resolve.conditions Vite also adds production/development,
|
|
3432
|
-
// see: https://github.com/vitejs/vite/blob/af2aa09575229462635b7cbb6d248ca853057ba2/packages/vite/src/node/plugins/resolve.ts#L1056-L1080
|
|
3433
|
-
const viteMajor = Number(version.split(".")[0]);
|
|
3434
|
-
const potentialConditions = new Set(viteMajor >= 6 ? ctx.vite.config.ssr.resolve?.conditions ?? [] : [
|
|
3246
|
+
}, viteMajor = Number(version.split(".")[0]), potentialConditions = new Set(viteMajor >= 6 ? ctx.vite.config.ssr.resolve?.conditions ?? [] : [
|
|
3435
3247
|
"production",
|
|
3436
3248
|
"development",
|
|
3437
3249
|
...ctx.vite.config.resolve.conditions
|
|
3438
|
-
])
|
|
3439
|
-
|
|
3440
|
-
if (condition === "production") return ctx.vite.config.isProduction;
|
|
3441
|
-
if (condition === "development") return !ctx.vite.config.isProduction;
|
|
3442
|
-
return true;
|
|
3250
|
+
]), conditions = [...potentialConditions].filter((condition) => {
|
|
3251
|
+
return condition === "production" ? ctx.vite.config.isProduction : condition === "development" ? !ctx.vite.config.isProduction : true;
|
|
3443
3252
|
}).map((condition) => {
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
}).flatMap((c) => ["--conditions", c]);
|
|
3447
|
-
// Instead of passing whole process.execArgv to the workers, pick allowed options.
|
|
3448
|
-
// Some options may crash worker, e.g. --prof, --title. nodejs/node#41103
|
|
3449
|
-
const execArgv = process.execArgv.filter((execArg) => execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir"));
|
|
3253
|
+
return viteMajor >= 6 && condition === "development|production" ? ctx.vite.config.isProduction ? "production" : "development" : condition;
|
|
3254
|
+
}).flatMap((c) => ["--conditions", c]), execArgv = process.execArgv.filter((execArg) => execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir"));
|
|
3450
3255
|
async function executeTests(method, files, invalidate) {
|
|
3451
3256
|
const options = {
|
|
3452
3257
|
execArgv: [...execArgv, ...conditions],
|
|
@@ -3462,8 +3267,7 @@ function createPool(ctx) {
|
|
|
3462
3267
|
};
|
|
3463
3268
|
// env are case-insensitive on Windows, but spawned processes don't support it
|
|
3464
3269
|
if (isWindows) for (const name in options.env) options.env[name.toUpperCase()] = options.env[name];
|
|
3465
|
-
const poolConcurrentPromises = /* @__PURE__ */ new Map();
|
|
3466
|
-
const customPools = /* @__PURE__ */ new Map();
|
|
3270
|
+
const poolConcurrentPromises = /* @__PURE__ */ new Map(), customPools = /* @__PURE__ */ new Map();
|
|
3467
3271
|
async function resolveCustomPool(filepath) {
|
|
3468
3272
|
if (customPools.has(filepath)) return customPools.get(filepath);
|
|
3469
3273
|
const pool = await ctx.runner.import(filepath);
|
|
@@ -3471,16 +3275,14 @@ function createPool(ctx) {
|
|
|
3471
3275
|
const poolInstance = await pool.default(ctx, options);
|
|
3472
3276
|
if (typeof poolInstance?.name !== "string") throw new TypeError(`Custom pool "${filepath}" should return an object with "name" property`);
|
|
3473
3277
|
if (typeof poolInstance?.[method] !== "function") throw new TypeError(`Custom pool "${filepath}" should return an object with "${method}" method`);
|
|
3474
|
-
customPools.set(filepath, poolInstance);
|
|
3475
|
-
return poolInstance;
|
|
3278
|
+
return customPools.set(filepath, poolInstance), poolInstance;
|
|
3476
3279
|
}
|
|
3477
3280
|
function getConcurrentPool(pool, fn) {
|
|
3478
3281
|
if (poolConcurrentPromises.has(pool)) return poolConcurrentPromises.get(pool);
|
|
3479
3282
|
const promise = fn().finally(() => {
|
|
3480
3283
|
poolConcurrentPromises.delete(pool);
|
|
3481
3284
|
});
|
|
3482
|
-
poolConcurrentPromises.set(pool, promise);
|
|
3483
|
-
return promise;
|
|
3285
|
+
return poolConcurrentPromises.set(pool, promise), promise;
|
|
3484
3286
|
}
|
|
3485
3287
|
function getCustomPool(pool) {
|
|
3486
3288
|
return getConcurrentPool(pool, () => resolveCustomPool(pool));
|
|
@@ -3491,9 +3293,7 @@ function createPool(ctx) {
|
|
|
3491
3293
|
return createBrowserPool(ctx);
|
|
3492
3294
|
});
|
|
3493
3295
|
}
|
|
3494
|
-
const groupedSpecifications = {}
|
|
3495
|
-
const groups = /* @__PURE__ */ new Set();
|
|
3496
|
-
const factories = {
|
|
3296
|
+
const groupedSpecifications = {}, groups = /* @__PURE__ */ new Set(), factories = {
|
|
3497
3297
|
vmThreads: () => createVmThreadsPool(ctx, options),
|
|
3498
3298
|
vmForks: () => createVmForksPool(ctx, options),
|
|
3499
3299
|
threads: () => createThreadsPool(ctx, options),
|
|
@@ -3502,12 +3302,9 @@ function createPool(ctx) {
|
|
|
3502
3302
|
};
|
|
3503
3303
|
for (const spec of files) {
|
|
3504
3304
|
const group = spec[0].config.sequence.groupOrder ?? 0;
|
|
3505
|
-
groups.add(group);
|
|
3506
|
-
groupedSpecifications[group] ??= [];
|
|
3507
|
-
groupedSpecifications[group].push(spec);
|
|
3305
|
+
groups.add(group), groupedSpecifications[group] ??= [], groupedSpecifications[group].push(spec);
|
|
3508
3306
|
}
|
|
3509
|
-
const Sequencer = ctx.config.sequence.sequencer;
|
|
3510
|
-
const sequencer = new Sequencer(ctx);
|
|
3307
|
+
const Sequencer = ctx.config.sequence.sequencer, sequencer = new Sequencer(ctx);
|
|
3511
3308
|
async function sortSpecs(specs) {
|
|
3512
3309
|
if (ctx.config.shard) {
|
|
3513
3310
|
if (!ctx.config.passWithNoTests && ctx.config.shard.count > specs.length) throw new Error(`--shard <count> must be a smaller than count of test files. Resolved ${specs.length} test files for --shard=${ctx.config.shard.index}/${ctx.config.shard.count}.`);
|
|
@@ -3528,25 +3325,18 @@ function createPool(ctx) {
|
|
|
3528
3325
|
};
|
|
3529
3326
|
specifications.forEach((specification) => {
|
|
3530
3327
|
const pool = specification[2].pool;
|
|
3531
|
-
filesByPool[pool] ??= [];
|
|
3532
|
-
|
|
3533
|
-
});
|
|
3534
|
-
await Promise.all(Object.entries(filesByPool).map(async (entry) => {
|
|
3328
|
+
filesByPool[pool] ??= [], filesByPool[pool].push(specification);
|
|
3329
|
+
}), await Promise.all(Object.entries(filesByPool).map(async (entry) => {
|
|
3535
3330
|
const [pool, files] = entry;
|
|
3536
3331
|
if (!files.length) return null;
|
|
3537
3332
|
const specs = await sortSpecs(files);
|
|
3538
3333
|
if (pool in factories) {
|
|
3539
3334
|
const factory = factories[pool];
|
|
3540
|
-
pools[pool] ??= factory();
|
|
3541
|
-
return pools[pool][method](specs, invalidate);
|
|
3542
|
-
}
|
|
3543
|
-
if (pool === "browser") {
|
|
3544
|
-
pools.browser ??= await getBrowserPool();
|
|
3545
|
-
return pools.browser[method](specs, invalidate);
|
|
3335
|
+
return pools[pool] ??= factory(), pools[pool][method](specs, invalidate);
|
|
3546
3336
|
}
|
|
3337
|
+
if (pool === "browser") return pools.browser ??= await getBrowserPool(), pools.browser[method](specs, invalidate);
|
|
3547
3338
|
const poolHandler = await getCustomPool(pool);
|
|
3548
|
-
pools[poolHandler.name] ??= poolHandler;
|
|
3549
|
-
return poolHandler[method](specs, invalidate);
|
|
3339
|
+
return pools[poolHandler.name] ??= poolHandler, poolHandler[method](specs, invalidate);
|
|
3550
3340
|
}));
|
|
3551
3341
|
}
|
|
3552
3342
|
}
|
|
@@ -3567,12 +3357,9 @@ class BaseSequencer {
|
|
|
3567
3357
|
}
|
|
3568
3358
|
// async so it can be extended by other sequelizers
|
|
3569
3359
|
async shard(files) {
|
|
3570
|
-
const { config } = this.ctx;
|
|
3571
|
-
const { index, count } = config.shard;
|
|
3572
|
-
const [shardStart, shardEnd] = this.calculateShardRange(files.length, index, count);
|
|
3360
|
+
const { config } = this.ctx, { index, count } = config.shard, [shardStart, shardEnd] = this.calculateShardRange(files.length, index, count);
|
|
3573
3361
|
return [...files].map((spec) => {
|
|
3574
|
-
const fullPath = resolve$1(slash(config.root), slash(spec.moduleId));
|
|
3575
|
-
const specPath = fullPath?.slice(config.root.length);
|
|
3362
|
+
const fullPath = resolve$1(slash(config.root), slash(spec.moduleId)), specPath = fullPath?.slice(config.root.length);
|
|
3576
3363
|
return {
|
|
3577
3364
|
spec,
|
|
3578
3365
|
hash: hash("sha1", specPath, "hex")
|
|
@@ -3583,37 +3370,24 @@ class BaseSequencer {
|
|
|
3583
3370
|
async sort(files) {
|
|
3584
3371
|
const cache = this.ctx.cache;
|
|
3585
3372
|
return [...files].sort((a, b) => {
|
|
3586
|
-
const keyA = `${a.project.name}:${relative(this.ctx.config.root, a.moduleId)}
|
|
3587
|
-
const keyB = `${b.project.name}:${relative(this.ctx.config.root, b.moduleId)}`;
|
|
3588
|
-
const aState = cache.getFileTestResults(keyA);
|
|
3589
|
-
const bState = cache.getFileTestResults(keyB);
|
|
3373
|
+
const keyA = `${a.project.name}:${relative(this.ctx.config.root, a.moduleId)}`, keyB = `${b.project.name}:${relative(this.ctx.config.root, b.moduleId)}`, aState = cache.getFileTestResults(keyA), bState = cache.getFileTestResults(keyB);
|
|
3590
3374
|
if (!aState || !bState) {
|
|
3591
|
-
const statsA = cache.getFileStats(keyA);
|
|
3592
|
-
const statsB = cache.getFileStats(keyB);
|
|
3593
|
-
// run unknown first
|
|
3594
|
-
if (!statsA || !statsB) return !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0;
|
|
3375
|
+
const statsA = cache.getFileStats(keyA), statsB = cache.getFileStats(keyB);
|
|
3595
3376
|
// run larger files first
|
|
3596
|
-
return statsB.size - statsA.size;
|
|
3377
|
+
return !statsA || !statsB ? !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0 : statsB.size - statsA.size;
|
|
3597
3378
|
}
|
|
3598
|
-
// run failed first
|
|
3599
|
-
if (aState.failed && !bState.failed) return -1;
|
|
3600
|
-
if (!aState.failed && bState.failed) return 1;
|
|
3601
3379
|
// run longer first
|
|
3602
|
-
return bState.duration - aState.duration;
|
|
3380
|
+
return aState.failed && !bState.failed ? -1 : !aState.failed && bState.failed ? 1 : bState.duration - aState.duration;
|
|
3603
3381
|
});
|
|
3604
3382
|
}
|
|
3605
3383
|
// Calculate distributed shard range [start, end] distributed equally
|
|
3606
3384
|
calculateShardRange(filesCount, index, count) {
|
|
3607
|
-
const baseShardSize = Math.floor(filesCount / count);
|
|
3608
|
-
const remainderTestFilesCount = filesCount % count;
|
|
3385
|
+
const baseShardSize = Math.floor(filesCount / count), remainderTestFilesCount = filesCount % count;
|
|
3609
3386
|
if (remainderTestFilesCount >= index) {
|
|
3610
|
-
const shardSize = baseShardSize + 1;
|
|
3611
|
-
const shardStart = shardSize * (index - 1);
|
|
3612
|
-
const shardEnd = shardSize * index;
|
|
3387
|
+
const shardSize = baseShardSize + 1, shardStart = shardSize * (index - 1), shardEnd = shardSize * index;
|
|
3613
3388
|
return [shardStart, shardEnd];
|
|
3614
3389
|
}
|
|
3615
|
-
const shardStart = remainderTestFilesCount * (baseShardSize + 1) + (index - remainderTestFilesCount - 1) * baseShardSize;
|
|
3616
|
-
const shardEnd = shardStart + baseShardSize;
|
|
3390
|
+
const shardStart = remainderTestFilesCount * (baseShardSize + 1) + (index - remainderTestFilesCount - 1) * baseShardSize, shardEnd = shardStart + baseShardSize;
|
|
3617
3391
|
return [shardStart, shardEnd];
|
|
3618
3392
|
}
|
|
3619
3393
|
}
|
|
@@ -3633,11 +3407,10 @@ function parseInspector(inspect) {
|
|
|
3633
3407
|
if (typeof inspect === "number") return { port: inspect };
|
|
3634
3408
|
if (inspect.match(/https?:\//)) throw new Error(`Inspector host cannot be a URL. Use "host:port" instead of "${inspect}"`);
|
|
3635
3409
|
const [host, port] = inspect.split(":");
|
|
3636
|
-
|
|
3637
|
-
return {
|
|
3410
|
+
return port ? {
|
|
3638
3411
|
host,
|
|
3639
3412
|
port: Number(port) || defaultInspectPort
|
|
3640
|
-
};
|
|
3413
|
+
} : { host };
|
|
3641
3414
|
}
|
|
3642
3415
|
function resolveApiServerConfig(options, defaultPort) {
|
|
3643
3416
|
let api;
|
|
@@ -3655,12 +3428,10 @@ function resolveApiServerConfig(options, defaultPort) {
|
|
|
3655
3428
|
return api;
|
|
3656
3429
|
}
|
|
3657
3430
|
function resolveInlineWorkerOption(value) {
|
|
3658
|
-
|
|
3659
|
-
else return Number(value);
|
|
3431
|
+
return typeof value === "string" && value.trim().endsWith("%") ? getWorkersCountByPercentage(value) : Number(value);
|
|
3660
3432
|
}
|
|
3661
3433
|
function resolveConfig$1(vitest, options, viteConfig) {
|
|
3662
|
-
const mode = vitest.mode;
|
|
3663
|
-
const logger = vitest.logger;
|
|
3434
|
+
const mode = vitest.mode, logger = vitest.logger;
|
|
3664
3435
|
if (options.dom) {
|
|
3665
3436
|
if (viteConfig.test?.environment != null && viteConfig.test.environment !== "happy-dom") logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} Your config.test.environment ("${viteConfig.test.environment}") conflicts with --dom flag ("happy-dom"), ignoring "${viteConfig.test.environment}"`));
|
|
3666
3437
|
options.environment = "happy-dom";
|
|
@@ -3671,25 +3442,17 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3671
3442
|
root: viteConfig.root,
|
|
3672
3443
|
mode
|
|
3673
3444
|
};
|
|
3674
|
-
resolved.project = toArray(resolved.project);
|
|
3675
|
-
resolved.provide ??= {};
|
|
3676
|
-
resolved.name = typeof options.name === "string" ? options.name : options.name?.label || "";
|
|
3677
|
-
resolved.color = typeof options.name !== "string" ? options.name?.color : void 0;
|
|
3678
|
-
if (resolved.environment === "browser") throw new Error(`Looks like you set "test.environment" to "browser". To enabled Browser Mode, use "test.browser.enabled" instead.`);
|
|
3445
|
+
if (resolved.project = toArray(resolved.project), resolved.provide ??= {}, resolved.name = typeof options.name === "string" ? options.name : options.name?.label || "", resolved.color = typeof options.name !== "string" ? options.name?.color : void 0, resolved.environment === "browser") throw new Error(`Looks like you set "test.environment" to "browser". To enabled Browser Mode, use "test.browser.enabled" instead.`);
|
|
3679
3446
|
const inspector = resolved.inspect || resolved.inspectBrk;
|
|
3680
|
-
resolved.inspector = {
|
|
3447
|
+
if (resolved.inspector = {
|
|
3681
3448
|
...resolved.inspector,
|
|
3682
3449
|
...parseInspector(inspector),
|
|
3683
3450
|
enabled: !!inspector,
|
|
3684
3451
|
waitForDebugger: options.inspector?.waitForDebugger ?? !!resolved.inspectBrk
|
|
3685
|
-
};
|
|
3686
|
-
if (
|
|
3687
|
-
resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true;
|
|
3688
|
-
if (options.shard) {
|
|
3452
|
+
}, viteConfig.base !== "/") resolved.base = viteConfig.base;
|
|
3453
|
+
if (resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true, options.shard) {
|
|
3689
3454
|
if (resolved.watch) throw new Error("You cannot use --shard option with enabled watch");
|
|
3690
|
-
const [indexString, countString] = options.shard.split("/");
|
|
3691
|
-
const index = Math.abs(Number.parseInt(indexString, 10));
|
|
3692
|
-
const count = Math.abs(Number.parseInt(countString, 10));
|
|
3455
|
+
const [indexString, countString] = options.shard.split("/"), index = Math.abs(Number.parseInt(indexString, 10)), count = Math.abs(Number.parseInt(countString, 10));
|
|
3693
3456
|
if (Number.isNaN(count) || count <= 0) throw new Error("--shard <count> must be a positive number");
|
|
3694
3457
|
if (Number.isNaN(index) || index <= 0 || index > count) throw new Error("--shard <index> must be a positive number less then <count>");
|
|
3695
3458
|
resolved.shard = {
|
|
@@ -3701,20 +3464,10 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3701
3464
|
if (resolved.mergeReports && resolved.watch) throw new Error(`Cannot merge reports with --watch enabled`);
|
|
3702
3465
|
if (resolved.maxWorkers) resolved.maxWorkers = resolveInlineWorkerOption(resolved.maxWorkers);
|
|
3703
3466
|
if (resolved.minWorkers) resolved.minWorkers = resolveInlineWorkerOption(resolved.minWorkers);
|
|
3704
|
-
|
|
3705
|
-
resolved.
|
|
3706
|
-
if (!resolved.fileParallelism) {
|
|
3707
|
-
// ignore user config, parallelism cannot be implemented without limiting workers
|
|
3708
|
-
resolved.maxWorkers = 1;
|
|
3709
|
-
resolved.minWorkers = 1;
|
|
3710
|
-
}
|
|
3711
|
-
if (resolved.maxConcurrency === 0) {
|
|
3712
|
-
logger.console.warn(c.yellow(`The option "maxConcurrency" cannot be set to 0. Using default value ${configDefaults.maxConcurrency} instead.`));
|
|
3713
|
-
resolved.maxConcurrency = configDefaults.maxConcurrency;
|
|
3714
|
-
}
|
|
3467
|
+
if (resolved.fileParallelism ??= mode !== "benchmark", !resolved.fileParallelism) resolved.maxWorkers = 1, resolved.minWorkers = 1;
|
|
3468
|
+
if (resolved.maxConcurrency === 0) logger.console.warn(c.yellow(`The option "maxConcurrency" cannot be set to 0. Using default value ${configDefaults.maxConcurrency} instead.`)), resolved.maxConcurrency = configDefaults.maxConcurrency;
|
|
3715
3469
|
if (resolved.inspect || resolved.inspectBrk) {
|
|
3716
|
-
const isSingleThread = resolved.pool === "threads" && resolved.poolOptions?.threads?.singleThread;
|
|
3717
|
-
const isSingleFork = resolved.pool === "forks" && resolved.poolOptions?.forks?.singleFork;
|
|
3470
|
+
const isSingleThread = resolved.pool === "threads" && resolved.poolOptions?.threads?.singleThread, isSingleFork = resolved.pool === "forks" && resolved.poolOptions?.forks?.singleFork;
|
|
3718
3471
|
if (resolved.fileParallelism && !isSingleThread && !isSingleFork) {
|
|
3719
3472
|
const inspectOption = `--inspect${resolved.inspectBrk ? "-brk" : ""}`;
|
|
3720
3473
|
throw new Error(`You cannot use ${inspectOption} without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"`);
|
|
@@ -3752,37 +3505,20 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3752
3505
|
} }, null, 2)}\n\n...or disable ${inspectOption}\n`);
|
|
3753
3506
|
}
|
|
3754
3507
|
}
|
|
3755
|
-
resolved.coverage.reporter = resolveCoverageReporters(resolved.coverage.reporter)
|
|
3756
|
-
if (resolved.coverage.enabled && resolved.coverage.reportsDirectory) {
|
|
3508
|
+
if (resolved.coverage.reporter = resolveCoverageReporters(resolved.coverage.reporter), resolved.coverage.enabled && resolved.coverage.reportsDirectory) {
|
|
3757
3509
|
const reportsDirectory = resolve$1(resolved.root, resolved.coverage.reportsDirectory);
|
|
3758
3510
|
if (reportsDirectory === resolved.root || reportsDirectory === process.cwd()) throw new Error(`You cannot set "coverage.reportsDirectory" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run`);
|
|
3759
3511
|
}
|
|
3760
3512
|
if (resolved.coverage.enabled && resolved.coverage.provider === "custom" && resolved.coverage.customProviderModule) resolved.coverage.customProviderModule = resolvePath(resolved.coverage.customProviderModule, resolved.root);
|
|
3761
|
-
resolved.expect ??= {};
|
|
3762
|
-
resolved.deps ??= {};
|
|
3763
|
-
resolved.deps.moduleDirectories ??= [];
|
|
3513
|
+
resolved.expect ??= {}, resolved.deps ??= {}, resolved.deps.moduleDirectories ??= [];
|
|
3764
3514
|
const envModuleDirectories = process.env.VITEST_MODULE_DIRECTORIES || process.env.npm_config_VITEST_MODULE_DIRECTORIES;
|
|
3765
3515
|
if (envModuleDirectories) resolved.deps.moduleDirectories.push(...envModuleDirectories.split(","));
|
|
3766
|
-
resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => {
|
|
3516
|
+
if (resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => {
|
|
3767
3517
|
if (!dir.startsWith("/")) dir = `/${dir}`;
|
|
3768
3518
|
if (!dir.endsWith("/")) dir += "/";
|
|
3769
3519
|
return normalize(dir);
|
|
3770
|
-
});
|
|
3771
|
-
if (
|
|
3772
|
-
resolved.deps.optimizer ??= {};
|
|
3773
|
-
resolved.deps.optimizer.ssr ??= {};
|
|
3774
|
-
resolved.deps.optimizer.ssr.enabled ??= false;
|
|
3775
|
-
resolved.deps.optimizer.client ??= {};
|
|
3776
|
-
resolved.deps.optimizer.client.enabled ??= false;
|
|
3777
|
-
resolved.deps.web ??= {};
|
|
3778
|
-
resolved.deps.web.transformAssets ??= true;
|
|
3779
|
-
resolved.deps.web.transformCss ??= true;
|
|
3780
|
-
resolved.deps.web.transformGlobPattern ??= [];
|
|
3781
|
-
resolved.setupFiles = toArray(resolved.setupFiles || []).map((file) => resolvePath(file, resolved.root));
|
|
3782
|
-
resolved.globalSetup = toArray(resolved.globalSetup || []).map((file) => resolvePath(file, resolved.root));
|
|
3783
|
-
// Add hard-coded default coverage exclusions. These cannot be overidden by user config.
|
|
3784
|
-
// Override original exclude array for cases where user re-uses same object in test.exclude.
|
|
3785
|
-
resolved.coverage.exclude = [
|
|
3520
|
+
}), !resolved.deps.moduleDirectories.includes("/node_modules/")) resolved.deps.moduleDirectories.push("/node_modules/");
|
|
3521
|
+
if (resolved.deps.optimizer ??= {}, resolved.deps.optimizer.ssr ??= {}, resolved.deps.optimizer.ssr.enabled ??= false, resolved.deps.optimizer.client ??= {}, resolved.deps.optimizer.client.enabled ??= false, resolved.deps.web ??= {}, resolved.deps.web.transformAssets ??= true, resolved.deps.web.transformCss ??= true, resolved.deps.web.transformGlobPattern ??= [], resolved.setupFiles = toArray(resolved.setupFiles || []).map((file) => resolvePath(file, resolved.root)), resolved.globalSetup = toArray(resolved.globalSetup || []).map((file) => resolvePath(file, resolved.root)), resolved.coverage.exclude = [
|
|
3786
3522
|
...resolved.coverage.exclude,
|
|
3787
3523
|
...resolved.setupFiles.map((file) => `${resolved.coverage.allowExternal ? "**/" : ""}${relative(resolved.root, file)}`),
|
|
3788
3524
|
...resolved.include,
|
|
@@ -3791,32 +3527,22 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3791
3527
|
"**/virtual:*",
|
|
3792
3528
|
"**/__x00__*",
|
|
3793
3529
|
"**/node_modules/**"
|
|
3794
|
-
].filter((pattern) => pattern != null);
|
|
3795
|
-
resolved.forceRerunTriggers = [...resolved.forceRerunTriggers, ...resolved.setupFiles];
|
|
3796
|
-
if (resolved.cliExclude) resolved.exclude.push(...resolved.cliExclude);
|
|
3530
|
+
].filter((pattern) => pattern != null), resolved.forceRerunTriggers = [...resolved.forceRerunTriggers, ...resolved.setupFiles], resolved.cliExclude) resolved.exclude.push(...resolved.cliExclude);
|
|
3797
3531
|
if (resolved.runner) resolved.runner = resolvePath(resolved.runner, resolved.root);
|
|
3798
|
-
resolved.attachmentsDir = resolve$1(resolved.root, resolved.attachmentsDir ?? ".vitest-attachments");
|
|
3799
|
-
if (resolved.
|
|
3800
|
-
resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
|
|
3801
|
-
if (resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) {
|
|
3802
|
-
resolved.snapshotFormat.plugins = [];
|
|
3532
|
+
if (resolved.attachmentsDir = resolve$1(resolved.root, resolved.attachmentsDir ?? ".vitest-attachments"), resolved.snapshotEnvironment) resolved.snapshotEnvironment = resolvePath(resolved.snapshotEnvironment, resolved.root);
|
|
3533
|
+
if (resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0, resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) {
|
|
3803
3534
|
// TODO: support it via separate config (like DiffOptions) or via `Function.toString()`
|
|
3804
|
-
if (typeof resolved.snapshotFormat.compareKeys === "function") throw new TypeError(`"snapshotFormat.compareKeys" function is not supported.`);
|
|
3535
|
+
if (resolved.snapshotFormat.plugins = [], typeof resolved.snapshotFormat.compareKeys === "function") throw new TypeError(`"snapshotFormat.compareKeys" function is not supported.`);
|
|
3805
3536
|
}
|
|
3806
3537
|
const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
|
|
3807
|
-
resolved.snapshotOptions = {
|
|
3538
|
+
if (resolved.snapshotOptions = {
|
|
3808
3539
|
expand: resolved.expandSnapshotDiff ?? false,
|
|
3809
3540
|
snapshotFormat: resolved.snapshotFormat || {},
|
|
3810
3541
|
updateSnapshot: isCI && !UPDATE_SNAPSHOT ? "none" : UPDATE_SNAPSHOT ? "all" : "new",
|
|
3811
3542
|
resolveSnapshotPath: options.resolveSnapshotPath,
|
|
3812
3543
|
snapshotEnvironment: null
|
|
3813
|
-
};
|
|
3814
|
-
resolved.
|
|
3815
|
-
resolved.snapshotSerializers = resolved.snapshotSerializers.map((file) => resolvePath(file, resolved.root));
|
|
3816
|
-
resolved.forceRerunTriggers.push(...resolved.snapshotSerializers);
|
|
3817
|
-
if (options.resolveSnapshotPath) delete resolved.resolveSnapshotPath;
|
|
3818
|
-
resolved.pool ??= "threads";
|
|
3819
|
-
if (process.env.VITEST_MAX_THREADS) resolved.poolOptions = {
|
|
3544
|
+
}, resolved.snapshotSerializers ??= [], resolved.snapshotSerializers = resolved.snapshotSerializers.map((file) => resolvePath(file, resolved.root)), resolved.forceRerunTriggers.push(...resolved.snapshotSerializers), options.resolveSnapshotPath) delete resolved.resolveSnapshotPath;
|
|
3545
|
+
if (resolved.pool ??= "threads", process.env.VITEST_MAX_THREADS) resolved.poolOptions = {
|
|
3820
3546
|
...resolved.poolOptions,
|
|
3821
3547
|
threads: {
|
|
3822
3548
|
...resolved.poolOptions?.threads,
|
|
@@ -3879,13 +3605,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3879
3605
|
resolved.benchmark = {
|
|
3880
3606
|
...benchmarkConfigDefaults,
|
|
3881
3607
|
...resolved.benchmark
|
|
3882
|
-
};
|
|
3883
|
-
// override test config
|
|
3884
|
-
resolved.coverage.enabled = false;
|
|
3885
|
-
resolved.typecheck.enabled = false;
|
|
3886
|
-
resolved.include = resolved.benchmark.include;
|
|
3887
|
-
resolved.exclude = resolved.benchmark.exclude;
|
|
3888
|
-
resolved.includeSource = resolved.benchmark.includeSource;
|
|
3608
|
+
}, resolved.coverage.enabled = false, resolved.typecheck.enabled = false, resolved.include = resolved.benchmark.include, resolved.exclude = resolved.benchmark.exclude, resolved.includeSource = resolved.benchmark.includeSource;
|
|
3889
3609
|
const reporters = Array.from(new Set([...toArray(resolved.benchmark.reporters), ...toArray(options.reporter)])).filter(Boolean);
|
|
3890
3610
|
if (reporters.length) resolved.benchmark.reporters = reporters;
|
|
3891
3611
|
else resolved.benchmark.reporters = ["default"];
|
|
@@ -3894,17 +3614,13 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3894
3614
|
if (options.compare) resolved.benchmark.compare = options.compare;
|
|
3895
3615
|
if (options.outputJson) resolved.benchmark.outputJson = options.outputJson;
|
|
3896
3616
|
}
|
|
3897
|
-
if (typeof resolved.diff === "string")
|
|
3898
|
-
resolved.diff = resolvePath(resolved.diff, resolved.root);
|
|
3899
|
-
resolved.forceRerunTriggers.push(resolved.diff);
|
|
3900
|
-
}
|
|
3617
|
+
if (typeof resolved.diff === "string") resolved.diff = resolvePath(resolved.diff, resolved.root), resolved.forceRerunTriggers.push(resolved.diff);
|
|
3901
3618
|
// the server has been created, we don't need to override vite.server options
|
|
3902
3619
|
const api = resolveApiServerConfig(options, defaultPort);
|
|
3903
|
-
resolved.api = {
|
|
3620
|
+
if (resolved.api = {
|
|
3904
3621
|
...api,
|
|
3905
3622
|
token: crypto.randomUUID()
|
|
3906
|
-
};
|
|
3907
|
-
if (options.related) resolved.related = toArray(options.related).map((file) => resolve$1(resolved.root, file));
|
|
3623
|
+
}, options.related) resolved.related = toArray(options.related).map((file) => resolve$1(resolved.root, file));
|
|
3908
3624
|
/*
|
|
3909
3625
|
* Reporters can be defined in many different ways:
|
|
3910
3626
|
* { reporter: 'json' }
|
|
@@ -3933,85 +3649,51 @@ function resolveConfig$1(vitest, options, viteConfig) {
|
|
|
3933
3649
|
if (mode !== "benchmark") {
|
|
3934
3650
|
// @ts-expect-error "reporter" is from CLI, should be absolute to the running directory
|
|
3935
3651
|
// it is passed down as "vitest --reporter ../reporter.js"
|
|
3936
|
-
const reportersFromCLI = resolved.reporter
|
|
3937
|
-
|
|
3938
|
-
// ./reporter.js || ../reporter.js, but not .reporters/reporter.js
|
|
3939
|
-
if (/^\.\.?\//.test(reporter)) return resolve$1(process.cwd(), reporter);
|
|
3940
|
-
return reporter;
|
|
3652
|
+
const reportersFromCLI = resolved.reporter, cliReporters = toArray(reportersFromCLI || []).map((reporter) => {
|
|
3653
|
+
return /^\.\.?\//.test(reporter) ? resolve$1(process.cwd(), reporter) : reporter;
|
|
3941
3654
|
});
|
|
3942
3655
|
if (cliReporters.length) resolved.reporters = Array.from(new Set(toArray(cliReporters))).filter(Boolean).map((reporter) => [reporter, {}]);
|
|
3943
3656
|
}
|
|
3944
3657
|
if (!resolved.reporters.length) {
|
|
3945
|
-
resolved.reporters.push(["default", {}]);
|
|
3946
3658
|
// also enable github-actions reporter as a default
|
|
3947
|
-
if (process.env.GITHUB_ACTIONS === "true") resolved.reporters.push(["github-actions", {}]);
|
|
3659
|
+
if (resolved.reporters.push(["default", {}]), process.env.GITHUB_ACTIONS === "true") resolved.reporters.push(["github-actions", {}]);
|
|
3948
3660
|
}
|
|
3949
3661
|
if (resolved.changed) resolved.passWithNoTests ??= true;
|
|
3950
|
-
resolved.css ??= {};
|
|
3951
|
-
if (typeof resolved.css === "object") {
|
|
3952
|
-
resolved.css.modules ??= {};
|
|
3953
|
-
resolved.css.modules.classNameStrategy ??= "stable";
|
|
3954
|
-
}
|
|
3662
|
+
if (resolved.css ??= {}, typeof resolved.css === "object") resolved.css.modules ??= {}, resolved.css.modules.classNameStrategy ??= "stable";
|
|
3955
3663
|
if (resolved.cache !== false) {
|
|
3956
3664
|
if (resolved.cache && typeof resolved.cache.dir === "string") vitest.logger.deprecate(`"cache.dir" is deprecated, use Vite's "cacheDir" instead if you want to change the cache director. Note caches will be written to "cacheDir\/vitest"`);
|
|
3957
3665
|
resolved.cache = { dir: viteConfig.cacheDir };
|
|
3958
3666
|
}
|
|
3959
|
-
resolved.sequence ??= {}
|
|
3960
|
-
if (resolved.sequence.shuffle && typeof resolved.sequence.shuffle === "object") {
|
|
3667
|
+
if (resolved.sequence ??= {}, resolved.sequence.shuffle && typeof resolved.sequence.shuffle === "object") {
|
|
3961
3668
|
const { files, tests } = resolved.sequence.shuffle;
|
|
3962
|
-
resolved.sequence.sequencer ??= files ? RandomSequencer : BaseSequencer;
|
|
3963
|
-
resolved.sequence.shuffle = tests;
|
|
3669
|
+
resolved.sequence.sequencer ??= files ? RandomSequencer : BaseSequencer, resolved.sequence.shuffle = tests;
|
|
3964
3670
|
}
|
|
3965
3671
|
if (!resolved.sequence?.sequencer)
|
|
3966
3672
|
// CLI flag has higher priority
|
|
3967
3673
|
resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
|
|
3968
|
-
resolved.sequence.groupOrder ??= 0;
|
|
3969
|
-
resolved.
|
|
3970
|
-
if (resolved.sequence.sequencer === RandomSequencer) resolved.sequence.seed ??= Date.now();
|
|
3971
|
-
resolved.typecheck = {
|
|
3674
|
+
if (resolved.sequence.groupOrder ??= 0, resolved.sequence.hooks ??= "stack", resolved.sequence.sequencer === RandomSequencer) resolved.sequence.seed ??= Date.now();
|
|
3675
|
+
if (resolved.typecheck = {
|
|
3972
3676
|
...configDefaults.typecheck,
|
|
3973
3677
|
...resolved.typecheck
|
|
3974
|
-
};
|
|
3975
|
-
resolved.
|
|
3976
|
-
resolved.typecheck.enabled ??= false;
|
|
3977
|
-
if (resolved.typecheck.enabled) logger.console.warn(c.yellow("Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it."));
|
|
3978
|
-
resolved.browser.enabled ??= false;
|
|
3979
|
-
resolved.browser.headless ??= isCI;
|
|
3980
|
-
resolved.browser.isolate ??= true;
|
|
3981
|
-
resolved.browser.fileParallelism ??= options.fileParallelism ?? mode !== "benchmark";
|
|
3982
|
-
// disable in headless mode by default, and if CI is detected
|
|
3983
|
-
resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI;
|
|
3984
|
-
if (resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve$1(resolved.root, resolved.browser.screenshotDirectory);
|
|
3678
|
+
}, resolved.typecheck ??= {}, resolved.typecheck.enabled ??= false, resolved.typecheck.enabled) logger.console.warn(c.yellow("Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it."));
|
|
3679
|
+
if (resolved.browser.enabled ??= false, resolved.browser.headless ??= isCI, resolved.browser.isolate ??= true, resolved.browser.fileParallelism ??= options.fileParallelism ?? mode !== "benchmark", resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI, resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve$1(resolved.root, resolved.browser.screenshotDirectory);
|
|
3985
3680
|
const isPreview = resolved.browser.provider === "preview";
|
|
3986
|
-
if (isPreview && resolved.browser.screenshotFailures === true)
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
} else resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui;
|
|
3994
|
-
resolved.browser.viewport ??= {};
|
|
3995
|
-
resolved.browser.viewport.width ??= 414;
|
|
3996
|
-
resolved.browser.viewport.height ??= 896;
|
|
3997
|
-
resolved.browser.locators ??= {};
|
|
3998
|
-
resolved.browser.locators.testIdAttribute ??= "data-testid";
|
|
3999
|
-
if (resolved.browser.enabled && provider === "stackblitz") resolved.browser.provider = "preview";
|
|
4000
|
-
resolved.browser.api = resolveApiServerConfig(resolved.browser, defaultBrowserPort) || { port: defaultBrowserPort };
|
|
3681
|
+
if (isPreview && resolved.browser.screenshotFailures === true) console.warn(c.yellow([
|
|
3682
|
+
`Browser provider "preview" doesn't support screenshots, `,
|
|
3683
|
+
`so "browser.screenshotFailures" option is forcefully disabled. `,
|
|
3684
|
+
`Set "browser.screenshotFailures" to false or remove it from the config to suppress this warning.`
|
|
3685
|
+
].join(""))), resolved.browser.screenshotFailures = false;
|
|
3686
|
+
else resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui;
|
|
3687
|
+
if (resolved.browser.viewport ??= {}, resolved.browser.viewport.width ??= 414, resolved.browser.viewport.height ??= 896, resolved.browser.locators ??= {}, resolved.browser.locators.testIdAttribute ??= "data-testid", resolved.browser.enabled && provider === "stackblitz") resolved.browser.provider = "preview";
|
|
4001
3688
|
// enable includeTaskLocation by default in UI mode
|
|
4002
|
-
if (resolved.browser.enabled) {
|
|
3689
|
+
if (resolved.browser.api = resolveApiServerConfig(resolved.browser, defaultBrowserPort) || { port: defaultBrowserPort }, resolved.browser.enabled) {
|
|
4003
3690
|
if (resolved.browser.ui) resolved.includeTaskLocation ??= true;
|
|
4004
3691
|
} else if (resolved.ui) resolved.includeTaskLocation ??= true;
|
|
4005
3692
|
const htmlReporter = toArray(resolved.reporters).some((reporter) => {
|
|
4006
|
-
|
|
4007
|
-
return false;
|
|
3693
|
+
return Array.isArray(reporter) ? reporter[0] === "html" : false;
|
|
4008
3694
|
});
|
|
4009
3695
|
if (htmlReporter) resolved.includeTaskLocation ??= true;
|
|
4010
|
-
resolved.server ??= {};
|
|
4011
|
-
resolved.server.deps ??= {};
|
|
4012
|
-
resolved.testTimeout ??= resolved.browser.enabled ? 15e3 : 5e3;
|
|
4013
|
-
resolved.hookTimeout ??= resolved.browser.enabled ? 3e4 : 1e4;
|
|
4014
|
-
return resolved;
|
|
3696
|
+
return resolved.server ??= {}, resolved.server.deps ??= {}, resolved.testTimeout ??= resolved.browser.enabled ? 15e3 : 5e3, resolved.hookTimeout ??= resolved.browser.enabled ? 3e4 : 1e4, resolved;
|
|
4015
3697
|
}
|
|
4016
3698
|
function isBrowserEnabled(config) {
|
|
4017
3699
|
return Boolean(config.browser?.enabled);
|
|
@@ -4047,14 +3729,11 @@ const THRESHOLD_KEYS = [
|
|
|
4047
3729
|
"functions",
|
|
4048
3730
|
"statements",
|
|
4049
3731
|
"branches"
|
|
4050
|
-
];
|
|
4051
|
-
const GLOBAL_THRESHOLDS_KEY = "global";
|
|
4052
|
-
const DEFAULT_PROJECT = Symbol.for("default-project");
|
|
3732
|
+
], GLOBAL_THRESHOLDS_KEY = "global", DEFAULT_PROJECT = Symbol.for("default-project");
|
|
4053
3733
|
let uniqueId = 0;
|
|
4054
3734
|
async function getCoverageProvider(options, loader) {
|
|
4055
3735
|
const coverageModule = await resolveCoverageProviderModule(options, loader);
|
|
4056
|
-
|
|
4057
|
-
return null;
|
|
3736
|
+
return coverageModule ? coverageModule.getProvider() : null;
|
|
4058
3737
|
}
|
|
4059
3738
|
class BaseCoverageProvider {
|
|
4060
3739
|
ctx;
|
|
@@ -4067,8 +3746,7 @@ class BaseCoverageProvider {
|
|
|
4067
3746
|
coverageFilesDirectory;
|
|
4068
3747
|
roots = [];
|
|
4069
3748
|
_initialize(ctx) {
|
|
4070
|
-
this.ctx = ctx
|
|
4071
|
-
if (ctx.version !== this.version) ctx.logger.warn(c.yellow(`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.
|
|
3749
|
+
if (this.ctx = ctx, ctx.version !== this.version) ctx.logger.warn(c.yellow(`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.
|
|
4072
3750
|
Running mixed versions is not supported and may lead into bugs
|
|
4073
3751
|
Update your dependencies and make sure the versions match.`));
|
|
4074
3752
|
const config = ctx.config.coverage;
|
|
@@ -4086,25 +3764,18 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4086
3764
|
statements: config.thresholds["100"] ? 100 : config.thresholds.statements
|
|
4087
3765
|
}
|
|
4088
3766
|
};
|
|
4089
|
-
const shard = this.ctx.config.shard
|
|
4090
|
-
const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
|
|
4091
|
-
this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory);
|
|
3767
|
+
const shard = this.ctx.config.shard, tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
|
|
4092
3768
|
// If --project filter is set pick only roots of resolved projects
|
|
4093
|
-
this.roots = ctx.config.project?.length ? [...new Set(ctx.projects.map((project) => project.config.root))] : [ctx.config.root];
|
|
3769
|
+
this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory), this.roots = ctx.config.project?.length ? [...new Set(ctx.projects.map((project) => project.config.root))] : [ctx.config.root];
|
|
4094
3770
|
}
|
|
4095
3771
|
/**
|
|
4096
3772
|
* Check if file matches `coverage.include` but not `coverage.exclude`
|
|
4097
3773
|
*/
|
|
4098
3774
|
isIncluded(_filename, root) {
|
|
4099
|
-
const roots = root ? [root] : this.roots;
|
|
4100
|
-
const filename = slash(_filename);
|
|
4101
|
-
const cacheHit = this.globCache.get(filename);
|
|
3775
|
+
const roots = root ? [root] : this.roots, filename = slash(_filename), cacheHit = this.globCache.get(filename);
|
|
4102
3776
|
if (cacheHit !== void 0) return cacheHit;
|
|
4103
3777
|
// File outside project root with default allowExternal
|
|
4104
|
-
if (this.options.allowExternal === false && roots.every((root) => !filename.startsWith(root)))
|
|
4105
|
-
this.globCache.set(filename, false);
|
|
4106
|
-
return false;
|
|
4107
|
-
}
|
|
3778
|
+
if (this.options.allowExternal === false && roots.every((root) => !filename.startsWith(root))) return this.globCache.set(filename, false), false;
|
|
4108
3779
|
// By default `coverage.include` matches all files, except "coverage.exclude"
|
|
4109
3780
|
const glob = this.options.include || "**";
|
|
4110
3781
|
let included = roots.some((root) => {
|
|
@@ -4116,9 +3787,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4116
3787
|
};
|
|
4117
3788
|
return pm.isMatch(filename, glob, options);
|
|
4118
3789
|
});
|
|
4119
|
-
included &&= existsSync(cleanUrl(filename));
|
|
4120
|
-
this.globCache.set(filename, included);
|
|
4121
|
-
return included;
|
|
3790
|
+
return included &&= existsSync(cleanUrl(filename)), this.globCache.set(filename, included), included;
|
|
4122
3791
|
}
|
|
4123
3792
|
async getUntestedFilesByRoot(testedFiles, include, root) {
|
|
4124
3793
|
let includedFiles = await glob(include, {
|
|
@@ -4128,15 +3797,12 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4128
3797
|
dot: true,
|
|
4129
3798
|
onlyFiles: true
|
|
4130
3799
|
});
|
|
4131
|
-
|
|
4132
|
-
includedFiles = includedFiles.filter((file) => this.isIncluded(file, root));
|
|
4133
|
-
if (this.ctx.config.changed) includedFiles = (this.ctx.config.related || []).filter((file) => includedFiles.includes(file));
|
|
3800
|
+
if (includedFiles = includedFiles.filter((file) => this.isIncluded(file, root)), this.ctx.config.changed) includedFiles = (this.ctx.config.related || []).filter((file) => includedFiles.includes(file));
|
|
4134
3801
|
return includedFiles.map((file) => slash(path.resolve(root, file)));
|
|
4135
3802
|
}
|
|
4136
3803
|
async getUntestedFiles(testedFiles) {
|
|
4137
3804
|
if (this.options.include == null) return [];
|
|
4138
|
-
const rootMapper = this.getUntestedFilesByRoot.bind(this, testedFiles, this.options.include);
|
|
4139
|
-
const matrix = await Promise.all(this.roots.map(rootMapper));
|
|
3805
|
+
const rootMapper = this.getUntestedFilesByRoot.bind(this, testedFiles, this.options.include), matrix = await Promise.all(this.roots.map(rootMapper));
|
|
4140
3806
|
return matrix.flatMap((files) => files);
|
|
4141
3807
|
}
|
|
4142
3808
|
createCoverageMap() {
|
|
@@ -4162,41 +3828,28 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4162
3828
|
force: true,
|
|
4163
3829
|
maxRetries: 10
|
|
4164
3830
|
});
|
|
4165
|
-
await promises$1.mkdir(this.coverageFilesDirectory, { recursive: true });
|
|
4166
|
-
this.coverageFiles = /* @__PURE__ */ new Map();
|
|
4167
|
-
this.pendingPromises = [];
|
|
3831
|
+
await promises$1.mkdir(this.coverageFilesDirectory, { recursive: true }), this.coverageFiles = /* @__PURE__ */ new Map(), this.pendingPromises = [];
|
|
4168
3832
|
}
|
|
4169
3833
|
onAfterSuiteRun({ coverage, environment, projectName, testFiles }) {
|
|
4170
3834
|
if (!coverage) return;
|
|
4171
3835
|
let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
|
|
4172
|
-
if (!entry) {
|
|
4173
|
-
|
|
4174
|
-
this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
|
|
4175
|
-
}
|
|
4176
|
-
const testFilenames = testFiles.join();
|
|
4177
|
-
const filename = resolve$1(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
|
|
4178
|
-
entry[environment] ??= {};
|
|
3836
|
+
if (!entry) entry = {}, this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
|
|
3837
|
+
const testFilenames = testFiles.join(), filename = resolve$1(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
|
|
4179
3838
|
// If there's a result from previous run, overwrite it
|
|
4180
|
-
entry[environment][testFilenames] = filename;
|
|
3839
|
+
entry[environment] ??= {}, entry[environment][testFilenames] = filename;
|
|
4181
3840
|
const promise = promises$1.writeFile(filename, JSON.stringify(coverage), "utf-8");
|
|
4182
3841
|
this.pendingPromises.push(promise);
|
|
4183
3842
|
}
|
|
4184
3843
|
async readCoverageFiles({ onFileRead, onFinished, onDebug }) {
|
|
4185
3844
|
let index = 0;
|
|
4186
3845
|
const total = this.pendingPromises.length;
|
|
4187
|
-
await Promise.all(this.pendingPromises);
|
|
4188
|
-
this.pendingPromises = [];
|
|
3846
|
+
await Promise.all(this.pendingPromises), this.pendingPromises = [];
|
|
4189
3847
|
for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) for (const [environment, coverageByTestfiles] of Object.entries(coveragePerProject)) {
|
|
4190
|
-
const filenames = Object.values(coverageByTestfiles);
|
|
4191
|
-
const project = this.ctx.getProjectByName(projectName);
|
|
3848
|
+
const filenames = Object.values(coverageByTestfiles), project = this.ctx.getProjectByName(projectName);
|
|
4192
3849
|
for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {
|
|
4193
|
-
if (onDebug.enabled) {
|
|
4194
|
-
index += chunk.length;
|
|
4195
|
-
onDebug(`Reading coverage results ${index}/${total}`);
|
|
4196
|
-
}
|
|
3850
|
+
if (onDebug.enabled) index += chunk.length, onDebug(`Reading coverage results ${index}/${total}`);
|
|
4197
3851
|
await Promise.all(chunk.map(async (filename) => {
|
|
4198
|
-
const contents = await promises$1.readFile(filename, "utf-8");
|
|
4199
|
-
const coverage = JSON.parse(contents);
|
|
3852
|
+
const contents = await promises$1.readFile(filename, "utf-8"), coverage = JSON.parse(contents);
|
|
4200
3853
|
onFileRead(coverage);
|
|
4201
3854
|
}));
|
|
4202
3855
|
}
|
|
@@ -4204,10 +3857,8 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4204
3857
|
}
|
|
4205
3858
|
}
|
|
4206
3859
|
async cleanAfterRun() {
|
|
4207
|
-
this.coverageFiles = /* @__PURE__ */ new Map();
|
|
4208
|
-
await promises$1.rm(this.coverageFilesDirectory, { recursive: true });
|
|
4209
3860
|
// Remove empty reports directory, e.g. when only text-reporter is used
|
|
4210
|
-
if (readdirSync(this.options.reportsDirectory).length === 0) await promises$1.rm(this.options.reportsDirectory, { recursive: true });
|
|
3861
|
+
if (this.coverageFiles = /* @__PURE__ */ new Map(), await promises$1.rm(this.coverageFilesDirectory, { recursive: true }), readdirSync(this.options.reportsDirectory).length === 0) await promises$1.rm(this.options.reportsDirectory, { recursive: true });
|
|
4211
3862
|
}
|
|
4212
3863
|
async onTestFailure() {
|
|
4213
3864
|
if (!this.options.reportOnFailure) await this.cleanAfterRun();
|
|
@@ -4220,11 +3871,9 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4220
3871
|
}
|
|
4221
3872
|
async reportThresholds(coverageMap, allTestsRun) {
|
|
4222
3873
|
const resolvedThresholds = this.resolveThresholds(coverageMap);
|
|
4223
|
-
this.checkThresholds(resolvedThresholds)
|
|
4224
|
-
if (this.options.thresholds?.autoUpdate && allTestsRun) {
|
|
3874
|
+
if (this.checkThresholds(resolvedThresholds), this.options.thresholds?.autoUpdate && allTestsRun) {
|
|
4225
3875
|
if (!this.ctx.server.config.configFile) throw new Error("Missing configurationFile. The \"coverage.thresholds.autoUpdate\" can only be enabled when configuration file is used.");
|
|
4226
|
-
const configFilePath = this.ctx.server.config.configFile;
|
|
4227
|
-
const configModule = await this.parseConfigModule(configFilePath);
|
|
3876
|
+
const configFilePath = this.ctx.server.config.configFile, configModule = await this.parseConfigModule(configFilePath);
|
|
4228
3877
|
await this.updateThresholds({
|
|
4229
3878
|
thresholds: resolvedThresholds,
|
|
4230
3879
|
configurationFile: configModule,
|
|
@@ -4238,16 +3887,10 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4238
3887
|
* for specific files defined by glob pattern or global for all other files.
|
|
4239
3888
|
*/
|
|
4240
3889
|
resolveThresholds(coverageMap) {
|
|
4241
|
-
const resolvedThresholds = [];
|
|
4242
|
-
const files = coverageMap.files();
|
|
4243
|
-
const globalCoverageMap = this.createCoverageMap();
|
|
3890
|
+
const resolvedThresholds = [], files = coverageMap.files(), globalCoverageMap = this.createCoverageMap();
|
|
4244
3891
|
for (const key of Object.keys(this.options.thresholds)) {
|
|
4245
3892
|
if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) continue;
|
|
4246
|
-
const glob = key;
|
|
4247
|
-
const globThresholds = resolveGlobThresholds(this.options.thresholds[glob]);
|
|
4248
|
-
const globCoverageMap = this.createCoverageMap();
|
|
4249
|
-
const matcher = pm(glob);
|
|
4250
|
-
const matchingFiles = files.filter((file) => matcher(relative(this.ctx.config.root, file)));
|
|
3893
|
+
const glob = key, globThresholds = resolveGlobThresholds(this.options.thresholds[glob]), globCoverageMap = this.createCoverageMap(), matcher = pm(glob), matchingFiles = files.filter((file) => matcher(relative(this.ctx.config.root, file)));
|
|
4251
3894
|
for (const file of matchingFiles) {
|
|
4252
3895
|
const fileCoverage = coverageMap.fileCoverageFor(file);
|
|
4253
3896
|
globCoverageMap.addFileCoverage(fileCoverage);
|
|
@@ -4263,7 +3906,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4263
3906
|
const fileCoverage = coverageMap.fileCoverageFor(file);
|
|
4264
3907
|
globalCoverageMap.addFileCoverage(fileCoverage);
|
|
4265
3908
|
}
|
|
4266
|
-
resolvedThresholds.unshift({
|
|
3909
|
+
return resolvedThresholds.unshift({
|
|
4267
3910
|
name: GLOBAL_THRESHOLDS_KEY,
|
|
4268
3911
|
coverageMap: globalCoverageMap,
|
|
4269
3912
|
thresholds: {
|
|
@@ -4272,8 +3915,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4272
3915
|
lines: this.options.thresholds?.lines,
|
|
4273
3916
|
statements: this.options.thresholds?.statements
|
|
4274
3917
|
}
|
|
4275
|
-
});
|
|
4276
|
-
return resolvedThresholds;
|
|
3918
|
+
}), resolvedThresholds;
|
|
4277
3919
|
}
|
|
4278
3920
|
/**
|
|
4279
3921
|
* Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.
|
|
@@ -4311,8 +3953,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4311
3953
|
this.ctx.logger.error(errorMessage);
|
|
4312
3954
|
}
|
|
4313
3955
|
} else {
|
|
4314
|
-
const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered;
|
|
4315
|
-
const absoluteThreshold = threshold * -1;
|
|
3956
|
+
const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered, absoluteThreshold = threshold * -1;
|
|
4316
3957
|
if (uncovered > absoluteThreshold) {
|
|
4317
3958
|
process.exitCode = 1;
|
|
4318
3959
|
/**
|
|
@@ -4336,8 +3977,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4336
3977
|
const config = resolveConfig(configurationFile);
|
|
4337
3978
|
assertConfigurationModule(config);
|
|
4338
3979
|
for (const { coverageMap, thresholds, name } of allThresholds) {
|
|
4339
|
-
const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => coverageMap.fileCoverageFor(file).toSummary()) : [coverageMap.getCoverageSummary()];
|
|
4340
|
-
const thresholdsToUpdate = [];
|
|
3980
|
+
const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => coverageMap.fileCoverageFor(file).toSummary()) : [coverageMap.getCoverageSummary()], thresholdsToUpdate = [];
|
|
4341
3981
|
for (const key of THRESHOLD_KEYS) {
|
|
4342
3982
|
const threshold = thresholds[key] ?? 100;
|
|
4343
3983
|
/**
|
|
@@ -4348,8 +3988,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4348
3988
|
const actual = Math.min(...summaries.map((summary) => summary[key].pct));
|
|
4349
3989
|
if (actual > threshold) thresholdsToUpdate.push([key, actual]);
|
|
4350
3990
|
} else {
|
|
4351
|
-
const absoluteThreshold = threshold * -1;
|
|
4352
|
-
const actual = Math.max(...summaries.map((summary) => summary[key].total - summary[key].covered));
|
|
3991
|
+
const absoluteThreshold = threshold * -1, actual = Math.max(...summaries.map((summary) => summary[key].total - summary[key].covered));
|
|
4353
3992
|
if (actual < absoluteThreshold) {
|
|
4354
3993
|
// If everything was covered, set new threshold to 100% (since a threshold of 0 would be considered as 0%)
|
|
4355
3994
|
const updatedThreshold = actual === 0 ? 100 : actual * -1;
|
|
@@ -4365,10 +4004,7 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4365
4004
|
glob[threshold] = newValue;
|
|
4366
4005
|
}
|
|
4367
4006
|
}
|
|
4368
|
-
if (updatedThresholds)
|
|
4369
|
-
this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds.");
|
|
4370
|
-
onUpdate();
|
|
4371
|
-
}
|
|
4007
|
+
if (updatedThresholds) this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds."), onUpdate();
|
|
4372
4008
|
}
|
|
4373
4009
|
async mergeReports(coverageMaps) {
|
|
4374
4010
|
const coverageMap = this.createCoverageMap();
|
|
@@ -4380,10 +4016,8 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4380
4016
|
}
|
|
4381
4017
|
toSlices(array, size) {
|
|
4382
4018
|
return array.reduce((chunks, item) => {
|
|
4383
|
-
const index = Math.max(0, chunks.length - 1);
|
|
4384
|
-
|
|
4385
|
-
chunks[index] = lastChunk;
|
|
4386
|
-
if (lastChunk.length >= size) chunks.push([item]);
|
|
4019
|
+
const index = Math.max(0, chunks.length - 1), lastChunk = chunks[index] || [];
|
|
4020
|
+
if (chunks[index] = lastChunk, lastChunk.length >= size) chunks.push([item]);
|
|
4387
4021
|
else lastChunk.push(item);
|
|
4388
4022
|
return chunks;
|
|
4389
4023
|
}, []);
|
|
@@ -4393,13 +4027,13 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4393
4027
|
root: project.config.root,
|
|
4394
4028
|
isBrowserEnabled: project.isBrowserEnabled(),
|
|
4395
4029
|
vite: project.vite
|
|
4396
|
-
})),
|
|
4030
|
+
})), (
|
|
4397
4031
|
// Check core last as it will match all files anyway
|
|
4398
|
-
{
|
|
4032
|
+
{
|
|
4399
4033
|
root: ctx.config.root,
|
|
4400
4034
|
vite: ctx.vite,
|
|
4401
4035
|
isBrowserEnabled: ctx.getRootProject().isBrowserEnabled()
|
|
4402
|
-
}];
|
|
4036
|
+
})];
|
|
4403
4037
|
return async function transformFile(filename) {
|
|
4404
4038
|
let lastError;
|
|
4405
4039
|
for (const { root, vite, isBrowserEnabled } of servers) {
|
|
@@ -4424,14 +4058,12 @@ Update your dependencies and make sure the versions match.`));
|
|
|
4424
4058
|
* Narrow down `unknown` glob thresholds to resolved ones
|
|
4425
4059
|
*/
|
|
4426
4060
|
function resolveGlobThresholds(thresholds) {
|
|
4427
|
-
|
|
4428
|
-
if (100 in thresholds && thresholds[100] === true) return {
|
|
4061
|
+
return !thresholds || typeof thresholds !== "object" ? {} : 100 in thresholds && thresholds[100] === true ? {
|
|
4429
4062
|
lines: 100,
|
|
4430
4063
|
branches: 100,
|
|
4431
4064
|
functions: 100,
|
|
4432
4065
|
statements: 100
|
|
4433
|
-
}
|
|
4434
|
-
return {
|
|
4066
|
+
} : {
|
|
4435
4067
|
lines: "lines" in thresholds && typeof thresholds.lines === "number" ? thresholds.lines : void 0,
|
|
4436
4068
|
branches: "branches" in thresholds && typeof thresholds.branches === "number" ? thresholds.branches : void 0,
|
|
4437
4069
|
functions: "functions" in thresholds && typeof thresholds.functions === "number" ? thresholds.functions : void 0,
|
|
@@ -4457,8 +4089,7 @@ function resolveConfig(configModule) {
|
|
|
4457
4089
|
if (config) return config;
|
|
4458
4090
|
// "export default mergeConfig(..., defineConfig(...))"
|
|
4459
4091
|
if (mod.$type === "function-call" && mod.$callee === "mergeConfig") {
|
|
4460
|
-
config = resolveMergeConfig(mod);
|
|
4461
|
-
if (config) return config;
|
|
4092
|
+
if (config = resolveMergeConfig(mod), config) return config;
|
|
4462
4093
|
}
|
|
4463
4094
|
} catch (error) {
|
|
4464
4095
|
// Reduce magicast's verbose errors to readable ones
|