refactor(test): share sessions_spawn e2e harness
This commit is contained in:
@@ -1,62 +1,18 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { createOpenClawTools } from "./openclaw-tools.js";
|
||||
import "./test-helpers/fast-core-tools.js";
|
||||
import {
|
||||
getCallGatewayMock,
|
||||
resetSessionsSpawnConfigOverride,
|
||||
setSessionsSpawnConfigOverride,
|
||||
} from "./openclaw-tools.subagents.sessions-spawn.test-harness.js";
|
||||
import { resetSubagentRegistryForTests } from "./subagent-registry.js";
|
||||
|
||||
type SessionsSpawnTestConfig = ReturnType<(typeof import("../config/config.js"))["loadConfig"]>;
|
||||
|
||||
const hoisted = vi.hoisted(() => {
|
||||
const callGatewayMock = vi.fn();
|
||||
const defaultConfigOverride = {
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
} as SessionsSpawnTestConfig;
|
||||
const state = { configOverride: defaultConfigOverride };
|
||||
return { callGatewayMock, defaultConfigOverride, state };
|
||||
});
|
||||
|
||||
const callGatewayMock = hoisted.callGatewayMock;
|
||||
|
||||
function resetConfigOverride() {
|
||||
hoisted.state.configOverride = hoisted.defaultConfigOverride;
|
||||
}
|
||||
|
||||
function setConfigOverride(next: SessionsSpawnTestConfig) {
|
||||
hoisted.state.configOverride = next;
|
||||
}
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
// Some tools import callGateway via "../../gateway/call.js" (from nested folders). Mock that too.
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
|
||||
// Same module, different specifier (used by tools under src/agents/tools/*).
|
||||
vi.mock("../../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
const callGatewayMock = getCallGatewayMock();
|
||||
|
||||
describe("openclaw-tools: subagents (sessions_spawn allowlist)", () => {
|
||||
beforeEach(() => {
|
||||
resetConfigOverride();
|
||||
resetSessionsSpawnConfigOverride();
|
||||
});
|
||||
|
||||
it("sessions_spawn only allows same-agent by default", async () => {
|
||||
@@ -84,7 +40,7 @@ describe("openclaw-tools: subagents (sessions_spawn allowlist)", () => {
|
||||
it("sessions_spawn forbids cross-agent spawning when not allowed", async () => {
|
||||
resetSubagentRegistryForTests();
|
||||
callGatewayMock.mockReset();
|
||||
setConfigOverride({
|
||||
setSessionsSpawnConfigOverride({
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
|
||||
@@ -1,60 +1,19 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { emitAgentEvent } from "../infra/agent-events.js";
|
||||
import { sleep } from "../utils.js";
|
||||
import { createOpenClawTools } from "./openclaw-tools.js";
|
||||
import "./test-helpers/fast-core-tools.js";
|
||||
import {
|
||||
getCallGatewayMock,
|
||||
resetSessionsSpawnConfigOverride,
|
||||
} from "./openclaw-tools.subagents.sessions-spawn.test-harness.js";
|
||||
import { resetSubagentRegistryForTests } from "./subagent-registry.js";
|
||||
|
||||
type SessionsSpawnTestConfig = ReturnType<(typeof import("../config/config.js"))["loadConfig"]>;
|
||||
|
||||
const hoisted = vi.hoisted(() => {
|
||||
const callGatewayMock = vi.fn();
|
||||
const defaultConfigOverride = {
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
} as SessionsSpawnTestConfig;
|
||||
const state = { configOverride: defaultConfigOverride };
|
||||
return { callGatewayMock, defaultConfigOverride, state };
|
||||
});
|
||||
|
||||
const callGatewayMock = hoisted.callGatewayMock;
|
||||
|
||||
function resetConfigOverride() {
|
||||
hoisted.state.configOverride = hoisted.defaultConfigOverride;
|
||||
}
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
// Some tools import callGateway via "../../gateway/call.js" (from nested folders). Mock that too.
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
|
||||
// Same module, different specifier (used by tools under src/agents/tools/*).
|
||||
vi.mock("../../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
const callGatewayMock = getCallGatewayMock();
|
||||
|
||||
describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => {
|
||||
beforeEach(() => {
|
||||
resetConfigOverride();
|
||||
resetSessionsSpawnConfigOverride();
|
||||
});
|
||||
|
||||
it("sessions_spawn runs cleanup flow after subagent completion", async () => {
|
||||
|
||||
@@ -1,63 +1,19 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./defaults.js";
|
||||
import "./test-helpers/fast-core-tools.js";
|
||||
import { createOpenClawTools } from "./openclaw-tools.js";
|
||||
import {
|
||||
getCallGatewayMock,
|
||||
resetSessionsSpawnConfigOverride,
|
||||
setSessionsSpawnConfigOverride,
|
||||
} from "./openclaw-tools.subagents.sessions-spawn.test-harness.js";
|
||||
import { resetSubagentRegistryForTests } from "./subagent-registry.js";
|
||||
|
||||
type SessionsSpawnTestConfig = ReturnType<(typeof import("../config/config.js"))["loadConfig"]>;
|
||||
|
||||
const hoisted = vi.hoisted(() => {
|
||||
const callGatewayMock = vi.fn();
|
||||
const defaultConfigOverride = {
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
} as SessionsSpawnTestConfig;
|
||||
const state = { configOverride: defaultConfigOverride };
|
||||
return { callGatewayMock, defaultConfigOverride, state };
|
||||
});
|
||||
|
||||
const callGatewayMock = hoisted.callGatewayMock;
|
||||
|
||||
function resetConfigOverride() {
|
||||
hoisted.state.configOverride = hoisted.defaultConfigOverride;
|
||||
}
|
||||
|
||||
function setConfigOverride(next: SessionsSpawnTestConfig) {
|
||||
hoisted.state.configOverride = next;
|
||||
}
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
// Some tools import callGateway via "../../gateway/call.js" (from nested folders). Mock that too.
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
|
||||
// Same module, different specifier (used by tools under src/agents/tools/*).
|
||||
vi.mock("../../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
const callGatewayMock = getCallGatewayMock();
|
||||
|
||||
describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
||||
beforeEach(() => {
|
||||
resetConfigOverride();
|
||||
resetSessionsSpawnConfigOverride();
|
||||
});
|
||||
|
||||
it("sessions_spawn applies a model to the child session", async () => {
|
||||
@@ -192,7 +148,7 @@ describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
||||
it("sessions_spawn applies default subagent model from defaults config", async () => {
|
||||
resetSubagentRegistryForTests();
|
||||
callGatewayMock.mockReset();
|
||||
setConfigOverride({
|
||||
setSessionsSpawnConfigOverride({
|
||||
session: { mainKey: "main", scope: "per-sender" },
|
||||
agents: { defaults: { subagents: { model: "minimax/MiniMax-M2.1" } } },
|
||||
});
|
||||
@@ -278,7 +234,7 @@ describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
||||
it("sessions_spawn prefers per-agent subagent model over defaults", async () => {
|
||||
resetSubagentRegistryForTests();
|
||||
callGatewayMock.mockReset();
|
||||
setConfigOverride({
|
||||
setSessionsSpawnConfigOverride({
|
||||
session: { mainKey: "main", scope: "per-sender" },
|
||||
agents: {
|
||||
defaults: { subagents: { model: "minimax/MiniMax-M2.1" } },
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
type SessionsSpawnTestConfig = ReturnType<(typeof import("../config/config.js"))["loadConfig"]>;
|
||||
|
||||
// Avoid exporting vitest mock types (TS2742 under pnpm + d.ts emit).
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
type AnyMock = any;
|
||||
|
||||
const hoisted = vi.hoisted(() => {
|
||||
const callGatewayMock = vi.fn();
|
||||
const defaultConfigOverride = {
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
} as SessionsSpawnTestConfig;
|
||||
const state = { configOverride: defaultConfigOverride };
|
||||
return { callGatewayMock, defaultConfigOverride, state };
|
||||
});
|
||||
|
||||
export function getCallGatewayMock(): AnyMock {
|
||||
return hoisted.callGatewayMock;
|
||||
}
|
||||
|
||||
export function resetSessionsSpawnConfigOverride(): void {
|
||||
hoisted.state.configOverride = hoisted.defaultConfigOverride;
|
||||
}
|
||||
|
||||
export function setSessionsSpawnConfigOverride(next: SessionsSpawnTestConfig): void {
|
||||
hoisted.state.configOverride = next;
|
||||
}
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
// Some tools import callGateway via "../../gateway/call.js" (from nested folders). Mock that too.
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => hoisted.callGatewayMock(opts),
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
|
||||
// Same module, different specifier (used by tools under src/agents/tools/*).
|
||||
vi.mock("../../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => hoisted.state.configOverride,
|
||||
resolveGatewayPort: () => 18789,
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user