import { describe, expect, it, vi } from "vitest"; import { dispatchBackgroundJob, historyCompactJob, historyCompactJobKey, MEDIA_JOB_QUEUE, MEDIA_LIBRARY_JOB_QUEUE, mediaLibrarySyncJob, mediaLibrarySyncJobKey, mediaRunJob, mediaRunJobKey, messagingDeliverJob, parseBackgroundJob, profileConsolidateJob, profileConsolidateJobKey, } from "./background-jobs.js"; import type { BackgroundJobHandlers } from "./types.js"; function handlers(): BackgroundJobHandlers { return { "run.continue": vi.fn(async () => undefined), "routine.wakeup": vi.fn(async () => undefined), "computer.update": vi.fn(async () => undefined), "computer.sleep": vi.fn(async () => undefined), "computer.control-expire": vi.fn(async () => undefined), "skill.teaching-expire": vi.fn(async () => undefined), "history.compact": vi.fn(async () => undefined), "messaging.deliver": vi.fn(async () => undefined), "cloud_agent.poll": vi.fn(async () => undefined), "profile.consolidate": vi.fn(async () => undefined), "media.run": vi.fn(async () => undefined), "media.library.sync": vi.fn(async () => undefined), }; } describe("background job contracts", () => { it("validates and dispatches messaging.deliver", async () => { const target = handlers(); await dispatchBackgroundJob(target, "messaging.deliver", { runId: "run-1" }); expect(target["messaging.deliver"]).toHaveBeenCalledWith({ runId: "run-1" }); expect(messagingDeliverJob("run-1")).toEqual({ name: "messaging.deliver", payload: { runId: "run-1" }, replaceKey: "messaging.deliver:run-1", }); expect(messagingDeliverJob()).toEqual({ name: "messaging.deliver", payload: {}, replaceKey: "messaging.deliver:drain", }); }); it("validates and dispatches a typed job", async () => { const target = handlers(); await dispatchBackgroundJob(target, "routine.wakeup", { routineId: "routine-1", scheduledFor: "2026-08-15T12:00:00.000Z", }); expect(target["routine.wakeup"]).toHaveBeenCalledWith({ routineId: "routine-1", scheduledFor: "2026-08-15T12:00:00.000Z", }); }); it("rejects unknown names and malformed deliveries", () => { expect(() => parseBackgroundJob("unknown", {})).toThrow("Unknown background job"); expect(() => parseBackgroundJob("routine.wakeup", { routineId: "routine-1", scheduledFor: "not-a-date", }), ).toThrow(); expect(() => parseBackgroundJob("run.continue", { runId: "" })).toThrow(); expect(() => parseBackgroundJob("computer.control-expire", { computerId: "computer-1", leaseId: "", }), ).toThrow(); }); it("validates and dispatches a control-expiry job", async () => { const target = handlers(); await dispatchBackgroundJob(target, "computer.control-expire", { computerId: "computer-1", leaseId: "lease-1", }); expect(target["computer.control-expire"]).toHaveBeenCalledWith({ computerId: "computer-1", leaseId: "lease-1", }); }); }); describe("historyCompactJob", () => { it("builds a job with a replace key scoped to the thread", () => { expect(historyCompactJob("thread-1")).toEqual({ name: "history.compact", payload: { threadId: "thread-1" }, replaceKey: historyCompactJobKey("thread-1"), }); }); it("keys different threads differently", () => { expect(historyCompactJobKey("thread-1")).not.toBe(historyCompactJobKey("thread-2")); }); }); describe("profileConsolidateJob", () => { it("validates, dispatches, and keys one pending consolidation per user", async () => { const target = handlers(); await dispatchBackgroundJob(target, "profile.consolidate", { userId: "user-1" }); expect(target["profile.consolidate"]).toHaveBeenCalledWith({ userId: "user-1" }); expect(() => parseBackgroundJob("profile.consolidate", { userId: "" })).toThrow(); expect(profileConsolidateJob("user-1")).toEqual({ name: "profile.consolidate", payload: { userId: "user-1" }, replaceKey: profileConsolidateJobKey("user-1"), }); expect(profileConsolidateJobKey("user-1")).not.toBe(profileConsolidateJobKey("user-2")); }); }); describe("mediaRunJob", () => { it("validates, dispatches, and runs every media job on the shared media queue", async () => { const target = handlers(); await dispatchBackgroundJob(target, "media.run", { jobId: "job-1" }); expect(target["media.run"]).toHaveBeenCalledWith({ jobId: "job-1" }); expect(() => parseBackgroundJob("media.run", { jobId: "" })).toThrow(); expect(mediaRunJob("job-1")).toEqual({ name: "media.run", payload: { jobId: "job-1" }, replaceKey: mediaRunJobKey("job-1"), queue: MEDIA_JOB_QUEUE, }); const at = new Date("2026-10-03T12:00:00.000Z"); expect(mediaRunJob("job-1", at).availableAt).toBe(at); expect(mediaRunJobKey("job-1")).not.toBe(mediaRunJobKey("job-2")); }); }); describe("mediaLibrarySyncJob", () => { it("validates, dispatches, and keeps one pending sync per folder on the library queue", async () => { const target = handlers(); await dispatchBackgroundJob(target, "media.library.sync", { sourceId: "source-1" }); expect(target["media.library.sync"]).toHaveBeenCalledWith({ sourceId: "source-1" }); expect(() => parseBackgroundJob("media.library.sync", { sourceId: "" })).toThrow(); const at = new Date("2026-10-05T12:00:00.000Z"); expect(mediaLibrarySyncJob("source-1", at)).toEqual({ name: "media.library.sync", payload: { sourceId: "source-1" }, replaceKey: mediaLibrarySyncJobKey("source-1"), queue: MEDIA_LIBRARY_JOB_QUEUE, availableAt: at, }); expect(mediaLibrarySyncJob("source-1").availableAt).toBeUndefined(); }); });