mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-25 06:23:03 +00:00
test: guard agent four-hit mock calls
This commit is contained in:
@@ -395,7 +395,7 @@ describe("wrapStreamFnWithDiagnosticModelCallEvents", () => {
|
||||
"model.call.started",
|
||||
"model.call.completed",
|
||||
]);
|
||||
const startedEvent = requireRecord(started.mock.calls[0]?.[0], "started hook event");
|
||||
const startedEvent = requireRecord(started.mock.calls.at(0)?.[0], "started hook event");
|
||||
expect(startedEvent.runId).toBe("run-1");
|
||||
expect(startedEvent.callId).toBe("call-hook");
|
||||
expect(startedEvent.sessionKey).toBe("session-key");
|
||||
@@ -404,20 +404,20 @@ describe("wrapStreamFnWithDiagnosticModelCallEvents", () => {
|
||||
expect(startedEvent.model).toBe("gpt-5.4");
|
||||
expect(startedEvent.api).toBe("openai-responses");
|
||||
expect(startedEvent.transport).toBe("http");
|
||||
const startedCtx = requireRecord(started.mock.calls[0]?.[1], "started hook context");
|
||||
const startedCtx = requireRecord(started.mock.calls.at(0)?.[1], "started hook context");
|
||||
expect(startedCtx.runId).toBe("run-1");
|
||||
expect(startedCtx.sessionKey).toBe("session-key");
|
||||
expect(startedCtx.sessionId).toBe("session-id");
|
||||
expect(startedCtx.modelProviderId).toBe("openai");
|
||||
expect(startedCtx.modelId).toBe("gpt-5.4");
|
||||
const endedEvent = requireRecord(ended.mock.calls[0]?.[0], "ended hook event");
|
||||
const endedEvent = requireRecord(ended.mock.calls.at(0)?.[0], "ended hook event");
|
||||
expect(endedEvent.runId).toBe("run-1");
|
||||
expect(endedEvent.callId).toBe("call-hook");
|
||||
expect(endedEvent.outcome).toBe("completed");
|
||||
expectNumberField(endedEvent, "durationMs");
|
||||
expectNumberField(endedEvent, "responseStreamBytes");
|
||||
expectNumberField(endedEvent, "timeToFirstByteMs");
|
||||
const endedCtx = requireRecord(ended.mock.calls[0]?.[1], "ended hook context");
|
||||
const endedCtx = requireRecord(ended.mock.calls.at(0)?.[1], "ended hook context");
|
||||
expect(endedCtx.runId).toBe("run-1");
|
||||
expect(Object.isFrozen(startedEvent)).toBe(true);
|
||||
expect(Object.isFrozen(startedCtx)).toBe(true);
|
||||
|
||||
@@ -93,7 +93,7 @@ describe("repairSessionFileIfNeeded", () => {
|
||||
expect(result.repaired).toBe(false);
|
||||
expect(result.reason).toBe("invalid session header");
|
||||
expect(warn).toHaveBeenCalledTimes(1);
|
||||
expect(warn.mock.calls[0]?.[0]).toContain("invalid session header");
|
||||
expect(warn.mock.calls.at(0)?.[0]).toContain("invalid session header");
|
||||
});
|
||||
|
||||
it("returns a detailed reason when read errors are not ENOENT", async () => {
|
||||
@@ -145,7 +145,7 @@ describe("repairSessionFileIfNeeded", () => {
|
||||
expect(result.rewrittenAssistantMessages).toBe(1);
|
||||
await expect(fs.readFile(requireBackupPath(result), "utf-8")).resolves.toBe(original);
|
||||
expect(debug).toHaveBeenCalledTimes(1);
|
||||
const debugMessage = debug.mock.calls[0]?.[0] as string;
|
||||
const debugMessage = debug.mock.calls.at(0)?.[0] as string;
|
||||
expect(debugMessage).toContain("rewrote 1 assistant message(s)");
|
||||
expect(debugMessage).not.toContain("dropped");
|
||||
|
||||
@@ -182,7 +182,7 @@ describe("repairSessionFileIfNeeded", () => {
|
||||
expect(result.repaired).toBe(true);
|
||||
expect(result.rewrittenUserMessages).toBe(1);
|
||||
expect(result.droppedBlankUserMessages).toBe(0);
|
||||
expect(debug.mock.calls[0]?.[0]).toContain("rewrote 1 user message(s)");
|
||||
expect(debug.mock.calls.at(0)?.[0]).toContain("rewrote 1 user message(s)");
|
||||
|
||||
const repaired = await fs.readFile(file, "utf-8");
|
||||
const repairedLines = repaired.trim().split("\n");
|
||||
@@ -279,7 +279,7 @@ describe("repairSessionFileIfNeeded", () => {
|
||||
expect(result.repaired).toBe(true);
|
||||
expect(result.droppedLines).toBe(1);
|
||||
expect(result.rewrittenAssistantMessages).toBe(1);
|
||||
const debugMessage = debug.mock.calls[0]?.[0] as string;
|
||||
const debugMessage = debug.mock.calls.at(0)?.[0] as string;
|
||||
expect(debugMessage).toContain("dropped 1 malformed line(s)");
|
||||
expect(debugMessage).toContain("rewrote 1 assistant message(s)");
|
||||
});
|
||||
|
||||
@@ -141,7 +141,7 @@ describe("skills-install fallback edge cases", () => {
|
||||
|
||||
expect(result.ok, testCase.label).toBe(false);
|
||||
testCase.assert(result);
|
||||
const sudoCall = runCommandWithTimeoutMock.mock.calls[0] as
|
||||
const sudoCall = runCommandWithTimeoutMock.mock.calls.at(0) as
|
||||
| [string[], { timeoutMs?: number }]
|
||||
| undefined;
|
||||
expect(sudoCall?.[0], testCase.label).toEqual(["sudo", "-n", "true"]);
|
||||
@@ -205,10 +205,10 @@ describe("skills-install fallback edge cases", () => {
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
const brewInstallCall = runCommandWithTimeoutMock.mock.calls[0] as
|
||||
const brewInstallCall = runCommandWithTimeoutMock.mock.calls.at(0) as
|
||||
| [string[], { timeoutMs?: number }]
|
||||
| undefined;
|
||||
const brewPrefixCall = runCommandWithTimeoutMock.mock.calls[1] as
|
||||
const brewPrefixCall = runCommandWithTimeoutMock.mock.calls.at(1) as
|
||||
| [string[], { timeoutMs?: number }]
|
||||
| undefined;
|
||||
expect(brewInstallCall?.[0]).toEqual(["/safe/homebrew/bin/brew", "install", "go"]);
|
||||
@@ -257,7 +257,7 @@ describe("skills-install fallback edge cases", () => {
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
const firstCall = runCommandWithTimeoutMock.mock.calls[0] as
|
||||
const firstCall = runCommandWithTimeoutMock.mock.calls.at(0) as
|
||||
| [string[], { timeoutMs?: number; env?: Record<string, string | undefined> }]
|
||||
| undefined;
|
||||
expect(firstCall?.[0]).toEqual(["uv", "tool", "install", "example-package"]);
|
||||
|
||||
@@ -369,7 +369,7 @@ describe("subagent announce seam flow", () => {
|
||||
});
|
||||
|
||||
expect(didAnnounce).toBe(true);
|
||||
const queuedCall = queueEmbeddedPiMessageWithOutcomeMock.mock.calls[0];
|
||||
const queuedCall = queueEmbeddedPiMessageWithOutcomeMock.mock.calls.at(0);
|
||||
expect(queuedCall?.[0]).toBe("session-origin-provider-steer");
|
||||
expect(queuedCall?.[1]).toContain("[Internal task completion event]");
|
||||
expect(queuedCall?.[1]).toContain("task: do thing");
|
||||
@@ -402,7 +402,7 @@ describe("subagent announce seam flow", () => {
|
||||
|
||||
expect(didAnnounce).toBe(true);
|
||||
expect(agentSpy).toHaveBeenCalledTimes(1);
|
||||
const agentCall = agentSpy.mock.calls[0]?.[0];
|
||||
const agentCall = agentSpy.mock.calls.at(0)?.[0];
|
||||
expect(agentCall?.method).toBe("agent");
|
||||
expect(agentCall?.params?.sessionKey).toBe("agent:main:main");
|
||||
expect(agentCall?.params?.deliver).toBe(false);
|
||||
@@ -435,7 +435,7 @@ describe("subagent announce seam flow", () => {
|
||||
|
||||
expect(didAnnounce).toBe(true);
|
||||
expect(agentSpy).toHaveBeenCalledTimes(1);
|
||||
const call = agentSpy.mock.calls[0]?.[0];
|
||||
const call = agentSpy.mock.calls.at(0)?.[0];
|
||||
const params = call?.params ?? {};
|
||||
expect(params.sessionKey).toBe("agent:main:subagent:orchestrator");
|
||||
expect(params.deliver).toBe(false);
|
||||
@@ -476,7 +476,7 @@ describe("subagent announce seam flow", () => {
|
||||
|
||||
expect(didAnnounce).toBe(true);
|
||||
expect(agentSpy).toHaveBeenCalledTimes(1);
|
||||
const agentCall = agentSpy.mock.calls[0]?.[0];
|
||||
const agentCall = agentSpy.mock.calls.at(0)?.[0];
|
||||
expect(agentCall?.params?.deliver).toBe(true);
|
||||
expect(agentCall?.params?.channel).toBe("telegram");
|
||||
expect(agentCall?.params?.accountId).toBe("bot-123");
|
||||
|
||||
@@ -91,7 +91,7 @@ async function expectSkippedRecovery(store: ReturnType<typeof sessions.loadSessi
|
||||
}
|
||||
|
||||
function getResumeMessage() {
|
||||
const call = vi.mocked(gateway.callGateway).mock.calls[0];
|
||||
const call = vi.mocked(gateway.callGateway).mock.calls.at(0);
|
||||
if (call === undefined) {
|
||||
throw new Error("expected resume gateway call");
|
||||
}
|
||||
@@ -150,7 +150,10 @@ describe("subagent-orphan-recovery", () => {
|
||||
|
||||
// Should have called callGateway to resume the session
|
||||
expect(gateway.callGateway).toHaveBeenCalledOnce();
|
||||
const callArgs = vi.mocked(gateway.callGateway).mock.calls[0];
|
||||
const callArgs = vi.mocked(gateway.callGateway).mock.calls.at(0);
|
||||
if (callArgs === undefined) {
|
||||
throw new Error("expected gateway resume call");
|
||||
}
|
||||
const opts = callArgs[0];
|
||||
expect(opts.method).toBe("agent");
|
||||
const params = opts.params as Record<string, unknown>;
|
||||
@@ -369,7 +372,14 @@ describe("subagent-orphan-recovery", () => {
|
||||
getActiveRuns: () => createActiveRuns(createTestRunRecord()),
|
||||
});
|
||||
|
||||
const [, updater] = vi.mocked(sessions.updateSessionStore).mock.calls[0];
|
||||
const updateCall = vi.mocked(sessions.updateSessionStore).mock.calls.at(0);
|
||||
if (updateCall === undefined) {
|
||||
throw new Error("expected update session store call");
|
||||
}
|
||||
const updater = updateCall[1];
|
||||
if (typeof updater !== "function") {
|
||||
throw new Error("expected update session store callback");
|
||||
}
|
||||
const mockStore: ReturnType<typeof sessions.loadSessionStore> = {
|
||||
"agent:main:subagent:test-session-1": {
|
||||
sessionId: "session-abc",
|
||||
@@ -414,7 +424,14 @@ describe("subagent-orphan-recovery", () => {
|
||||
expect(gateway.callGateway).not.toHaveBeenCalled();
|
||||
expect(sessions.updateSessionStore).toHaveBeenCalledOnce();
|
||||
|
||||
const [, updater] = vi.mocked(sessions.updateSessionStore).mock.calls[0];
|
||||
const updateCall = vi.mocked(sessions.updateSessionStore).mock.calls.at(0);
|
||||
if (updateCall === undefined) {
|
||||
throw new Error("expected update session store call");
|
||||
}
|
||||
const updater = updateCall[1];
|
||||
if (typeof updater !== "function") {
|
||||
throw new Error("expected update session store callback");
|
||||
}
|
||||
const mockStore: ReturnType<typeof sessions.loadSessionStore> = {
|
||||
"agent:main:subagent:test-session-1": {
|
||||
sessionId: "session-abc",
|
||||
|
||||
@@ -103,7 +103,7 @@ function requireSubagentEndedHookCall(runId: string): {
|
||||
}
|
||||
|
||||
function requireSessionLifecycleEventCall(label: string): Record<string, unknown> {
|
||||
const call = emitSessionLifecycleEventMock.mock.calls[0];
|
||||
const call = emitSessionLifecycleEventMock.mock.calls.at(0);
|
||||
if (!call) {
|
||||
throw new Error(`expected ${label}`);
|
||||
}
|
||||
@@ -332,7 +332,7 @@ describe("subagent registry steer restarts", () => {
|
||||
expect(hookCall.event.runId).toBe("run-new");
|
||||
expect(hookCall.ctx.runId).toBe("run-new");
|
||||
|
||||
const announce = (announceSpy.mock.calls[0]?.[0] ?? {}) as { childRunId?: string };
|
||||
const announce = (announceSpy.mock.calls.at(0)?.[0] ?? {}) as { childRunId?: string };
|
||||
expect(announce.childRunId).toBe("run-new");
|
||||
}
|
||||
});
|
||||
@@ -572,7 +572,7 @@ describe("subagent registry steer restarts", () => {
|
||||
await flushAnnounce();
|
||||
|
||||
expect(announceSpy).toHaveBeenCalledTimes(1);
|
||||
const announce = (announceSpy.mock.calls[0]?.[0] ?? {}) as { childRunId?: string };
|
||||
const announce = (announceSpy.mock.calls.at(0)?.[0] ?? {}) as { childRunId?: string };
|
||||
expect(announce.childRunId).toBe("run-failed-restart");
|
||||
});
|
||||
|
||||
@@ -668,7 +668,7 @@ describe("subagent registry steer restarts", () => {
|
||||
await flushAnnounce();
|
||||
|
||||
expect(announceSpy).toHaveBeenCalledTimes(1);
|
||||
const announce = (announceSpy.mock.calls[0]?.[0] ?? {}) as { childRunId?: string };
|
||||
const announce = (announceSpy.mock.calls.at(0)?.[0] ?? {}) as { childRunId?: string };
|
||||
expect(announce.childRunId).toBe("run-kill-race");
|
||||
|
||||
const run = listMainRuns()[0];
|
||||
|
||||
Reference in New Issue
Block a user