vitest 3.2.0-beta.2 → 3.2.0-beta.3
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/dist/browser.d.ts +3 -3
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.DwtwORaC.js → base.D4119yLM.js} +4 -3
- package/dist/chunks/{benchmark.BoF7jW0Q.js → benchmark.Cf_PACH1.js} +1 -1
- package/dist/chunks/{cac.I9MLYfT-.js → cac.DWaWHIIE.js} +18 -15
- package/dist/chunks/{cli-api.d6IK1pnk.js → cli-api.CnmEXkxs.js} +250 -49
- package/dist/chunks/{config.d.UqE-KR0o.d.ts → config.d.D2ROskhv.d.ts} +2 -0
- package/dist/chunks/{console.K1NMVOSc.js → console.Cwr-MFPV.js} +3 -2
- package/dist/chunks/{constants.BZZyIeIE.js → constants.DnKduX2e.js} +1 -0
- package/dist/chunks/{coverage.OGU09Jbh.js → coverage.C73DaDgS.js} +116 -12
- package/dist/chunks/{creator.DGAdZ4Hj.js → creator.C8WKy2eW.js} +10 -7
- package/dist/chunks/{date.CDOsz-HY.js → date.ByMsSlOr.js} +25 -0
- package/dist/chunks/{defaults.DSxsTG0h.js → defaults.DpVH7vbg.js} +1 -0
- package/dist/chunks/{environment.d.D8YDy2v5.d.ts → environment.d.cL3nLXbE.d.ts} +1 -0
- package/dist/chunks/{execute.JlGHLJZT.js → execute.B3q-2LPV.js} +25 -0
- package/dist/chunks/{global.d.BPa1eL3O.d.ts → global.d.BNLIi6yo.d.ts} +3 -1
- package/dist/chunks/{globals.CpxW8ccg.js → globals.CI21aWXF.js} +7 -6
- package/dist/chunks/{index.DFXFpH3w.js → index.2jgTs_Q5.js} +19 -1
- package/dist/chunks/{index.CV36oG_L.js → index.Bter3jj9.js} +83 -16
- package/dist/chunks/{index.DswW_LEs.js → index.CbT4iuwc.js} +7 -4
- package/dist/chunks/index.D3XRDfWc.js +213 -0
- package/dist/chunks/{index.CfXMNXHg.js → index.DNgLEKsQ.js} +4 -2
- package/dist/chunks/{index.CmC5OK9L.js → index.JOzufsrU.js} +2 -1
- package/dist/chunks/{inspector.DbDkSkFn.js → inspector.BFsh5KO0.js} +3 -0
- package/dist/chunks/{node.3xsWotC9.js → node.Be-ntJnD.js} +1 -1
- package/dist/chunks/{reporters.d.CLC9rhKy.d.ts → reporters.d.Bt4IGtsa.d.ts} +24 -6
- package/dist/chunks/{rpc.D9_013TY.js → rpc.BKExFSRG.js} +2 -1
- package/dist/chunks/{runBaseTests.Dn2vyej_.js → runBaseTests.B_M1TTsK.js} +19 -10
- package/dist/chunks/{setup-common.CYo3Y0dD.js → setup-common.CF-O-dZX.js} +2 -1
- package/dist/chunks/{typechecker.DnTrplSJ.js → typechecker.BgzF-6iO.js} +78 -21
- package/dist/chunks/{utils.CgTj3MsC.js → utils.BlI4TC7Y.js} +1 -0
- package/dist/chunks/{utils.BfxieIyZ.js → utils.DPCq3gzW.js} +3 -0
- package/dist/chunks/{vi.BFR5YIgu.js → vi.pkoYCV6A.js} +25 -2
- package/dist/chunks/{vite.d.CBZ3M_ru.d.ts → vite.d.B-Kx3KCF.d.ts} +3 -1
- package/dist/chunks/{vm.C1HHjtNS.js → vm.DPYem2so.js} +72 -4
- package/dist/chunks/{worker.d.CoCI7hzP.d.ts → worker.d.BKbBp2ga.d.ts} +2 -2
- package/dist/chunks/{worker.d.D5Xdi-Zr.d.ts → worker.d.Bl1O4kuf.d.ts} +1 -1
- package/dist/cli.js +4 -4
- package/dist/config.cjs +2 -0
- package/dist/config.d.ts +7 -6
- package/dist/config.js +2 -2
- package/dist/coverage.d.ts +4 -4
- package/dist/coverage.js +5 -5
- package/dist/environments.d.ts +6 -2
- package/dist/environments.js +1 -1
- package/dist/execute.d.ts +9 -3
- package/dist/execute.js +1 -1
- package/dist/index.d.ts +24 -12
- package/dist/index.js +5 -5
- package/dist/node.d.ts +18 -10
- package/dist/node.js +14 -12
- package/dist/reporters.d.ts +4 -4
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +13 -5
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +9 -5
- package/dist/workers/forks.js +6 -4
- package/dist/workers/runVmTests.js +14 -9
- package/dist/workers/threads.js +4 -4
- package/dist/workers/vmForks.js +6 -6
- package/dist/workers/vmThreads.js +6 -6
- package/dist/workers.d.ts +4 -4
- package/dist/workers.js +10 -10
- package/package.json +18 -18
- package/dist/chunks/index.CK1YOQaa.js +0 -143
|
@@ -64,9 +64,11 @@ function getOutputFile(config, reporter) {
|
|
|
64
64
|
function wrapSerializableConfig(config) {
|
|
65
65
|
let testNamePattern = config.testNamePattern;
|
|
66
66
|
let defines = config.defines;
|
|
67
|
+
// v8 serialize does not support regex
|
|
67
68
|
if (testNamePattern && typeof testNamePattern !== "string") {
|
|
68
69
|
testNamePattern = `${REGEXP_WRAP_PREFIX}${testNamePattern.toString()}`;
|
|
69
70
|
}
|
|
71
|
+
// v8 serialize drops properties with undefined value
|
|
70
72
|
if (defines) {
|
|
71
73
|
defines = {
|
|
72
74
|
keys: Object.keys(defines),
|
|
@@ -402,11 +404,14 @@ async function collectTests(ctx, filepath) {
|
|
|
402
404
|
].includes(callee.object.name)) {
|
|
403
405
|
return callee.object?.name;
|
|
404
406
|
}
|
|
407
|
+
// direct call as `__vite_ssr_exports_0__.test()`
|
|
405
408
|
if (callee.object?.name?.startsWith("__vite_ssr_")) {
|
|
406
409
|
return getName(callee.property);
|
|
407
410
|
}
|
|
411
|
+
// call as `__vite_ssr__.test.skip()`
|
|
408
412
|
return getName(callee.object?.property);
|
|
409
413
|
}
|
|
414
|
+
// unwrap (0, ...)
|
|
410
415
|
if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
|
|
411
416
|
const [e0, e1] = callee.expressions;
|
|
412
417
|
if (e0.type === "Literal" && e0.value === 0) {
|
|
@@ -431,6 +436,7 @@ async function collectTests(ctx, filepath) {
|
|
|
431
436
|
}
|
|
432
437
|
const property = callee?.property?.name;
|
|
433
438
|
let mode = !property || property === name ? "run" : property;
|
|
439
|
+
// they will be picked up in the next iteration
|
|
434
440
|
if ([
|
|
435
441
|
"each",
|
|
436
442
|
"for",
|
|
@@ -441,6 +447,7 @@ async function collectTests(ctx, filepath) {
|
|
|
441
447
|
}
|
|
442
448
|
let start;
|
|
443
449
|
const end = node.end;
|
|
450
|
+
// .each
|
|
444
451
|
if (callee.type === "CallExpression") {
|
|
445
452
|
start = callee.end;
|
|
446
453
|
} else if (callee.type === "TaggedTemplateExpression") {
|
|
@@ -451,6 +458,7 @@ async function collectTests(ctx, filepath) {
|
|
|
451
458
|
const { arguments: [messageNode] } = node;
|
|
452
459
|
const isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral";
|
|
453
460
|
const message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
|
|
461
|
+
// cannot statically analyze, so we always skip it
|
|
454
462
|
if (mode === "skipIf" || mode === "runIf") {
|
|
455
463
|
mode = "skip";
|
|
456
464
|
}
|
|
@@ -474,6 +482,7 @@ async function collectTests(ctx, filepath) {
|
|
|
474
482
|
const latestSuite = updateLatestSuite(definition.start);
|
|
475
483
|
let mode = definition.mode;
|
|
476
484
|
if (latestSuite.mode !== "run") {
|
|
485
|
+
// inherit suite mode, if it's set
|
|
477
486
|
mode = latestSuite.mode;
|
|
478
487
|
}
|
|
479
488
|
if (definition.type === "suite") {
|
|
@@ -530,6 +539,7 @@ async function makeTscErrorInfo(errInfo) {
|
|
|
530
539
|
return ["unknown filepath", null];
|
|
531
540
|
}
|
|
532
541
|
const errMsgRaw = errMsgRawArr.join("").trim();
|
|
542
|
+
// get filePath, line, col
|
|
533
543
|
const [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
|
|
534
544
|
if (!errFilePath || !errPos) {
|
|
535
545
|
return ["unknown filepath", null];
|
|
@@ -538,6 +548,7 @@ async function makeTscErrorInfo(errInfo) {
|
|
|
538
548
|
if (!errLine || !errCol) {
|
|
539
549
|
return [errFilePath, null];
|
|
540
550
|
}
|
|
551
|
+
// get errCode, errMsg
|
|
541
552
|
const execArr = errCodeRegExp.exec(errMsgRaw);
|
|
542
553
|
if (!execArr) {
|
|
543
554
|
return [errFilePath, null];
|
|
@@ -559,6 +570,7 @@ async function makeTscErrorInfo(errInfo) {
|
|
|
559
570
|
}
|
|
560
571
|
async function getRawErrsMapFromTsCompile(tscErrorStdout) {
|
|
561
572
|
const rawErrsMap = new Map();
|
|
573
|
+
// Merge details line with main line (i.e. which contains file path)
|
|
562
574
|
const infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
|
|
563
575
|
if (!next) {
|
|
564
576
|
return prev;
|
|
@@ -686,6 +698,7 @@ class Typechecker {
|
|
|
686
698
|
return;
|
|
687
699
|
}
|
|
688
700
|
const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)];
|
|
701
|
+
// has no map for ".js" files that use // @ts-check
|
|
689
702
|
const traceMap = map && new TraceMap(map);
|
|
690
703
|
const indexMap = createIndexMap(parsed);
|
|
691
704
|
const markState = (task, state) => {
|
|
@@ -743,6 +756,7 @@ class Typechecker {
|
|
|
743
756
|
const suiteErrors = errors.map((info) => {
|
|
744
757
|
const limit = Error.stackTraceLimit;
|
|
745
758
|
Error.stackTraceLimit = 0;
|
|
759
|
+
// Some expect-type errors have the most useful information on the second line e.g. `This expression is not callable.\n Type 'ExpectString<number>' has no call signatures.`
|
|
746
760
|
const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1");
|
|
747
761
|
const error = new TypeCheckError(errMsg, [{
|
|
748
762
|
file: filepath,
|
|
@@ -784,10 +798,7 @@ class Typechecker {
|
|
|
784
798
|
getOutput() {
|
|
785
799
|
return this._output;
|
|
786
800
|
}
|
|
787
|
-
async
|
|
788
|
-
if (this.process) {
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
801
|
+
async spawn() {
|
|
791
802
|
const { root, watch, typecheck } = this.project.config;
|
|
792
803
|
const args = [
|
|
793
804
|
"--noEmit",
|
|
@@ -797,6 +808,7 @@ class Typechecker {
|
|
|
797
808
|
"--tsBuildInfoFile",
|
|
798
809
|
join(process.versions.pnp ? join(nodeos__default.tmpdir(), this.project.hash) : distDir, "tsconfig.tmp.tsbuildinfo")
|
|
799
810
|
];
|
|
811
|
+
// use builtin watcher because it's faster
|
|
800
812
|
if (watch) {
|
|
801
813
|
args.push("--watch");
|
|
802
814
|
}
|
|
@@ -816,30 +828,72 @@ class Typechecker {
|
|
|
816
828
|
throwOnError: false
|
|
817
829
|
});
|
|
818
830
|
this.process = child.process;
|
|
819
|
-
await this._onParseStart?.();
|
|
820
831
|
let rerunTriggered = false;
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
if (!
|
|
832
|
+
let dataReceived = false;
|
|
833
|
+
return new Promise((resolve, reject) => {
|
|
834
|
+
if (!child.process || !child.process.stdout) {
|
|
835
|
+
reject(new Error(`Failed to initialize ${typecheck.checker}. This is a bug in Vitest - please, open an issue with reproduction.`));
|
|
824
836
|
return;
|
|
825
837
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
this.
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
rerunTriggered
|
|
838
|
+
child.process.stdout.on("data", (chunk) => {
|
|
839
|
+
dataReceived = true;
|
|
840
|
+
this._output += chunk;
|
|
841
|
+
if (!watch) {
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
if (this._output.includes("File change detected") && !rerunTriggered) {
|
|
845
|
+
this._onWatcherRerun?.();
|
|
846
|
+
this._startTime = performance.now();
|
|
847
|
+
this._result.sourceErrors = [];
|
|
848
|
+
this._result.files = [];
|
|
849
|
+
this._tests = null;
|
|
850
|
+
rerunTriggered = true;
|
|
851
|
+
}
|
|
852
|
+
if (/Found \w+ errors*. Watching for/.test(this._output)) {
|
|
853
|
+
rerunTriggered = false;
|
|
854
|
+
this.prepareResults(this._output).then((result) => {
|
|
855
|
+
this._result = result;
|
|
856
|
+
this._onParseEnd?.(result);
|
|
857
|
+
});
|
|
858
|
+
this._output = "";
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
const timeout = setTimeout(() => reject(new Error(`${typecheck.checker} spawn timed out`)), this.project.config.typecheck.spawnTimeout);
|
|
862
|
+
function onError(cause) {
|
|
863
|
+
clearTimeout(timeout);
|
|
864
|
+
reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
|
|
833
865
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
866
|
+
child.process.once("spawn", () => {
|
|
867
|
+
this._onParseStart?.();
|
|
868
|
+
child.process?.off("error", onError);
|
|
869
|
+
clearTimeout(timeout);
|
|
870
|
+
if (process.platform === "win32") {
|
|
871
|
+
// on Windows, the process might be spawned but fail to start
|
|
872
|
+
// we wait for a potential error here. if "close" event didn't trigger,
|
|
873
|
+
// we resolve the promise
|
|
874
|
+
setTimeout(() => {
|
|
875
|
+
resolve({ result: child });
|
|
876
|
+
}, 200);
|
|
877
|
+
} else {
|
|
878
|
+
resolve({ result: child });
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
if (process.platform === "win32") {
|
|
882
|
+
child.process.once("close", (code) => {
|
|
883
|
+
if (code != null && code !== 0 && !dataReceived) {
|
|
884
|
+
onError(new Error(`The ${typecheck.checker} command exited with code ${code}.`));
|
|
885
|
+
}
|
|
839
886
|
});
|
|
840
|
-
this._output = "";
|
|
841
887
|
}
|
|
888
|
+
child.process.once("error", onError);
|
|
842
889
|
});
|
|
890
|
+
}
|
|
891
|
+
async start() {
|
|
892
|
+
if (this.process) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const { watch } = this.project.config;
|
|
896
|
+
const { result: child } = await this.spawn();
|
|
843
897
|
if (!watch) {
|
|
844
898
|
await child;
|
|
845
899
|
this._result = await this.prepareResults(this._output);
|
|
@@ -875,6 +929,9 @@ function findGeneratedPosition(traceMap, { line, column, source }) {
|
|
|
875
929
|
if (found.line !== null) {
|
|
876
930
|
return found;
|
|
877
931
|
}
|
|
932
|
+
// find the next source token position when the exact error position doesn't exist in source map.
|
|
933
|
+
// this can happen, for example, when the type error is in the comment "// @ts-expect-error"
|
|
934
|
+
// and comments are stripped away in the generated code.
|
|
878
935
|
const mappings = [];
|
|
879
936
|
eachMapping(traceMap, (m) => {
|
|
880
937
|
if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) {
|
|
@@ -2,6 +2,7 @@ import { getSafeTimers } from '@vitest/utils';
|
|
|
2
2
|
|
|
3
3
|
const NAME_WORKER_STATE = "__vitest_worker__";
|
|
4
4
|
function getWorkerState() {
|
|
5
|
+
// @ts-expect-error untyped global
|
|
5
6
|
const workerState = globalThis[NAME_WORKER_STATE];
|
|
6
7
|
if (!workerState) {
|
|
7
8
|
const errorMsg = "Vitest failed to access its internal state." + "\n\nOne of the following is possible:" + "\n- \"vitest\" is imported directly without running \"vitest\" command" + "\n- \"vitest\" is imported inside \"globalSetup\" (to fix this, use \"setupFiles\" instead, because \"globalSetup\" runs in a different context)" + "\n- \"vitest\" is imported inside Vite / Vitest config file" + "\n- Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues\n";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { parseRegexp } from '@vitest/utils';
|
|
2
2
|
|
|
3
3
|
const REGEXP_WRAP_PREFIX = "$$vitest:";
|
|
4
|
+
// Store global APIs in case process is overwritten by tests
|
|
4
5
|
const processSend = process.send?.bind(process);
|
|
5
6
|
const processOn = process.on?.bind(process);
|
|
6
7
|
const processOff = process.off?.bind(process);
|
|
@@ -32,6 +33,7 @@ function createForksRpcOptions(nodeV8) {
|
|
|
32
33
|
},
|
|
33
34
|
on(fn) {
|
|
34
35
|
const handler = (message, ...extras) => {
|
|
36
|
+
// Do not react on Tinypool's internal messaging
|
|
35
37
|
if (message?.__tinypool_worker_message__) {
|
|
36
38
|
return;
|
|
37
39
|
}
|
|
@@ -55,6 +57,7 @@ function unwrapSerializableConfig(config) {
|
|
|
55
57
|
if (config.defines && Array.isArray(config.defines.keys) && config.defines.original) {
|
|
56
58
|
const { keys, original } = config.defines;
|
|
57
59
|
const defines = {};
|
|
60
|
+
// Apply all keys from the original. Entries which had undefined value are missing from original now
|
|
58
61
|
for (const key of keys) {
|
|
59
62
|
defines[key] = original[key];
|
|
60
63
|
}
|
|
@@ -2,15 +2,16 @@ import { equals, iterableEquality, subsetEquality, JestExtend, JestChaiExpect, J
|
|
|
2
2
|
import { getCurrentTest } from '@vitest/runner';
|
|
3
3
|
import { getNames, getTestName } from '@vitest/runner/utils';
|
|
4
4
|
import * as chai$1 from 'chai';
|
|
5
|
-
import { g as getWorkerState, a as getCurrentEnvironment, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.
|
|
5
|
+
import { g as getWorkerState, a as getCurrentEnvironment, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.BlI4TC7Y.js';
|
|
6
6
|
import { getSafeTimers, assertTypes, createSimpleStackTrace } from '@vitest/utils';
|
|
7
7
|
import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
|
|
8
8
|
import { stripSnapshotIndentation, addSerializer, SnapshotClient } from '@vitest/snapshot';
|
|
9
9
|
import '@vitest/utils/error';
|
|
10
10
|
import { fn, spyOn, mocks, isMockFunction } from '@vitest/spy';
|
|
11
11
|
import { parseSingleStack } from '@vitest/utils/source-map';
|
|
12
|
-
import { R as RealDate, r as resetDate, m as mockDate } from './date.
|
|
12
|
+
import { R as RealDate, r as resetDate, m as mockDate } from './date.ByMsSlOr.js';
|
|
13
13
|
|
|
14
|
+
// these matchers are not supported because they don't make sense with poll
|
|
14
15
|
const unsupported = [
|
|
15
16
|
"matchSnapshot",
|
|
16
17
|
"toMatchSnapshot",
|
|
@@ -28,6 +29,7 @@ function createExpectPoll(expect) {
|
|
|
28
29
|
const state = getWorkerState();
|
|
29
30
|
const defaults = state.config.expect?.poll ?? {};
|
|
30
31
|
const { interval = defaults.interval ?? 50, timeout = defaults.timeout ?? 1e3, message } = options;
|
|
32
|
+
// @ts-expect-error private poll access
|
|
31
33
|
const assertion = expect(null, message).withContext({ poll: true });
|
|
32
34
|
fn = fn.bind(assertion);
|
|
33
35
|
const test = chai$1.util.flag(assertion, "vitest-test");
|
|
@@ -89,6 +91,8 @@ function createExpectPoll(expect) {
|
|
|
89
91
|
}
|
|
90
92
|
});
|
|
91
93
|
let resultPromise;
|
|
94
|
+
// only .then is enough to check awaited, but we type this as `Promise<void>` in global types
|
|
95
|
+
// so let's follow it
|
|
92
96
|
return {
|
|
93
97
|
then(onFulfilled, onRejected) {
|
|
94
98
|
awaited = true;
|
|
@@ -222,7 +226,9 @@ function createAssertionMessage(util, assertion, hasArgs) {
|
|
|
222
226
|
}
|
|
223
227
|
function recordAsyncExpect(_test, promise, assertion, error) {
|
|
224
228
|
const test = _test;
|
|
229
|
+
// record promise for test, that resolves before test ends
|
|
225
230
|
if (test && promise instanceof Promise) {
|
|
231
|
+
// if promise is explicitly awaited, remove it from the list
|
|
226
232
|
promise = promise.finally(() => {
|
|
227
233
|
if (!test.promises) {
|
|
228
234
|
return;
|
|
@@ -232,6 +238,7 @@ function recordAsyncExpect(_test, promise, assertion, error) {
|
|
|
232
238
|
test.promises.splice(index, 1);
|
|
233
239
|
}
|
|
234
240
|
});
|
|
241
|
+
// record promise
|
|
235
242
|
if (!test.promises) {
|
|
236
243
|
test.promises = [];
|
|
237
244
|
}
|
|
@@ -281,6 +288,7 @@ function getError(expected, promise) {
|
|
|
281
288
|
if (!promise) {
|
|
282
289
|
throw new Error(`expected must be a function, received ${typeof expected}`);
|
|
283
290
|
}
|
|
291
|
+
// when "promised", it receives thrown error
|
|
284
292
|
return expected;
|
|
285
293
|
}
|
|
286
294
|
try {
|
|
@@ -442,6 +450,7 @@ function createExpect(test) {
|
|
|
442
450
|
const assert = chai$1.expect(value, message);
|
|
443
451
|
const _test = test || getCurrentTest();
|
|
444
452
|
if (_test) {
|
|
453
|
+
// @ts-expect-error internal
|
|
445
454
|
return assert.withTest(_test);
|
|
446
455
|
} else {
|
|
447
456
|
return assert;
|
|
@@ -451,6 +460,7 @@ function createExpect(test) {
|
|
|
451
460
|
Object.assign(expect, globalThis[ASYMMETRIC_MATCHERS_OBJECT]);
|
|
452
461
|
expect.getState = () => getState(expect);
|
|
453
462
|
expect.setState = (state) => setState(state, expect);
|
|
463
|
+
// @ts-expect-error global is not typed
|
|
454
464
|
const globalState = getState(globalThis[GLOBAL_EXPECT]) || {};
|
|
455
465
|
setState({
|
|
456
466
|
...globalState,
|
|
@@ -465,9 +475,11 @@ function createExpect(test) {
|
|
|
465
475
|
},
|
|
466
476
|
currentTestName: test ? getTestName(test) : globalState.currentTestName
|
|
467
477
|
}, expect);
|
|
478
|
+
// @ts-expect-error untyped
|
|
468
479
|
expect.extend = (matchers) => chai$1.expect.extend(expect, matchers);
|
|
469
480
|
expect.addEqualityTesters = (customTesters) => addCustomEqualityTesters(customTesters);
|
|
470
481
|
expect.soft = (...args) => {
|
|
482
|
+
// @ts-expect-error private soft access
|
|
471
483
|
return expect(...args).withContext({ soft: true });
|
|
472
484
|
};
|
|
473
485
|
expect.poll = createExpectPoll(expect);
|
|
@@ -3611,6 +3623,12 @@ var fakeTimersSrcExports = requireFakeTimersSrc();
|
|
|
3611
3623
|
class FakeTimers {
|
|
3612
3624
|
_global;
|
|
3613
3625
|
_clock;
|
|
3626
|
+
// | _fakingTime | _fakingDate |
|
|
3627
|
+
// +-------------+-------------+
|
|
3628
|
+
// | false | falsy | initial
|
|
3629
|
+
// | false | truthy | vi.setSystemTime called first (for mocking only Date without fake timers)
|
|
3630
|
+
// | true | falsy | vi.useFakeTimers called first
|
|
3631
|
+
// | true | truthy | unreachable
|
|
3614
3632
|
_fakingTime;
|
|
3615
3633
|
_fakingDate;
|
|
3616
3634
|
_fakeTimers;
|
|
@@ -3655,6 +3673,7 @@ class FakeTimers {
|
|
|
3655
3673
|
if (this._checkFakeTimers()) {
|
|
3656
3674
|
for (let i = steps; i > 0; i--) {
|
|
3657
3675
|
this._clock.next();
|
|
3676
|
+
// Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
|
|
3658
3677
|
this._clock.tick(0);
|
|
3659
3678
|
if (this._clock.countTimers() === 0) {
|
|
3660
3679
|
break;
|
|
@@ -3666,6 +3685,7 @@ class FakeTimers {
|
|
|
3666
3685
|
if (this._checkFakeTimers()) {
|
|
3667
3686
|
for (let i = steps; i > 0; i--) {
|
|
3668
3687
|
await this._clock.nextAsync();
|
|
3688
|
+
// Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
|
|
3669
3689
|
this._clock.tick(0);
|
|
3670
3690
|
if (this._clock.countTimers() === 0) {
|
|
3671
3691
|
break;
|
|
@@ -3690,6 +3710,7 @@ class FakeTimers {
|
|
|
3690
3710
|
}
|
|
3691
3711
|
runAllTicks() {
|
|
3692
3712
|
if (this._checkFakeTimers()) {
|
|
3713
|
+
// @ts-expect-error method not exposed
|
|
3693
3714
|
this._clock.runMicrotasks();
|
|
3694
3715
|
}
|
|
3695
3716
|
}
|
|
@@ -4124,6 +4145,7 @@ function createVitest() {
|
|
|
4124
4145
|
const vitest = createVitest();
|
|
4125
4146
|
const vi = vitest;
|
|
4126
4147
|
function _mocker() {
|
|
4148
|
+
// @ts-expect-error injected by vite-nide
|
|
4127
4149
|
return typeof __vitest_mocker__ !== "undefined" ? __vitest_mocker__ : new Proxy({}, { get(_, name) {
|
|
4128
4150
|
throw new Error("Vitest mocker was not initialized in this environment. " + `vi.${String(name)}() is forbidden.`);
|
|
4129
4151
|
} });
|
|
@@ -4131,6 +4153,7 @@ function _mocker() {
|
|
|
4131
4153
|
function getImporter(name) {
|
|
4132
4154
|
const stackTrace = createSimpleStackTrace({ stackTraceLimit: 5 });
|
|
4133
4155
|
const stackArray = stackTrace.split("\n");
|
|
4156
|
+
// if there is no message in a stack trace, use the item - 1
|
|
4134
4157
|
const importerStackIndex = stackArray.findIndex((stack) => {
|
|
4135
4158
|
return stack.includes(` at Object.${name}`) || stack.includes(`${name}@`);
|
|
4136
4159
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HookHandler } from 'vite';
|
|
2
|
-
import { V as Vitest, T as TestProject, b as TestProjectConfiguration, I as InlineConfig } from './reporters.d.
|
|
2
|
+
import { V as Vitest, T as TestProject, b as TestProjectConfiguration, I as InlineConfig } from './reporters.d.Bt4IGtsa.js';
|
|
3
3
|
|
|
4
4
|
interface VitestPluginContext {
|
|
5
5
|
vitest: Vitest;
|
|
@@ -7,6 +7,8 @@ interface VitestPluginContext {
|
|
|
7
7
|
injectTestProjects: (config: TestProjectConfiguration | TestProjectConfiguration[]) => Promise<TestProject[]>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/* eslint-disable unused-imports/no-unused-vars */
|
|
11
|
+
|
|
10
12
|
type VitestInlineConfig = InlineConfig;
|
|
11
13
|
declare module "vite" {
|
|
12
14
|
interface UserConfig {
|
|
@@ -2,14 +2,14 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
2
2
|
import vm, { isContext } from 'node:vm';
|
|
3
3
|
import { dirname, basename, extname, normalize, join, resolve } from 'pathe';
|
|
4
4
|
import { distDir } from '../path.js';
|
|
5
|
-
import { createCustomConsole } from './console.
|
|
6
|
-
import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.
|
|
5
|
+
import { createCustomConsole } from './console.Cwr-MFPV.js';
|
|
6
|
+
import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.B3q-2LPV.js';
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import { dirname as dirname$1 } from 'node:path';
|
|
9
9
|
import { isPrimitive, isNodeBuiltin, toArray, getCachedData, setCacheData, isBareImport } from 'vite-node/utils';
|
|
10
10
|
import { createRequire, Module } from 'node:module';
|
|
11
11
|
import { CSS_LANGS_RE, KNOWN_ASSET_RE } from 'vite-node/constants';
|
|
12
|
-
import { p as provideWorkerState } from './utils.
|
|
12
|
+
import { p as provideWorkerState } from './utils.BlI4TC7Y.js';
|
|
13
13
|
|
|
14
14
|
function interopCommonJsModule(interopDefault, mod) {
|
|
15
15
|
if (isPrimitive(mod) || Array.isArray(mod) || mod instanceof Promise) {
|
|
@@ -58,6 +58,7 @@ class CommonjsExecutor {
|
|
|
58
58
|
this.fs = options.fileMap;
|
|
59
59
|
this.interopDefault = options.interopDefault;
|
|
60
60
|
const primitives = vm.runInContext("({ Object, Array, Error })", this.context);
|
|
61
|
+
// eslint-disable-next-line ts/no-this-alias
|
|
61
62
|
const executor = this;
|
|
62
63
|
this.Module = class Module$1 {
|
|
63
64
|
exports;
|
|
@@ -71,6 +72,7 @@ class CommonjsExecutor {
|
|
|
71
72
|
paths = [];
|
|
72
73
|
constructor(id = "", parent) {
|
|
73
74
|
this.exports = primitives.Object.create(Object.prototype);
|
|
75
|
+
// in our case the path should always be resolved already
|
|
74
76
|
this.path = dirname(id);
|
|
75
77
|
this.id = id;
|
|
76
78
|
this.filename = id;
|
|
@@ -89,12 +91,16 @@ class CommonjsExecutor {
|
|
|
89
91
|
static register = () => {
|
|
90
92
|
throw new Error(`[vitest] "register" is not available when running in Vitest.`);
|
|
91
93
|
};
|
|
94
|
+
static registerHooks = () => {
|
|
95
|
+
throw new Error(`[vitest] "registerHooks" is not available when running in Vitest.`);
|
|
96
|
+
};
|
|
92
97
|
_compile(code, filename) {
|
|
93
98
|
const cjsModule = Module$1.wrap(code);
|
|
94
99
|
const script = new vm.Script(cjsModule, {
|
|
95
100
|
filename,
|
|
96
101
|
importModuleDynamically: options.importModuleDynamically
|
|
97
102
|
});
|
|
103
|
+
// @ts-expect-error mark script with current identifier
|
|
98
104
|
script.identifier = filename;
|
|
99
105
|
const fn = script.runInContext(executor.context);
|
|
100
106
|
const __dirname = dirname(filename);
|
|
@@ -106,6 +112,7 @@ class CommonjsExecutor {
|
|
|
106
112
|
this.loaded = true;
|
|
107
113
|
}
|
|
108
114
|
}
|
|
115
|
+
// exposed for external use, Node.js does the opposite
|
|
109
116
|
static _load = (request, parent, _isMain) => {
|
|
110
117
|
const require = Module$1.createRequire(parent?.filename ?? request);
|
|
111
118
|
return require(request);
|
|
@@ -126,11 +133,17 @@ class CommonjsExecutor {
|
|
|
126
133
|
static runMain = () => {
|
|
127
134
|
throw new primitives.Error("[vitest] \"runMain\" is not implemented.");
|
|
128
135
|
};
|
|
136
|
+
// @ts-expect-error not typed
|
|
129
137
|
static _resolveFilename = Module._resolveFilename;
|
|
138
|
+
// @ts-expect-error not typed
|
|
130
139
|
static _findPath = Module._findPath;
|
|
140
|
+
// @ts-expect-error not typed
|
|
131
141
|
static _initPaths = Module._initPaths;
|
|
142
|
+
// @ts-expect-error not typed
|
|
132
143
|
static _preloadModules = Module._preloadModules;
|
|
144
|
+
// @ts-expect-error not typed
|
|
133
145
|
static _resolveLookupPaths = Module._resolveLookupPaths;
|
|
146
|
+
// @ts-expect-error not typed
|
|
134
147
|
static globalPaths = Module.globalPaths;
|
|
135
148
|
static isBuiltin = Module.isBuiltin;
|
|
136
149
|
static constants = Module.constants;
|
|
@@ -189,6 +202,7 @@ class CommonjsExecutor {
|
|
|
189
202
|
}
|
|
190
203
|
});
|
|
191
204
|
}
|
|
205
|
+
// very naive implementation for Node.js require
|
|
192
206
|
loadCommonJSModule(module, filename) {
|
|
193
207
|
const cached = this.requireCache.get(filename);
|
|
194
208
|
if (cached) {
|
|
@@ -204,6 +218,7 @@ class CommonjsExecutor {
|
|
|
204
218
|
let currentExtension;
|
|
205
219
|
let index;
|
|
206
220
|
let startIndex = 0;
|
|
221
|
+
// eslint-disable-next-line no-cond-assign
|
|
207
222
|
while ((index = name.indexOf(".", startIndex)) !== -1) {
|
|
208
223
|
startIndex = index + 1;
|
|
209
224
|
if (index === 0) {
|
|
@@ -239,6 +254,7 @@ class CommonjsExecutor {
|
|
|
239
254
|
return this.moduleCache.get(identifier);
|
|
240
255
|
}
|
|
241
256
|
const exports = this.require(path);
|
|
257
|
+
// TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
|
|
242
258
|
const { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports);
|
|
243
259
|
const module = new SyntheticModule([...keys, "default"], function() {
|
|
244
260
|
for (const key of keys) {
|
|
@@ -252,6 +268,42 @@ class CommonjsExecutor {
|
|
|
252
268
|
this.moduleCache.set(identifier, module);
|
|
253
269
|
return module;
|
|
254
270
|
}
|
|
271
|
+
// TODO: use this in strict mode, when available in #2854
|
|
272
|
+
// private _getNamedCjsExports(path: string): Set<string> {
|
|
273
|
+
// const cachedNamedExports = this.cjsNamedExportsMap.get(path)
|
|
274
|
+
// if (cachedNamedExports) {
|
|
275
|
+
// return cachedNamedExports
|
|
276
|
+
// }
|
|
277
|
+
// if (extname(path) === '.node') {
|
|
278
|
+
// const moduleExports = this.require(path)
|
|
279
|
+
// const namedExports = new Set(Object.keys(moduleExports))
|
|
280
|
+
// this.cjsNamedExportsMap.set(path, namedExports)
|
|
281
|
+
// return namedExports
|
|
282
|
+
// }
|
|
283
|
+
// const code = this.fs.readFile(path)
|
|
284
|
+
// const { exports, reexports } = parseCjs(code, path)
|
|
285
|
+
// const namedExports = new Set(exports)
|
|
286
|
+
// this.cjsNamedExportsMap.set(path, namedExports)
|
|
287
|
+
// for (const reexport of reexports) {
|
|
288
|
+
// if (isNodeBuiltin(reexport)) {
|
|
289
|
+
// const exports = this.require(reexport)
|
|
290
|
+
// if (exports !== null && typeof exports === 'object') {
|
|
291
|
+
// for (const e of Object.keys(exports)) {
|
|
292
|
+
// namedExports.add(e)
|
|
293
|
+
// }
|
|
294
|
+
// }
|
|
295
|
+
// }
|
|
296
|
+
// else {
|
|
297
|
+
// const require = this.createRequire(path)
|
|
298
|
+
// const resolved = require.resolve(reexport)
|
|
299
|
+
// const exports = this._getNamedCjsExports(resolved)
|
|
300
|
+
// for (const e of exports) {
|
|
301
|
+
// namedExports.add(e)
|
|
302
|
+
// }
|
|
303
|
+
// }
|
|
304
|
+
// }
|
|
305
|
+
// return namedExports
|
|
306
|
+
// }
|
|
255
307
|
require(identifier) {
|
|
256
308
|
const ext = extname(identifier);
|
|
257
309
|
if (ext === ".node" || isNodeBuiltin(identifier)) {
|
|
@@ -273,6 +325,7 @@ class CommonjsExecutor {
|
|
|
273
325
|
return module.exports;
|
|
274
326
|
}
|
|
275
327
|
this.builtinCache[normalized] = _require.cache[normalized];
|
|
328
|
+
// TODO: should we wrap module to rethrow context errors?
|
|
276
329
|
return moduleExports;
|
|
277
330
|
}
|
|
278
331
|
}
|
|
@@ -308,6 +361,7 @@ class EsmExecutor {
|
|
|
308
361
|
}
|
|
309
362
|
async loadEsModule(fileURL, getCode) {
|
|
310
363
|
const code = await getCode();
|
|
364
|
+
// TODO: should not be allowed in strict mode, implement in #2854
|
|
311
365
|
if (fileURL.endsWith(".json")) {
|
|
312
366
|
const m = new SyntheticModule(["default"], function() {
|
|
313
367
|
const result = JSON.parse(code);
|
|
@@ -345,13 +399,14 @@ class EsmExecutor {
|
|
|
345
399
|
return m;
|
|
346
400
|
}
|
|
347
401
|
async createNetworkModule(fileUrl) {
|
|
402
|
+
// https://nodejs.org/api/esm.html#https-and-http-imports
|
|
348
403
|
if (fileUrl.startsWith("http:")) {
|
|
349
404
|
const url = new URL(fileUrl);
|
|
350
405
|
if (url.hostname !== "localhost" && url.hostname !== "::1" && (IPnumber(url.hostname) & IPmask(8)) !== this.#httpIp) {
|
|
351
406
|
throw new Error(
|
|
352
407
|
// we don't know the importer, so it's undefined (the same happens in --pool=threads)
|
|
353
408
|
`import of '${fileUrl}' by undefined is not supported: ` + "http can only be used to load local resources (use https instead)."
|
|
354
|
-
);
|
|
409
|
+
);
|
|
355
410
|
}
|
|
356
411
|
}
|
|
357
412
|
return this.createEsModule(fileUrl, () => fetch(fileUrl).then((r) => r.text()));
|
|
@@ -496,6 +551,7 @@ class ViteExecutor {
|
|
|
496
551
|
return result.code;
|
|
497
552
|
}
|
|
498
553
|
} catch (cause) {
|
|
554
|
+
// rethrow vite error if it cannot load the module because it's not resolved
|
|
499
555
|
if (typeof cause === "object" && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url")) {
|
|
500
556
|
const error = new Error(`Cannot find module '${fileUrl}'`, { cause });
|
|
501
557
|
error.code = "ERR_MODULE_NOT_FOUND";
|
|
@@ -548,7 +604,9 @@ class ViteExecutor {
|
|
|
548
604
|
}
|
|
549
605
|
|
|
550
606
|
const { existsSync, statSync } = fs;
|
|
607
|
+
// always defined when we use vm pool
|
|
551
608
|
const nativeResolve = import.meta.resolve;
|
|
609
|
+
// TODO: improve Node.js strict mode support in #2854
|
|
552
610
|
class ExternalModulesExecutor {
|
|
553
611
|
cjs;
|
|
554
612
|
esm;
|
|
@@ -587,6 +645,7 @@ class ExternalModulesExecutor {
|
|
|
587
645
|
createRequire(identifier) {
|
|
588
646
|
return this.cjs.createRequire(identifier);
|
|
589
647
|
}
|
|
648
|
+
// dynamic import can be used in both ESM and CJS, so we have it in the executor
|
|
590
649
|
importModuleDynamically = async (specifier, referencer) => {
|
|
591
650
|
const module = await this.resolveModule(specifier, referencer.identifier);
|
|
592
651
|
return await this.esm.evaluateModule(module);
|
|
@@ -605,6 +664,7 @@ class ExternalModulesExecutor {
|
|
|
605
664
|
return id;
|
|
606
665
|
}
|
|
607
666
|
}
|
|
667
|
+
// import.meta.resolve can be asynchronous in older +18 Node versions
|
|
608
668
|
return nativeResolve(specifier, parent);
|
|
609
669
|
}
|
|
610
670
|
findNearestPackageData(basedir) {
|
|
@@ -667,6 +727,8 @@ class ExternalModulesExecutor {
|
|
|
667
727
|
} else if (extension === ".cjs") {
|
|
668
728
|
type = "commonjs";
|
|
669
729
|
} else if (extension === ".wasm") {
|
|
730
|
+
// still experimental on NodeJS --experimental-wasm-modules
|
|
731
|
+
// cf. ESM_FILE_FORMAT(url) in https://nodejs.org/docs/latest-v20.x/api/esm.html#resolution-algorithm
|
|
670
732
|
type = "wasm";
|
|
671
733
|
} else {
|
|
672
734
|
const pkgData = this.findNearestPackageData(normalize(pathUrl));
|
|
@@ -680,6 +742,8 @@ class ExternalModulesExecutor {
|
|
|
680
742
|
}
|
|
681
743
|
createModule(identifier) {
|
|
682
744
|
const { type, url, path } = this.getModuleInformation(identifier);
|
|
745
|
+
// create ERR_MODULE_NOT_FOUND on our own since latest NodeJS's import.meta.resolve doesn't throw on non-existing namespace or path
|
|
746
|
+
// https://github.com/nodejs/node/pull/49038
|
|
683
747
|
if ((type === "module" || type === "commonjs" || type === "wasm") && !existsSync(path)) {
|
|
684
748
|
const error = new Error(`Cannot find ${isBareImport(path) ? "package" : "module"} '${path}'`);
|
|
685
749
|
error.code = "ERR_MODULE_NOT_FOUND";
|
|
@@ -767,9 +831,13 @@ async function runVmTests(method, state) {
|
|
|
767
831
|
throw new TypeError(`Environment ${environment.name} doesn't provide a valid context. It should be created by "vm.createContext" method.`);
|
|
768
832
|
}
|
|
769
833
|
provideWorkerState(context, state);
|
|
834
|
+
// this is unfortunately needed for our own dependencies
|
|
835
|
+
// we need to find a way to not rely on this by default
|
|
836
|
+
// because browser doesn't provide these globals
|
|
770
837
|
context.process = process;
|
|
771
838
|
context.global = context;
|
|
772
839
|
context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state);
|
|
840
|
+
// TODO: don't hardcode setImmediate in fake timers defaults
|
|
773
841
|
context.setImmediate = setImmediate;
|
|
774
842
|
context.clearImmediate = clearImmediate;
|
|
775
843
|
const stubs = getDefaultRequestStubs(context);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { File, TaskResultPack, TaskEventPack, CancelReason, FileSpecification, Task } from '@vitest/runner';
|
|
2
2
|
import { ViteNodeResolveId, ModuleCacheMap, ModuleExecutionInfo } from 'vite-node';
|
|
3
|
-
import { a as SerializedConfig } from './config.d.
|
|
4
|
-
import { T as TransformMode, U as UserConsoleLog, A as AfterSuiteRunMeta, E as Environment } from './environment.d.
|
|
3
|
+
import { a as SerializedConfig } from './config.d.D2ROskhv.js';
|
|
4
|
+
import { T as TransformMode, U as UserConsoleLog, A as AfterSuiteRunMeta, E as Environment } from './environment.d.cL3nLXbE.js';
|
|
5
5
|
import { SnapshotResult } from '@vitest/snapshot';
|
|
6
6
|
|
|
7
7
|
type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;
|
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { c as createCLI } from './chunks/cac.
|
|
1
|
+
import { c as createCLI } from './chunks/cac.DWaWHIIE.js';
|
|
2
2
|
import '@vitest/utils';
|
|
3
3
|
import 'events';
|
|
4
4
|
import 'pathe';
|
|
5
5
|
import 'tinyrainbow';
|
|
6
|
-
import './chunks/constants.
|
|
7
|
-
import './chunks/index.
|
|
6
|
+
import './chunks/constants.DnKduX2e.js';
|
|
7
|
+
import './chunks/index.Bter3jj9.js';
|
|
8
8
|
import 'node:perf_hooks';
|
|
9
9
|
import '@vitest/runner/utils';
|
|
10
10
|
import '@vitest/utils/source-map';
|
|
11
11
|
import './chunks/env.Dq0hM4Xv.js';
|
|
12
12
|
import 'std-env';
|
|
13
|
-
import './chunks/typechecker.
|
|
13
|
+
import './chunks/typechecker.BgzF-6iO.js';
|
|
14
14
|
import 'node:os';
|
|
15
15
|
import 'tinyexec';
|
|
16
16
|
import './path.js';
|