server/test/news.test.ts
33 lines · 1564 bytes
1import assert from "node:assert/strict";
2import { test } from "node:test";
3import { digestDue, digestPayload, localDate, pickHeadlines, type Article } from "../src/news.ts";
4
5test("digest is due in the first 10 minutes of 09:00 local", () => {
6 const at = (iso: string) => new Date(iso);
7 assert.equal(digestDue(at("2026-10-18T14:00:00Z"), -300), true); // 09:00 CDT
8 assert.equal(digestDue(at("2026-10-18T14:09:59Z"), -300), true);
9 assert.equal(digestDue(at("2026-10-18T14:10:00Z"), -300), false);
10 assert.equal(digestDue(at("2026-10-17T23:30:00Z"), 570), true); // 09:00 ACST, next day
11});
12
13test("local date follows the offset", () => {
14 assert.equal(localDate(new Date("2026-10-17T23:30:00Z"), 570), "2026-10-18");
15 assert.equal(localDate(new Date("2026-10-18T02:00:00Z"), -300), "2026-10-17");
16});
17
18test("picks three recent headlines from different sites, skipping APOD", () => {
19 const now = new Date("2026-10-18T16:00:00Z");
20 const a = (id: number, site: string, hoursAgo: number, title = `t${id}`): Article =>
21 ({ id, title, news_site: site, published_at: new Date(now.getTime() - hoursAgo * 3600_000).toISOString() });
22 const picked = pickHeadlines([
23 a(1, "NASA", 1, "APOD: 2026 October 18"),
24 a(2, "SpaceNews", 2),
25 a(3, "SpaceNews", 1.5),
26 a(4, "ESA", 5),
27 a(5, "NASA", 30),
28 a(6, "Spaceflight Now", 20),
29 a(7, "NASASpaceflight", 23),
30 ], now);
31 assert.deepEqual(picked.map((p) => p.id), [3, 4, 6]);
32 assert.match(digestPayload(picked).aps.alert.body, /^t3 \(SpaceNews\)\nt4 \(ESA\)\nt6 \(Spaceflight Now\)$/);
33});