mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:50:43 +00:00
test: simplify changed test routing
This commit is contained in:
@@ -5,12 +5,11 @@ import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
detectChangedLanes,
|
||||
isLiveDockerPackageScriptOnlyChange,
|
||||
isPackageScriptOnlyChange,
|
||||
} from "../../scripts/changed-lanes.mjs";
|
||||
import {
|
||||
CHANGED_CHECK_VITEST_NO_OUTPUT_TIMEOUT_MS,
|
||||
createChangedCheckChildEnv,
|
||||
createChangedCheckPlan,
|
||||
createChangedCheckVitestEnv,
|
||||
} from "../../scripts/check-changed.mjs";
|
||||
import { cleanupTempDirs, makeTempRepoRoot } from "../helpers/temp-repo.js";
|
||||
|
||||
@@ -216,8 +215,8 @@ describe("scripts/changed-lanes", () => {
|
||||
extensionTests: true,
|
||||
all: false,
|
||||
});
|
||||
expect(plan.runExtensionTests).toBe(true);
|
||||
expect(plan.testTargets).toEqual(["src/plugin-sdk/core.test.ts"]);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:extensions");
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:extensions:test");
|
||||
});
|
||||
|
||||
it("fails safe for root config changes", () => {
|
||||
@@ -225,8 +224,8 @@ describe("scripts/changed-lanes", () => {
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(result.lanes.all).toBe(true);
|
||||
expect(plan.runFullTests).toBe(true);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:all");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("routes gitignore changes to tooling instead of all lanes", () => {
|
||||
@@ -237,10 +236,9 @@ describe("scripts/changed-lanes", () => {
|
||||
tooling: true,
|
||||
all: false,
|
||||
});
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.runChangedTestsBroad).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("lint:scripts");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("tsgo:all");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("routes live Docker ACP tooling changes through a focused gate", () => {
|
||||
@@ -258,8 +256,6 @@ describe("scripts/changed-lanes", () => {
|
||||
all: false,
|
||||
tooling: false,
|
||||
});
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.runChangedTestsBroad).toBe(false);
|
||||
expect(plan.commands.map((command) => command.name)).toEqual([
|
||||
"conflict markers",
|
||||
"typecheck core tests",
|
||||
@@ -267,8 +263,6 @@ describe("scripts/changed-lanes", () => {
|
||||
"lint scripts",
|
||||
"live Docker shell syntax",
|
||||
"live Docker scheduler dry run",
|
||||
"ACP bind unit tests",
|
||||
"ACPX extension tests",
|
||||
]);
|
||||
expect(
|
||||
plan.commands.find((command) => command.name === "live Docker shell syntax"),
|
||||
@@ -330,7 +324,6 @@ describe("scripts/changed-lanes", () => {
|
||||
releaseMetadata: false,
|
||||
all: false,
|
||||
});
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.commands.map((command) => command.name)).toContain("live Docker scheduler dry run");
|
||||
});
|
||||
|
||||
@@ -400,6 +393,77 @@ describe("scripts/changed-lanes", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("classifies normal package script changes from the git diff", () => {
|
||||
const dir = makeTempRepoRoot(tempDirs, "openclaw-package-scripts-");
|
||||
git(dir, ["init", "-q", "--initial-branch=main"]);
|
||||
writeFileSync(
|
||||
path.join(dir, "package.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: "fixture",
|
||||
scripts: {
|
||||
test: "node scripts/test-projects.mjs",
|
||||
},
|
||||
dependencies: {
|
||||
leftpad: "1.0.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
"utf8",
|
||||
);
|
||||
git(dir, ["add", "package.json"]);
|
||||
git(dir, [
|
||||
"-c",
|
||||
"user.email=test@example.com",
|
||||
"-c",
|
||||
"user.name=Test User",
|
||||
"commit",
|
||||
"-q",
|
||||
"-m",
|
||||
"initial",
|
||||
]);
|
||||
|
||||
writeFileSync(
|
||||
path.join(dir, "package.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: "fixture",
|
||||
scripts: {
|
||||
test: "node scripts/test-projects.mjs",
|
||||
"test:profile": "node scripts/profile-tests.mjs",
|
||||
},
|
||||
dependencies: {
|
||||
leftpad: "1.0.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const output = execFileSync(
|
||||
process.execPath,
|
||||
[path.join(repoRoot, "scripts", "changed-lanes.mjs"), "--json", "--base", "HEAD"],
|
||||
{
|
||||
cwd: dir,
|
||||
encoding: "utf8",
|
||||
env: createNestedGitEnv(),
|
||||
},
|
||||
);
|
||||
|
||||
expect(JSON.parse(output)).toMatchObject({
|
||||
paths: ["package.json"],
|
||||
lanes: {
|
||||
tooling: true,
|
||||
all: false,
|
||||
liveDockerTooling: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps non-script package changes off the live Docker focused gate", () => {
|
||||
const before = `${JSON.stringify(
|
||||
{ name: "fixture", scripts: {}, dependencies: { leftpad: "1.0.0" } },
|
||||
@@ -422,6 +486,41 @@ describe("scripts/changed-lanes", () => {
|
||||
expect(isLiveDockerPackageScriptOnlyChange(before, after)).toBe(false);
|
||||
});
|
||||
|
||||
it("routes package script-only changes through the tooling gate", () => {
|
||||
const before = `${JSON.stringify(
|
||||
{ name: "fixture", scripts: { test: "node test.js" }, dependencies: { leftpad: "1.0.0" } },
|
||||
null,
|
||||
2,
|
||||
)}\n`;
|
||||
const after = `${JSON.stringify(
|
||||
{
|
||||
name: "fixture",
|
||||
scripts: {
|
||||
test: "node test.js",
|
||||
"test:profile": "node scripts/profile-tests.mjs",
|
||||
},
|
||||
dependencies: { leftpad: "1.0.0" },
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`;
|
||||
|
||||
expect(isPackageScriptOnlyChange(before, after)).toBe(true);
|
||||
|
||||
const result = detectChangedLanes(["package.json"], {
|
||||
packageJsonChangeKind: "tooling",
|
||||
});
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(result.lanes).toMatchObject({
|
||||
tooling: true,
|
||||
all: false,
|
||||
liveDockerTooling: false,
|
||||
});
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("lint:scripts");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("tsgo:all");
|
||||
});
|
||||
|
||||
it("keeps release metadata commits off the full changed gate", () => {
|
||||
const result = detectChangedLanes([
|
||||
"CHANGELOG.md",
|
||||
@@ -443,7 +542,6 @@ describe("scripts/changed-lanes", () => {
|
||||
core: false,
|
||||
apps: false,
|
||||
});
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toEqual([
|
||||
"check:no-conflict-markers",
|
||||
"release-metadata:check",
|
||||
@@ -519,26 +617,24 @@ describe("scripts/changed-lanes", () => {
|
||||
tooling: true,
|
||||
all: false,
|
||||
});
|
||||
expect(plan.testTargets).toEqual(["test/git-hooks-pre-commit.test.ts"]);
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("lint:scripts");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("keeps shared Vitest wiring changes on the broad changed test path", () => {
|
||||
it("keeps shared Vitest wiring changes out of check test execution", () => {
|
||||
const result = detectChangedLanes(["test/vitest/vitest.shared.config.ts"]);
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(plan.testTargets).toEqual([]);
|
||||
expect(plan.runChangedTestsBroad).toBe(true);
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("lint:scripts");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("keeps setup changes on the broad changed test path", () => {
|
||||
it("keeps setup changes out of check test execution", () => {
|
||||
const result = detectChangedLanes(["test/setup.ts"]);
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(plan.testTargets).toEqual([]);
|
||||
expect(plan.runChangedTestsBroad).toBe(true);
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("lint:scripts");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("does not route generated A2UI artifacts as direct Vitest targets", () => {
|
||||
@@ -548,17 +644,16 @@ describe("scripts/changed-lanes", () => {
|
||||
]);
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(plan.testTargets).toEqual(["test/scripts/bundle-a2ui.test.ts"]);
|
||||
expect(plan.runChangedTestsBroad).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:core");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("routes changed extension Vitest configs to only their owning shard", () => {
|
||||
const result = detectChangedLanes(["test/vitest/vitest.extension-discord.config.ts"]);
|
||||
const plan = createChangedCheckPlan(result);
|
||||
|
||||
expect(plan.testTargets).toEqual(["test/vitest/vitest.extension-discord.config.ts"]);
|
||||
expect(plan.runChangedTestsBroad).toBe(false);
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("lint:scripts");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("test");
|
||||
});
|
||||
|
||||
it("keeps an empty changed path list as a no-op", () => {
|
||||
@@ -580,8 +675,6 @@ describe("scripts/changed-lanes", () => {
|
||||
expect(plan.commands).toEqual([
|
||||
{ name: "conflict markers", args: ["check:no-conflict-markers"] },
|
||||
]);
|
||||
expect(plan.runChangedTestsBroad).toBe(false);
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps docs-only changes cheap", () => {
|
||||
@@ -592,40 +685,5 @@ describe("scripts/changed-lanes", () => {
|
||||
expect(plan.commands).toEqual([
|
||||
{ name: "conflict markers", args: ["check:no-conflict-markers"] },
|
||||
]);
|
||||
expect(plan.runChangedTestsBroad).toBe(false);
|
||||
expect(plan.runFullTests).toBe(false);
|
||||
});
|
||||
|
||||
it("sets a ten-minute Vitest watchdog for changed checks", () => {
|
||||
expect(CHANGED_CHECK_VITEST_NO_OUTPUT_TIMEOUT_MS).toBe("600000");
|
||||
expect(createChangedCheckVitestEnv({ PATH: "/usr/bin" })).toMatchObject({
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: CHANGED_CHECK_VITEST_NO_OUTPUT_TIMEOUT_MS,
|
||||
OPENCLAW_VITEST_NO_OUTPUT_RETRY: "0",
|
||||
OPENCLAW_TEST_PROJECTS_SERIAL: "1",
|
||||
OPENCLAW_VITEST_MAX_WORKERS: "1",
|
||||
});
|
||||
|
||||
expect(
|
||||
createChangedCheckVitestEnv({
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "45000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_RETRY: "1",
|
||||
}),
|
||||
).toMatchObject({
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "45000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_RETRY: "1",
|
||||
});
|
||||
});
|
||||
|
||||
it("does not force serial changed-check tests in CI or when workers are explicit", () => {
|
||||
expect(createChangedCheckVitestEnv({ CI: "true" })).not.toHaveProperty(
|
||||
"OPENCLAW_VITEST_MAX_WORKERS",
|
||||
);
|
||||
expect(createChangedCheckVitestEnv({ OPENCLAW_VITEST_MAX_WORKERS: "4" })).toMatchObject({
|
||||
OPENCLAW_VITEST_MAX_WORKERS: "4",
|
||||
});
|
||||
expect(
|
||||
createChangedCheckVitestEnv({ OPENCLAW_TEST_PROJECTS_PARALLEL: "4" }),
|
||||
).not.toHaveProperty("OPENCLAW_TEST_PROJECTS_SERIAL");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,12 +25,23 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
).toEqual(["src/shared/string-normalization.test.ts", "src/utils/provider-utils.test.ts"]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run for Vitest wiring edits", () => {
|
||||
it("keeps changed mode focused by default for Vitest wiring edits", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"test/vitest/vitest.shared.config.ts",
|
||||
"src/utils/provider-utils.ts",
|
||||
]),
|
||||
).toEqual(["src/utils/provider-utils.test.ts"]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run available for Vitest wiring edits", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(
|
||||
["--changed", "origin/main"],
|
||||
process.cwd(),
|
||||
() => ["test/vitest/vitest.shared.config.ts", "src/utils/provider-utils.ts"],
|
||||
{ env: { OPENCLAW_TEST_CHANGED_BROAD: "1" } },
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
@@ -129,11 +140,22 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run for shared test helpers", () => {
|
||||
it("keeps shared test helpers cheap by default when no precise target exists", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"test/helpers/channels/plugin.ts",
|
||||
]),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run available for shared test helpers", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(
|
||||
["--changed", "origin/main"],
|
||||
process.cwd(),
|
||||
() => ["test/helpers/channels/plugin.ts"],
|
||||
{ env: { OPENCLAW_TEST_CHANGED_BROAD: "1" } },
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
@@ -174,11 +196,22 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run for unknown root surfaces", () => {
|
||||
it("keeps unknown root surfaces cheap by default", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"unknown/file.txt",
|
||||
]),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps the broad changed run available for unknown root surfaces", () => {
|
||||
expect(
|
||||
resolveChangedTargetArgs(
|
||||
["--changed", "origin/main"],
|
||||
process.cwd(),
|
||||
() => ["unknown/file.txt"],
|
||||
{ env: { OPENCLAW_TEST_CHANGED_BROAD: "1" } },
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
@@ -204,11 +237,29 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("adds extension tests for public plugin SDK changes", () => {
|
||||
it("keeps public plugin SDK changes focused by default", () => {
|
||||
const plans = buildVitestRunPlans(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"src/plugin-sdk/provider-entry.ts",
|
||||
]);
|
||||
|
||||
expect(plans).toEqual([
|
||||
{
|
||||
config: "test/vitest/vitest.unit-fast.config.ts",
|
||||
forwardedArgs: [],
|
||||
includePatterns: ["src/plugin-sdk/provider-entry.test.ts"],
|
||||
watchMode: false,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("adds extension tests for public plugin SDK changes in broad changed mode", () => {
|
||||
const plans = buildVitestRunPlans(
|
||||
["--changed", "origin/main"],
|
||||
process.cwd(),
|
||||
() => ["src/plugin-sdk/provider-entry.ts"],
|
||||
{ env: { OPENCLAW_TEST_CHANGED_BROAD: "1" } },
|
||||
);
|
||||
|
||||
expect(plans).toEqual([
|
||||
{
|
||||
config: "test/vitest/vitest.unit-fast.config.ts",
|
||||
@@ -485,11 +536,29 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("routes plugin-sdk source files with sibling tests narrowly plus extension tests", () => {
|
||||
it("routes plugin-sdk source files with sibling tests narrowly by default", () => {
|
||||
const plans = buildVitestRunPlans(["--changed", "origin/main"], process.cwd(), () => [
|
||||
"src/plugin-sdk/facade-runtime.ts",
|
||||
]);
|
||||
|
||||
expect(plans).toEqual([
|
||||
{
|
||||
config: "test/vitest/vitest.bundled.config.ts",
|
||||
forwardedArgs: [],
|
||||
includePatterns: ["src/plugin-sdk/facade-runtime.test.ts"],
|
||||
watchMode: false,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("routes plugin-sdk source files with sibling tests plus extensions in broad changed mode", () => {
|
||||
const plans = buildVitestRunPlans(
|
||||
["--changed", "origin/main"],
|
||||
process.cwd(),
|
||||
() => ["src/plugin-sdk/facade-runtime.ts"],
|
||||
{ env: { OPENCLAW_TEST_CHANGED_BROAD: "1" } },
|
||||
);
|
||||
|
||||
expect(plans).toEqual([
|
||||
{
|
||||
config: "test/vitest/vitest.bundled.config.ts",
|
||||
@@ -521,22 +590,27 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps focused changed mode to precise targets only", () => {
|
||||
expect(
|
||||
resolveChangedTestTargetPlan(["package.json", "src/commands/channels.add.ts"], {
|
||||
focused: true,
|
||||
}),
|
||||
).toEqual({
|
||||
it("keeps changed mode to precise targets by default", () => {
|
||||
expect(resolveChangedTestTargetPlan(["package.json", "src/commands/channels.add.ts"])).toEqual({
|
||||
mode: "targets",
|
||||
targets: ["src/commands/channels.add.test.ts"],
|
||||
});
|
||||
});
|
||||
|
||||
it("uses import-graph targets in focused changed mode", () => {
|
||||
it("keeps broad changed fallback available through explicit env", () => {
|
||||
expect(
|
||||
resolveChangedTestTargetPlan(["test/helpers/plugins/plugin-registration.ts"], {
|
||||
focused: true,
|
||||
}).targets,
|
||||
resolveChangedTestTargetPlan(["package.json", "src/commands/channels.add.ts"], {
|
||||
env: { OPENCLAW_TEST_CHANGED_BROAD: "1" },
|
||||
}),
|
||||
).toEqual({
|
||||
mode: "broad",
|
||||
targets: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("uses import-graph targets in default changed mode", () => {
|
||||
expect(
|
||||
resolveChangedTestTargetPlan(["test/helpers/plugins/plugin-registration.ts"]).targets,
|
||||
).toContain("extensions/openrouter/index.test.ts");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user