test(cron): clean per-case SQLite stores (#113004)

* test(cron): clean per-case SQLite stores

* style(cron): iterate tracked stores directly
This commit is contained in:
Peter Steinberger
2026-07-23 08:52:56 -04:00
committed by GitHub
parent 525a7f4c96
commit 1fdef60392
2 changed files with 71 additions and 2 deletions
+48
View File
@@ -0,0 +1,48 @@
// Cron service harness tests cover per-case SQLite and filesystem cleanup.
import { describe, expect, it } from "vitest";
import { createCronStoreHarness, writeCronStoreSnapshot } from "./service.test-harness.js";
import { loadCronStore } from "./store.js";
const { makeStorePath } = createCronStoreHarness({ prefix: "openclaw-cron-harness-" });
let previousStorePath: string | undefined;
function testJob() {
return {
id: "job-1",
name: "Test job",
enabled: true,
createdAtMs: 1,
updatedAtMs: 1,
schedule: { kind: "every" as const, everyMs: 60_000 },
sessionTarget: "main" as const,
wakeMode: "next-heartbeat" as const,
payload: { kind: "systemEvent" as const, text: "tick" },
state: {},
};
}
describe("createCronStoreHarness", () => {
it("tracks stores that callers do not explicitly clean", async () => {
const store = await makeStorePath();
previousStorePath = store.storePath;
await writeCronStoreSnapshot({ storePath: store.storePath, jobs: [testJob()] });
expect((await loadCronStore(store.storePath)).jobs).toHaveLength(1);
});
it("clears tracked SQLite rows after each test", async () => {
if (!previousStorePath) {
throw new Error("expected previous test store path");
}
expect((await loadCronStore(previousStorePath)).jobs).toEqual([]);
});
it("supports explicit idempotent cleanup", async () => {
const store = await makeStorePath();
await writeCronStoreSnapshot({ storePath: store.storePath, jobs: [testJob()] });
await store.cleanup();
await store.cleanup();
expect((await loadCronStore(store.storePath)).jobs).toEqual([]);
});
});
+23 -2
View File
@@ -30,12 +30,31 @@ export function createNoopLogger(): NoopLogger {
export function createCronStoreHarness(options?: { prefix?: string }) {
let fixtureRoot = "";
let caseId = 0;
const stores = new Map<string, string>();
beforeAll(async () => {
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), options?.prefix ?? "openclaw-cron-"));
});
async function cleanupStore(storePath: string, dir: string) {
if (!stores.has(storePath)) {
return;
}
await saveCronStore(storePath, { version: 1, jobs: [] });
await fs.rm(dir, { recursive: true, force: true });
stores.delete(storePath);
}
afterEach(async () => {
for (const [storePath, dir] of stores) {
await cleanupStore(storePath, dir);
}
});
afterAll(async () => {
for (const [storePath, dir] of stores) {
await cleanupStore(storePath, dir);
}
if (!fixtureRoot) {
return;
}
@@ -45,9 +64,11 @@ export function createCronStoreHarness(options?: { prefix?: string }) {
async function makeStorePath() {
const dir = path.join(fixtureRoot, `case-${caseId++}`);
await fs.mkdir(dir, { recursive: true });
const storePath = path.join(dir, "cron", "jobs.json");
stores.set(storePath, dir);
return {
storePath: path.join(dir, "cron", "jobs.json"),
cleanup: async () => {},
storePath,
cleanup: async () => await cleanupStore(storePath, dir),
};
}