Files
gacha-event-tracker/test/redesign-settings-pages.test.tsx
T
Lucas WintherandClaude Opus 5.5 50c6e91b00 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 <noreply@anthropic.com>
2026-10-18 01:55:16 +02:00

104 lines
3.1 KiB
TypeScript

import { expect, test } from "bun:test";
import { renderToStaticMarkup as render } from "react-dom/server";
import { AboutPage } from "../src/client/components/redesign/AboutPage.tsx";
import {
DataSourcesPage,
sourceReason,
} from "../src/client/components/redesign/DataSourcesPage.tsx";
import type { SourceHealth } from "../src/shared/feed.ts";
const now = Date.parse("2026-10-17T12:00:00.000Z");
const hoursAgo = (h: number) => new Date(now - h * 3_600_000).toISOString();
const source = (over: Partial<SourceHealth> = {}): SourceHealth => ({
sourceId: "genshin-events",
game: "genshin",
url: "https://genshin-impact.fandom.com/wiki/Event",
lastSuccessAt: hoursAgo(2),
lastConfirmedAt: hoursAgo(2),
contentChangedAt: hoursAgo(6),
eventCount: 3,
parsedCount: null,
statesNoEvents: false,
...over,
});
test("About holds credits and the disclaimer, not data freshness", () => {
const html = render(<AboutPage sources={[source()]} />);
for (const part of [
"Made by",
"With thanks to the source editors",
"The studios and games",
"Ideas and acknowledgements",
"Unofficial and unaffiliated",
"Genshin Impact",
])
expect(html).toContain(part);
expect(html).toContain('class="game-name" style="color:');
expect(html).not.toContain("See data freshness");
expect(html).not.toContain("last refreshed");
});
test("Data & sources holds the refresh time and one row per game", () => {
const html = render(
<DataSourcesPage
sources={[
source(),
source({ sourceId: "genshin-game8", url: "https://game8.co/x" }),
]}
now={now}
timezone={null}
onRefresh={async () => "same"}
/>,
);
expect(html).toContain("Event data last refreshed");
expect(html).toContain("Check for new data");
expect(html.match(/class="source-row"/g)?.length).toBe(1);
expect(html).toContain("Last successful check:");
expect(html).toContain("Check source page");
});
test("each source reads as one of the mockup's four states", () => {
expect(sourceReason(source(), now).current).toBe(true);
expect(
sourceReason(source({ contentChangedAt: hoursAgo(24 * 9) }), now).text,
).toContain("Site has no new updates");
expect(
sourceReason(
source({
lastSuccessAt: hoursAgo(24 * 6),
lastConfirmedAt: hoursAgo(24 * 6),
}),
now,
).text,
).toContain("Pull overdue");
expect(
sourceReason(
source({
lastSuccessAt: null,
lastConfirmedAt: null,
contentChangedAt: null,
}),
now,
).text,
).toContain("No successful source fetch");
});
test("Data & sources offers the standard-banner pulls choice beside the other list options", () => {
const html = render(
<DataSourcesPage
sources={[source()]}
now={now}
timezone={null}
showUpcoming={false}
detectDaily={false}
standardPulls={true}
onPrefs={() => {}}
/>,
);
expect(html).toContain("Offer standard-banner pulls in the library");
expect(html).toContain("Premium pulls are always offered.");
expect(html.indexOf("Offer standard-banner pulls")).toBeLessThan(
html.indexOf('class="source-row"'),
);
});