mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-08 19:12:22 +00:00
fix(test): chunk broad script test routing
This commit is contained in:
@@ -561,6 +561,29 @@ function isExplicitTestFileArg(arg) {
|
||||
return EXPLICIT_TEST_FILE_RE.test(arg) && isExplicitFileTargetArg(arg);
|
||||
}
|
||||
|
||||
function isDelegableBroadProjectRouterTarget(arg, cwd) {
|
||||
const relative = toRepoRelativeArg(arg, cwd).replace(/\/+$/u, "");
|
||||
return (
|
||||
relative === "test/scripts" ||
|
||||
relative === "test/scripts/*.test.ts" ||
|
||||
relative === "test/scripts/**/*.test.ts"
|
||||
);
|
||||
}
|
||||
|
||||
function isExplicitProjectRouterTargetArg(arg, cwd = process.cwd(), fsImpl = fs) {
|
||||
if (!isPathLikeExplicitFileArg(arg)) {
|
||||
return false;
|
||||
}
|
||||
if (GLOB_PATTERN_CHARS_RE.test(arg)) {
|
||||
return isDelegableBroadProjectRouterTarget(arg, cwd);
|
||||
}
|
||||
if (isExplicitFileTargetArg(arg)) {
|
||||
return true;
|
||||
}
|
||||
const filePath = path.isAbsolute(arg) ? arg : path.resolve(cwd, arg);
|
||||
return fsImpl.existsSync(filePath) && isDelegableBroadProjectRouterTarget(arg, cwd);
|
||||
}
|
||||
|
||||
function collectExplicitFileTargetArgs(argv, predicate = isExplicitFileTargetArg) {
|
||||
const files = [];
|
||||
for (let index = 0; index < argv.length; index += 1) {
|
||||
@@ -582,6 +605,12 @@ function collectExplicitFileTargetArgs(argv, predicate = isExplicitFileTargetArg
|
||||
return files;
|
||||
}
|
||||
|
||||
function collectExplicitProjectRouterTargetArgs(argv, cwd = process.cwd(), fsImpl = fs) {
|
||||
return collectExplicitFileTargetArgs(argv, (arg) =>
|
||||
isExplicitProjectRouterTargetArg(arg, cwd, fsImpl),
|
||||
);
|
||||
}
|
||||
|
||||
function collectExplicitTestFileArgs(argv) {
|
||||
return collectExplicitFileTargetArgs(argv, isExplicitTestFileArg);
|
||||
}
|
||||
@@ -701,9 +730,9 @@ function hasNonRunVitestSubcommand(argv) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates default or explicit-file runs to the repo test-projects runner.
|
||||
* Delegates explicit path runs to the repo test-projects runner.
|
||||
*/
|
||||
export function resolveTestProjectsDelegationArgs(argv) {
|
||||
export function resolveTestProjectsDelegationArgs(argv, cwd = process.cwd()) {
|
||||
if (
|
||||
hasExplicitVitestConfigArg(argv) ||
|
||||
hasAlternateVitestRootArg(argv) ||
|
||||
@@ -712,7 +741,7 @@ export function resolveTestProjectsDelegationArgs(argv) {
|
||||
hasNonRunVitestSubcommand(argv) ||
|
||||
hasExplicitDisabledRunFlag(argv) ||
|
||||
hasSeparateVitestOptionValueArg(argv) ||
|
||||
collectExplicitFileTargetArgs(argv).length === 0
|
||||
collectExplicitProjectRouterTargetArgs(argv, cwd).length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -287,6 +287,11 @@ const TOOLING_ISOLATED_VITEST_CONFIG = "test/vitest/vitest.tooling-isolated.conf
|
||||
const TOOLING_VITEST_CONFIG = "test/vitest/vitest.tooling.config.ts";
|
||||
const TOOLING_DOCKER_TEST_TARGET = "test/scripts/docker-build-helper.test.ts";
|
||||
const TOOLING_ISOLATED_TEST_TARGET = "test/scripts/openclaw-e2e-instance.test.ts";
|
||||
const BROAD_TOOLING_SCRIPT_TEST_PATTERNS = new Set([
|
||||
"test/scripts/**/*.test.ts",
|
||||
"test/scripts/*.test.ts",
|
||||
]);
|
||||
const BROAD_TOOLING_SCRIPT_TEST_TARGET_CHUNK_SIZE = 60;
|
||||
const TUI_VITEST_CONFIG = "test/vitest/vitest.tui.config.ts";
|
||||
const TUI_PTY_VITEST_CONFIG = "test/vitest/vitest.tui-pty.config.ts";
|
||||
const UI_VITEST_CONFIG = "test/vitest/vitest.ui.config.ts";
|
||||
@@ -1465,6 +1470,64 @@ function splitTargetChunks(targets, chunkCount) {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function listBroadScriptTestTargets(pattern, cwd) {
|
||||
const root = path.join(cwd, "test/scripts");
|
||||
if (!fs.existsSync(root)) {
|
||||
return [];
|
||||
}
|
||||
return listRepoFilesRecursive(root, cwd)
|
||||
.filter((file) => file.endsWith(".test.ts") && path.matchesGlob(file, pattern))
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
function listBroadToolingScriptTestTargets(pattern, cwd) {
|
||||
return listBroadScriptTestTargets(pattern, cwd).filter(
|
||||
(file) => classifyTarget(file, cwd) === "tooling",
|
||||
);
|
||||
}
|
||||
|
||||
function createBroadToolingScriptPlans({ config, forwardedArgs, includePatterns, watchMode, cwd }) {
|
||||
if (watchMode || config !== TOOLING_VITEST_CONFIG || !includePatterns) {
|
||||
return null;
|
||||
}
|
||||
const [pattern] = includePatterns;
|
||||
const targets =
|
||||
includePatterns.length === 1 && BROAD_TOOLING_SCRIPT_TEST_PATTERNS.has(pattern)
|
||||
? listBroadToolingScriptTestTargets(pattern, cwd)
|
||||
: includePatterns.every((target) => target.startsWith("test/scripts/"))
|
||||
? includePatterns
|
||||
: [];
|
||||
if (targets.length <= BROAD_TOOLING_SCRIPT_TEST_TARGET_CHUNK_SIZE) {
|
||||
return null;
|
||||
}
|
||||
const chunkCount = Math.ceil(targets.length / BROAD_TOOLING_SCRIPT_TEST_TARGET_CHUNK_SIZE);
|
||||
const chunks = splitTargetChunks(targets, chunkCount);
|
||||
return chunks.length > 0
|
||||
? chunks.map((chunk) => ({
|
||||
config,
|
||||
forwardedArgs,
|
||||
includePatterns: chunk,
|
||||
watchMode,
|
||||
}))
|
||||
: null;
|
||||
}
|
||||
|
||||
function expandBroadToolingScriptTargets(targetArgs, cwd, watchMode) {
|
||||
if (watchMode) {
|
||||
return targetArgs;
|
||||
}
|
||||
return uniqueOrdered(
|
||||
targetArgs.flatMap((targetArg) => {
|
||||
const pattern = toScopedIncludePattern(targetArg, cwd);
|
||||
if (!BROAD_TOOLING_SCRIPT_TEST_PATTERNS.has(pattern)) {
|
||||
return [targetArg];
|
||||
}
|
||||
const targets = listBroadScriptTestTargets(pattern, cwd);
|
||||
return targets.length > 0 ? targets : [targetArg];
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function isExistingPathTarget(arg, cwd) {
|
||||
return fs.existsSync(path.resolve(cwd, arg));
|
||||
}
|
||||
@@ -2755,7 +2818,11 @@ export function buildVitestRunPlans(
|
||||
const changedTargetArgs =
|
||||
targetArgs.length === 0 ? resolveChangedTargetArgs(args, cwd, listChangedPaths, options) : null;
|
||||
const requestedTargetArgs = changedTargetArgs ?? targetArgs;
|
||||
const activeTargetArgs = expandExplicitSourceTestTargets(requestedTargetArgs, cwd);
|
||||
const activeTargetArgs = expandBroadToolingScriptTargets(
|
||||
expandExplicitSourceTestTargets(requestedTargetArgs, cwd),
|
||||
cwd,
|
||||
watchMode,
|
||||
);
|
||||
const activeForwardedArgs =
|
||||
changedTargetArgs !== null ? stripChangedArgs(forwardedArgs) : forwardedArgs;
|
||||
if (changedTargetArgs !== null && activeTargetArgs.length === 0) {
|
||||
@@ -2964,9 +3031,21 @@ export function buildVitestRunPlans(
|
||||
}),
|
||||
);
|
||||
const scopedTargetArgs = useCliTargetArgs ? uniqueOrdered(grouped) : [];
|
||||
const forwardedPlanArgs = [...nonTargetArgs, ...scopedTargetArgs];
|
||||
const broadToolingScriptPlans = createBroadToolingScriptPlans({
|
||||
config,
|
||||
cwd,
|
||||
forwardedArgs: forwardedPlanArgs,
|
||||
includePatterns,
|
||||
watchMode,
|
||||
});
|
||||
if (broadToolingScriptPlans) {
|
||||
plans.push(...broadToolingScriptPlans);
|
||||
continue;
|
||||
}
|
||||
plans.push({
|
||||
config,
|
||||
forwardedArgs: [...nonTargetArgs, ...scopedTargetArgs],
|
||||
forwardedArgs: forwardedPlanArgs,
|
||||
includePatterns,
|
||||
watchMode,
|
||||
});
|
||||
|
||||
@@ -293,6 +293,19 @@ describe("scripts/run-vitest", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("delegates bare explicit directories and globs to the project router", () => {
|
||||
expect(resolveTestProjectsDelegationArgs(["test/scripts"])).toEqual(["test/scripts"]);
|
||||
expect(
|
||||
resolveTestProjectsDelegationArgs(["run", "test/scripts", "--reporter=verbose"]),
|
||||
).toEqual(["test/scripts", "--reporter=verbose"]);
|
||||
expect(resolveTestProjectsDelegationArgs(["test/scripts/*.test.ts"])).toEqual([
|
||||
"test/scripts/*.test.ts",
|
||||
]);
|
||||
expect(resolveTestProjectsDelegationArgs(["src/agents/**/*.ts"])).toBeNull();
|
||||
expect(resolveTestProjectsDelegationArgs(["src/**/*.test.ts"])).toBeNull();
|
||||
expect(resolveTestProjectsDelegationArgs(["./src"])).toBeNull();
|
||||
});
|
||||
|
||||
it("delegates mixed filters when an explicit file target is present", () => {
|
||||
expect(
|
||||
resolveTestProjectsDelegationArgs(["src/agents", "test/scripts/run-vitest.test.ts"]),
|
||||
|
||||
@@ -1610,8 +1610,14 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("includes the isolated tooling shard for broad shell helper targets", () => {
|
||||
expect(buildVitestRunPlans(["test/scripts"], process.cwd())).toEqual([
|
||||
it("chunks the broad shell helper tooling shard after isolated targets", () => {
|
||||
const plans = buildVitestRunPlans(["test/scripts"], process.cwd());
|
||||
expect(plans.slice(0, 3)).toEqual([
|
||||
expect.objectContaining({
|
||||
config: "test/vitest/vitest.unit-fast.config.ts",
|
||||
includePatterns: expect.arrayContaining(["test/scripts/arg-utils.test.ts"]),
|
||||
watchMode: false,
|
||||
}),
|
||||
{
|
||||
config: "test/vitest/vitest.tooling-docker.config.ts",
|
||||
forwardedArgs: [],
|
||||
@@ -1624,13 +1630,19 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
includePatterns: ["test/scripts/openclaw-e2e-instance.test.ts"],
|
||||
watchMode: false,
|
||||
},
|
||||
{
|
||||
config: "test/vitest/vitest.tooling.config.ts",
|
||||
forwardedArgs: [],
|
||||
includePatterns: ["test/scripts/**/*.test.ts"],
|
||||
watchMode: false,
|
||||
},
|
||||
]);
|
||||
const toolingPlans = plans.slice(3);
|
||||
const toolingTargets = toolingPlans.flatMap((plan) => plan.includePatterns ?? []);
|
||||
|
||||
expect(toolingPlans.length).toBeGreaterThan(1);
|
||||
expect(
|
||||
toolingPlans.every((plan) => plan.config === "test/vitest/vitest.tooling.config.ts"),
|
||||
).toBe(true);
|
||||
expect(toolingPlans.every((plan) => (plan.includePatterns?.length ?? 0) <= 60)).toBe(true);
|
||||
expect(toolingTargets).toContain("test/scripts/run-opengrep.test.ts");
|
||||
expect(toolingTargets).not.toContain("test/scripts/docker-build-helper.test.ts");
|
||||
expect(toolingTargets).not.toContain("test/scripts/openclaw-e2e-instance.test.ts");
|
||||
expect(new Set(toolingTargets).size).toBe(toolingTargets.length);
|
||||
});
|
||||
|
||||
it("routes the src scripts test root to the tooling shard", () => {
|
||||
@@ -1722,8 +1734,14 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("includes the isolated tooling shard for broad shell helper globs", () => {
|
||||
expect(buildVitestRunPlans(["test/scripts/*.test.ts"], process.cwd())).toEqual([
|
||||
it("chunks broad shell helper globs after isolated targets", () => {
|
||||
const plans = buildVitestRunPlans(["test/scripts/*.test.ts"], process.cwd());
|
||||
expect(plans.slice(0, 3)).toEqual([
|
||||
expect.objectContaining({
|
||||
config: "test/vitest/vitest.unit-fast.config.ts",
|
||||
includePatterns: expect.arrayContaining(["test/scripts/arg-utils.test.ts"]),
|
||||
watchMode: false,
|
||||
}),
|
||||
{
|
||||
config: "test/vitest/vitest.tooling-docker.config.ts",
|
||||
forwardedArgs: [],
|
||||
@@ -1736,13 +1754,19 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
includePatterns: ["test/scripts/openclaw-e2e-instance.test.ts"],
|
||||
watchMode: false,
|
||||
},
|
||||
{
|
||||
config: "test/vitest/vitest.tooling.config.ts",
|
||||
forwardedArgs: [],
|
||||
includePatterns: ["test/scripts/*.test.ts"],
|
||||
watchMode: false,
|
||||
},
|
||||
]);
|
||||
const toolingPlans = plans.slice(3);
|
||||
const toolingTargets = toolingPlans.flatMap((plan) => plan.includePatterns ?? []);
|
||||
|
||||
expect(toolingPlans.length).toBeGreaterThan(1);
|
||||
expect(
|
||||
toolingPlans.every((plan) => plan.config === "test/vitest/vitest.tooling.config.ts"),
|
||||
).toBe(true);
|
||||
expect(toolingPlans.every((plan) => (plan.includePatterns?.length ?? 0) <= 60)).toBe(true);
|
||||
expect(toolingTargets).toContain("test/scripts/run-opengrep.test.ts");
|
||||
expect(toolingTargets).not.toContain("test/scripts/docker-build-helper.test.ts");
|
||||
expect(toolingTargets).not.toContain("test/scripts/openclaw-e2e-instance.test.ts");
|
||||
expect(new Set(toolingTargets).size).toBe(toolingTargets.length);
|
||||
});
|
||||
|
||||
it("keeps broad shell helper watch targets in one tooling shard", () => {
|
||||
|
||||
Reference in New Issue
Block a user