refactor(test): dedupe agent harnesses and routing fixtures

This commit is contained in:
Peter Steinberger
2026-02-18 04:48:40 +00:00
parent 8a9fddedc9
commit 31f83c86b2
12 changed files with 440 additions and 755 deletions

View File

@@ -13,15 +13,40 @@ vi.mock("../media/image-ops.js", () => ({
import "./test-helpers/fast-core-tools.js";
import { createOpenClawTools } from "./openclaw-tools.js";
describe("nodes camera_snap", () => {
beforeEach(() => {
callGateway.mockReset();
});
const NODE_ID = "mac-1";
const BASE_RUN_INPUT = { action: "run", node: NODE_ID, command: ["echo", "hi"] } as const;
function unexpectedGatewayMethod(method: unknown): never {
throw new Error(`unexpected method: ${String(method)}`);
}
function getNodesTool() {
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
return tool;
}
async function executeNodes(input: Record<string, unknown>) {
return getNodesTool().execute("call1", input as never);
}
function mockNodeList(commands?: string[]) {
return {
nodes: [{ nodeId: NODE_ID, ...(commands ? { commands } : {}) }],
};
}
beforeEach(() => {
callGateway.mockReset();
});
describe("nodes camera_snap", () => {
it("maps jpg payloads to image/jpeg", async () => {
callGateway.mockImplementation(async ({ method }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1" }] };
return mockNodeList();
}
if (method === "node.invoke") {
return {
@@ -33,17 +58,12 @@ describe("nodes camera_snap", () => {
},
};
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
const result = await tool.execute("call1", {
const result = await executeNodes({
action: "camera_snap",
node: "mac-1",
node: NODE_ID,
facing: "front",
});
@@ -55,7 +75,7 @@ describe("nodes camera_snap", () => {
it("passes deviceId when provided", async () => {
callGateway.mockImplementation(async ({ method, params }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1" }] };
return mockNodeList();
}
if (method === "node.invoke") {
expect(params).toMatchObject({
@@ -71,17 +91,12 @@ describe("nodes camera_snap", () => {
},
};
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
await tool.execute("call1", {
await executeNodes({
action: "camera_snap",
node: "mac-1",
node: NODE_ID,
facing: "front",
deviceId: "cam-123",
});
@@ -89,18 +104,14 @@ describe("nodes camera_snap", () => {
});
describe("nodes run", () => {
beforeEach(() => {
callGateway.mockReset();
});
it("passes invoke and command timeouts", async () => {
callGateway.mockImplementation(async ({ method, params }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1", commands: ["system.run"] }] };
return mockNodeList(["system.run"]);
}
if (method === "node.invoke") {
expect(params).toMatchObject({
nodeId: "mac-1",
nodeId: NODE_ID,
command: "system.run",
timeoutMs: 45_000,
params: {
@@ -114,18 +125,11 @@ describe("nodes run", () => {
payload: { stdout: "", stderr: "", exitCode: 0, success: true },
};
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
await tool.execute("call1", {
action: "run",
node: "mac-1",
command: ["echo", "hi"],
await executeNodes({
...BASE_RUN_INPUT,
cwd: "/tmp",
env: ["FOO=bar"],
commandTimeoutMs: 12_000,
@@ -138,7 +142,7 @@ describe("nodes run", () => {
let approvalId: string | null = null;
callGateway.mockImplementation(async ({ method, params }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1", commands: ["system.run"] }] };
return mockNodeList(["system.run"]);
}
if (method === "node.invoke") {
invokeCalls += 1;
@@ -146,7 +150,7 @@ describe("nodes run", () => {
throw new Error("SYSTEM_RUN_DENIED: approval required");
}
expect(params).toMatchObject({
nodeId: "mac-1",
nodeId: NODE_ID,
command: "system.run",
params: {
command: ["echo", "hi"],
@@ -170,26 +174,17 @@ describe("nodes run", () => {
: null;
return { decision: "allow-once" };
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
await tool.execute("call1", {
action: "run",
node: "mac-1",
command: ["echo", "hi"],
});
await executeNodes(BASE_RUN_INPUT);
expect(invokeCalls).toBe(2);
});
it("fails with user denied when approval decision is deny", async () => {
callGateway.mockImplementation(async ({ method }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1", commands: ["system.run"] }] };
return mockNodeList(["system.run"]);
}
if (method === "node.invoke") {
throw new Error("SYSTEM_RUN_DENIED: approval required");
@@ -197,32 +192,16 @@ describe("nodes run", () => {
if (method === "exec.approval.request") {
return { decision: "deny" };
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
await expect(
tool.execute("call1", {
action: "run",
node: "mac-1",
command: ["echo", "hi"],
}),
).rejects.toThrow("exec denied: user denied");
await expect(executeNodes(BASE_RUN_INPUT)).rejects.toThrow("exec denied: user denied");
});
it("fails closed for timeout and invalid approval decisions", async () => {
const tool = createOpenClawTools().find((candidate) => candidate.name === "nodes");
if (!tool) {
throw new Error("missing nodes tool");
}
callGateway.mockImplementation(async ({ method }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1", commands: ["system.run"] }] };
return mockNodeList(["system.run"]);
}
if (method === "node.invoke") {
throw new Error("SYSTEM_RUN_DENIED: approval required");
@@ -230,19 +209,13 @@ describe("nodes run", () => {
if (method === "exec.approval.request") {
return {};
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
await expect(
tool.execute("call1", {
action: "run",
node: "mac-1",
command: ["echo", "hi"],
}),
).rejects.toThrow("exec denied: approval timed out");
await expect(executeNodes(BASE_RUN_INPUT)).rejects.toThrow("exec denied: approval timed out");
callGateway.mockImplementation(async ({ method }) => {
if (method === "node.list") {
return { nodes: [{ nodeId: "mac-1", commands: ["system.run"] }] };
return mockNodeList(["system.run"]);
}
if (method === "node.invoke") {
throw new Error("SYSTEM_RUN_DENIED: approval required");
@@ -250,14 +223,10 @@ describe("nodes run", () => {
if (method === "exec.approval.request") {
return { decision: "allow-never" };
}
throw new Error(`unexpected method: ${String(method)}`);
return unexpectedGatewayMethod(method);
});
await expect(
tool.execute("call1", {
action: "run",
node: "mac-1",
command: ["echo", "hi"],
}),
).rejects.toThrow("exec denied: invalid approval decision");
await expect(executeNodes(BASE_RUN_INPUT)).rejects.toThrow(
"exec denied: invalid approval decision",
);
});
});