From 0a758dc7105a737e0c5b485c1a3c155c8ead9409 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Feb 2026 11:29:15 +0000 Subject: [PATCH] test(cron): improve fire-and-forget harness coverage --- src/cron/service.every-jobs-fire.test.ts | 66 ++++++++----------- src/cron/service.read-ops-nonblocking.test.ts | 42 ++++++------ src/cron/service.test-harness.ts | 16 +++++ 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/src/cron/service.every-jobs-fire.test.ts b/src/cron/service.every-jobs-fire.test.ts index f1ef2d9eeb4..fa7b53e5986 100644 --- a/src/cron/service.every-jobs-fire.test.ts +++ b/src/cron/service.every-jobs-fire.test.ts @@ -1,5 +1,3 @@ -import fs from "node:fs/promises"; -import path from "node:path"; import { describe, expect, it, vi } from "vitest"; import { CronService } from "./service.js"; import { @@ -7,6 +5,7 @@ import { createCronStoreHarness, createNoopLogger, installCronTestHooks, + writeCronStoreSnapshot, } from "./service.test-harness.js"; const noopLogger = createNoopLogger(); @@ -120,44 +119,35 @@ describe("CronService interval/cron jobs fire on time", () => { const requestHeartbeatNow = vi.fn(); const nowMs = Date.parse("2025-12-13T00:00:00.000Z"); - await fs.mkdir(path.dirname(store.storePath), { recursive: true }); - await fs.writeFile( - store.storePath, - JSON.stringify( + await writeCronStoreSnapshot({ + storePath: store.storePath, + jobs: [ { - version: 1, - jobs: [ - { - id: "legacy-every", - name: "legacy every", - enabled: true, - createdAtMs: nowMs, - updatedAtMs: nowMs, - schedule: { kind: "every", everyMs: 120_000 }, - sessionTarget: "main", - wakeMode: "now", - payload: { kind: "systemEvent", text: "sf-tick" }, - state: { nextRunAtMs: nowMs + 120_000 }, - }, - { - id: "minute-cron", - name: "minute cron", - enabled: true, - createdAtMs: nowMs, - updatedAtMs: nowMs, - schedule: { kind: "cron", expr: "* * * * *", tz: "UTC" }, - sessionTarget: "main", - wakeMode: "now", - payload: { kind: "systemEvent", text: "minute-tick" }, - state: { nextRunAtMs: nowMs + 60_000 }, - }, - ], + id: "legacy-every", + name: "legacy every", + enabled: true, + createdAtMs: nowMs, + updatedAtMs: nowMs, + schedule: { kind: "every", everyMs: 120_000 }, + sessionTarget: "main", + wakeMode: "now", + payload: { kind: "systemEvent", text: "sf-tick" }, + state: { nextRunAtMs: nowMs + 120_000 }, }, - null, - 2, - ), - "utf-8", - ); + { + id: "minute-cron", + name: "minute cron", + enabled: true, + createdAtMs: nowMs, + updatedAtMs: nowMs, + schedule: { kind: "cron", expr: "* * * * *", tz: "UTC" }, + sessionTarget: "main", + wakeMode: "now", + payload: { kind: "systemEvent", text: "minute-tick" }, + state: { nextRunAtMs: nowMs + 60_000 }, + }, + ], + }); const cron = new CronService({ storePath: store.storePath, diff --git a/src/cron/service.read-ops-nonblocking.test.ts b/src/cron/service.read-ops-nonblocking.test.ts index 120061de448..e6a24957a79 100644 --- a/src/cron/service.read-ops-nonblocking.test.ts +++ b/src/cron/service.read-ops-nonblocking.test.ts @@ -3,6 +3,7 @@ import os from "node:os"; import path from "node:path"; import { describe, expect, it, vi } from "vitest"; import { CronService } from "./service.js"; +import { writeCronStoreSnapshot } from "./service.test-harness.js"; const noopLogger = { debug: vi.fn(), @@ -167,29 +168,24 @@ describe("CronService read ops while job is running", () => { const requestHeartbeatNow = vi.fn(); const nowMs = Date.parse("2025-12-13T00:00:00.000Z"); - await fs.mkdir(path.dirname(store.storePath), { recursive: true }); - await fs.writeFile( - store.storePath, - JSON.stringify({ - version: 1, - jobs: [ - { - id: "startup-catchup", - name: "startup catch-up", - enabled: true, - createdAtMs: nowMs - 86_400_000, - updatedAtMs: nowMs - 86_400_000, - schedule: { kind: "at", at: new Date(nowMs - 60_000).toISOString() }, - sessionTarget: "isolated", - wakeMode: "next-heartbeat", - payload: { kind: "agentTurn", message: "startup replay" }, - delivery: { mode: "none" }, - state: { nextRunAtMs: nowMs - 60_000 }, - }, - ], - }), - "utf-8", - ); + await writeCronStoreSnapshot({ + storePath: store.storePath, + jobs: [ + { + id: "startup-catchup", + name: "startup catch-up", + enabled: true, + createdAtMs: nowMs - 86_400_000, + updatedAtMs: nowMs - 86_400_000, + schedule: { kind: "at", at: new Date(nowMs - 60_000).toISOString() }, + sessionTarget: "isolated", + wakeMode: "next-heartbeat", + payload: { kind: "agentTurn", message: "startup replay" }, + delivery: { mode: "none" }, + state: { nextRunAtMs: nowMs - 60_000 }, + }, + ], + }); const isolatedRun = createDeferredIsolatedRun(); diff --git a/src/cron/service.test-harness.ts b/src/cron/service.test-harness.ts index 641f8fd3a96..5ed45e33761 100644 --- a/src/cron/service.test-harness.ts +++ b/src/cron/service.test-harness.ts @@ -51,6 +51,22 @@ export function createCronStoreHarness(options?: { prefix?: string }) { return { makeStorePath }; } +export async function writeCronStoreSnapshot(params: { storePath: string; jobs: CronJob[] }) { + await fs.mkdir(path.dirname(params.storePath), { recursive: true }); + await fs.writeFile( + params.storePath, + JSON.stringify( + { + version: 1, + jobs: params.jobs, + }, + null, + 2, + ), + "utf-8", + ); +} + export function installCronTestHooks(options: { logger: ReturnType; baseTimeIso?: string;