





















@@ -1,4 +1,5 @@
11import { spawn } from "node:child_process";
2+import fs from "node:fs";
23import { createRequire } from "node:module";
34import path from "node:path";
45import { isUiTestTarget, isUnitUiTestTarget } from "../test/vitest/vitest.ui-paths.mjs";
@@ -16,6 +17,60 @@ const ANSI_CSI_SUFFIX_RE = /^[0-?]*[ -/]*[@-~]/u;
1617const SUPPRESSED_VITEST_STDERR_PATTERNS = ["[PLUGIN_TIMINGS]"];
1718const UI_VITEST_CONFIG = "test/vitest/vitest.ui.config.ts";
1819const UNIT_UI_VITEST_CONFIG = "test/vitest/vitest.unit-ui.config.ts";
20+const EXPLICIT_TEST_FILE_RE = /\.(?:test|e2e|live)\.(?:[cm]?[jt]sx?)$/u;
21+const GLOB_PATTERN_CHARS_RE = /[*?[\]{}]/u;
22+const VITEST_OPTIONS_WITH_VALUE = new Set([
23+"--attachmentsDir",
24+"--bail",
25+"--browser",
26+"--config",
27+"--configLoader",
28+"-c",
29+"--changed",
30+"--dir",
31+"--environment",
32+"--exclude",
33+"--execArgv",
34+"--hookTimeout",
35+"--inspect",
36+"--inspect-brk",
37+"--listTags",
38+"--maxConcurrency",
39+"--maxWorkers",
40+"--mergeReports",
41+"--mode",
42+"--outputFile",
43+"--pool",
44+"--project",
45+"--reporter",
46+"--reporters",
47+"--retry",
48+"--root",
49+"-r",
50+"--sequence.shuffle.seed",
51+"--shard",
52+"--silent",
53+"--slowTestThreshold",
54+"--tagsFilter",
55+"--teardownTimeout",
56+"--testNamePattern",
57+"-t",
58+"--testTimeout",
59+"--update",
60+"-u",
61+"--vmMemoryLimit",
62+]);
63+const VITEST_DOTTED_OPTIONS_WITH_VALUE_PREFIXES = [
64+"--browser.",
65+"--coverage.",
66+"--diff.",
67+"--expect.",
68+"--experimental.",
69+"--outputFile.",
70+"--retry.",
71+"--sequence.",
72+"--typecheck.",
73+];
1974const require = createRequire(import.meta.url);
20752176function isTruthyEnvValue(value) {
@@ -99,6 +154,69 @@ function hasExplicitVitestConfigArg(argv) {
99154return argv.some((arg) => arg === "--config" || arg === "-c" || arg.startsWith("--config="));
100155}
101156157+function optionConsumesNextArg(arg) {
158+if (arg.includes("=")) {
159+return false;
160+}
161+return (
162+VITEST_OPTIONS_WITH_VALUE.has(arg) ||
163+VITEST_DOTTED_OPTIONS_WITH_VALUE_PREFIXES.some((prefix) => arg.startsWith(prefix))
164+);
165+}
166+167+function isExplicitTestFileArg(arg) {
168+if (!EXPLICIT_TEST_FILE_RE.test(arg) || GLOB_PATTERN_CHARS_RE.test(arg)) {
169+return false;
170+}
171+return (
172+path.isAbsolute(arg) || arg.startsWith("./") || arg.startsWith("../") || /[/\\]/u.test(arg)
173+);
174+}
175+176+function collectExplicitTestFileArgs(argv) {
177+const files = [];
178+for (let index = 0; index < argv.length; index += 1) {
179+const arg = argv[index];
180+if (arg === "--") {
181+break;
182+}
183+if (optionConsumesNextArg(arg)) {
184+index += 1;
185+continue;
186+}
187+if (arg.startsWith("-")) {
188+continue;
189+}
190+if (isExplicitTestFileArg(arg)) {
191+files.push(arg);
192+}
193+}
194+return files;
195+}
196+197+function hasAlternateVitestRootArg(argv) {
198+return argv.some(
199+(arg) =>
200+arg === "--root" ||
201+arg === "-r" ||
202+arg === "--dir" ||
203+arg.startsWith("--root=") ||
204+arg.startsWith("--dir="),
205+);
206+}
207+208+export function resolveMissingExplicitTestFiles(argv, cwd = process.cwd(), fsImpl = fs) {
209+if (hasExplicitVitestConfigArg(argv) || hasAlternateVitestRootArg(argv)) {
210+return [];
211+}
212+return collectExplicitTestFileArgs(argv)
213+.filter((arg) => {
214+const filePath = path.isAbsolute(arg) ? arg : path.resolve(cwd, arg);
215+return !fsImpl.existsSync(filePath);
216+})
217+.map((arg) => toRepoRelativeArg(arg, cwd));
218+}
219+102220function toRepoRelativeArg(arg, cwd) {
103221const normalized = path.isAbsolute(arg) ? path.relative(cwd, arg) : arg;
104222return normalized.replaceAll(path.sep, "/").replace(/^\.\//u, "");
@@ -309,6 +427,17 @@ function main(argv = process.argv.slice(2), env = process.env) {
309427process.exit(1);
310428}
311429430+const missingTestFiles = resolveMissingExplicitTestFiles(argv);
431+if (missingTestFiles.length > 0) {
432+console.error(
433+[
434+"[vitest] explicit test file(s) not found:",
435+ ...missingTestFiles.map((file) => ` - ${file}`),
436+].join("\n"),
437+);
438+process.exit(1);
439+}
440+312441const vitestArgs = resolveImplicitVitestArgs(argv);
313442const { child, teardown } = spawnWatchedVitestProcess({
314443pnpmArgs: [
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。