/** * DST-guard and date-math checks with fixed instants — the acceptance proof * that the double crons fire exactly once at 8 AM ET (digest) and midnight * Saturday ET (review issue) on BOTH UTC offsets. */ import { describe, expect, test } from "bun:test"; import { addDays, campaignDay, campaignWeek, etDate, etHour, isoWeek, rng, sample, weekdayOf } from "./srs.ts"; describe("DST-proof cron guard", () => { test("digest fires only at ET hour 8 — EDT (UTC-4)", () => { // Cron pair 12:00 / 13:00 UTC during EDT (2026-08-29 is EDT). expect(etHour(new Date("2026-08-29T12:00:00Z"))).toBe(8); // fires expect(etHour(new Date("2026-08-29T13:00:00Z"))).toBe(9); // no-op }); test("digest fires only at ET hour 8 — EST (UTC-5)", () => { // DST ends 2026-11-01; 2026-11-05 is EST. expect(etHour(new Date("2026-11-05T12:00:00Z"))).toBe(7); // no-op expect(etHour(new Date("2026-11-05T13:00:00Z"))).toBe(8); // fires }); test("saturday review fires only at ET midnight — both offsets", () => { // EDT Saturday: 4 UTC = 0 ET fires, 5 UTC = 1 ET no-op. expect(etHour(new Date("2026-08-29T04:00:00Z"))).toBe(0); expect(weekdayOf(etDate(new Date("2026-08-29T04:00:00Z")))).toBe(6); expect(etHour(new Date("2026-08-29T05:00:00Z"))).toBe(1); // EST Saturday (2026-11-07): 5 UTC = 0 ET fires, 4 UTC = 11 PM FRIDAY ET. expect(etHour(new Date("2026-11-07T05:00:00Z"))).toBe(0); expect(weekdayOf(etDate(new Date("2026-11-07T05:00:00Z")))).toBe(6); expect(etHour(new Date("2026-11-07T04:00:00Z"))).toBe(23); expect(etDate(new Date("2026-11-07T04:00:00Z"))).toBe("2026-11-06"); // still Friday ET }); }); describe("date math (noon-UTC anchored)", () => { test("addDays crosses the DST-end boundary without drift", () => { expect(addDays("2026-10-31", 2)).toBe("2026-11-02"); expect(addDays("2026-08-24", 2)).toBe("2026-08-26"); }); test("campaign math", () => { expect(campaignDay("2026-08-17")).toBe(1); expect(campaignDay("2026-08-24")).toBe(8); expect(campaignWeek("2026-08-24")).toBe(2); expect(campaignWeek("2026-08-30")).toBe(2); expect(campaignWeek("2026-08-31")).toBe(3); }); test("iso week is stable across a week", () => { expect(isoWeek("2026-08-24")).toBe(isoWeek("2026-08-29")); expect(isoWeek("2026-08-30")).toBe(isoWeek("2026-08-24")); // Sun ends the ISO week expect(isoWeek("2026-08-31")).toBe(isoWeek("2026-08-24") + 1); }); }); describe("deterministic sampling", () => { test("same seed, same picks", () => { const pool = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; expect(sample(pool, 3, rng("drill-2026-08-31"))).toEqual(sample(pool, 3, rng("drill-2026-08-31"))); expect(sample(pool, 3, rng("drill-2026-09-01"))).not.toEqual(sample(pool, 3, rng("drill-2026-08-31"))); }); });