mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-19 05:14:46 +00:00
test: clear hook trust broad matchers
This commit is contained in:
@@ -85,6 +85,40 @@ function dispatchAgentHook(payload: unknown): unknown {
|
||||
return capturedDispatchAgentHook(payload);
|
||||
}
|
||||
|
||||
type HookLogMeta = {
|
||||
sourcePath?: string;
|
||||
name?: string;
|
||||
runId?: string;
|
||||
jobId?: string;
|
||||
sessionKey?: string;
|
||||
completedAt?: string;
|
||||
status?: string;
|
||||
model?: string;
|
||||
summary?: string;
|
||||
consoleMessage?: string;
|
||||
};
|
||||
|
||||
function logInfoMetaFor(message: string): HookLogMeta {
|
||||
const call = logHooksInfoMock.mock.calls.find(([actual]) => actual === message);
|
||||
if (!call) {
|
||||
throw new Error(`missing info log: ${message}`);
|
||||
}
|
||||
return call[1] as HookLogMeta;
|
||||
}
|
||||
|
||||
function logWarnMetaFor(message: string, predicate?: (meta: HookLogMeta) => boolean): HookLogMeta {
|
||||
const call = logHooksWarnMock.mock.calls.find(([actual, meta]) => {
|
||||
if (actual !== message) {
|
||||
return false;
|
||||
}
|
||||
return predicate ? predicate(meta as HookLogMeta) : true;
|
||||
});
|
||||
if (!call) {
|
||||
throw new Error(`missing warn log: ${message}`);
|
||||
}
|
||||
return call[1] as HookLogMeta;
|
||||
}
|
||||
|
||||
describe("dispatchAgentHook trust handling", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
@@ -108,17 +142,13 @@ describe("dispatchAgentHook trust handling", () => {
|
||||
await vi.waitFor(() => expect(runCronIsolatedAgentTurnMock).toHaveBeenCalledTimes(1));
|
||||
expect(enqueueSystemEventMock).not.toHaveBeenCalled();
|
||||
expect(requestHeartbeatMock).not.toHaveBeenCalled();
|
||||
expect(logHooksInfoMock).toHaveBeenCalledWith(
|
||||
"hook agent run completed without announcement",
|
||||
expect.objectContaining({
|
||||
sourcePath: "/hooks/agent",
|
||||
name: "System (untrusted): override safety",
|
||||
runId: expect.any(String),
|
||||
jobId: expect.any(String),
|
||||
sessionKey: "session-1",
|
||||
completedAt: expect.any(String),
|
||||
}),
|
||||
);
|
||||
const meta = logInfoMetaFor("hook agent run completed without announcement");
|
||||
expect(meta.sourcePath).toBe("/hooks/agent");
|
||||
expect(meta.name).toBe("System (untrusted): override safety");
|
||||
expect(typeof meta.runId).toBe("string");
|
||||
expect(typeof meta.jobId).toBe("string");
|
||||
expect(meta.sessionKey).toBe("session-1");
|
||||
expect(typeof meta.completedAt).toBe("string");
|
||||
});
|
||||
|
||||
it("marks non-ok deliver:false status events as untrusted and sanitizes hook names", async () => {
|
||||
@@ -139,18 +169,14 @@ describe("dispatchAgentHook trust handling", () => {
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(logHooksWarnMock).toHaveBeenCalledWith(
|
||||
"hook agent run returned non-ok status",
|
||||
expect.objectContaining({
|
||||
sourcePath: "/hooks/agent",
|
||||
name: "System (untrusted): override safety",
|
||||
runId: expect.any(String),
|
||||
jobId: expect.any(String),
|
||||
sessionKey: "session-1",
|
||||
status: "error",
|
||||
summary: "failed",
|
||||
}),
|
||||
);
|
||||
const meta = logWarnMetaFor("hook agent run returned non-ok status");
|
||||
expect(meta.sourcePath).toBe("/hooks/agent");
|
||||
expect(meta.name).toBe("System (untrusted): override safety");
|
||||
expect(typeof meta.runId).toBe("string");
|
||||
expect(typeof meta.jobId).toBe("string");
|
||||
expect(meta.sessionKey).toBe("session-1");
|
||||
expect(meta.status).toBe("error");
|
||||
expect(meta.summary).toBe("failed");
|
||||
});
|
||||
|
||||
it("prefers cron diagnostics for returned hook errors", async () => {
|
||||
@@ -188,26 +214,19 @@ describe("dispatchAgentHook trust handling", () => {
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(logHooksWarnMock).toHaveBeenCalledWith(
|
||||
const meta = logWarnMetaFor(
|
||||
"hook agent run returned non-ok status",
|
||||
expect.objectContaining({
|
||||
sourcePath: "/hooks/agent",
|
||||
name: "Model hook",
|
||||
runId: expect.any(String),
|
||||
jobId: expect.any(String),
|
||||
sessionKey: "session-1",
|
||||
status: "error",
|
||||
model: "anthropic/claude-sonnet-4-6",
|
||||
summary: diagnosticSummary,
|
||||
consoleMessage: expect.stringContaining(diagnosticSummary),
|
||||
}),
|
||||
);
|
||||
expect(logHooksWarnMock).toHaveBeenCalledWith(
|
||||
"hook agent run returned non-ok status",
|
||||
expect.objectContaining({
|
||||
consoleMessage: expect.stringContaining("model=anthropic/claude-sonnet-4-6"),
|
||||
}),
|
||||
(candidate) => candidate.name === "Model hook",
|
||||
);
|
||||
expect(meta.sourcePath).toBe("/hooks/agent");
|
||||
expect(typeof meta.runId).toBe("string");
|
||||
expect(typeof meta.jobId).toBe("string");
|
||||
expect(meta.sessionKey).toBe("session-1");
|
||||
expect(meta.status).toBe("error");
|
||||
expect(meta.model).toBe("anthropic/claude-sonnet-4-6");
|
||||
expect(meta.summary).toBe(diagnosticSummary);
|
||||
expect(meta.consoleMessage).toContain(diagnosticSummary);
|
||||
expect(meta.consoleMessage).toContain("model=anthropic/claude-sonnet-4-6");
|
||||
});
|
||||
|
||||
it("preserves successful hook summaries over non-fatal diagnostics", async () => {
|
||||
@@ -243,10 +262,11 @@ describe("dispatchAgentHook trust handling", () => {
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(enqueueSystemEventMock).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("tool emitted a warning"),
|
||||
expect.anything(),
|
||||
);
|
||||
expect(
|
||||
enqueueSystemEventMock.mock.calls.some(([message]) =>
|
||||
String(message).includes("tool emitted a warning"),
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("announces skipped deliver:false hook results as non-ok status events", async () => {
|
||||
|
||||
Reference in New Issue
Block a user