From a6cd7ef49ca278bb8038d7f788917d2272956cf8 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 14 Feb 2026 23:18:17 +0000 Subject: [PATCH] refactor(test): share cron service fixtures --- src/cron/service.every-jobs-fire.test.ts | 52 +++-------------- ...runs-one-shot-main-job-disables-it.test.ts | 52 +++-------------- src/cron/service.test-harness.ts | 58 +++++++++++++++++++ 3 files changed, 76 insertions(+), 86 deletions(-) create mode 100644 src/cron/service.test-harness.ts diff --git a/src/cron/service.every-jobs-fire.test.ts b/src/cron/service.every-jobs-fire.test.ts index a861d597f..c67e3b8d3 100644 --- a/src/cron/service.every-jobs-fire.test.ts +++ b/src/cron/service.every-jobs-fire.test.ts @@ -1,38 +1,17 @@ import fs from "node:fs/promises"; -import os from "node:os"; import path from "node:path"; -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import type { CronEvent } from "./service.js"; import { CronService } from "./service.js"; +import { + createCronStoreHarness, + createNoopLogger, + installCronTestHooks, +} from "./service.test-harness.js"; -const noopLogger = { - debug: vi.fn(), - info: vi.fn(), - warn: vi.fn(), - error: vi.fn(), -}; - -let fixtureRoot = ""; -let caseId = 0; - -beforeAll(async () => { - fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cron-")); -}); - -afterAll(async () => { - if (fixtureRoot) { - await fs.rm(fixtureRoot, { recursive: true, force: true }); - } -}); - -async function makeStorePath() { - const dir = path.join(fixtureRoot, `case-${caseId++}`); - await fs.mkdir(dir, { recursive: true }); - return { - storePath: path.join(dir, "cron", "jobs.json"), - cleanup: async () => {}, - }; -} +const noopLogger = createNoopLogger(); +const { makeStorePath } = createCronStoreHarness(); +installCronTestHooks({ logger: noopLogger }); function createFinishedBarrier() { const resolvers = new Map void>(); @@ -56,19 +35,6 @@ function createFinishedBarrier() { } describe("CronService interval/cron jobs fire on time", () => { - beforeEach(() => { - vi.useFakeTimers(); - vi.setSystemTime(new Date("2025-12-13T00:00:00.000Z")); - noopLogger.debug.mockClear(); - noopLogger.info.mockClear(); - noopLogger.warn.mockClear(); - noopLogger.error.mockClear(); - }); - - afterEach(() => { - vi.useRealTimers(); - }); - it("fires an every-type main job when the timer fires a few ms late", async () => { const store = await makeStorePath(); const enqueueSystemEvent = vi.fn(); diff --git a/src/cron/service.runs-one-shot-main-job-disables-it.test.ts b/src/cron/service.runs-one-shot-main-job-disables-it.test.ts index 47c44af9e..738b6a356 100644 --- a/src/cron/service.runs-one-shot-main-job-disables-it.test.ts +++ b/src/cron/service.runs-one-shot-main-job-disables-it.test.ts @@ -1,39 +1,18 @@ import fs from "node:fs/promises"; -import os from "node:os"; import path from "node:path"; -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import type { HeartbeatRunResult } from "../infra/heartbeat-wake.js"; import type { CronJob } from "./types.js"; import { CronService } from "./service.js"; +import { + createCronStoreHarness, + createNoopLogger, + installCronTestHooks, +} from "./service.test-harness.js"; -const noopLogger = { - debug: vi.fn(), - info: vi.fn(), - warn: vi.fn(), - error: vi.fn(), -}; - -let fixtureRoot = ""; -let caseId = 0; - -beforeAll(async () => { - fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cron-")); -}); - -afterAll(async () => { - if (fixtureRoot) { - await fs.rm(fixtureRoot, { recursive: true, force: true }); - } -}); - -async function makeStorePath() { - const dir = path.join(fixtureRoot, `case-${caseId++}`); - await fs.mkdir(dir, { recursive: true }); - return { - storePath: path.join(dir, "cron", "jobs.json"), - cleanup: async () => {}, - }; -} +const noopLogger = createNoopLogger(); +const { makeStorePath } = createCronStoreHarness(); +installCronTestHooks({ logger: noopLogger }); async function waitForJobs(cron: CronService, predicate: (jobs: CronJob[]) => boolean) { let latest: CronJob[] = []; @@ -48,19 +27,6 @@ async function waitForJobs(cron: CronService, predicate: (jobs: CronJob[]) => bo } describe("CronService", () => { - beforeEach(() => { - vi.useFakeTimers(); - vi.setSystemTime(new Date("2025-12-13T00:00:00.000Z")); - noopLogger.debug.mockClear(); - noopLogger.info.mockClear(); - noopLogger.warn.mockClear(); - noopLogger.error.mockClear(); - }); - - afterEach(() => { - vi.useRealTimers(); - }); - it("runs a one-shot main job and disables it after success when requested", async () => { const store = await makeStorePath(); const enqueueSystemEvent = vi.fn(); diff --git a/src/cron/service.test-harness.ts b/src/cron/service.test-harness.ts new file mode 100644 index 000000000..d111a8c2e --- /dev/null +++ b/src/cron/service.test-harness.ts @@ -0,0 +1,58 @@ +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import { afterAll, afterEach, beforeAll, beforeEach, vi } from "vitest"; + +export function createNoopLogger() { + return { + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }; +} + +export function createCronStoreHarness(options?: { prefix?: string }) { + let fixtureRoot = ""; + let caseId = 0; + + beforeAll(async () => { + fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), options?.prefix ?? "openclaw-cron-")); + }); + + afterAll(async () => { + if (!fixtureRoot) { + return; + } + await fs.rm(fixtureRoot, { recursive: true, force: true }); + }); + + async function makeStorePath() { + const dir = path.join(fixtureRoot, `case-${caseId++}`); + await fs.mkdir(dir, { recursive: true }); + return { + storePath: path.join(dir, "cron", "jobs.json"), + cleanup: async () => {}, + }; + } + + return { makeStorePath }; +} + +export function installCronTestHooks(options: { + logger: ReturnType; + baseTimeIso?: string; +}) { + beforeEach(() => { + vi.useFakeTimers(); + vi.setSystemTime(new Date(options.baseTimeIso ?? "2025-12-13T00:00:00.000Z")); + options.logger.debug.mockClear(); + options.logger.info.mockClear(); + options.logger.warn.mockClear(); + options.logger.error.mockClear(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); +}