import { mkdtemp, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { DEMO_DEFAULT_JOBS, DEMO_DEFAULT_PIPELINE_RUNS, DEMO_DEFAULT_SETTINGS, DEMO_DEFAULT_STAGE_EVENTS, } from "@server/config/demo-defaults"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const originalEnv = { ...process.env }; function sortedPairs(map: Record) { return Object.entries(map).sort(([a], [b]) => a.localeCompare(b)); } describe.sequential("demo seed baseline", () => { let tempDir: string; let closeDb: (() => void) | null = null; beforeEach(async () => { vi.resetModules(); tempDir = await mkdtemp(join(tmpdir(), "job-ops-demo-seed-test-")); process.env = { ...originalEnv, DATA_DIR: tempDir, NODE_ENV: "test", MODEL: "test-model", DEMO_MODE: "true", }; await import("../db/migrate"); const dbMod = await import("../db/index"); closeDb = dbMod.closeDb; }); afterEach(async () => { if (closeDb) closeDb(); await rm(tempDir, { recursive: true, force: true }); process.env = { ...originalEnv }; }); it("buildDemoBaseline returns deterministic, schema-shaped fixtures", async () => { const { buildDemoBaseline } = await import("./demo-seed"); const now = new Date("2026-02-05T12:00:00.000Z"); const baseline = buildDemoBaseline(now); expect(baseline.resetAt).toBe(now.toISOString()); expect(Object.keys(baseline.settings).length).toBeGreaterThan(0); expect(baseline.pipelineRuns).toHaveLength( DEMO_DEFAULT_PIPELINE_RUNS.length, ); expect(baseline.jobs).toHaveLength(DEMO_DEFAULT_JOBS.length); expect(baseline.stageEvents).toHaveLength(DEMO_DEFAULT_STAGE_EVENTS.length); const seededJobIds = baseline.jobs.map((job) => job.id).sort(); expect(seededJobIds).toEqual(DEMO_DEFAULT_JOBS.map((job) => job.id).sort()); }); it("resetDemoData restores settings and data to demo defaults", async () => { const { db, schema } = await import("../db/index"); const { resetDemoData } = await import("./demo-mode"); const { setSetting, getAllSettings } = await import( "../repositories/settings" ); await resetDemoData(); await db.delete(schema.jobs); await db.insert(schema.jobs).values({ id: "mutated-job", source: "manual", title: "Mutated Job", employer: "Mutated Employer", jobUrl: "https://demo.job-ops.local/jobs/mutated", status: "discovered", }); await setSetting("llmProvider", "openai"); await resetDemoData(); const allJobs = await db.select({ id: schema.jobs.id }).from(schema.jobs); expect(allJobs.map((row) => row.id).sort()).toEqual( DEMO_DEFAULT_JOBS.map((job) => job.id).sort(), ); const allSettings = (await getAllSettings()) as Record; expect(sortedPairs(allSettings)).toEqual( sortedPairs(DEMO_DEFAULT_SETTINGS as Record), ); }); it("reset is idempotent for logical baseline content", async () => { const { db, schema } = await import("../db/index"); const { resetDemoData } = await import("./demo-mode"); const logicalSnapshot = async () => { const [settingsRows, runRows, jobRows, stageRows] = await Promise.all([ db .select({ key: schema.settings.key, value: schema.settings.value }) .from(schema.settings), db .select({ id: schema.pipelineRuns.id, status: schema.pipelineRuns.status, jobsDiscovered: schema.pipelineRuns.jobsDiscovered, jobsProcessed: schema.pipelineRuns.jobsProcessed, errorMessage: schema.pipelineRuns.errorMessage, }) .from(schema.pipelineRuns), db .select({ id: schema.jobs.id, status: schema.jobs.status, source: schema.jobs.source, title: schema.jobs.title, employer: schema.jobs.employer, }) .from(schema.jobs), db .select({ id: schema.stageEvents.id, applicationId: schema.stageEvents.applicationId, fromStage: schema.stageEvents.fromStage, toStage: schema.stageEvents.toStage, title: schema.stageEvents.title, }) .from(schema.stageEvents), ]); return { settings: settingsRows.sort((a, b) => a.key.localeCompare(b.key)), runs: runRows.sort((a, b) => a.id.localeCompare(b.id)), jobs: jobRows.sort((a, b) => a.id.localeCompare(b.id)), stageEvents: stageRows.sort((a, b) => a.id.localeCompare(b.id)), }; }; await resetDemoData(); const first = await logicalSnapshot(); await resetDemoData(); const second = await logicalSnapshot(); expect(second).toEqual(first); }); });