import assert from "node:assert/strict" import { test } from "node:test" import { parseSchedulerRunSnapshot } from "./scheduler-run-snapshot" const snapshot = { v: 1, job: "backups", sampledAt: "2026-10-01T00:00:00Z", due: true, created: 2, failures: 0, pruned: 1, uploadFailures: 1, pruneFailures: 1, metadataError: "metadata unavailable", eventErrors: ["event unavailable"], errors: ["S3 unavailable"] } test("JSONB object and legacy JSON preserve the same snapshot and partial diagnostics", () => { assert.deepEqual(parseSchedulerRunSnapshot(snapshot), snapshot) assert.deepEqual(parseSchedulerRunSnapshot(JSON.stringify(snapshot)), snapshot) }) test("missing, primitive, broken and future snapshots never throw or become valid empty data", () => { for (const raw of [undefined, null, "", " ", "{", 1, false, [], "null", { ...snapshot, v: 2 }, { ...snapshot, job: "unknown" }, { ...snapshot, sampledAt: "bad" }]) assert.equal(parseSchedulerRunSnapshot(raw), null) }) test("invalid backup counts, flags and diagnostic fields are rejected without zero substitution", () => { for (const patch of [{ created: -1 }, { failures: "0" }, { pruned: 1.5 }, { created: undefined }, { due: undefined }, { skipped: "true" }, { errors: [{}] }, { eventErrors: [null] }, { metadataError: {} }, { uploadFailures: -1 }]) assert.equal(parseSchedulerRunSnapshot({ ...snapshot, ...patch }), null) }) test("other collector envelopes support both representations and keep missing arrays unknown", () => { for (const job of ["traffic", "uptime_resources", "servers_rest_ping", "uptime_ping", "uptime_speed"]) { const key = job === "uptime_ping" ? "probes" : job === "uptime_speed" ? "runs" : "servers" const value = { v: 1, job, sampledAt: snapshot.sampledAt, [key]: [] } assert.deepEqual(parseSchedulerRunSnapshot(value), value); assert.deepEqual(parseSchedulerRunSnapshot(JSON.stringify(value)), value) assert.equal(parseSchedulerRunSnapshot({ ...value, [key]: undefined }), null) } })