test: guard agent four-hit mock calls

This commit is contained in:
Peter Steinberger
2026-05-12 09:34:09 +01:00
parent dda4632d38
commit 2afca35577
6 changed files with 41 additions and 24 deletions

View File

@@ -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);

View File

@@ -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)");
});

View File

@@ -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"]);

View File

@@ -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");

View File

@@ -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",

View File

@@ -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];