55 lines
2.7 KiB
TypeScript
55 lines
2.7 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { motifs, sagas, songs } from "../src/data/sample";
|
|
import { gapYears, motifsInSong, sagaOf, songsWithMotif } from "../src/data/query";
|
|
|
|
describe("sample data", () => {
|
|
test("every song references a known saga", () => {
|
|
const ids = new Set(sagas.map((s) => s.id));
|
|
for (const song of songs) expect(ids.has(song.sagaId)).toBe(true);
|
|
});
|
|
test("every part motif id exists", () => {
|
|
const ids = new Set(motifs.map((m) => m.id));
|
|
for (const song of songs) for (const part of song.parts) for (const id of part.motifIds) expect(ids.has(id)).toBe(true);
|
|
});
|
|
test("every motif appears in at least one song", () => {
|
|
for (const m of motifs) expect(songsWithMotif(m.id).length).toBeGreaterThanOrEqual(1);
|
|
});
|
|
test("saga coverage", () => {
|
|
expect(songs.filter((s) => s.sagaId === "troy")).toHaveLength(5);
|
|
expect(songs.filter((s) => s.sagaId === "cyclops")).toHaveLength(4);
|
|
expect(songs.filter((s) => s.sagaId !== "troy" && s.sagaId !== "cyclops").length).toBeGreaterThanOrEqual(1);
|
|
});
|
|
test("every song has parts, facts and videos", () => {
|
|
for (const s of songs) {
|
|
expect(s.parts.length).toBeGreaterThanOrEqual(1);
|
|
expect(s.facts.length).toBeGreaterThanOrEqual(1);
|
|
expect(s.videos.length).toBeGreaterThanOrEqual(1);
|
|
}
|
|
});
|
|
test("songs are sorted by track and the first gap is non-negative", () => {
|
|
const tracks = songs.map((s) => s.track);
|
|
expect(tracks).toEqual([...tracks].sort((a, b) => a - b));
|
|
expect(gapYears(songs[0]!, songs[1]!)).toBeGreaterThanOrEqual(0);
|
|
});
|
|
test("ids are unique", () => {
|
|
for (const list of [songs, motifs, sagas]) expect(new Set(list.map((x) => x.id)).size).toBe(list.length);
|
|
});
|
|
test("motif mix and distinct colours", () => {
|
|
expect(motifs.filter((m) => m.kind === "motif").length).toBeGreaterThanOrEqual(4);
|
|
expect(motifs.filter((m) => m.kind === "character").length).toBeGreaterThanOrEqual(3);
|
|
expect(new Set(motifs.map((m) => m.color)).size).toBe(motifs.length);
|
|
});
|
|
test("a later song reuses an earlier motif", () => {
|
|
const later = songs.filter((s) => s.sagaId !== "troy" && s.sagaId !== "cyclops");
|
|
const earlier = new Set(songs.filter((s) => s.sagaId === "troy" || s.sagaId === "cyclops").flatMap((s) => motifsInSong(s).map((m) => m.id)));
|
|
expect(later.some((s) => motifsInSong(s).some((m) => earlier.has(m.id)))).toBe(true);
|
|
});
|
|
test("motifsInSong is unique and in first-appearance order; sagaOf resolves", () => {
|
|
const s = songs[0]!;
|
|
const ids = motifsInSong(s).map((m) => m.id);
|
|
expect(new Set(ids).size).toBe(ids.length);
|
|
expect(ids).toEqual([...new Set(s.parts.flatMap((p) => p.motifIds))]);
|
|
expect(sagaOf(s).id).toBe(s.sagaId);
|
|
});
|
|
});
|