import "../../setup.ts"; import { assert, assertEquals } from "@std/assert"; import { DatabaseSync } from "node:sqlite"; import { up as up0020 } from "../../../db/migrations/0020_digest_schedule.ts"; Deno.test("migration 0020 spreads existing users' first digests over the coming period", () => { const db = new DatabaseSync(":memory:"); db.exec(`CREATE TABLE users (id TEXT PRIMARY KEY);`); const ids = Array.from({ length: 40 }, () => crypto.randomUUID()); for (const id of ids) { db.prepare(`INSERT INTO users (id) VALUES (?);`).run(id); } const before = Date.now(); up0020(db); up0020(db); // idempotent const rows = db.prepare( `SELECT user_id, cadence, window_start FROM digest_schedule;`, ).all() as { user_id: string; cadence: string; window_start: string }[]; assertEquals(rows.length, 80); const due = (cadence: string, days: number) => rows.filter((r) => r.cadence === cadence).map((r) => new Date(r.window_start).getTime() + days * 86_400_000 ); for (const [cadence, days] of [["weekly", 7], ["monthly", 30]] as const) { const dues = due(cadence, days); // Each first digest falls due within the coming period, not all at once. assert( dues.every((t) => t >= before - 1000 && t <= Date.now() + days * 86_400_000 ), ); assert(new Set(dues.map((t) => Math.floor(t / 3_600_000))).size > 10); } db.close(); });