From 615f6e1e4055d934272a39841a85028897460f66 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 14 Feb 2026 23:07:46 +0000 Subject: [PATCH] refactor(test): share sessions_spawn e2e mocks --- ...ross-agent-spawning-configured.e2e.test.ts | 46 +++++-------------- ...es-agent-wait-lifecycle-events.e2e.test.ts | 35 +++----------- ...wn-applies-model-child-session.e2e.test.ts | 42 ++++------------- ...rmalizes-allowlisted-agent-ids.e2e.test.ts | 44 +++++------------- ...efers-per-agent-subagent-model.e2e.test.ts | 42 ++++------------- ...lves-main-announce-target-from.e2e.test.ts | 37 +++------------ ...aw-tools.subagents.sessions-spawn.mocks.ts | 36 +++++++++++++++ 7 files changed, 92 insertions(+), 190 deletions(-) create mode 100644 src/agents/openclaw-tools.subagents.sessions-spawn.mocks.ts diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn-allows-cross-agent-spawning-configured.e2e.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn-allows-cross-agent-spawning-configured.e2e.test.ts index a95f6aed6a8..980119b8721 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn-allows-cross-agent-spawning-configured.e2e.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn-allows-cross-agent-spawning-configured.e2e.test.ts @@ -1,44 +1,22 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; - -const callGatewayMock = vi.fn(); -vi.mock("../gateway/call.js", () => ({ - callGateway: (opts: unknown) => callGatewayMock(opts), -})); - -let configOverride: ReturnType<(typeof import("../config/config.js"))["loadConfig"]> = { - session: { - mainKey: "main", - scope: "per-sender", - }, -}; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - loadConfig: () => configOverride, - resolveGatewayPort: () => 18789, - }; -}); - -import "./test-helpers/fast-core-tools.js"; +import { beforeEach, describe, expect, it } from "vitest"; import { createOpenClawTools } from "./openclaw-tools.js"; +import "./test-helpers/fast-core-tools.js"; +import { + callGatewayMock, + resetConfigOverride, + setConfigOverride, +} from "./openclaw-tools.subagents.sessions-spawn.mocks.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js"; describe("openclaw-tools: subagents", () => { beforeEach(() => { - configOverride = { - session: { - mainKey: "main", - scope: "per-sender", - }, - }; + resetConfigOverride(); }); it("sessions_spawn allows cross-agent spawning when configured", async () => { resetSubagentRegistryForTests(); callGatewayMock.mockReset(); - configOverride = { + setConfigOverride({ session: { mainKey: "main", scope: "per-sender", @@ -53,7 +31,7 @@ describe("openclaw-tools: subagents", () => { }, ], }, - }; + }); let childSessionKey: string | undefined; callGatewayMock.mockImplementation(async (opts: unknown) => { @@ -91,7 +69,7 @@ describe("openclaw-tools: subagents", () => { it("sessions_spawn allows any agent when allowlist is *", async () => { resetSubagentRegistryForTests(); callGatewayMock.mockReset(); - configOverride = { + setConfigOverride({ session: { mainKey: "main", scope: "per-sender", @@ -106,7 +84,7 @@ describe("openclaw-tools: subagents", () => { }, ], }, - }; + }); let childSessionKey: string | undefined; callGatewayMock.mockImplementation(async (opts: unknown) => { diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn-announces-agent-wait-lifecycle-events.e2e.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn-announces-agent-wait-lifecycle-events.e2e.test.ts index da5765f1a14..df5d0e01635 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn-announces-agent-wait-lifecycle-events.e2e.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn-announces-agent-wait-lifecycle-events.e2e.test.ts @@ -1,39 +1,16 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; - -const callGatewayMock = vi.fn(); -vi.mock("../gateway/call.js", () => ({ - callGateway: (opts: unknown) => callGatewayMock(opts), -})); - -let configOverride: ReturnType<(typeof import("../config/config.js"))["loadConfig"]> = { - session: { - mainKey: "main", - scope: "per-sender", - }, -}; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - loadConfig: () => configOverride, - resolveGatewayPort: () => 18789, - }; -}); - -import "./test-helpers/fast-core-tools.js"; import { sleep } from "../utils.js"; +import "./test-helpers/fast-core-tools.js"; import { createOpenClawTools } from "./openclaw-tools.js"; +import { + callGatewayMock, + resetConfigOverride, +} from "./openclaw-tools.subagents.sessions-spawn.mocks.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js"; describe("openclaw-tools: subagents", () => { beforeEach(() => { - configOverride = { - session: { - mainKey: "main", - scope: "per-sender", - }, - }; + resetConfigOverride(); }); it("sessions_spawn deletes session when cleanup=delete via agent.wait", async () => { diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn-applies-model-child-session.e2e.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn-applies-model-child-session.e2e.test.ts index 7801acb2e22..719b9a1efee 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn-applies-model-child-session.e2e.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn-applies-model-child-session.e2e.test.ts @@ -1,38 +1,16 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; - -const callGatewayMock = vi.fn(); -vi.mock("../gateway/call.js", () => ({ - callGateway: (opts: unknown) => callGatewayMock(opts), -})); - -let configOverride: ReturnType<(typeof import("../config/config.js"))["loadConfig"]> = { - session: { - mainKey: "main", - scope: "per-sender", - }, -}; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - loadConfig: () => configOverride, - resolveGatewayPort: () => 18789, - }; -}); - -import "./test-helpers/fast-core-tools.js"; +import { beforeEach, describe, expect, it } from "vitest"; import { createOpenClawTools } from "./openclaw-tools.js"; +import "./test-helpers/fast-core-tools.js"; +import { + callGatewayMock, + resetConfigOverride, + setConfigOverride, +} from "./openclaw-tools.subagents.sessions-spawn.mocks.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js"; describe("openclaw-tools: subagents", () => { beforeEach(() => { - configOverride = { - session: { - mainKey: "main", - scope: "per-sender", - }, - }; + resetConfigOverride(); }); it("sessions_spawn applies a model to the child session", async () => { @@ -164,10 +142,10 @@ describe("openclaw-tools: subagents", () => { it("sessions_spawn applies default subagent model from defaults config", async () => { resetSubagentRegistryForTests(); callGatewayMock.mockReset(); - configOverride = { + setConfigOverride({ session: { mainKey: "main", scope: "per-sender" }, agents: { defaults: { subagents: { model: "minimax/MiniMax-M2.1" } } }, - }; + }); const calls: Array<{ method?: string; params?: unknown }> = []; callGatewayMock.mockImplementation(async (opts: unknown) => { diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn-normalizes-allowlisted-agent-ids.e2e.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn-normalizes-allowlisted-agent-ids.e2e.test.ts index 411653e606c..be79e2384f1 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn-normalizes-allowlisted-agent-ids.e2e.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn-normalizes-allowlisted-agent-ids.e2e.test.ts @@ -1,45 +1,23 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; - -const callGatewayMock = vi.fn(); -vi.mock("../gateway/call.js", () => ({ - callGateway: (opts: unknown) => callGatewayMock(opts), -})); - -let configOverride: ReturnType<(typeof import("../config/config.js"))["loadConfig"]> = { - session: { - mainKey: "main", - scope: "per-sender", - }, -}; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - loadConfig: () => configOverride, - resolveGatewayPort: () => 18789, - }; -}); - import { emitAgentEvent } from "../infra/agent-events.js"; -import "./test-helpers/fast-core-tools.js"; import { createOpenClawTools } from "./openclaw-tools.js"; +import "./test-helpers/fast-core-tools.js"; +import { + callGatewayMock, + resetConfigOverride, + setConfigOverride, +} from "./openclaw-tools.subagents.sessions-spawn.mocks.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js"; describe("openclaw-tools: subagents", () => { beforeEach(() => { - configOverride = { - session: { - mainKey: "main", - scope: "per-sender", - }, - }; + resetConfigOverride(); }); it("sessions_spawn normalizes allowlisted agent ids", async () => { resetSubagentRegistryForTests(); callGatewayMock.mockReset(); - configOverride = { + setConfigOverride({ session: { mainKey: "main", scope: "per-sender", @@ -54,7 +32,7 @@ describe("openclaw-tools: subagents", () => { }, ], }, - }; + }); let childSessionKey: string | undefined; callGatewayMock.mockImplementation(async (opts: unknown) => { @@ -92,7 +70,7 @@ describe("openclaw-tools: subagents", () => { it("sessions_spawn forbids cross-agent spawning when not allowed", async () => { resetSubagentRegistryForTests(); callGatewayMock.mockReset(); - configOverride = { + setConfigOverride({ session: { mainKey: "main", scope: "per-sender", @@ -107,7 +85,7 @@ describe("openclaw-tools: subagents", () => { }, ], }, - }; + }); const tool = createOpenClawTools({ agentSessionKey: "main", diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn-prefers-per-agent-subagent-model.e2e.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn-prefers-per-agent-subagent-model.e2e.test.ts index 5003ddbfc36..13dd9229391 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn-prefers-per-agent-subagent-model.e2e.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn-prefers-per-agent-subagent-model.e2e.test.ts @@ -1,50 +1,28 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; - -const callGatewayMock = vi.fn(); -vi.mock("../gateway/call.js", () => ({ - callGateway: (opts: unknown) => callGatewayMock(opts), -})); - -let configOverride: ReturnType<(typeof import("../config/config.js"))["loadConfig"]> = { - session: { - mainKey: "main", - scope: "per-sender", - }, -}; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - loadConfig: () => configOverride, - resolveGatewayPort: () => 18789, - }; -}); - -import "./test-helpers/fast-core-tools.js"; +import { beforeEach, describe, expect, it } from "vitest"; import { createOpenClawTools } from "./openclaw-tools.js"; +import "./test-helpers/fast-core-tools.js"; +import { + callGatewayMock, + resetConfigOverride, + setConfigOverride, +} from "./openclaw-tools.subagents.sessions-spawn.mocks.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js"; describe("openclaw-tools: subagents", () => { beforeEach(() => { - configOverride = { - session: { - mainKey: "main", - scope: "per-sender", - }, - }; + resetConfigOverride(); }); it("sessions_spawn prefers per-agent subagent model over defaults", async () => { resetSubagentRegistryForTests(); callGatewayMock.mockReset(); - configOverride = { + setConfigOverride({ session: { mainKey: "main", scope: "per-sender" }, agents: { defaults: { subagents: { model: "minimax/MiniMax-M2.1" } }, list: [{ id: "research", subagents: { model: "opencode/claude" } }], }, - }; + }); const calls: Array<{ method?: string; params?: unknown }> = []; callGatewayMock.mockImplementation(async (opts: unknown) => { diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn-resolves-main-announce-target-from.e2e.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn-resolves-main-announce-target-from.e2e.test.ts index 0548d703575..161826410ee 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn-resolves-main-announce-target-from.e2e.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn-resolves-main-announce-target-from.e2e.test.ts @@ -1,40 +1,17 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { sleep } from "../utils.ts"; - -const callGatewayMock = vi.fn(); -vi.mock("../gateway/call.js", () => ({ - callGateway: (opts: unknown) => callGatewayMock(opts), -})); - -let configOverride: ReturnType<(typeof import("../config/config.js"))["loadConfig"]> = { - session: { - mainKey: "main", - scope: "per-sender", - }, -}; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - loadConfig: () => configOverride, - resolveGatewayPort: () => 18789, - }; -}); - import { emitAgentEvent } from "../infra/agent-events.js"; -import "./test-helpers/fast-core-tools.js"; +import { sleep } from "../utils.ts"; import { createOpenClawTools } from "./openclaw-tools.js"; +import "./test-helpers/fast-core-tools.js"; +import { + callGatewayMock, + resetConfigOverride, +} from "./openclaw-tools.subagents.sessions-spawn.mocks.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js"; describe("openclaw-tools: subagents", () => { beforeEach(() => { - configOverride = { - session: { - mainKey: "main", - scope: "per-sender", - }, - }; + resetConfigOverride(); }); it("sessions_spawn runs cleanup flow after subagent completion", async () => { diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn.mocks.ts b/src/agents/openclaw-tools.subagents.sessions-spawn.mocks.ts new file mode 100644 index 00000000000..814d70b4775 --- /dev/null +++ b/src/agents/openclaw-tools.subagents.sessions-spawn.mocks.ts @@ -0,0 +1,36 @@ +import { vi } from "vitest"; + +export const callGatewayMock = vi.fn(); +vi.mock("../gateway/call.js", () => ({ + callGateway: (opts: unknown) => callGatewayMock(opts), +})); + +export type SessionsSpawnTestConfig = ReturnType< + (typeof import("../config/config.js"))["loadConfig"] +>; + +const defaultConfigOverride: SessionsSpawnTestConfig = { + session: { + mainKey: "main", + scope: "per-sender", + }, +}; + +let configOverride: SessionsSpawnTestConfig = defaultConfigOverride; + +export function resetConfigOverride() { + configOverride = defaultConfigOverride; +} + +export function setConfigOverride(next: SessionsSpawnTestConfig) { + configOverride = next; +} + +vi.mock("../config/config.js", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + loadConfig: () => configOverride, + resolveGatewayPort: () => 18789, + }; +});