Files
gacha-event-tracker/test/article-feed.test.ts
T
Lucas WintherandClaude Opus 5.5 24327ea99b feat(feed): show the end a Genshin article states
Genshin and Miliastra rows take the end their own wiki article states, because
the table's date can mean 03:59, 14:59, 17:59 or one instant worldwide. Rows with
no usable time stay on the daily-reset reading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 02:16:57 +01:00

76 lines
2.8 KiB
TypeScript

import { afterEach, beforeEach, expect, test } from "bun:test";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { ArticleStore } from "../src/ingest/articleStore.ts";
import { EventFeed } from "../src/shared/feed.ts";
import { SnapshotStore } from "../src/ingest/snapshots.ts";
const NOW = "2026-11-07T00:00:00.000Z";
const dir = "fixtures/genshin/articles";
let root: string;
beforeEach(async () => {
root = await mkdtemp(join(tmpdir(), "event-clock-feed-"));
await new SnapshotStore(root).save("genshin-fandom-events", {
url: "https://genshin-impact.fandom.com/api.php?action=parse&page=Event",
body: await Bun.file(`${dir}/event-table-2026-11-06.html`).text(),
etag: null,
lastModified: null,
at: "2026-11-06T17:27:59.858Z",
eventCount: 15,
});
});
afterEach(async () => {
await rm(root, { recursive: true, force: true });
});
async function buildFeed() {
const out = join(root, "feed.json");
const proc = Bun.spawn(["bun", "run", "scripts/build-feed.ts"], {
env: { ...process.env, SNAPSHOT_DIR: root, EVENT_FEED_OUT: out, EVENT_FEED_NOW: NOW },
stdout: "pipe",
stderr: "pipe",
});
const stderr = await new Response(proc.stderr).text();
const log = await new Response(proc.stdout).text();
expect(`${await proc.exited} ${stderr}`).toBe("0 ");
return { feed: EventFeed.parse(await Bun.file(out).json()), log };
}
const hourOfRuin = "genshin:hour-of-ruin:2026-11-04";
test("the feed carries the end the article states, on an unchanged id", async () => {
await new ArticleStore(root).saveRead(
"Hour_of_Ruin_(Event)",
await Bun.file(`${dir}/hour-of-ruin-2026-11-07.html`).text(),
NOW,
);
const { feed } = await buildFeed();
const row = feed.events.find((e) => e.id === hourOfRuin)!;
expect(row.endPrecision).toBe("exact");
expect(row.regionScoped).toBe(true);
expect(row.regionEnds?.europe).toBe("2026-12-15T13:59:00.000Z");
expect(row.startsAt).toBe("2026-11-04T00:00:00.000Z");
});
test("no articles directory builds the same day-precision row as today", async () => {
const { feed } = await buildFeed();
const row = feed.events.find((e) => e.id === hourOfRuin)!;
expect(row.endPrecision).toBe("day");
expect(row.endsAt).toBe("2026-12-15T00:00:00.000Z");
expect(row.regionEnds).toBeNull();
});
test("an article that disagrees on the date is named in the build log", async () => {
const body = (await Bun.file(`${dir}/hour-of-ruin-2026-11-07.html`).text()).replace(
"December 15, 2026 14:59",
"December 20, 2026 14:59",
);
await new ArticleStore(root).saveRead("Hour_of_Ruin_(Event)", body, NOW);
const { feed, log } = await buildFeed();
expect(feed.events.find((e) => e.id === hourOfRuin)?.endPrecision).toBe("day");
expect(log).toContain("article:");
expect(log).toContain("Hour of Ruin");
});