Files
Epic-The-Musical-Timeline/tests/app-content.test.ts
T
Lucas WintherandClaude Opus 5.5 2fbf3a6980 feat(app): content client and side panel
About, Listen & lyrics (real player, synced lyrics, Watch), Paths (strip
when the timeline is hidden, motif rows, nine-place chart), Fan works.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 05:09:22 +01:00

87 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { afterEach, expect, test } from "bun:test";
import { loadBook, loadLibrary, loadLyrics, passageStart, realFor } from "../src/app/content";
import { songById } from "../src/data/album";
import type { HomerBook } from "../src/content/homer";
// Placeholder text only: never real lyrics in tests.
const realFetch = globalThis.fetch;
afterEach(() => { globalThis.fetch = realFetch; });
function mockFetch(routes: Record<string, () => Response>) {
const seen: string[] = [];
globalThis.fetch = (async (input: RequestInfo | URL) => {
const url = String(input);
seen.push(url);
const hit = routes[url];
return hit ? hit() : new Response("Not found", { status: 404 });
}) as typeof fetch;
return seen;
}
const library = {
sagas: [
{
name: "The Circe Saga", year: 2024, cover: "/content/files/circe/folder.jpg",
songs: [
{ track: 2, title: "Wouldn't You Like", audio: "/content/files/circe/02.flac", lyrics: { url: "/content/files/circe/02.lrc", timed: true } },
{ track: 3, title: "Done For", audio: "/content/files/circe/03.flac", lyrics: { url: "/content/files/circe/03.txt", timed: false } },
],
},
],
};
test("loadLibrary is false when /content 404s", async () => {
mockFetch({});
expect(await loadLibrary()).toBe(false);
expect(realFor(songById("polyphemus")!)).toBeNull();
});
test("loadLibrary is false when the request times out", async () => {
globalThis.fetch = ((_: RequestInfo | URL, init?: RequestInit) =>
new Promise((_res, rej) => init?.signal?.addEventListener("abort", () => rej(new Error("aborted"))))) as typeof fetch;
expect(await loadLibrary(20)).toBe(false);
});
test("realFor matches by normalised title, including a curly apostrophe", async () => {
mockFetch({ "/content/library.json": () => Response.json(library) });
expect(await loadLibrary()).toBe(true);
const song = songById("wouldnt-you-like")!;
expect(song.title).toBe("Wouldn’t You Like");
expect(realFor(song)).toEqual({
audio: "/content/files/circe/02.flac",
cover: "/content/files/circe/folder.jpg",
lyrics: { url: "/content/files/circe/02.lrc", timed: true },
});
expect(realFor(songById("polyphemus")!)).toBeNull();
});
test("loadLyrics parses .lrc as timed lines and .txt as plain lines", async () => {
mockFetch({
"/content/files/x/a.lrc": () => new Response("[ar:Someone]\n[00:02.00]Line B\n[00:01.00]Line A\n"),
"/content/files/x/a.txt": () => new Response("Line A\r\n\r\nLine B\n"),
});
expect(await loadLyrics({ url: "/content/files/x/a.lrc", timed: true })).toEqual({
timed: true, lines: [{ time: 1, text: "Line A" }, { time: 2, text: "Line B" }],
});
expect(await loadLyrics({ url: "/content/files/x/a.txt", timed: false })).toEqual({ timed: false, lines: ["Line A", "", "Line B"] });
expect(await loadLyrics({ url: "/content/files/x/missing.lrc", timed: true })).toBeNull();
});
test("loadBook fetches one book, null when missing", async () => {
const book: HomerBook = { book: 11, heading: "BOOK XI", summary: "S", paragraphs: ["p"] };
const seen = mockFetch({ "/content/homer/odyssey/11.json": () => Response.json(book) });
expect(await loadBook(11)).toEqual(book);
expect(await loadBook(30)).toBeNull();
expect(seen).toContain("/content/homer/odyssey/11.json");
});
test("passageStart finds the first paragraph with a keyword, else 0", () => {
const book: HomerBook = {
book: 9, heading: "BOOK IX", summary: "",
paragraphs: ["Nothing here.", "Still nothing, cyclopean is not a word match.", "Then the Cyclops spoke.", "The cave again."],
};
expect(passageStart(book, ["cave", "Cyclops"])).toEqual({ index: 2, word: "Cyclops" });
expect(passageStart(book, ["Noman"])).toEqual({ index: 0, word: null });
expect(passageStart(book, [])).toEqual({ index: 0, word: null });
});