Skip to content

Commit 344e04b

Browse files
committed
fix(testing): route source targets through test planner
1 parent ec47d1c commit 344e04b

2 files changed

Lines changed: 81 additions & 9 deletions

File tree

scripts/run-vitest.mjs

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ const TOOLING_EXCLUDED_TESTS = new Set([
3535
...boundaryTestFiles,
3636
"test/scripts/openclaw-e2e-instance.test.ts",
3737
]);
38+
const EXPLICIT_FILE_TARGET_RE = /\.(?:[cm]?[jt]sx?)$/u;
3839
const EXPLICIT_TEST_FILE_RE = /\.(?:test|e2e|live)\.(?:[cm]?[jt]sx?)$/u;
3940
const GLOB_PATTERN_CHARS_RE = /[*?[\]{}]/u;
41+
const NON_RUN_VITEST_SUBCOMMANDS = new Set(["bench", "list", "related"]);
4042
const VITEST_OPTIONS_WITH_VALUE = new Set([
4143
"--attachmentsDir",
4244
"--bail",
@@ -46,6 +48,7 @@ const VITEST_OPTIONS_WITH_VALUE = new Set([
4648
"-c",
4749
"--changed",
4850
"--dir",
51+
"--diff",
4952
"--environment",
5053
"--exclude",
5154
"--execArgv",
@@ -426,16 +429,24 @@ function optionConsumesNextArg(arg) {
426429
);
427430
}
428431

429-
function isExplicitTestFileArg(arg) {
430-
if (!EXPLICIT_TEST_FILE_RE.test(arg) || GLOB_PATTERN_CHARS_RE.test(arg)) {
431-
return false;
432-
}
432+
function isPathLikeExplicitFileArg(arg) {
433433
return (
434434
path.isAbsolute(arg) || arg.startsWith("./") || arg.startsWith("../") || /[/\\]/u.test(arg)
435435
);
436436
}
437437

438-
function collectExplicitTestFileArgs(argv) {
438+
function isExplicitFileTargetArg(arg) {
439+
if (!EXPLICIT_FILE_TARGET_RE.test(arg) || GLOB_PATTERN_CHARS_RE.test(arg)) {
440+
return false;
441+
}
442+
return isPathLikeExplicitFileArg(arg);
443+
}
444+
445+
function isExplicitTestFileArg(arg) {
446+
return EXPLICIT_TEST_FILE_RE.test(arg) && isExplicitFileTargetArg(arg);
447+
}
448+
449+
function collectExplicitFileTargetArgs(argv, predicate = isExplicitFileTargetArg) {
439450
const files = [];
440451
for (let index = 0; index < argv.length; index += 1) {
441452
const arg = argv[index];
@@ -449,13 +460,17 @@ function collectExplicitTestFileArgs(argv) {
449460
if (arg.startsWith("-")) {
450461
continue;
451462
}
452-
if (isExplicitTestFileArg(arg)) {
463+
if (predicate(arg)) {
453464
files.push(arg);
454465
}
455466
}
456467
return files;
457468
}
458469

470+
function collectExplicitTestFileArgs(argv) {
471+
return collectExplicitFileTargetArgs(argv, isExplicitTestFileArg);
472+
}
473+
459474
export function resolveExplicitTestFileNoPassArgs(argv) {
460475
if (collectExplicitTestFileArgs(argv).length === 0) {
461476
return argv;
@@ -549,15 +564,34 @@ function stripRunSubcommand(argv) {
549564
return stripped;
550565
}
551566

567+
function hasNonRunVitestSubcommand(argv) {
568+
for (let index = 0; index < argv.length; index += 1) {
569+
const arg = argv[index];
570+
if (arg === "--") {
571+
return false;
572+
}
573+
if (optionConsumesNextArg(arg)) {
574+
index += 1;
575+
continue;
576+
}
577+
if (arg.startsWith("-")) {
578+
continue;
579+
}
580+
return NON_RUN_VITEST_SUBCOMMANDS.has(arg);
581+
}
582+
return false;
583+
}
584+
552585
export function resolveTestProjectsDelegationArgs(argv) {
553586
if (
554587
hasExplicitVitestConfigArg(argv) ||
555588
hasAlternateVitestRootArg(argv) ||
556589
hasExplicitVitestProjectArg(argv) ||
557590
resolveExplicitVitestMode(argv) === "watch" ||
591+
hasNonRunVitestSubcommand(argv) ||
558592
hasExplicitDisabledRunFlag(argv) ||
559593
hasSeparateVitestOptionValueArg(argv) ||
560-
collectExplicitTestFileArgs(argv).length === 0
594+
collectExplicitFileTargetArgs(argv).length === 0
561595
) {
562596
return null;
563597
}
@@ -568,7 +602,7 @@ export function resolveMissingExplicitTestFiles(argv, cwd = process.cwd(), fsImp
568602
if (hasExplicitVitestConfigArg(argv) || hasAlternateVitestRootArg(argv)) {
569603
return [];
570604
}
571-
return collectExplicitTestFileArgs(argv)
605+
return collectExplicitFileTargetArgs(argv)
572606
.filter((arg) => {
573607
const filePath = path.isAbsolute(arg) ? arg : path.resolve(cwd, arg);
574608
return !fsImpl.existsSync(filePath);
@@ -856,7 +890,7 @@ function main(argv = process.argv.slice(2), env = process.env) {
856890
if (missingTestFiles.length > 0) {
857891
console.error(
858892
[
859-
"[vitest] explicit test file(s) not found:",
893+
"[vitest] explicit test/source file(s) not found:",
860894
...missingTestFiles.map((file) => ` - ${file}`),
861895
].join("\n"),
862896
);

test/scripts/run-vitest.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,25 @@ describe("scripts/run-vitest", () => {
243243
}
244244
});
245245

246+
it("delegates bare explicit source files to the project router", () => {
247+
const file = "extensions/codex/src/app-server/dynamic-tool-profile.ts";
248+
249+
expect(resolveTestProjectsDelegationArgs([file])).toEqual([file]);
250+
expect(resolveTestProjectsDelegationArgs(["run", file, "--reporter=verbose"])).toEqual([
251+
file,
252+
"--reporter=verbose",
253+
]);
254+
});
255+
256+
it("delegates mixed filters when an explicit file target is present", () => {
257+
expect(
258+
resolveTestProjectsDelegationArgs(["src/agents", "test/scripts/run-vitest.test.ts"]),
259+
).toEqual(["src/agents", "test/scripts/run-vitest.test.ts"]);
260+
expect(
261+
resolveTestProjectsDelegationArgs(["src/**/*.test.ts", "src/agents/bash-tools.ts"]),
262+
).toEqual(["src/**/*.test.ts", "src/agents/bash-tools.ts"]);
263+
});
264+
246265
it("keeps direct Vitest runs when project routing could change option semantics", () => {
247266
const directArgvCases = [
248267
[
@@ -255,10 +274,14 @@ describe("scripts/run-vitest", () => {
255274
["--project", "tooling", "test/scripts/run-vitest.test.ts"],
256275
["watch", "test/scripts/run-vitest.test.ts"],
257276
["dev", "test/scripts/run-vitest.test.ts"],
277+
["related", "src/agents/bash-tools.ts"],
278+
["list", "src/agents/bash-tools.ts"],
279+
["bench", "src/agents/bash-tools.ts"],
258280
["--watch", "test/scripts/run-vitest.test.ts"],
259281
["--run=false", "test/scripts/run-vitest.test.ts"],
260282
["--no-run", "test/scripts/run-vitest.test.ts"],
261283
["--run", "false", "test/scripts/run-vitest.test.ts"],
284+
["--diff", "scripts/run-vitest.mjs"],
262285
["--testNamePattern", "run", "test/scripts/run-vitest.test.ts"],
263286
["run", "test/scripts/run-vitest.test.ts", "-t", "src"],
264287
];
@@ -282,6 +305,21 @@ describe("scripts/run-vitest", () => {
282305
).toEqual(["test/agents/bash-tools.exec.background-abort.test.ts"]);
283306
});
284307

308+
it("reports missing explicit source files before Vitest can fan out by project", () => {
309+
const fsImpl = {
310+
existsSync: (filePath: string) =>
311+
filePath.replaceAll("\\", "/").endsWith("src/agents/bash-tools.ts"),
312+
};
313+
314+
expect(
315+
resolveMissingExplicitTestFiles(
316+
["src/agents/bash-tools.ts", "extensions/codex/src/app-server/missing.ts"],
317+
"/repo",
318+
fsImpl,
319+
),
320+
).toEqual(["extensions/codex/src/app-server/missing.ts"]);
321+
});
322+
285323
it("does not treat option values or glob patterns as explicit missing files", () => {
286324
const fsImpl = {
287325
existsSync: () => false,

0 commit comments

Comments
 (0)