feat: the redesigned Event Clock
The new reader app replaces the old UI: Checklist with a rail (focus pills, Next to expire, today's dailies, pinned routines), Timeline in a new and a classic look, Routines, Archive and a Settings area, in a Structured (default) and a Relaxed interface. It follows the approved Round 6 B and Round 7 mockups, corrected screen by screen with the owner. Reader data moves to a v2 store (gacha-tracker:v2:*). Existing v1 data is migrated on first load, a recovery copy is written first, and the v1 keys are never removed, so a rollback finds them unchanged. Redeem codes for Genshin arrive as their own feed. Also: live's urgency ramp, editable per theme; completion and section-complete fireworks; a returning-user tour; the design mockups, specs, plans, reviews and handoff record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ddd9673f86
commit
50c6e91b00
@@ -0,0 +1,58 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import { runRefresh } from "../scripts/refresh-sources.ts";
|
||||
import { SnapshotStore } from "../src/ingest/snapshots.ts";
|
||||
import { CODE_SOURCES } from "../src/ingest/codes/registry.ts";
|
||||
import { sampleEvent } from "./helpers/reader.ts";
|
||||
test("event and code sources share host spacing and snapshot gates", async () => {
|
||||
const root = await mkdtemp("/tmp/codes-refresh-");
|
||||
try {
|
||||
const html = await Bun.file(
|
||||
"fixtures/genshin/game8-codes-2026-10-16.html",
|
||||
).text();
|
||||
const slept: number[] = [];
|
||||
const code = CODE_SOURCES[0]!;
|
||||
const summary = await runRefresh({
|
||||
adapters: [
|
||||
{ ...code, id: "event-test", parse: () => [sampleEvent] },
|
||||
code,
|
||||
],
|
||||
store: new SnapshotStore(root),
|
||||
robots: {
|
||||
allows: async () => ({ allowed: true, reason: "test permission" }),
|
||||
},
|
||||
fetchImpl: async () => new Response(html, { status: 200 }),
|
||||
userAgent: "event-clock-test",
|
||||
now: () => new Date("2026-10-16T12:00:00Z"),
|
||||
sleep: async (n) => {
|
||||
slept.push(n);
|
||||
},
|
||||
dryRun: false,
|
||||
only: null,
|
||||
force: false,
|
||||
timeoutMs: 20000,
|
||||
log: () => {},
|
||||
rebuildFeed: null,
|
||||
});
|
||||
expect(summary.changed).toBe(2);
|
||||
expect(slept).toEqual([2000]);
|
||||
expect(summary.outcomes[1]?.eventCount).toBe(10);
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
test("the CLI recognises the code source during a request-free dry run", () => {
|
||||
const p = Bun.spawnSync(
|
||||
[
|
||||
"bun",
|
||||
"run",
|
||||
"scripts/refresh-sources.ts",
|
||||
"--dry-run",
|
||||
"--only",
|
||||
"genshin-game8-codes",
|
||||
],
|
||||
{ stdout: "pipe", stderr: "pipe" },
|
||||
);
|
||||
expect(p.exitCode).toBe(0);
|
||||
expect(new TextDecoder().decode(p.stdout)).toContain("genshin-game8-codes");
|
||||
});
|
||||
Reference in New Issue
Block a user