mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 17:38:27 +00:00
refactor(test): share cron service fixtures
This commit is contained in:
@@ -1,38 +1,17 @@
|
|||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import os from "node:os";
|
|
||||||
import path from "node:path";
|
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 type { CronEvent } from "./service.js";
|
||||||
import { CronService } from "./service.js";
|
import { CronService } from "./service.js";
|
||||||
|
import {
|
||||||
|
createCronStoreHarness,
|
||||||
|
createNoopLogger,
|
||||||
|
installCronTestHooks,
|
||||||
|
} from "./service.test-harness.js";
|
||||||
|
|
||||||
const noopLogger = {
|
const noopLogger = createNoopLogger();
|
||||||
debug: vi.fn(),
|
const { makeStorePath } = createCronStoreHarness();
|
||||||
info: vi.fn(),
|
installCronTestHooks({ logger: noopLogger });
|
||||||
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 () => {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createFinishedBarrier() {
|
function createFinishedBarrier() {
|
||||||
const resolvers = new Map<string, (evt: CronEvent) => void>();
|
const resolvers = new Map<string, (evt: CronEvent) => void>();
|
||||||
@@ -56,19 +35,6 @@ function createFinishedBarrier() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("CronService interval/cron jobs fire on time", () => {
|
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 () => {
|
it("fires an every-type main job when the timer fires a few ms late", async () => {
|
||||||
const store = await makeStorePath();
|
const store = await makeStorePath();
|
||||||
const enqueueSystemEvent = vi.fn();
|
const enqueueSystemEvent = vi.fn();
|
||||||
|
|||||||
@@ -1,39 +1,18 @@
|
|||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import os from "node:os";
|
|
||||||
import path from "node:path";
|
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 { HeartbeatRunResult } from "../infra/heartbeat-wake.js";
|
||||||
import type { CronJob } from "./types.js";
|
import type { CronJob } from "./types.js";
|
||||||
import { CronService } from "./service.js";
|
import { CronService } from "./service.js";
|
||||||
|
import {
|
||||||
|
createCronStoreHarness,
|
||||||
|
createNoopLogger,
|
||||||
|
installCronTestHooks,
|
||||||
|
} from "./service.test-harness.js";
|
||||||
|
|
||||||
const noopLogger = {
|
const noopLogger = createNoopLogger();
|
||||||
debug: vi.fn(),
|
const { makeStorePath } = createCronStoreHarness();
|
||||||
info: vi.fn(),
|
installCronTestHooks({ logger: noopLogger });
|
||||||
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 () => {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitForJobs(cron: CronService, predicate: (jobs: CronJob[]) => boolean) {
|
async function waitForJobs(cron: CronService, predicate: (jobs: CronJob[]) => boolean) {
|
||||||
let latest: CronJob[] = [];
|
let latest: CronJob[] = [];
|
||||||
@@ -48,19 +27,6 @@ async function waitForJobs(cron: CronService, predicate: (jobs: CronJob[]) => bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("CronService", () => {
|
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 () => {
|
it("runs a one-shot main job and disables it after success when requested", async () => {
|
||||||
const store = await makeStorePath();
|
const store = await makeStorePath();
|
||||||
const enqueueSystemEvent = vi.fn();
|
const enqueueSystemEvent = vi.fn();
|
||||||
|
|||||||
58
src/cron/service.test-harness.ts
Normal file
58
src/cron/service.test-harness.ts
Normal file
@@ -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<typeof createNoopLogger>;
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user