perf: split acp and ui vitest lanes

This commit is contained in:
Peter Steinberger
2026-04-04 02:03:50 +01:00
parent fb0ff6896a
commit e941d425ac
10 changed files with 103 additions and 23 deletions

View File

@@ -6,6 +6,7 @@ import { isBoundaryTestFile, isBundledPluginDependentUnitTestFile } from "../vit
const DEFAULT_VITEST_CONFIG = "vitest.unit.config.ts";
const AGENTS_VITEST_CONFIG = "vitest.agents.config.ts";
const ACP_VITEST_CONFIG = "vitest.acp.config.ts";
const AUTO_REPLY_VITEST_CONFIG = "vitest.auto-reply.config.ts";
const BOUNDARY_VITEST_CONFIG = "vitest.boundary.config.ts";
const BUNDLED_VITEST_CONFIG = "vitest.bundled.config.ts";
@@ -15,6 +16,7 @@ const CONTRACTS_VITEST_CONFIG = "vitest.contracts.config.ts";
const E2E_VITEST_CONFIG = "vitest.e2e.config.ts";
const EXTENSIONS_VITEST_CONFIG = "vitest.extensions.config.ts";
const GATEWAY_VITEST_CONFIG = "vitest.gateway.config.ts";
const UI_VITEST_CONFIG = "vitest.ui.config.ts";
const INCLUDE_FILE_ENV_KEY = "OPENCLAW_VITEST_INCLUDE_FILE";
function normalizePathPattern(value) {
@@ -98,6 +100,9 @@ function classifyTarget(arg, cwd) {
if (relative.startsWith("src/gateway/")) {
return "gateway";
}
if (relative.startsWith("src/acp/")) {
return "acp";
}
if (relative.startsWith("src/commands/")) {
return "command";
}
@@ -107,6 +112,9 @@ function classifyTarget(arg, cwd) {
if (relative.startsWith("src/agents/")) {
return "agent";
}
if (relative.startsWith("ui/src/ui/")) {
return "ui";
}
return "default";
}
@@ -177,9 +185,11 @@ export function buildVitestRunPlans(args, cwd = process.cwd()) {
"contracts",
"bundled",
"gateway",
"acp",
"command",
"autoReply",
"agent",
"ui",
"e2e",
"channel",
"extension",
@@ -199,19 +209,23 @@ export function buildVitestRunPlans(args, cwd = process.cwd()) {
? BUNDLED_VITEST_CONFIG
: kind === "gateway"
? GATEWAY_VITEST_CONFIG
: kind === "command"
? COMMANDS_VITEST_CONFIG
: kind === "autoReply"
? AUTO_REPLY_VITEST_CONFIG
: kind === "agent"
? AGENTS_VITEST_CONFIG
: kind === "e2e"
? E2E_VITEST_CONFIG
: kind === "channel"
? CHANNEL_VITEST_CONFIG
: kind === "extension"
? EXTENSIONS_VITEST_CONFIG
: DEFAULT_VITEST_CONFIG;
: kind === "acp"
? ACP_VITEST_CONFIG
: kind === "command"
? COMMANDS_VITEST_CONFIG
: kind === "autoReply"
? AUTO_REPLY_VITEST_CONFIG
: kind === "agent"
? AGENTS_VITEST_CONFIG
: kind === "ui"
? UI_VITEST_CONFIG
: kind === "e2e"
? E2E_VITEST_CONFIG
: kind === "channel"
? CHANNEL_VITEST_CONFIG
: kind === "extension"
? EXTENSIONS_VITEST_CONFIG
: DEFAULT_VITEST_CONFIG;
const includePatterns =
kind === "default" || kind === "e2e"
? null

View File

@@ -168,6 +168,17 @@ describe("test-projects args", () => {
]);
});
it("routes acp targets to the acp config", () => {
expect(buildVitestRunPlans(["src/acp/control-plane/manager.test.ts"])).toEqual([
{
config: "vitest.acp.config.ts",
forwardedArgs: [],
includePatterns: ["src/acp/control-plane/manager.test.ts"],
watchMode: false,
},
]);
});
it("widens non-test helper file targets to sibling tests inside the routed suite", () => {
expect(buildVitestRunPlans(["src/gateway/gateway-connection.test-mocks.ts"])).toEqual([
{
@@ -192,6 +203,17 @@ describe("test-projects args", () => {
]);
});
it("routes ui targets to the ui config", () => {
expect(buildVitestRunPlans(["ui/src/ui/views/channels.test.ts"])).toEqual([
{
config: "vitest.ui.config.ts",
forwardedArgs: [],
includePatterns: ["ui/src/ui/views/channels.test.ts"],
watchMode: false,
},
]);
});
it("widens top-level test helpers to sibling repo tests under contracts", () => {
expect(buildVitestRunPlans(["test/helpers/temp-home.ts"])).toEqual([
{

View File

@@ -2,10 +2,12 @@ import { describe, expect, it } from "vitest";
import baseConfig from "../vitest.config.ts";
describe("projects vitest config", () => {
it("defines unit and boundary project config files at the root", () => {
it("defines unit, boundary, acp, and ui project config files at the root", () => {
expect(baseConfig.test?.projects).toEqual([
"vitest.unit.config.ts",
"vitest.boundary.config.ts",
"vitest.acp.config.ts",
"vitest.ui.config.ts",
]);
});
});

View File

@@ -2,6 +2,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { createAcpVitestConfig } from "../vitest.acp.config.ts";
import { createAgentsVitestConfig } from "../vitest.agents.config.ts";
import { createAutoReplyVitestConfig } from "../vitest.auto-reply.config.ts";
import { createChannelsVitestConfig } from "../vitest.channels.config.ts";
@@ -9,6 +10,7 @@ import { createCommandsVitestConfig } from "../vitest.commands.config.ts";
import { createExtensionsVitestConfig } from "../vitest.extensions.config.ts";
import { createGatewayVitestConfig } from "../vitest.gateway.config.ts";
import { createScopedVitestConfig, resolveVitestIsolation } from "../vitest.scoped-config.ts";
import { createUiVitestConfig } from "../vitest.ui.config.ts";
import { BUNDLED_PLUGIN_TEST_GLOB, bundledPluginFile } from "./helpers/bundled-plugin-paths.js";
const EXTENSIONS_CHANNEL_GLOB = ["extensions", "channel", "**"].join("/");
@@ -65,11 +67,13 @@ describe("createScopedVitestConfig", () => {
describe("scoped vitest configs", () => {
const defaultChannelsConfig = createChannelsVitestConfig({});
const defaultAcpConfig = createAcpVitestConfig({});
const defaultExtensionsConfig = createExtensionsVitestConfig({});
const defaultGatewayConfig = createGatewayVitestConfig({});
const defaultCommandsConfig = createCommandsVitestConfig({});
const defaultAutoReplyConfig = createAutoReplyVitestConfig({});
const defaultAgentsConfig = createAgentsVitestConfig({});
const defaultUiConfig = createUiVitestConfig({});
it("defaults channel tests to non-isolated mode", () => {
expect(defaultChannelsConfig.test?.isolate).toBe(false);
@@ -135,6 +139,11 @@ describe("scoped vitest configs", () => {
expect(defaultGatewayConfig.test?.include).toEqual(["**/*.test.ts"]);
});
it("normalizes acp include patterns relative to the scoped dir", () => {
expect(defaultAcpConfig.test?.dir).toBe("src/acp");
expect(defaultAcpConfig.test?.include).toEqual(["**/*.test.ts"]);
});
it("normalizes commands include patterns relative to the scoped dir", () => {
expect(defaultCommandsConfig.test?.dir).toBe("src/commands");
expect(defaultCommandsConfig.test?.include).toEqual(["**/*.test.ts"]);
@@ -149,4 +158,9 @@ describe("scoped vitest configs", () => {
expect(defaultAgentsConfig.test?.dir).toBe("src/agents");
expect(defaultAgentsConfig.test?.include).toEqual(["**/*.test.ts"]);
});
it("normalizes ui include patterns relative to the scoped dir", () => {
expect(defaultUiConfig.test?.dir).toBe("ui/src/ui");
expect(defaultUiConfig.test?.include).toEqual(["**/*.test.ts"]);
});
});

View File

@@ -72,6 +72,13 @@ describe("unit vitest config", () => {
expect(unitConfig.test?.isolate).toBe(false);
});
it("keeps acp and ui tests out of the generic unit lane", () => {
const unitConfig = createUnitVitestConfig({});
expect(unitConfig.test?.exclude).toEqual(
expect.arrayContaining(["src/acp/**", "ui/src/ui/**"]),
);
});
it("adds the OpenClaw runtime setup hooks on top of the base setup", () => {
const unitConfig = createUnitVitestConfig({});
expect(unitConfig.test?.setupFiles).toEqual([

10
vitest.acp.config.ts Normal file
View File

@@ -0,0 +1,10 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createAcpVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/acp/**/*.test.ts"], {
dir: "src/acp",
env,
});
}
export default createAcpVitestConfig();

View File

@@ -7,6 +7,11 @@ export default defineConfig({
...sharedVitestConfig,
test: {
...sharedVitestConfig.test,
projects: ["vitest.unit.config.ts", "vitest.boundary.config.ts"],
projects: [
"vitest.unit.config.ts",
"vitest.boundary.config.ts",
"vitest.acp.config.ts",
"vitest.ui.config.ts",
],
},
});

View File

@@ -95,6 +95,7 @@ export const sharedVitestConfig = {
"scripts/test-projects.mjs",
"vitest.channel-paths.mjs",
"vitest.channels.config.ts",
"vitest.acp.config.ts",
"vitest.boundary.config.ts",
"vitest.bundled.config.ts",
"vitest.config.ts",
@@ -106,6 +107,7 @@ export const sharedVitestConfig = {
"vitest.performance-config.ts",
"vitest.scoped-config.ts",
"vitest.shared.config.ts",
"vitest.ui.config.ts",
"vitest.unit.config.ts",
"vitest.unit-paths.mjs",
],

10
vitest.ui.config.ts Normal file
View File

@@ -0,0 +1,10 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createUiVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["ui/src/ui/**/*.test.ts"], {
dir: "ui/src/ui",
env,
});
}
export default createUiVitestConfig();

View File

@@ -5,14 +5,6 @@ export const unitTestIncludePatterns = [
"src/**/*.test.ts",
"packages/**/*.test.ts",
"test/**/*.test.ts",
"ui/src/ui/app-chat.test.ts",
"ui/src/ui/chat/**/*.test.ts",
"ui/src/ui/views/agents-utils.test.ts",
"ui/src/ui/views/channels.test.ts",
"ui/src/ui/views/chat.test.ts",
"ui/src/ui/views/usage-render-details.test.ts",
"ui/src/ui/controllers/agents.test.ts",
"ui/src/ui/controllers/chat.test.ts",
];
export const boundaryTestFiles = [
@@ -42,6 +34,7 @@ export const unitTestAdditionalExcludePatterns = [
`${BUNDLED_PLUGIN_ROOT_DIR}/**`,
"src/browser/**",
"src/line/**",
"src/acp/**",
"src/agents/**",
"src/auto-reply/**",
"src/commands/**",
@@ -60,6 +53,7 @@ export const unitTestAdditionalExcludePatterns = [
"src/config/schema.base.generated.test.ts",
"src/config/schema.help.quality.test.ts",
"test/**",
"ui/src/ui/**",
];
const sharedBaseExcludePatterns = [