test: move Vitest configs under test

This commit is contained in:
Peter Steinberger
2026-04-10 13:40:04 +01:00
parent 64f2b20963
commit 2ccb5cff22
145 changed files with 896 additions and 774 deletions

View File

@@ -33,7 +33,7 @@ describe("scripts/run-vitest-profile", () => {
"./node_modules/vitest/vitest.mjs",
"run",
"--config",
"vitest.unit.config.ts",
"test/vitest/vitest.unit.config.ts",
"--no-file-parallelism",
],
});
@@ -47,7 +47,7 @@ describe("scripts/run-vitest-profile", () => {
"vitest",
"run",
"--config",
"vitest.unit.config.ts",
"test/vitest/vitest.unit.config.ts",
"--no-file-parallelism",
"--execArgv=--cpu-prof",
"--execArgv=--cpu-prof-dir=/tmp/profile-runner",

View File

@@ -38,7 +38,7 @@ describe("scripts/test-extension.mjs", () => {
expect(plan.extensionId).toBe("slack");
expect(plan.extensionDir).toBe(bundledPluginRoot("slack"));
expect(plan.config).toBe("vitest.extension-channels.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-channels.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("slack"));
expect(plan.hasTests).toBe(true);
});
@@ -47,7 +47,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "bluebubbles", cwd: process.cwd() });
expect(plan.extensionId).toBe("bluebubbles");
expect(plan.config).toBe("vitest.extension-bluebubbles.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-bluebubbles.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("bluebubbles"));
expect(plan.hasTests).toBe(true);
});
@@ -56,7 +56,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "acpx", cwd: process.cwd() });
expect(plan.extensionId).toBe("acpx");
expect(plan.config).toBe("vitest.extension-acpx.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-acpx.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("acpx"));
expect(plan.hasTests).toBe(true);
});
@@ -65,7 +65,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "diffs", cwd: process.cwd() });
expect(plan.extensionId).toBe("diffs");
expect(plan.config).toBe("vitest.extension-diffs.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-diffs.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("diffs"));
expect(plan.hasTests).toBe(true);
});
@@ -74,7 +74,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "feishu", cwd: process.cwd() });
expect(plan.extensionId).toBe("feishu");
expect(plan.config).toBe("vitest.extension-feishu.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-feishu.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("feishu"));
expect(plan.hasTests).toBe(true);
});
@@ -83,7 +83,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "openai", cwd: process.cwd() });
expect(plan.extensionId).toBe("openai");
expect(plan.config).toBe("vitest.extension-providers.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-providers.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("openai"));
expect(plan.hasTests).toBe(true);
});
@@ -92,7 +92,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "matrix", cwd: process.cwd() });
expect(plan.extensionId).toBe("matrix");
expect(plan.config).toBe("vitest.extension-matrix.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-matrix.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("matrix"));
expect(plan.hasTests).toBe(true);
});
@@ -101,7 +101,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "telegram", cwd: process.cwd() });
expect(plan.extensionId).toBe("telegram");
expect(plan.config).toBe("vitest.extension-telegram.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-telegram.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("telegram"));
expect(plan.hasTests).toBe(true);
});
@@ -110,7 +110,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "whatsapp", cwd: process.cwd() });
expect(plan.extensionId).toBe("whatsapp");
expect(plan.config).toBe("vitest.extension-whatsapp.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-whatsapp.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("whatsapp"));
expect(plan.hasTests).toBe(true);
});
@@ -119,7 +119,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "voice-call", cwd: process.cwd() });
expect(plan.extensionId).toBe("voice-call");
expect(plan.config).toBe("vitest.extension-voice-call.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-voice-call.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("voice-call"));
expect(plan.hasTests).toBe(true);
});
@@ -128,7 +128,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "mattermost", cwd: process.cwd() });
expect(plan.extensionId).toBe("mattermost");
expect(plan.config).toBe("vitest.extension-mattermost.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-mattermost.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("mattermost"));
expect(plan.hasTests).toBe(true);
});
@@ -137,7 +137,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "irc", cwd: process.cwd() });
expect(plan.extensionId).toBe("irc");
expect(plan.config).toBe("vitest.extension-irc.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-irc.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("irc"));
expect(plan.hasTests).toBe(true);
});
@@ -146,7 +146,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "zalo", cwd: process.cwd() });
expect(plan.extensionId).toBe("zalo");
expect(plan.config).toBe("vitest.extension-zalo.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-zalo.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("zalo"));
expect(plan.hasTests).toBe(true);
});
@@ -155,7 +155,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "memory-core", cwd: process.cwd() });
expect(plan.extensionId).toBe("memory-core");
expect(plan.config).toBe("vitest.extension-memory.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-memory.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("memory-core"));
expect(plan.hasTests).toBe(true);
});
@@ -164,7 +164,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "msteams", cwd: process.cwd() });
expect(plan.extensionId).toBe("msteams");
expect(plan.config).toBe("vitest.extension-msteams.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-msteams.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("msteams"));
expect(plan.hasTests).toBe(true);
});
@@ -173,7 +173,7 @@ describe("scripts/test-extension.mjs", () => {
const plan = resolveExtensionTestPlan({ targetArg: "firecrawl", cwd: process.cwd() });
expect(plan.extensionId).toBe("firecrawl");
expect(plan.config).toBe("vitest.extensions.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extensions.config.ts");
expect(plan.roots).toContain(bundledPluginRoot("firecrawl"));
expect(plan.hasTests).toBe(true);
});
@@ -183,7 +183,7 @@ describe("scripts/test-extension.mjs", () => {
expect(plan.roots).toContain(bundledPluginRoot("line"));
expect(plan.roots).not.toContain("src/line");
expect(plan.config).toBe("vitest.extension-channels.config.ts");
expect(plan.config).toBe("test/vitest/vitest.extension-channels.config.ts");
expect(plan.hasTests).toBe(true);
});
@@ -281,97 +281,97 @@ describe("scripts/test-extension.mjs", () => {
]);
expect(batch.planGroups).toEqual([
{
config: "vitest.extension-acpx.config.ts",
config: "test/vitest/vitest.extension-acpx.config.ts",
extensionIds: ["acpx"],
roots: [bundledPluginRoot("acpx")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-bluebubbles.config.ts",
config: "test/vitest/vitest.extension-bluebubbles.config.ts",
extensionIds: ["bluebubbles"],
roots: [bundledPluginRoot("bluebubbles")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-channels.config.ts",
config: "test/vitest/vitest.extension-channels.config.ts",
extensionIds: ["line", "slack"],
roots: [bundledPluginRoot("slack"), bundledPluginRoot("line")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-diffs.config.ts",
config: "test/vitest/vitest.extension-diffs.config.ts",
extensionIds: ["diffs"],
roots: [bundledPluginRoot("diffs")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-feishu.config.ts",
config: "test/vitest/vitest.extension-feishu.config.ts",
extensionIds: ["feishu"],
roots: [bundledPluginRoot("feishu")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-irc.config.ts",
config: "test/vitest/vitest.extension-irc.config.ts",
extensionIds: ["irc"],
roots: [bundledPluginRoot("irc")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-matrix.config.ts",
config: "test/vitest/vitest.extension-matrix.config.ts",
extensionIds: ["matrix"],
roots: [bundledPluginRoot("matrix")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-mattermost.config.ts",
config: "test/vitest/vitest.extension-mattermost.config.ts",
extensionIds: ["mattermost"],
roots: [bundledPluginRoot("mattermost")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-memory.config.ts",
config: "test/vitest/vitest.extension-memory.config.ts",
extensionIds: ["memory-core"],
roots: [bundledPluginRoot("memory-core")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-msteams.config.ts",
config: "test/vitest/vitest.extension-msteams.config.ts",
extensionIds: ["msteams"],
roots: [bundledPluginRoot("msteams")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-providers.config.ts",
config: "test/vitest/vitest.extension-providers.config.ts",
extensionIds: ["openai"],
roots: [bundledPluginRoot("openai")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-telegram.config.ts",
config: "test/vitest/vitest.extension-telegram.config.ts",
extensionIds: ["telegram"],
roots: [bundledPluginRoot("telegram")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-voice-call.config.ts",
config: "test/vitest/vitest.extension-voice-call.config.ts",
extensionIds: ["voice-call"],
roots: [bundledPluginRoot("voice-call")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-whatsapp.config.ts",
config: "test/vitest/vitest.extension-whatsapp.config.ts",
extensionIds: ["whatsapp"],
roots: [bundledPluginRoot("whatsapp")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extension-zalo.config.ts",
config: "test/vitest/vitest.extension-zalo.config.ts",
extensionIds: ["zalo", "zalouser"],
roots: [bundledPluginRoot("zalo"), bundledPluginRoot("zalouser")],
testFileCount: expect.any(Number),
},
{
config: "vitest.extensions.config.ts",
config: "test/vitest/vitest.extensions.config.ts",
extensionIds: ["firecrawl"],
roots: [bundledPluginRoot("firecrawl")],
testFileCount: expect.any(Number),

View File

@@ -18,7 +18,7 @@ describe("scripts/test-projects changed-target routing", () => {
it("keeps the broad changed run for Vitest wiring edits", () => {
expect(
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
"vitest.shared.config.ts",
"test/vitest/vitest.shared.config.ts",
"src/utils/provider-utils.ts",
]),
).toBeNull();
@@ -39,7 +39,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.unit.config.ts",
config: "test/vitest/vitest.unit.config.ts",
forwardedArgs: [],
includePatterns: ["packages/sdk/src/**/*.test.ts"],
watchMode: false,
@@ -55,13 +55,13 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.unit-fast.config.ts",
config: "test/vitest/vitest.unit-fast.config.ts",
forwardedArgs: [],
includePatterns: ["src/shared/string-normalization.test.ts"],
watchMode: false,
},
{
config: "vitest.utils.config.ts",
config: "test/vitest/vitest.utils.config.ts",
forwardedArgs: [],
includePatterns: ["src/utils/**/*.test.ts"],
watchMode: false,
@@ -74,7 +74,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.plugin-sdk-light.config.ts",
config: "test/vitest/vitest.plugin-sdk-light.config.ts",
forwardedArgs: [],
includePatterns: ["src/plugin-sdk/temp-path.test.ts"],
watchMode: false,
@@ -87,7 +87,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.commands-light.config.ts",
config: "test/vitest/vitest.commands-light.config.ts",
forwardedArgs: [],
includePatterns: ["src/commands/status-json-runtime.test.ts"],
watchMode: false,
@@ -103,7 +103,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.unit-fast.config.ts",
config: "test/vitest/vitest.unit-fast.config.ts",
forwardedArgs: [],
includePatterns: ["src/commands/status-overview-values.test.ts"],
watchMode: false,
@@ -118,7 +118,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.unit-fast.config.ts",
config: "test/vitest/vitest.unit-fast.config.ts",
forwardedArgs: [],
includePatterns: ["src/plugin-sdk/provider-entry.test.ts"],
watchMode: false,
@@ -134,7 +134,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.unit-fast.config.ts",
config: "test/vitest/vitest.unit-fast.config.ts",
forwardedArgs: [],
includePatterns: [
"src/commands/status-overview-values.test.ts",
@@ -152,7 +152,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.plugin-sdk.config.ts",
config: "test/vitest/vitest.plugin-sdk.config.ts",
forwardedArgs: [],
includePatterns: ["src/plugin-sdk/**/*.test.ts"],
watchMode: false,
@@ -167,7 +167,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.commands.config.ts",
config: "test/vitest/vitest.commands.config.ts",
forwardedArgs: [],
includePatterns: ["src/commands/**/*.test.ts"],
watchMode: false,
@@ -184,7 +184,7 @@ describe("scripts/test-projects changed-target routing", () => {
expect(plans).toEqual([
{
config: "vitest.e2e.config.ts",
config: "test/vitest/vitest.e2e.config.ts",
forwardedArgs: [target],
includePatterns: null,
watchMode: false,
@@ -203,37 +203,37 @@ describe("scripts/test-projects full-suite sharding", () => {
process.env.OPENCLAW_TEST_PROJECTS_SERIAL = "1";
try {
expect(buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config)).toEqual([
"vitest.full-core-unit-fast.config.ts",
"vitest.full-core-unit-src.config.ts",
"vitest.full-core-unit-security.config.ts",
"vitest.full-core-unit-ui.config.ts",
"vitest.full-core-unit-support.config.ts",
"vitest.full-core-support-boundary.config.ts",
"vitest.full-core-contracts.config.ts",
"vitest.full-core-bundled.config.ts",
"vitest.full-core-runtime.config.ts",
"vitest.full-agentic.config.ts",
"vitest.full-auto-reply.config.ts",
"vitest.extension-acpx.config.ts",
"vitest.extension-bluebubbles.config.ts",
"vitest.extension-channels.config.ts",
"vitest.extension-diffs.config.ts",
"vitest.extension-feishu.config.ts",
"vitest.extension-irc.config.ts",
"vitest.extension-mattermost.config.ts",
"vitest.extension-matrix.config.ts",
"vitest.extension-memory.config.ts",
"vitest.extension-messaging.config.ts",
"vitest.extension-msteams.config.ts",
"vitest.extension-providers.config.ts",
"vitest.extension-telegram.config.ts",
"vitest.extension-voice-call.config.ts",
"vitest.extension-whatsapp.config.ts",
"vitest.extension-zalo.config.ts",
"vitest.extension-browser.config.ts",
"vitest.extension-qa.config.ts",
"vitest.extension-media.config.ts",
"vitest.extension-misc.config.ts",
"test/vitest/vitest.full-core-unit-fast.config.ts",
"test/vitest/vitest.full-core-unit-src.config.ts",
"test/vitest/vitest.full-core-unit-security.config.ts",
"test/vitest/vitest.full-core-unit-ui.config.ts",
"test/vitest/vitest.full-core-unit-support.config.ts",
"test/vitest/vitest.full-core-support-boundary.config.ts",
"test/vitest/vitest.full-core-contracts.config.ts",
"test/vitest/vitest.full-core-bundled.config.ts",
"test/vitest/vitest.full-core-runtime.config.ts",
"test/vitest/vitest.full-agentic.config.ts",
"test/vitest/vitest.full-auto-reply.config.ts",
"test/vitest/vitest.extension-acpx.config.ts",
"test/vitest/vitest.extension-bluebubbles.config.ts",
"test/vitest/vitest.extension-channels.config.ts",
"test/vitest/vitest.extension-diffs.config.ts",
"test/vitest/vitest.extension-feishu.config.ts",
"test/vitest/vitest.extension-irc.config.ts",
"test/vitest/vitest.extension-mattermost.config.ts",
"test/vitest/vitest.extension-matrix.config.ts",
"test/vitest/vitest.extension-memory.config.ts",
"test/vitest/vitest.extension-messaging.config.ts",
"test/vitest/vitest.extension-msteams.config.ts",
"test/vitest/vitest.extension-providers.config.ts",
"test/vitest/vitest.extension-telegram.config.ts",
"test/vitest/vitest.extension-voice-call.config.ts",
"test/vitest/vitest.extension-whatsapp.config.ts",
"test/vitest/vitest.extension-zalo.config.ts",
"test/vitest/vitest.extension-browser.config.ts",
"test/vitest/vitest.extension-qa.config.ts",
"test/vitest/vitest.extension-media.config.ts",
"test/vitest/vitest.extension-misc.config.ts",
]);
} finally {
if (previousParallel === undefined) {
@@ -267,10 +267,10 @@ describe("scripts/test-projects full-suite sharding", () => {
try {
const configs = buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config);
expect(configs).toContain("vitest.gateway.config.ts");
expect(configs).toContain("vitest.extension-telegram.config.ts");
expect(configs).not.toContain("vitest.full-agentic.config.ts");
expect(configs).not.toContain("vitest.full-core-unit-fast.config.ts");
expect(configs).toContain("test/vitest/vitest.gateway-server.config.ts");
expect(configs).toContain("test/vitest/vitest.extension-telegram.config.ts");
expect(configs).not.toContain("test/vitest/vitest.full-agentic.config.ts");
expect(configs).not.toContain("test/vitest/vitest.full-core-unit-fast.config.ts");
} finally {
if (previousLeafShards === undefined) {
delete process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS;
@@ -320,8 +320,8 @@ describe("scripts/test-projects full-suite sharding", () => {
try {
const configs = buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config);
expect(configs).not.toContain("vitest.full-extensions.config.ts");
expect(configs).toContain("vitest.full-auto-reply.config.ts");
expect(configs).not.toContain("test/vitest/vitest.full-extensions.config.ts");
expect(configs).toContain("test/vitest/vitest.full-auto-reply.config.ts");
} finally {
if (previous === undefined) {
delete process.env.OPENCLAW_TEST_SKIP_FULL_EXTENSIONS_SHARD;
@@ -356,64 +356,67 @@ describe("scripts/test-projects full-suite sharding", () => {
}
expect(plans.map((plan) => plan.config)).toEqual([
"vitest.unit-fast.config.ts",
"vitest.unit-src.config.ts",
"vitest.unit-security.config.ts",
"vitest.unit-ui.config.ts",
"vitest.unit-support.config.ts",
"vitest.boundary.config.ts",
"vitest.tooling.config.ts",
"vitest.contracts.config.ts",
"vitest.bundled.config.ts",
"vitest.infra.config.ts",
"vitest.hooks.config.ts",
"vitest.acp.config.ts",
"vitest.runtime-config.config.ts",
"vitest.secrets.config.ts",
"vitest.logging.config.ts",
"vitest.process.config.ts",
"vitest.cron.config.ts",
"vitest.media.config.ts",
"vitest.media-understanding.config.ts",
"vitest.shared-core.config.ts",
"vitest.tasks.config.ts",
"vitest.tui.config.ts",
"vitest.ui.config.ts",
"vitest.utils.config.ts",
"vitest.wizard.config.ts",
"vitest.gateway.config.ts",
"vitest.cli.config.ts",
"vitest.commands-light.config.ts",
"vitest.commands.config.ts",
"vitest.agents.config.ts",
"vitest.daemon.config.ts",
"vitest.plugin-sdk-light.config.ts",
"vitest.plugin-sdk.config.ts",
"vitest.plugins.config.ts",
"vitest.channels.config.ts",
"vitest.auto-reply-core.config.ts",
"vitest.auto-reply-top-level.config.ts",
"vitest.auto-reply-reply.config.ts",
"vitest.extension-acpx.config.ts",
"vitest.extension-bluebubbles.config.ts",
"vitest.extension-channels.config.ts",
"vitest.extension-diffs.config.ts",
"vitest.extension-feishu.config.ts",
"vitest.extension-irc.config.ts",
"vitest.extension-mattermost.config.ts",
"vitest.extension-matrix.config.ts",
"vitest.extension-memory.config.ts",
"vitest.extension-messaging.config.ts",
"vitest.extension-msteams.config.ts",
"vitest.extension-providers.config.ts",
"vitest.extension-telegram.config.ts",
"vitest.extension-voice-call.config.ts",
"vitest.extension-whatsapp.config.ts",
"vitest.extension-zalo.config.ts",
"vitest.extension-browser.config.ts",
"vitest.extension-qa.config.ts",
"vitest.extension-media.config.ts",
"vitest.extension-misc.config.ts",
"test/vitest/vitest.unit-fast.config.ts",
"test/vitest/vitest.unit-src.config.ts",
"test/vitest/vitest.unit-security.config.ts",
"test/vitest/vitest.unit-ui.config.ts",
"test/vitest/vitest.unit-support.config.ts",
"test/vitest/vitest.boundary.config.ts",
"test/vitest/vitest.tooling.config.ts",
"test/vitest/vitest.contracts.config.ts",
"test/vitest/vitest.bundled.config.ts",
"test/vitest/vitest.infra.config.ts",
"test/vitest/vitest.hooks.config.ts",
"test/vitest/vitest.acp.config.ts",
"test/vitest/vitest.runtime-config.config.ts",
"test/vitest/vitest.secrets.config.ts",
"test/vitest/vitest.logging.config.ts",
"test/vitest/vitest.process.config.ts",
"test/vitest/vitest.cron.config.ts",
"test/vitest/vitest.media.config.ts",
"test/vitest/vitest.media-understanding.config.ts",
"test/vitest/vitest.shared-core.config.ts",
"test/vitest/vitest.tasks.config.ts",
"test/vitest/vitest.tui.config.ts",
"test/vitest/vitest.ui.config.ts",
"test/vitest/vitest.utils.config.ts",
"test/vitest/vitest.wizard.config.ts",
"test/vitest/vitest.gateway-core.config.ts",
"test/vitest/vitest.gateway-client.config.ts",
"test/vitest/vitest.gateway-methods.config.ts",
"test/vitest/vitest.gateway-server.config.ts",
"test/vitest/vitest.cli.config.ts",
"test/vitest/vitest.commands-light.config.ts",
"test/vitest/vitest.commands.config.ts",
"test/vitest/vitest.agents.config.ts",
"test/vitest/vitest.daemon.config.ts",
"test/vitest/vitest.plugin-sdk-light.config.ts",
"test/vitest/vitest.plugin-sdk.config.ts",
"test/vitest/vitest.plugins.config.ts",
"test/vitest/vitest.channels.config.ts",
"test/vitest/vitest.auto-reply-core.config.ts",
"test/vitest/vitest.auto-reply-top-level.config.ts",
"test/vitest/vitest.auto-reply-reply.config.ts",
"test/vitest/vitest.extension-acpx.config.ts",
"test/vitest/vitest.extension-bluebubbles.config.ts",
"test/vitest/vitest.extension-channels.config.ts",
"test/vitest/vitest.extension-diffs.config.ts",
"test/vitest/vitest.extension-feishu.config.ts",
"test/vitest/vitest.extension-irc.config.ts",
"test/vitest/vitest.extension-mattermost.config.ts",
"test/vitest/vitest.extension-matrix.config.ts",
"test/vitest/vitest.extension-memory.config.ts",
"test/vitest/vitest.extension-messaging.config.ts",
"test/vitest/vitest.extension-msteams.config.ts",
"test/vitest/vitest.extension-providers.config.ts",
"test/vitest/vitest.extension-telegram.config.ts",
"test/vitest/vitest.extension-voice-call.config.ts",
"test/vitest/vitest.extension-whatsapp.config.ts",
"test/vitest/vitest.extension-zalo.config.ts",
"test/vitest/vitest.extension-browser.config.ts",
"test/vitest/vitest.extension-qa.config.ts",
"test/vitest/vitest.extension-media.config.ts",
"test/vitest/vitest.extension-misc.config.ts",
]);
expect(plans).toEqual(
plans.map((plan) => ({
@@ -433,9 +436,9 @@ describe("scripts/test-projects full-suite sharding", () => {
try {
const configs = buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config);
expect(configs).not.toContain("vitest.extensions.config.ts");
expect(configs).not.toContain("vitest.extension-providers.config.ts");
expect(configs).toContain("vitest.auto-reply-reply.config.ts");
expect(configs).not.toContain("test/vitest/vitest.extensions.config.ts");
expect(configs).not.toContain("test/vitest/vitest.extension-providers.config.ts");
expect(configs).toContain("test/vitest/vitest.auto-reply-reply.config.ts");
} finally {
if (previousLeafShards === undefined) {
delete process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS;
@@ -458,8 +461,8 @@ describe("scripts/test-projects full-suite sharding", () => {
try {
const configs = buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config);
expect(configs).toContain("vitest.extension-telegram.config.ts");
expect(configs).not.toContain("vitest.full-extensions.config.ts");
expect(configs).toContain("test/vitest/vitest.extension-telegram.config.ts");
expect(configs).not.toContain("test/vitest/vitest.full-extensions.config.ts");
} finally {
if (previousLeafShards === undefined) {
delete process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS;

View File

@@ -95,7 +95,7 @@ describe("scripts/test-report-utils runVitestJsonReport", () => {
expect(
runVitestJsonReport({
config: "vitest.unit.config.ts",
config: "test/vitest/vitest.unit.config.ts",
reportPath,
}),
).toBe(reportPath);
@@ -107,7 +107,7 @@ describe("scripts/test-report-utils runVitestJsonReport", () => {
"vitest",
"run",
"--config",
"vitest.unit.config.ts",
"test/vitest/vitest.unit.config.ts",
"--reporter=json",
"--outputFile",
reportPath,

View File

@@ -2,8 +2,8 @@ import { describe, expect, it } from "vitest";
import {
createBoundaryVitestConfig,
loadBoundaryIncludePatternsFromEnv,
} from "../vitest.boundary.config.ts";
import { boundaryTestFiles } from "../vitest.unit-paths.mjs";
} from "./vitest/vitest.boundary.config.ts";
import { boundaryTestFiles } from "./vitest/vitest.unit-paths.mjs";
describe("loadBoundaryIncludePatternsFromEnv", () => {
it("returns null when no include file is configured", () => {

View File

@@ -1,7 +1,7 @@
import { afterEach, describe, expect, it } from "vitest";
import { loadIncludePatternsFromEnv } from "../vitest.extensions.config.ts";
import { bundledPluginFile } from "./helpers/bundled-plugin-paths.js";
import { createPatternFileHelper } from "./helpers/pattern-file.js";
import { loadIncludePatternsFromEnv } from "./vitest/vitest.extensions.config.ts";
const patternFiles = createPatternFileHelper("openclaw-vitest-extensions-config-");

View File

@@ -2,11 +2,11 @@ import { describe, expect, it } from "vitest";
import {
isCommandsLightTarget,
resolveCommandsLightIncludePattern,
} from "../vitest.commands-light-paths.mjs";
} from "./vitest/vitest.commands-light-paths.mjs";
import {
isPluginSdkLightTarget,
resolvePluginSdkLightIncludePattern,
} from "../vitest.plugin-sdk-paths.mjs";
} from "./vitest/vitest.plugin-sdk-paths.mjs";
describe("light vitest path routing", () => {
it("maps plugin-sdk allowlist source and test files to sibling light tests", () => {

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { loadVitestExperimentalConfig } from "../vitest.performance-config.ts";
import { loadVitestExperimentalConfig } from "./vitest/vitest.performance-config.ts";
describe("loadVitestExperimentalConfig", () => {
it("enables the filesystem module cache by default", () => {

View File

@@ -1,15 +1,15 @@
import { describe, expect, it } from "vitest";
import { createAgentsVitestConfig } from "../vitest.agents.config.ts";
import bundledConfig from "../vitest.bundled.config.ts";
import { createCommandsLightVitestConfig } from "../vitest.commands-light.config.ts";
import { createCommandsVitestConfig } from "../vitest.commands.config.ts";
import baseConfig, { rootVitestProjects } from "../vitest.config.ts";
import { createContractsVitestConfig } from "../vitest.contracts.config.ts";
import { createGatewayVitestConfig } from "../vitest.gateway.config.ts";
import { createPluginSdkLightVitestConfig } from "../vitest.plugin-sdk-light.config.ts";
import { createUiVitestConfig } from "../vitest.ui.config.ts";
import { createUnitFastVitestConfig } from "../vitest.unit-fast.config.ts";
import { createUnitVitestConfig } from "../vitest.unit.config.ts";
import { createAgentsVitestConfig } from "./vitest/vitest.agents.config.ts";
import bundledConfig from "./vitest/vitest.bundled.config.ts";
import { createCommandsLightVitestConfig } from "./vitest/vitest.commands-light.config.ts";
import { createCommandsVitestConfig } from "./vitest/vitest.commands.config.ts";
import baseConfig, { rootVitestProjects } from "./vitest/vitest.config.ts";
import { createContractsVitestConfig } from "./vitest/vitest.contracts.config.ts";
import { createGatewayVitestConfig } from "./vitest/vitest.gateway.config.ts";
import { createPluginSdkLightVitestConfig } from "./vitest/vitest.plugin-sdk-light.config.ts";
import { createUiVitestConfig } from "./vitest/vitest.ui.config.ts";
import { createUnitFastVitestConfig } from "./vitest/vitest.unit-fast.config.ts";
import { createUnitVitestConfig } from "./vitest/vitest.unit.config.ts";
describe("projects vitest config", () => {
it("defines the native root project list for all non-live Vitest lanes", () => {

View File

@@ -2,59 +2,59 @@ 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 { createAutoReplyCoreVitestConfig } from "../vitest.auto-reply-core.config.ts";
import { createAutoReplyReplyVitestConfig } from "../vitest.auto-reply-reply.config.ts";
import { createAutoReplyTopLevelVitestConfig } from "../vitest.auto-reply-top-level.config.ts";
import { createAutoReplyVitestConfig } from "../vitest.auto-reply.config.ts";
import bundledVitestConfig from "../vitest.bundled.config.ts";
import { createChannelsVitestConfig } from "../vitest.channels.config.ts";
import { createCliVitestConfig } from "../vitest.cli.config.ts";
import { createCommandsLightVitestConfig } from "../vitest.commands-light.config.ts";
import { createCommandsVitestConfig } from "../vitest.commands.config.ts";
import { createCronVitestConfig } from "../vitest.cron.config.ts";
import { createDaemonVitestConfig } from "../vitest.daemon.config.ts";
import { createExtensionAcpxVitestConfig } from "../vitest.extension-acpx.config.ts";
import { createExtensionBlueBubblesVitestConfig } from "../vitest.extension-bluebubbles.config.ts";
import { createExtensionChannelsVitestConfig } from "../vitest.extension-channels.config.ts";
import { createExtensionDiffsVitestConfig } from "../vitest.extension-diffs.config.ts";
import { createExtensionFeishuVitestConfig } from "../vitest.extension-feishu.config.ts";
import { createExtensionIrcVitestConfig } from "../vitest.extension-irc.config.ts";
import { createExtensionMatrixVitestConfig } from "../vitest.extension-matrix.config.ts";
import { createExtensionMattermostVitestConfig } from "../vitest.extension-mattermost.config.ts";
import { createExtensionMemoryVitestConfig } from "../vitest.extension-memory.config.ts";
import { createExtensionMessagingVitestConfig } from "../vitest.extension-messaging.config.ts";
import { createExtensionMsTeamsVitestConfig } from "../vitest.extension-msteams.config.ts";
import { createExtensionProvidersVitestConfig } from "../vitest.extension-providers.config.ts";
import { createExtensionTelegramVitestConfig } from "../vitest.extension-telegram.config.ts";
import { createExtensionVoiceCallVitestConfig } from "../vitest.extension-voice-call.config.ts";
import { createExtensionWhatsAppVitestConfig } from "../vitest.extension-whatsapp.config.ts";
import { createExtensionZaloVitestConfig } from "../vitest.extension-zalo.config.ts";
import { createExtensionsVitestConfig } from "../vitest.extensions.config.ts";
import { createGatewayVitestConfig } from "../vitest.gateway.config.ts";
import { createHooksVitestConfig } from "../vitest.hooks.config.ts";
import { createInfraVitestConfig } from "../vitest.infra.config.ts";
import { createLoggingVitestConfig } from "../vitest.logging.config.ts";
import { createMediaUnderstandingVitestConfig } from "../vitest.media-understanding.config.ts";
import { createMediaVitestConfig } from "../vitest.media.config.ts";
import { createPluginSdkLightVitestConfig } from "../vitest.plugin-sdk-light.config.ts";
import { createPluginSdkVitestConfig } from "../vitest.plugin-sdk.config.ts";
import { createPluginsVitestConfig } from "../vitest.plugins.config.ts";
import { createProcessVitestConfig } from "../vitest.process.config.ts";
import { createRuntimeConfigVitestConfig } from "../vitest.runtime-config.config.ts";
import { createScopedVitestConfig, resolveVitestIsolation } from "../vitest.scoped-config.ts";
import { createSecretsVitestConfig } from "../vitest.secrets.config.ts";
import { createSharedCoreVitestConfig } from "../vitest.shared-core.config.ts";
import { createTasksVitestConfig } from "../vitest.tasks.config.ts";
import { createToolingVitestConfig } from "../vitest.tooling.config.ts";
import { createTuiVitestConfig } from "../vitest.tui.config.ts";
import { createUiVitestConfig } from "../vitest.ui.config.ts";
import { bundledPluginDependentUnitTestFiles } from "../vitest.unit-paths.mjs";
import { createUtilsVitestConfig } from "../vitest.utils.config.ts";
import { createWizardVitestConfig } from "../vitest.wizard.config.ts";
import { BUNDLED_PLUGIN_TEST_GLOB, bundledPluginFile } from "./helpers/bundled-plugin-paths.js";
import { cleanupTempDirs, makeTempDir } from "./helpers/temp-dir.js";
import { createAcpVitestConfig } from "./vitest/vitest.acp.config.ts";
import { createAgentsVitestConfig } from "./vitest/vitest.agents.config.ts";
import { createAutoReplyCoreVitestConfig } from "./vitest/vitest.auto-reply-core.config.ts";
import { createAutoReplyReplyVitestConfig } from "./vitest/vitest.auto-reply-reply.config.ts";
import { createAutoReplyTopLevelVitestConfig } from "./vitest/vitest.auto-reply-top-level.config.ts";
import { createAutoReplyVitestConfig } from "./vitest/vitest.auto-reply.config.ts";
import bundledVitestConfig from "./vitest/vitest.bundled.config.ts";
import { createChannelsVitestConfig } from "./vitest/vitest.channels.config.ts";
import { createCliVitestConfig } from "./vitest/vitest.cli.config.ts";
import { createCommandsLightVitestConfig } from "./vitest/vitest.commands-light.config.ts";
import { createCommandsVitestConfig } from "./vitest/vitest.commands.config.ts";
import { createCronVitestConfig } from "./vitest/vitest.cron.config.ts";
import { createDaemonVitestConfig } from "./vitest/vitest.daemon.config.ts";
import { createExtensionAcpxVitestConfig } from "./vitest/vitest.extension-acpx.config.ts";
import { createExtensionBlueBubblesVitestConfig } from "./vitest/vitest.extension-bluebubbles.config.ts";
import { createExtensionChannelsVitestConfig } from "./vitest/vitest.extension-channels.config.ts";
import { createExtensionDiffsVitestConfig } from "./vitest/vitest.extension-diffs.config.ts";
import { createExtensionFeishuVitestConfig } from "./vitest/vitest.extension-feishu.config.ts";
import { createExtensionIrcVitestConfig } from "./vitest/vitest.extension-irc.config.ts";
import { createExtensionMatrixVitestConfig } from "./vitest/vitest.extension-matrix.config.ts";
import { createExtensionMattermostVitestConfig } from "./vitest/vitest.extension-mattermost.config.ts";
import { createExtensionMemoryVitestConfig } from "./vitest/vitest.extension-memory.config.ts";
import { createExtensionMessagingVitestConfig } from "./vitest/vitest.extension-messaging.config.ts";
import { createExtensionMsTeamsVitestConfig } from "./vitest/vitest.extension-msteams.config.ts";
import { createExtensionProvidersVitestConfig } from "./vitest/vitest.extension-providers.config.ts";
import { createExtensionTelegramVitestConfig } from "./vitest/vitest.extension-telegram.config.ts";
import { createExtensionVoiceCallVitestConfig } from "./vitest/vitest.extension-voice-call.config.ts";
import { createExtensionWhatsAppVitestConfig } from "./vitest/vitest.extension-whatsapp.config.ts";
import { createExtensionZaloVitestConfig } from "./vitest/vitest.extension-zalo.config.ts";
import { createExtensionsVitestConfig } from "./vitest/vitest.extensions.config.ts";
import { createGatewayVitestConfig } from "./vitest/vitest.gateway.config.ts";
import { createHooksVitestConfig } from "./vitest/vitest.hooks.config.ts";
import { createInfraVitestConfig } from "./vitest/vitest.infra.config.ts";
import { createLoggingVitestConfig } from "./vitest/vitest.logging.config.ts";
import { createMediaUnderstandingVitestConfig } from "./vitest/vitest.media-understanding.config.ts";
import { createMediaVitestConfig } from "./vitest/vitest.media.config.ts";
import { createPluginSdkLightVitestConfig } from "./vitest/vitest.plugin-sdk-light.config.ts";
import { createPluginSdkVitestConfig } from "./vitest/vitest.plugin-sdk.config.ts";
import { createPluginsVitestConfig } from "./vitest/vitest.plugins.config.ts";
import { createProcessVitestConfig } from "./vitest/vitest.process.config.ts";
import { createRuntimeConfigVitestConfig } from "./vitest/vitest.runtime-config.config.ts";
import { createScopedVitestConfig, resolveVitestIsolation } from "./vitest/vitest.scoped-config.ts";
import { createSecretsVitestConfig } from "./vitest/vitest.secrets.config.ts";
import { createSharedCoreVitestConfig } from "./vitest/vitest.shared-core.config.ts";
import { createTasksVitestConfig } from "./vitest/vitest.tasks.config.ts";
import { createToolingVitestConfig } from "./vitest/vitest.tooling.config.ts";
import { createTuiVitestConfig } from "./vitest/vitest.tui.config.ts";
import { createUiVitestConfig } from "./vitest/vitest.ui.config.ts";
import { bundledPluginDependentUnitTestFiles } from "./vitest/vitest.unit-paths.mjs";
import { createUtilsVitestConfig } from "./vitest/vitest.utils.config.ts";
import { createWizardVitestConfig } from "./vitest/vitest.wizard.config.ts";
const EXTENSIONS_CHANNEL_GLOB = ["extensions", "channel", "**"].join("/");

View File

@@ -1,11 +1,11 @@
import { afterEach, describe, expect, it } from "vitest";
import { createPatternFileHelper } from "./helpers/pattern-file.js";
import {
createUnitVitestConfig,
createUnitVitestConfigWithOptions,
loadExtraExcludePatternsFromEnv,
loadIncludePatternsFromEnv,
} from "../vitest.unit.config.ts";
import { createPatternFileHelper } from "./helpers/pattern-file.js";
} from "./vitest/vitest.unit.config.ts";
const patternFiles = createPatternFileHelper("openclaw-vitest-unit-config-");

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { createCommandsLightVitestConfig } from "../vitest.commands-light.config.ts";
import { createPluginSdkLightVitestConfig } from "../vitest.plugin-sdk-light.config.ts";
import { createCommandsLightVitestConfig } from "./vitest/vitest.commands-light.config.ts";
import { createPluginSdkLightVitestConfig } from "./vitest/vitest.plugin-sdk-light.config.ts";
import {
classifyUnitFastTestFileContent,
collectBroadUnitFastTestCandidates,
@@ -9,8 +9,8 @@ import {
isUnitFastTestFile,
unitFastTestFiles,
resolveUnitFastTestIncludePattern,
} from "../vitest.unit-fast-paths.mjs";
import { createUnitFastVitestConfig } from "../vitest.unit-fast.config.ts";
} from "./vitest/vitest.unit-fast-paths.mjs";
import { createUnitFastVitestConfig } from "./vitest/vitest.unit-fast.config.ts";
describe("unit-fast vitest lane", () => {
it("runs cache-friendly tests without the reset-heavy runner or runtime setup", () => {

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { isUnitConfigTestFile } from "../vitest.unit-paths.mjs";
import { bundledPluginFile } from "./helpers/bundled-plugin-paths.js";
import { isUnitConfigTestFile } from "./vitest/vitest.unit-paths.mjs";
describe("isUnitConfigTestFile", () => {
it("accepts unit-config src tests", () => {

View File

@@ -0,0 +1,11 @@
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,
name: "acp",
});
}
export default createAcpVitestConfig();

View File

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

View File

@@ -0,0 +1,13 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
import { autoReplyCoreTestExclude, autoReplyCoreTestInclude } from "./vitest.test-shards.mjs";
export function createAutoReplyCoreVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig([...autoReplyCoreTestInclude], {
dir: "src/auto-reply",
env,
exclude: [...autoReplyCoreTestExclude],
name: "auto-reply-core",
});
}
export default createAutoReplyCoreVitestConfig();

View File

@@ -0,0 +1,17 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
import { autoReplyReplySubtreeTestInclude } from "./vitest.test-shards.mjs";
export function createAutoReplyReplyVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig([...autoReplyReplySubtreeTestInclude], {
dir: "src/auto-reply",
env,
fileParallelism: false,
maxWorkers: 1,
name: "auto-reply-reply",
sequence: {
groupOrder: 1,
},
});
}
export default createAutoReplyReplyVitestConfig();

View File

@@ -0,0 +1,12 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
import { autoReplyTopLevelReplyTestInclude } from "./vitest.test-shards.mjs";
export function createAutoReplyTopLevelVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig([...autoReplyTopLevelReplyTestInclude], {
dir: "src/auto-reply",
env,
name: "auto-reply-top-level",
});
}
export default createAutoReplyTopLevelVitestConfig();

View File

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

View File

@@ -0,0 +1,35 @@
import { defineProject } from "vitest/config";
import { loadPatternListFromEnv, narrowIncludePatternsForCli } from "./vitest.pattern-file.ts";
import { resolveVitestIsolation } from "./vitest.scoped-config.ts";
import { sharedVitestConfig } from "./vitest.shared.config.ts";
import { boundaryTestFiles } from "./vitest.unit-paths.mjs";
export function loadBoundaryIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createBoundaryVitestConfig(
env: Record<string, string | undefined> = process.env,
argv: string[] = process.argv,
) {
const cliIncludePatterns = narrowIncludePatternsForCli(boundaryTestFiles, argv);
const isolate = resolveVitestIsolation(env);
return defineProject({
...sharedVitestConfig,
test: {
...sharedVitestConfig.test,
name: "boundary",
isolate,
...(isolate ? { runner: undefined } : { runner: "./test/non-isolated-runner.ts" }),
include: loadBoundaryIncludePatternsFromEnv(env) ?? cliIncludePatterns ?? boundaryTestFiles,
...(cliIncludePatterns !== null ? { passWithNoTests: true } : {}),
// Boundary workers still need the shared isolated HOME/bootstrap. Only
// per-file module isolation is disabled here.
setupFiles: sharedVitestConfig.test.setupFiles,
},
});
}
export default createBoundaryVitestConfig();

View File

@@ -0,0 +1,5 @@
export const BUNDLED_PLUGIN_ROOT_DIR = "extensions";
export const BUNDLED_PLUGIN_PATH_PREFIX = `${BUNDLED_PLUGIN_ROOT_DIR}/`;
export const BUNDLED_PLUGIN_TEST_GLOB = `${BUNDLED_PLUGIN_ROOT_DIR}/**/*.test.ts`;
export const BUNDLED_PLUGIN_E2E_TEST_GLOB = `${BUNDLED_PLUGIN_ROOT_DIR}/**/*.e2e.test.ts`;
export const BUNDLED_PLUGIN_LIVE_TEST_GLOB = `${BUNDLED_PLUGIN_ROOT_DIR}/**/*.live.test.ts`;

View File

@@ -0,0 +1,36 @@
import path from "node:path";
import {
bundledPluginDependentUnitTestFiles,
unitTestAdditionalExcludePatterns,
} from "./vitest.unit-paths.mjs";
import { createUnitVitestConfigWithOptions } from "./vitest.unit.config.ts";
function normalizeGlobCandidate(value: string): string {
return value.split(path.sep).join("/");
}
function excludePatternCouldMatchFile(pattern: string, file: string): boolean {
const normalizedPattern = normalizeGlobCandidate(pattern);
const normalizedFile = normalizeGlobCandidate(file);
if (normalizedPattern === normalizedFile) {
return true;
}
if (normalizedPattern.endsWith("/**")) {
const prefix = normalizedPattern.slice(0, -3);
return normalizedFile === prefix || normalizedFile.startsWith(`${prefix}/`);
}
return path.matchesGlob(normalizedFile, normalizedPattern);
}
const bundledUnitExcludePatterns = unitTestAdditionalExcludePatterns.filter(
(pattern) =>
!bundledPluginDependentUnitTestFiles.some((file) =>
excludePatternCouldMatchFile(pattern, file),
),
);
export default createUnitVitestConfigWithOptions(process.env, {
includePatterns: bundledPluginDependentUnitTestFiles,
extraExcludePatterns: bundledUnitExcludePatterns,
name: "bundled",
});

View File

@@ -0,0 +1,75 @@
import path from "node:path";
import {
BUNDLED_PLUGIN_PATH_PREFIX,
bundledPluginRoot,
} from "../../scripts/lib/bundled-plugin-paths.mjs";
const normalizeRepoPath = (value) => value.split(path.sep).join("/");
export const extensionRoutedChannelTestFiles = [];
const extensionRoutedChannelTestFileSet = new Set(extensionRoutedChannelTestFiles);
export const channelTestRoots = [
"src/channels",
bundledPluginRoot("discord"),
bundledPluginRoot("slack"),
bundledPluginRoot("signal"),
bundledPluginRoot("imessage"),
bundledPluginRoot("line"),
];
export const extensionChannelTestRoots = channelTestRoots.filter((root) =>
root.startsWith(BUNDLED_PLUGIN_PATH_PREFIX),
);
export const coreChannelTestRoots = channelTestRoots.filter(
(root) => !root.startsWith(BUNDLED_PLUGIN_PATH_PREFIX),
);
export const channelTestPrefixes = channelTestRoots.map((root) => `${root}/`);
export const channelTestInclude = channelTestRoots.map((root) => `${root}/**/*.test.ts`);
export const extensionChannelTestInclude = extensionChannelTestRoots.map(
(root) => `${root}/**/*.test.ts`,
);
export const coreChannelTestInclude = coreChannelTestRoots.map((root) => `${root}/**/*.test.ts`);
export const channelTestExclude = channelTestRoots.map((root) => `${root}/**`);
const extensionChannelRootOverrideBasenames = new Map();
for (const file of extensionRoutedChannelTestFiles) {
if (!file.startsWith(BUNDLED_PLUGIN_PATH_PREFIX)) {
continue;
}
const relativeFile = file.slice(BUNDLED_PLUGIN_PATH_PREFIX.length);
const separator = relativeFile.indexOf("/");
if (separator === -1) {
continue;
}
const root = relativeFile.slice(0, separator);
const baseName = path.basename(relativeFile, ".test.ts");
const current = extensionChannelRootOverrideBasenames.get(root) ?? [];
current.push(baseName);
extensionChannelRootOverrideBasenames.set(root, current);
}
export const extensionExcludedChannelTestGlobs = channelTestRoots
.filter((root) => root.startsWith(BUNDLED_PLUGIN_PATH_PREFIX))
.map((root) => root.slice(BUNDLED_PLUGIN_PATH_PREFIX.length))
.map((relativeRoot) => {
const allowedBasenames = extensionChannelRootOverrideBasenames.get(relativeRoot) ?? [];
if (allowedBasenames.length === 0) {
return `${relativeRoot}/**`;
}
const alternation = allowedBasenames.join("|");
return `${relativeRoot}/**/!(${alternation}).test.ts`;
});
export const extensionChannelOverrideExcludeGlobs = extensionRoutedChannelTestFiles
.filter((file) => file.startsWith(BUNDLED_PLUGIN_PATH_PREFIX))
.map((file) => file.slice(BUNDLED_PLUGIN_PATH_PREFIX.length));
export function isChannelSurfaceTestFile(filePath) {
const normalizedFile = normalizeRepoPath(filePath);
return (
channelTestPrefixes.some((prefix) => normalizedFile.startsWith(prefix)) &&
!extensionRoutedChannelTestFileSet.has(normalizedFile)
);
}

View File

@@ -0,0 +1,20 @@
import { coreChannelTestInclude } from "./vitest.channel-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createChannelsVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(loadIncludePatternsFromEnv(env) ?? coreChannelTestInclude, {
env,
exclude: ["src/gateway/**", "src/channels/plugins/contracts/**"],
name: "channels",
passWithNoTests: true,
});
}
export default createChannelsVitestConfig();

View File

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

View File

@@ -0,0 +1,69 @@
const normalizeRepoPath = (value) => value.replaceAll("\\", "/");
const commandsLightEntries = [
{ source: "src/commands/cleanup-utils.ts", test: "src/commands/cleanup-utils.test.ts" },
{
source: "src/commands/dashboard.links.ts",
test: "src/commands/dashboard.links.test.ts",
},
{ source: "src/commands/doctor-browser.ts", test: "src/commands/doctor-browser.test.ts" },
{
source: "src/commands/doctor-gateway-auth-token.ts",
test: "src/commands/doctor-gateway-auth-token.test.ts",
},
{
source: "src/commands/gateway-status/helpers.ts",
test: "src/commands/gateway-status/helpers.test.ts",
},
{
source: "src/commands/sandbox-formatters.ts",
test: "src/commands/sandbox-formatters.test.ts",
},
{
source: "src/commands/status-json-command.ts",
test: "src/commands/status-json-command.test.ts",
},
{
source: "src/commands/status-json-payload.ts",
test: "src/commands/status-json-payload.test.ts",
},
{
source: "src/commands/status-json-runtime.ts",
test: "src/commands/status-json-runtime.test.ts",
},
{
source: "src/commands/status-overview-rows.ts",
test: "src/commands/status-overview-rows.test.ts",
},
{
source: "src/commands/status-overview-surface.ts",
test: "src/commands/status-overview-surface.test.ts",
},
{
source: "src/commands/status-overview-values.ts",
test: "src/commands/status-overview-values.test.ts",
},
{ source: "src/commands/text-format.ts", test: "src/commands/text-format.test.ts" },
];
const commandsLightIncludePatternByFile = new Map(
commandsLightEntries.flatMap(({ source, test }) => [
[source, test],
[test, test],
]),
);
export const commandsLightSourceFiles = commandsLightEntries.map(({ source }) => source);
export const commandsLightTestFiles = commandsLightEntries.map(({ test }) => test);
export function isCommandsLightTarget(file) {
return commandsLightIncludePatternByFile.has(normalizeRepoPath(file));
}
export function isCommandsLightTestFile(file) {
return commandsLightTestFiles.includes(normalizeRepoPath(file));
}
export function resolveCommandsLightIncludePattern(file) {
return commandsLightIncludePatternByFile.get(normalizeRepoPath(file)) ?? null;
}

View File

@@ -0,0 +1,16 @@
import { commandsLightTestFiles } from "./vitest.commands-light-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
import { unitFastTestFiles } from "./vitest.unit-fast-paths.mjs";
export function createCommandsLightVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(commandsLightTestFiles, {
dir: "src/commands",
env,
exclude: unitFastTestFiles,
includeOpenClawRuntimeSetup: false,
name: "commands-light",
passWithNoTests: true,
});
}
export default createCommandsLightVitestConfig();

View File

@@ -0,0 +1,13 @@
import { commandsLightTestFiles } from "./vitest.commands-light-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createCommandsVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/commands/**/*.test.ts"], {
dir: "src/commands",
env,
exclude: commandsLightTestFiles,
name: "commands",
});
}
export default createCommandsVitestConfig();

View File

@@ -0,0 +1,74 @@
import { defineConfig } from "vitest/config";
import {
resolveDefaultVitestPool,
resolveLocalVitestMaxWorkers,
resolveLocalVitestScheduling,
sharedVitestConfig,
} from "./vitest.shared.config.ts";
export { resolveDefaultVitestPool, resolveLocalVitestMaxWorkers, resolveLocalVitestScheduling };
export const rootVitestProjects = [
"test/vitest/vitest.unit.config.ts",
"test/vitest/vitest.infra.config.ts",
"test/vitest/vitest.boundary.config.ts",
"test/vitest/vitest.contracts.config.ts",
"test/vitest/vitest.bundled.config.ts",
"test/vitest/vitest.gateway-core.config.ts",
"test/vitest/vitest.gateway-client.config.ts",
"test/vitest/vitest.gateway-methods.config.ts",
"test/vitest/vitest.gateway-server.config.ts",
"test/vitest/vitest.hooks.config.ts",
"test/vitest/vitest.acp.config.ts",
"test/vitest/vitest.runtime-config.config.ts",
"test/vitest/vitest.secrets.config.ts",
"test/vitest/vitest.cli.config.ts",
"test/vitest/vitest.commands-light.config.ts",
"test/vitest/vitest.commands.config.ts",
"test/vitest/vitest.auto-reply.config.ts",
"test/vitest/vitest.agents.config.ts",
"test/vitest/vitest.daemon.config.ts",
"test/vitest/vitest.media.config.ts",
"test/vitest/vitest.unit-fast.config.ts",
"test/vitest/vitest.plugin-sdk-light.config.ts",
"test/vitest/vitest.plugin-sdk.config.ts",
"test/vitest/vitest.plugins.config.ts",
"test/vitest/vitest.logging.config.ts",
"test/vitest/vitest.process.config.ts",
"test/vitest/vitest.cron.config.ts",
"test/vitest/vitest.media-understanding.config.ts",
"test/vitest/vitest.shared-core.config.ts",
"test/vitest/vitest.tasks.config.ts",
"test/vitest/vitest.tooling.config.ts",
"test/vitest/vitest.tui.config.ts",
"test/vitest/vitest.ui.config.ts",
"test/vitest/vitest.utils.config.ts",
"test/vitest/vitest.wizard.config.ts",
"test/vitest/vitest.channels.config.ts",
"test/vitest/vitest.extension-acpx.config.ts",
"test/vitest/vitest.extension-bluebubbles.config.ts",
"test/vitest/vitest.extension-channels.config.ts",
"test/vitest/vitest.extension-diffs.config.ts",
"test/vitest/vitest.extension-feishu.config.ts",
"test/vitest/vitest.extension-irc.config.ts",
"test/vitest/vitest.extension-mattermost.config.ts",
"test/vitest/vitest.extension-matrix.config.ts",
"test/vitest/vitest.extension-memory.config.ts",
"test/vitest/vitest.extension-msteams.config.ts",
"test/vitest/vitest.extension-messaging.config.ts",
"test/vitest/vitest.extension-providers.config.ts",
"test/vitest/vitest.extension-telegram.config.ts",
"test/vitest/vitest.extension-voice-call.config.ts",
"test/vitest/vitest.extension-whatsapp.config.ts",
"test/vitest/vitest.extension-zalo.config.ts",
"test/vitest/vitest.extensions.config.ts",
] as const;
export default defineConfig({
...sharedVitestConfig,
test: {
...sharedVitestConfig.test,
runner: "./test/non-isolated-runner.ts",
projects: [...rootVitestProjects],
},
});

View File

@@ -0,0 +1,24 @@
import { defineConfig } from "vitest/config";
import { sharedVitestConfig } from "./vitest.shared.config.ts";
const base = sharedVitestConfig as Record<string, unknown>;
const baseTest = sharedVitestConfig.test ?? {};
export function createContractsVitestConfig() {
return defineConfig({
...base,
test: {
...baseTest,
isolate: false,
runner: "./test/non-isolated-runner.ts",
setupFiles: baseTest.setupFiles ?? [],
include: [
"src/channels/plugins/contracts/**/*.test.ts",
"src/plugins/contracts/**/*.test.ts",
],
passWithNoTests: true,
},
});
}
export default createContractsVitestConfig();

View File

@@ -0,0 +1,22 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createCronVitestConfig(env?: Record<string, string | undefined>) {
const config = createScopedVitestConfig(["src/cron/**/*.test.ts"], {
dir: "src",
env,
name: "cron",
passWithNoTests: true,
});
config.test = {
...config.test,
maxWorkers: 1,
fileParallelism: false,
sequence: {
...config.test?.sequence,
groupOrder: 1,
},
};
return config;
}
export default createCronVitestConfig();

View File

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

View File

@@ -0,0 +1,45 @@
import os from "node:os";
import { defineConfig } from "vitest/config";
import { BUNDLED_PLUGIN_E2E_TEST_GLOB } from "./vitest.bundled-plugin-paths.ts";
import baseConfig from "./vitest.config.ts";
const base = baseConfig as unknown as Record<string, unknown>;
const isCI = process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
const cpuCount = os.cpus().length;
// Keep e2e runs cheap by default; callers can still override via OPENCLAW_E2E_WORKERS.
const defaultWorkers = isCI ? Math.min(2, Math.max(1, Math.floor(cpuCount * 0.25))) : 1;
const requestedWorkers = Number.parseInt(process.env.OPENCLAW_E2E_WORKERS ?? "", 10);
const e2eWorkers =
Number.isFinite(requestedWorkers) && requestedWorkers > 0
? Math.min(16, requestedWorkers)
: defaultWorkers;
const verboseE2E = process.env.OPENCLAW_E2E_VERBOSE === "1";
const baseTestWithProjects =
(baseConfig as { test?: { exclude?: string[]; projects?: string[]; setupFiles?: string[] } })
.test ?? {};
const { projects: _projects, ...baseTest } = baseTestWithProjects as {
exclude?: string[];
projects?: string[];
setupFiles?: string[];
};
const exclude = (baseTest.exclude ?? []).filter((p) => p !== "**/*.e2e.test.ts");
export default defineConfig({
...base,
test: {
...baseTest,
maxWorkers: e2eWorkers,
silent: !verboseE2E,
setupFiles: [...new Set([...(baseTest.setupFiles ?? []), "test/setup-openclaw-runtime.ts"])],
include: [
"test/**/*.e2e.test.ts",
"src/**/*.e2e.test.ts",
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
BUNDLED_PLUGIN_E2E_TEST_GLOB,
],
exclude,
},
});

View File

@@ -0,0 +1,5 @@
export const acpxExtensionTestRoots = ["extensions/acpx"];
export function isAcpxExtensionRoot(root) {
return acpxExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,26 @@
import { acpxExtensionTestRoots } from "./vitest.extension-acpx-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionAcpxVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ?? acpxExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-acpx",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionAcpxVitestConfig();

View File

@@ -0,0 +1,5 @@
export const blueBubblesExtensionTestRoots = ["extensions/bluebubbles"];
export function isBlueBubblesExtensionRoot(root) {
return blueBubblesExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { blueBubblesExtensionTestRoots } from "./vitest.extension-bluebubbles-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionBlueBubblesVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
blueBubblesExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-bluebubbles",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionBlueBubblesVitestConfig();

View File

@@ -0,0 +1,8 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export default createScopedVitestConfig(["browser/**/*.test.ts"], {
dir: "extensions",
name: "extension-browser",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
});

View File

@@ -0,0 +1,19 @@
import {
extensionChannelOverrideExcludeGlobs,
extensionChannelTestInclude,
} from "./vitest.channel-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createExtensionChannelsVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(extensionChannelTestInclude, {
dir: "extensions",
env,
exclude: extensionChannelOverrideExcludeGlobs,
name: "extension-channels",
passWithNoTests: true,
});
}
export default createExtensionChannelsVitestConfig();

View File

@@ -0,0 +1,5 @@
export const diffsExtensionTestRoots = ["extensions/diffs"];
export function isDiffsExtensionRoot(root) {
return diffsExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { diffsExtensionTestRoots } from "./vitest.extension-diffs-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionDiffsVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
diffsExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-diffs",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionDiffsVitestConfig();

View File

@@ -0,0 +1,9 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const feishuExtensionIds = ["feishu"];
export const feishuExtensionTestRoots = feishuExtensionIds.map((id) => bundledPluginRoot(id));
export function isFeishuExtensionRoot(root) {
return feishuExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { feishuExtensionTestRoots } from "./vitest.extension-feishu-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionFeishuVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
feishuExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-feishu",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionFeishuVitestConfig();

View File

@@ -0,0 +1,5 @@
export const ircExtensionTestRoots = ["extensions/irc"];
export function isIrcExtensionRoot(root) {
return ircExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,26 @@
import { ircExtensionTestRoots } from "./vitest.extension-irc-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionIrcVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ?? ircExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-irc",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionIrcVitestConfig();

View File

@@ -0,0 +1,9 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const matrixExtensionIds = ["matrix"];
export const matrixExtensionTestRoots = matrixExtensionIds.map((id) => bundledPluginRoot(id));
export function isMatrixExtensionRoot(root) {
return matrixExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,17 @@
import { matrixExtensionTestRoots } from "./vitest.extension-matrix-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createExtensionMatrixVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(
matrixExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-matrix",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionMatrixVitestConfig();

View File

@@ -0,0 +1,11 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const mattermostExtensionIds = ["mattermost"];
export const mattermostExtensionTestRoots = mattermostExtensionIds.map((id) =>
bundledPluginRoot(id),
);
export function isMattermostExtensionRoot(root) {
return mattermostExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { mattermostExtensionTestRoots } from "./vitest.extension-mattermost-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionMattermostVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
mattermostExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-mattermost",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionMattermostVitestConfig();

View File

@@ -0,0 +1,22 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export default createScopedVitestConfig(
[
"alibaba/**/*.test.ts",
"deepgram/**/*.test.ts",
"elevenlabs/**/*.test.ts",
"fal/**/*.test.ts",
"image-generation-core/**/*.test.ts",
"runway/**/*.test.ts",
"talk-voice/**/*.test.ts",
"video-generation-core/**/*.test.ts",
"vydra/**/*.test.ts",
"xiaomi/**/*.test.ts",
],
{
dir: "extensions",
name: "extension-media",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);

View File

@@ -0,0 +1,9 @@
export const memoryExtensionTestRoots = [
"extensions/memory-core",
"extensions/memory-lancedb",
"extensions/memory-wiki",
];
export function isMemoryExtensionRoot(root) {
return memoryExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,28 @@
import { memoryExtensionTestRoots } from "./vitest.extension-memory-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionMemoryVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
memoryExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-memory",
pool: "forks",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionMemoryVitestConfig();

View File

@@ -0,0 +1,20 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const messagingExtensionIds = [
"bluebubbles",
"googlechat",
"mattermost",
"nextcloud-talk",
"nostr",
"qqbot",
"synology-chat",
"tlon",
"twitch",
"voice-call",
];
export const messagingExtensionTestRoots = messagingExtensionIds.map((id) => bundledPluginRoot(id));
export function isMessagingExtensionRoot(root) {
return messagingExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { messagingExtensionTestRoots } from "./vitest.extension-messaging-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionMessagingVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
messagingExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-messaging",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionMessagingVitestConfig();

View File

@@ -0,0 +1,35 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export default createScopedVitestConfig(
[
"arcee/**/*.test.ts",
"brave/**/*.test.ts",
"device-pair/**/*.test.ts",
"diagnostics-otel/**/*.test.ts",
"duckduckgo/**/*.test.ts",
"exa/**/*.test.ts",
"firecrawl/**/*.test.ts",
"fireworks/**/*.test.ts",
"kilocode/**/*.test.ts",
"litellm/**/*.test.ts",
"llm-task/**/*.test.ts",
"lobster/**/*.test.ts",
"opencode/**/*.test.ts",
"opencode-go/**/*.test.ts",
"openshell/**/*.test.ts",
"perplexity/**/*.test.ts",
"phone-control/**/*.test.ts",
"searxng/**/*.test.ts",
"synthetic/**/*.test.ts",
"tavily/**/*.test.ts",
"thread-ownership/**/*.test.ts",
"vercel-ai-gateway/**/*.test.ts",
"webhooks/**/*.test.ts",
],
{
dir: "extensions",
name: "extension-misc",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);

View File

@@ -0,0 +1,9 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const msTeamsExtensionIds = ["msteams"];
export const msTeamsExtensionTestRoots = msTeamsExtensionIds.map((id) => bundledPluginRoot(id));
export function isMsTeamsExtensionRoot(root) {
return msTeamsExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,17 @@
import { msTeamsExtensionTestRoots } from "./vitest.extension-msteams-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createExtensionMsTeamsVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(
msTeamsExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-msteams",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionMsTeamsVitestConfig();

View File

@@ -0,0 +1,40 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const providerExtensionIds = [
"amazon-bedrock",
"amazon-bedrock-mantle",
"anthropic",
"anthropic-vertex",
"byteplus",
"chutes",
"comfy",
"deepseek",
"github-copilot",
"google",
"groq",
"huggingface",
"kimi-coding",
"microsoft",
"microsoft-foundry",
"minimax",
"mistral",
"qwen",
"moonshot",
"nvidia",
"ollama",
"openai",
"openrouter",
"qianfan",
"stepfun",
"together",
"venice",
"volcengine",
"xai",
"zai",
];
export const providerExtensionTestRoots = providerExtensionIds.map((id) => bundledPluginRoot(id));
export function isProviderExtensionRoot(root) {
return providerExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { providerExtensionTestRoots } from "./vitest.extension-provider-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionProvidersVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
providerExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-providers",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionProvidersVitestConfig();

View File

@@ -0,0 +1,8 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export default createScopedVitestConfig(["qa-channel/**/*.test.ts", "qa-lab/**/*.test.ts"], {
dir: "extensions",
name: "extension-qa",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
});

View File

@@ -0,0 +1,5 @@
export const telegramExtensionTestRoots = ["extensions/telegram"];
export function isTelegramExtensionRoot(root) {
return telegramExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { telegramExtensionTestRoots } from "./vitest.extension-telegram-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionTelegramVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
telegramExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-telegram",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionTelegramVitestConfig();

View File

@@ -0,0 +1,9 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const voiceCallExtensionIds = ["voice-call"];
export const voiceCallExtensionTestRoots = voiceCallExtensionIds.map((id) => bundledPluginRoot(id));
export function isVoiceCallExtensionRoot(root) {
return voiceCallExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { voiceCallExtensionTestRoots } from "./vitest.extension-voice-call-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionVoiceCallVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
voiceCallExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-voice-call",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionVoiceCallVitestConfig();

View File

@@ -0,0 +1,9 @@
import { bundledPluginRoot } from "../../scripts/lib/bundled-plugin-paths.mjs";
export const whatsAppExtensionIds = ["whatsapp"];
export const whatsAppExtensionTestRoots = whatsAppExtensionIds.map((id) => bundledPluginRoot(id));
export function isWhatsAppExtensionRoot(root) {
return whatsAppExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,27 @@
import { whatsAppExtensionTestRoots } from "./vitest.extension-whatsapp-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionWhatsAppVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ??
whatsAppExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-whatsapp",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionWhatsAppVitestConfig();

View File

@@ -0,0 +1,5 @@
export const zaloExtensionTestRoots = ["extensions/zalo", "extensions/zalouser"];
export function isZaloExtensionRoot(root) {
return zaloExtensionTestRoots.includes(root);
}

View File

@@ -0,0 +1,26 @@
import { zaloExtensionTestRoots } from "./vitest.extension-zalo-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionZaloVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(
loadIncludePatternsFromEnv(env) ?? zaloExtensionTestRoots.map((root) => `${root}/**/*.test.ts`),
{
dir: "extensions",
env,
name: "extension-zalo",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
},
);
}
export default createExtensionZaloVitestConfig();

View File

@@ -0,0 +1,59 @@
import { BUNDLED_PLUGIN_TEST_GLOB } from "./vitest.bundled-plugin-paths.ts";
import { extensionExcludedChannelTestGlobs } from "./vitest.channel-paths.mjs";
import { acpxExtensionTestRoots } from "./vitest.extension-acpx-paths.mjs";
import { blueBubblesExtensionTestRoots } from "./vitest.extension-bluebubbles-paths.mjs";
import { diffsExtensionTestRoots } from "./vitest.extension-diffs-paths.mjs";
import { feishuExtensionTestRoots } from "./vitest.extension-feishu-paths.mjs";
import { ircExtensionTestRoots } from "./vitest.extension-irc-paths.mjs";
import { matrixExtensionTestRoots } from "./vitest.extension-matrix-paths.mjs";
import { mattermostExtensionTestRoots } from "./vitest.extension-mattermost-paths.mjs";
import { memoryExtensionTestRoots } from "./vitest.extension-memory-paths.mjs";
import { messagingExtensionTestRoots } from "./vitest.extension-messaging-paths.mjs";
import { msTeamsExtensionTestRoots } from "./vitest.extension-msteams-paths.mjs";
import { providerExtensionTestRoots } from "./vitest.extension-provider-paths.mjs";
import { telegramExtensionTestRoots } from "./vitest.extension-telegram-paths.mjs";
import { voiceCallExtensionTestRoots } from "./vitest.extension-voice-call-paths.mjs";
import { whatsAppExtensionTestRoots } from "./vitest.extension-whatsapp-paths.mjs";
import { zaloExtensionTestRoots } from "./vitest.extension-zalo-paths.mjs";
import { loadPatternListFromEnv } from "./vitest.pattern-file.ts";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function loadIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createExtensionsVitestConfig(
env: Record<string, string | undefined> = process.env,
) {
return createScopedVitestConfig(loadIncludePatternsFromEnv(env) ?? [BUNDLED_PLUGIN_TEST_GLOB], {
dir: "extensions",
env,
name: "extensions",
passWithNoTests: true,
setupFiles: ["test/setup.extensions.ts"],
// Some bundled plugins still run on the channel surface; keep those roots
// out of the shared extensions lane.
exclude: [
...extensionExcludedChannelTestGlobs,
...acpxExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...blueBubblesExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...diffsExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...feishuExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...ircExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...matrixExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...mattermostExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...memoryExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...messagingExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...msTeamsExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...providerExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...telegramExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...voiceCallExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...whatsAppExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
...zaloExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`),
],
});
}
export default createExtensionsVitestConfig();

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-agentic.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-auto-reply.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-bundled.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-contracts.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-runtime.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-support-boundary.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,11 @@
import { defineConfig } from "vitest/config";
import { sharedVitestConfig } from "./vitest.shared.config.ts";
export default defineConfig({
...sharedVitestConfig,
test: {
...sharedVitestConfig.test,
runner: undefined,
projects: ["test/vitest/vitest.unit-fast.config.ts"],
},
});

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-unit-security.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-unit-src.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-unit-support.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-core-unit-ui.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,4 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(fullSuiteVitestShards[0].projects);

View File

@@ -0,0 +1,8 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find(
(shard) => shard.config === "test/vitest/vitest.full-extensions.config.ts",
)?.projects ?? [],
);

View File

@@ -0,0 +1,21 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createGatewayClientVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(
[
"src/gateway/protocol/**/*.test.ts",
"src/gateway/**/*client*.test.ts",
"src/gateway/**/*reconnect*.test.ts",
"src/gateway/**/*android-node*.test.ts",
"src/gateway/**/*gateway-cli-backend*.test.ts",
],
{
dir: "src/gateway",
env,
exclude: ["src/gateway/**/*server*.test.ts"],
name: "gateway-client",
},
);
}
export default createGatewayClientVitestConfig();

View File

@@ -0,0 +1,25 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
const nonCoreGatewayTestExclude = [
"src/gateway/server-methods/**/*.test.ts",
"src/gateway/protocol/**/*.test.ts",
"src/gateway/**/*client*.test.ts",
"src/gateway/**/*reconnect*.test.ts",
"src/gateway/**/*android-node*.test.ts",
"src/gateway/**/*gateway-cli-backend*.test.ts",
"src/gateway/**/*server*.test.ts",
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
];
export function createGatewayCoreVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/gateway/**/*.test.ts"], {
dir: "src/gateway",
env,
exclude: nonCoreGatewayTestExclude,
name: "gateway-core",
});
}
export default createGatewayCoreVitestConfig();

View File

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

View File

@@ -0,0 +1,17 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createGatewayServerVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/gateway/**/*server*.test.ts"], {
dir: "src/gateway",
env,
exclude: [
"src/gateway/server-methods/**/*.test.ts",
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
],
name: "gateway-server",
});
}
export default createGatewayServerVitestConfig();

View File

@@ -0,0 +1,16 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createGatewayVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/gateway/**/*.test.ts"], {
dir: "src/gateway",
env,
exclude: [
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
],
name: "gateway",
});
}
export default createGatewayVitestConfig();

View File

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

View File

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

View File

@@ -0,0 +1,27 @@
import { defineConfig } from "vitest/config";
import { BUNDLED_PLUGIN_LIVE_TEST_GLOB } from "./vitest.bundled-plugin-paths.ts";
import baseConfig from "./vitest.config.ts";
const base = baseConfig as unknown as Record<string, unknown>;
const baseTestWithProjects =
(baseConfig as { test?: { exclude?: string[]; setupFiles?: string[] } }).test ?? {};
const { projects: _projects, ...baseTest } = baseTestWithProjects as {
exclude?: string[];
projects?: string[];
setupFiles?: string[];
};
const exclude = (baseTest.exclude ?? []).filter((p) => p !== "**/*.live.test.ts");
export default defineConfig({
...base,
test: {
...baseTest,
// Live suites need immediate provider/gateway progress output rather than
// Vitest's buffered per-test console capture.
disableConsoleIntercept: true,
maxWorkers: 1,
setupFiles: [...new Set([...(baseTest.setupFiles ?? []), "test/setup-openclaw-runtime.ts"])],
include: ["src/**/*.live.test.ts", "test/**/*.live.test.ts", BUNDLED_PLUGIN_LIVE_TEST_GLOB],
exclude,
},
});

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,75 @@
import fs from "node:fs";
import path from "node:path";
function normalizeCliPattern(value: string): string {
let normalized = value
.trim()
.replace(/^\.\/+/u, "")
.replace(/\/+$/u, "");
if (
/^(?:src|test|extensions|ui|packages|apps)(?:\/|$)/u.test(normalized) &&
!/[?*[\]{}]/u.test(normalized) &&
!/\.(?:[cm]?[jt]sx?)$/u.test(normalized)
) {
normalized = `${normalized}/**/*.test.*`;
}
return normalized;
}
function looksLikeCliIncludePattern(value: string): boolean {
const normalized = normalizeCliPattern(value);
return (
normalized.includes(".test.") ||
normalized.includes(".e2e.") ||
normalized.includes(".live.") ||
/^(?:src|test|extensions|ui|packages|apps)(?:\/|$)/u.test(normalized)
);
}
export function loadPatternListFile(filePath: string, label: string): string[] {
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8")) as unknown;
if (!Array.isArray(parsed)) {
throw new TypeError(`${label} must point to a JSON array: ${filePath}`);
}
return parsed.filter((value): value is string => typeof value === "string" && value.length > 0);
}
export function loadPatternListFromEnv(
envKey: string,
env: Record<string, string | undefined> = process.env,
): string[] | null {
const filePath = env[envKey]?.trim();
if (!filePath) {
return null;
}
return loadPatternListFile(filePath, envKey);
}
export function loadPatternListFromArgv(argv: string[] = process.argv): string[] | null {
const patterns = argv
.slice(2)
.filter((value) => value !== "run" && value !== "watch" && value !== "bench")
.filter((value) => !value.startsWith("-"))
.filter(looksLikeCliIncludePattern)
.map(normalizeCliPattern);
return patterns.length > 0 ? [...new Set(patterns)] : null;
}
export function narrowIncludePatternsForCli(
includePatterns: string[],
argv: string[] = process.argv,
): string[] | null {
const cliPatterns = loadPatternListFromArgv(argv);
if (!cliPatterns) {
return null;
}
const matched = cliPatterns.filter((value) =>
includePatterns.some(
(pattern) => path.matchesGlob(value, pattern) || path.matchesGlob(pattern, value),
),
);
return [...new Set(matched)];
}

View File

@@ -0,0 +1,59 @@
type EnvMap = Record<string, string | undefined>;
const isEnabled = (value: string | undefined): boolean => {
const normalized = value?.trim().toLowerCase();
return normalized === "1" || normalized === "true";
};
const isDisabled = (value: string | undefined): boolean => {
const normalized = value?.trim().toLowerCase();
return normalized === "0" || normalized === "false";
};
const isWindowsEnv = (env: EnvMap, platform: NodeJS.Platform): boolean => {
if (platform === "win32") {
return true;
}
const runnerOs = env.RUNNER_OS?.trim().toLowerCase();
return runnerOs === "windows";
};
type VitestExperimentalConfig = {
experimental?: {
fsModuleCache?: true;
fsModuleCachePath?: string;
importDurations?: { print: true };
printImportBreakdown?: true;
};
};
export function loadVitestExperimentalConfig(
env: EnvMap = process.env,
platform: NodeJS.Platform = process.platform,
): VitestExperimentalConfig {
const experimental: {
fsModuleCache?: true;
fsModuleCachePath?: string;
importDurations?: { print: true };
printImportBreakdown?: true;
} = {};
const windowsEnv = isWindowsEnv(env, platform);
if (!windowsEnv && !isDisabled(env.OPENCLAW_VITEST_FS_MODULE_CACHE)) {
experimental.fsModuleCache = true;
}
if (windowsEnv && isEnabled(env.OPENCLAW_VITEST_FS_MODULE_CACHE)) {
experimental.fsModuleCache = true;
}
if (experimental.fsModuleCache && env.OPENCLAW_VITEST_FS_MODULE_CACHE_PATH?.trim()) {
experimental.fsModuleCachePath = env.OPENCLAW_VITEST_FS_MODULE_CACHE_PATH.trim();
}
if (isEnabled(env.OPENCLAW_VITEST_IMPORT_DURATIONS)) {
experimental.importDurations = { print: true };
}
if (isEnabled(env.OPENCLAW_VITEST_PRINT_IMPORT_BREAKDOWN)) {
experimental.printImportBreakdown = true;
}
return Object.keys(experimental).length > 0 ? { experimental } : {};
}

View File

@@ -0,0 +1,16 @@
import { pluginSdkLightTestFiles } from "./vitest.plugin-sdk-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
import { unitFastTestFiles } from "./vitest.unit-fast-paths.mjs";
export function createPluginSdkLightVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(pluginSdkLightTestFiles, {
dir: "src",
env,
exclude: unitFastTestFiles,
includeOpenClawRuntimeSetup: false,
name: "plugin-sdk-light",
passWithNoTests: true,
});
}
export default createPluginSdkLightVitestConfig();

View File

@@ -0,0 +1,56 @@
const normalizeRepoPath = (value) => value.replaceAll("\\", "/");
const pluginSdkLightEntries = [
{ source: "src/plugin-sdk/acp-runtime.ts", test: "src/plugin-sdk/acp-runtime.test.ts" },
{ source: "src/plugin-sdk/allow-from.ts", test: "src/plugin-sdk/allow-from.test.ts" },
{
source: "src/plugin-sdk/keyed-async-queue.ts",
test: "src/plugin-sdk/keyed-async-queue.test.ts",
},
{ source: "src/plugin-sdk/lazy-value.ts", test: "src/plugin-sdk/lazy-value.test.ts" },
{
source: "src/plugin-sdk/persistent-dedupe.ts",
test: "src/plugin-sdk/persistent-dedupe.test.ts",
},
{ source: "src/plugin-sdk/provider-entry.ts", test: "src/plugin-sdk/provider-entry.test.ts" },
{
source: "src/plugin-sdk/provider-model-shared.ts",
test: "src/plugin-sdk/provider-model-shared.test.ts",
},
{ source: "src/plugin-sdk/provider-tools.ts", test: "src/plugin-sdk/provider-tools.test.ts" },
{
source: "src/plugin-sdk/status-helpers.ts",
test: "src/plugin-sdk/status-helpers.test.ts",
},
{ source: "src/plugin-sdk/temp-path.ts", test: "src/plugin-sdk/temp-path.test.ts" },
{
source: "src/plugin-sdk/text-chunking.ts",
test: "src/plugin-sdk/text-chunking.test.ts",
},
{
source: "src/plugin-sdk/webhook-targets.ts",
test: "src/plugin-sdk/webhook-targets.test.ts",
},
];
const pluginSdkLightIncludePatternByFile = new Map(
pluginSdkLightEntries.flatMap(({ source, test }) => [
[source, test],
[test, test],
]),
);
export const pluginSdkLightSourceFiles = pluginSdkLightEntries.map(({ source }) => source);
export const pluginSdkLightTestFiles = pluginSdkLightEntries.map(({ test }) => test);
export function isPluginSdkLightTarget(file) {
return pluginSdkLightIncludePatternByFile.has(normalizeRepoPath(file));
}
export function isPluginSdkLightTestFile(file) {
return pluginSdkLightTestFiles.includes(normalizeRepoPath(file));
}
export function resolvePluginSdkLightIncludePattern(file) {
return pluginSdkLightIncludePatternByFile.get(normalizeRepoPath(file)) ?? null;
}

View File

@@ -0,0 +1,14 @@
import { pluginSdkLightTestFiles } from "./vitest.plugin-sdk-paths.mjs";
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createPluginSdkVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/plugin-sdk/**/*.test.ts"], {
dir: "src",
env,
exclude: pluginSdkLightTestFiles,
name: "plugin-sdk",
passWithNoTests: true,
});
}
export default createPluginSdkVitestConfig();

View File

@@ -0,0 +1,14 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createPluginsVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(["src/plugins/**/*.test.ts"], {
dir: "src/plugins",
env,
exclude: ["src/plugins/contracts/**"],
isolate: true,
name: "plugins",
passWithNoTests: true,
});
}
export default createPluginsVitestConfig();

View File

@@ -0,0 +1,23 @@
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
export function createProcessVitestConfig(env?: Record<string, string | undefined>) {
const config = createScopedVitestConfig(["src/process/**/*.test.ts"], {
dir: "src",
env,
includeOpenClawRuntimeSetup: false,
name: "process",
passWithNoTests: true,
});
return {
...config,
test: {
...config.test,
sequence: {
...config.test?.sequence,
groupOrder: 2,
},
},
};
}
export default createProcessVitestConfig();

Some files were not shown because too many files have changed in this diff Show More