test: tighten cron timer assertions

This commit is contained in:
Peter Steinberger
2026-05-10 23:45:58 +01:00
parent de1ef3c6bb
commit c8f0d8911f

View File

@@ -49,6 +49,19 @@ function requireTimestamp(value: number | undefined, label: string): number {
return value;
}
function requireRecord(value: unknown): Record<string, unknown> {
expect(value).toBeTruthy();
expect(typeof value).toBe("object");
expect(Array.isArray(value)).toBe(false);
return value as Record<string, unknown>;
}
function firstMockArg(mock: unknown): unknown {
const calls = (mock as { mock: { calls: readonly (readonly unknown[])[] } }).mock.calls;
expect(calls[0]).toBeTruthy();
return calls[0]?.[0];
}
describe("cron service timer regressions", () => {
it("caps timer delay to 60s for far-future schedules", async () => {
const timeoutSpy = vi.spyOn(globalThis, "setTimeout");
@@ -101,7 +114,7 @@ describe("cron service timer regressions", () => {
await onTimer(state);
expect(timeoutSpy).toHaveBeenCalled();
expect(state.timer).toEqual(expect.anything());
expect(state.timer).toBeTruthy();
const delays = timeoutSpy.mock.calls
.map(([, delay]) => delay)
.filter((d): d is number => typeof d === "number");
@@ -1124,24 +1137,26 @@ describe("cron service timer regressions", () => {
await onTimer(state);
expect(state.store?.jobs).toStrictEqual([]);
expect(log.warn).not.toHaveBeenCalledWith(
expect.anything(),
"cron: applyOutcomeToStoredJob — job not found after forceReload, result discarded",
);
expect(
log.warn.mock.calls.some(
([, message]) =>
message ===
"cron: applyOutcomeToStoredJob — job not found after forceReload, result discarded",
),
).toBe(false);
expect(log.info).toHaveBeenCalledWith(
{ jobId: selfRemovingJob.id },
"cron: finalized successful run after job was removed during execution",
);
expect(events).toContainEqual(
expect.objectContaining({
jobId: selfRemovingJob.id,
action: "finished",
status: "ok",
summary: `finished ${selfRemovingJob.id}`,
delivered: true,
deliveryStatus: "delivered",
}),
const event = events.find(
(candidate) => candidate.jobId === selfRemovingJob.id && candidate.action === "finished",
);
expect(event).toBeTruthy();
expect(event?.action).toBe("finished");
expect(event?.status).toBe("ok");
expect(event?.summary).toBe(`finished ${selfRemovingJob.id}`);
expect(event?.delivered).toBe(true);
expect(event?.deliveryStatus).toBe("delivered");
});
it("keeps missing-job discard semantics for failed isolated outcomes", async () => {
@@ -1335,15 +1350,15 @@ describe("cron service timer regressions", () => {
await timerPromise;
expect(abortObserved).toBe(true);
expect(cleanupTimedOutAgentRun).toHaveBeenCalledWith({
job: expect.objectContaining({ id: "timeout-cleanup-stuck-run" }),
timeoutMs: 1_000,
execution: {
jobId: "timeout-cleanup-stuck-run",
agentId: "main",
sessionId: "cron-run-session",
sessionKey: "agent:main:cron:timeout-cleanup-stuck-run:run:cron-run-session",
},
expect(cleanupTimedOutAgentRun).toHaveBeenCalledTimes(1);
const cleanupArgs = requireRecord(firstMockArg(cleanupTimedOutAgentRun));
expect(requireRecord(cleanupArgs.job).id).toBe("timeout-cleanup-stuck-run");
expect(cleanupArgs.timeoutMs).toBe(1_000);
expect(cleanupArgs.execution).toEqual({
jobId: "timeout-cleanup-stuck-run",
agentId: "main",
sessionId: "cron-run-session",
sessionKey: "agent:main:cron:timeout-cleanup-stuck-run:run:cron-run-session",
});
const job = state.store?.jobs.find((entry) => entry.id === "timeout-cleanup-stuck-run");
expect(job?.state.lastStatus).toBe("error");
@@ -1404,11 +1419,11 @@ describe("cron service timer regressions", () => {
expect(abortObserved).toBe(true);
expect(job.state.lastStatus).toBe("error");
expect(job.state.lastError).toContain("setup timed out before runner start");
expect(cleanupTimedOutAgentRun).toHaveBeenCalledWith({
job: expect.objectContaining({ id: "isolated-setup-timeout-74803" }),
timeoutMs: 120_000,
execution: undefined,
});
expect(cleanupTimedOutAgentRun).toHaveBeenCalledTimes(1);
const cleanupArgs = requireRecord(firstMockArg(cleanupTimedOutAgentRun));
expect(requireRecord(cleanupArgs.job).id).toBe("isolated-setup-timeout-74803");
expect(cleanupArgs.timeoutMs).toBe(120_000);
expect(cleanupArgs.execution).toBeUndefined();
} finally {
vi.useRealTimers();
}
@@ -1490,14 +1505,13 @@ describe("cron service timer regressions", () => {
expect(job.state.lastStatus).toBe("error");
expect(job.state.lastError).toContain("stalled before first model call");
expect(job.state.lastError).toContain("context-engine");
expect(cleanupTimedOutAgentRun).toHaveBeenCalledWith({
job: expect.objectContaining({ id: "isolated-pre-model-timeout-74803" }),
timeoutMs: 1_200_000,
execution: expect.objectContaining({
jobId: "isolated-pre-model-timeout-74803",
phase: "context_engine",
}),
});
expect(cleanupTimedOutAgentRun).toHaveBeenCalledTimes(1);
const cleanupArgs = requireRecord(firstMockArg(cleanupTimedOutAgentRun));
expect(requireRecord(cleanupArgs.job).id).toBe("isolated-pre-model-timeout-74803");
expect(cleanupArgs.timeoutMs).toBe(1_200_000);
const execution = requireRecord(cleanupArgs.execution);
expect(execution.jobId).toBe("isolated-pre-model-timeout-74803");
expect(execution.phase).toBe("context_engine");
} finally {
vi.useRealTimers();
}
@@ -1741,10 +1755,16 @@ describe("cron service timer regressions", () => {
endedAt,
});
expect(job.state.lastDiagnostics).toMatchObject({
summary: "exec stderr tail",
entries: [{ source: "exec", severity: "error", message: "exec stderr tail", exitCode: 1 }],
});
expect(job.state.lastDiagnostics?.summary).toBe("exec stderr tail");
expect(job.state.lastDiagnostics?.entries).toEqual([
{
ts: startedAt,
source: "exec",
severity: "error",
message: "exec stderr tail",
exitCode: 1,
},
]);
expect(job.state.lastDiagnosticSummary).toBe("exec stderr tail");
expect(log.warn).toHaveBeenCalledWith(
{