import { describe, test, expect } from "bun:test"; import { getBookById, getBookByNumber, getBooksByTestament, getBooksBySection, isAdjacent, bookNumberToId, bookIdToNumber, bibleBooks, } from "$lib/server/bible"; describe("bibleBooks data integrity", () => { test("contains exactly 66 books", () => { expect(bibleBooks).toHaveLength(66); }); test("order numbers are 1 through 66 with no gaps or duplicates", () => { const orders = bibleBooks.map((b) => b.order).sort((a, b) => a - b); for (let i = 0; i < 66; i++) { expect(orders[i]).toBe(i + 1); } }); test("book IDs are unique", () => { const ids = bibleBooks.map((b) => b.id); const unique = new Set(ids); expect(unique.size).toBe(66); }); test("every book has a non-empty name", () => { for (const book of bibleBooks) { expect(book.name.length).toBeGreaterThan(0); } }); test("Old Testament has 39 books", () => { expect(bibleBooks.filter((b) => b.testament === "old")).toHaveLength(39); }); test("New Testament has 27 books", () => { expect(bibleBooks.filter((b) => b.testament === "new")).toHaveLength(27); }); test("Genesis is first and Revelation is last", () => { const sorted = [...bibleBooks].sort((a, b) => a.order - b.order); expect(sorted[0].id).toBe("GEN"); expect(sorted[65].id).toBe("REV"); }); test("Matthew is the first New Testament book", () => { const nt = bibleBooks .filter((b) => b.testament === "new") .sort((a, b) => a.order - b.order); expect(nt[0].id).toBe("MAT"); }); }); describe("section counts", () => { test("Law: 5 books", () => { expect(getBooksBySection("Law")).toHaveLength(5); }); test("History: 13 books (12 OT + Acts)", () => { expect(getBooksBySection("History")).toHaveLength(13); }); test("Wisdom: 5 books", () => { expect(getBooksBySection("Wisdom")).toHaveLength(5); }); test("Major Prophets: 5 books", () => { expect(getBooksBySection("Major Prophets")).toHaveLength(5); }); test("Minor Prophets: 12 books", () => { expect(getBooksBySection("Minor Prophets")).toHaveLength(12); }); test("Gospels: 4 books", () => { expect(getBooksBySection("Gospels")).toHaveLength(4); }); test("Pauline Epistles: 13 books", () => { expect(getBooksBySection("Pauline Epistles")).toHaveLength(13); }); test("General Epistles: 8 books", () => { expect(getBooksBySection("General Epistles")).toHaveLength(8); }); test("Apocalyptic: 1 book (Revelation)", () => { const books = getBooksBySection("Apocalyptic"); expect(books).toHaveLength(1); expect(books[0].id).toBe("REV"); }); test("all sections sum to 66", () => { const total = getBooksBySection("Law").length + getBooksBySection("History").length + getBooksBySection("Wisdom").length + getBooksBySection("Major Prophets").length + getBooksBySection("Minor Prophets").length + getBooksBySection("Gospels").length + getBooksBySection("Pauline Epistles").length + getBooksBySection("General Epistles").length + getBooksBySection("Apocalyptic").length; expect(total).toBe(66); }); }); describe("getBookById", () => { test("returns Genesis for GEN", () => { const book = getBookById("GEN"); expect(book).toBeDefined(); expect(book!.name).toBe("Genesis"); }); test("returns Revelation for REV", () => { const book = getBookById("REV"); expect(book!.name).toBe("Revelation"); }); test("returns undefined for unknown ID", () => { expect(getBookById("UNKNOWN")).toBeUndefined(); }); }); describe("getBookByNumber", () => { test("1 → Genesis", () => { expect(getBookByNumber(1)!.id).toBe("GEN"); }); test("66 → Revelation", () => { expect(getBookByNumber(66)!.id).toBe("REV"); }); test("40 → Matthew (first NT book)", () => { expect(getBookByNumber(40)!.id).toBe("MAT"); }); test("0 → undefined", () => { expect(getBookByNumber(0)).toBeUndefined(); }); test("67 → undefined", () => { expect(getBookByNumber(67)).toBeUndefined(); }); }); describe("getBooksByTestament", () => { test("old returns 39 books", () => { expect(getBooksByTestament("old")).toHaveLength(39); }); test("new returns 27 books", () => { expect(getBooksByTestament("new")).toHaveLength(27); }); test("all OT books have testament = old", () => { for (const book of getBooksByTestament("old")) { expect(book.testament).toBe("old"); } }); test("all NT books have testament = new", () => { for (const book of getBooksByTestament("new")) { expect(book.testament).toBe("new"); } }); }); describe("isAdjacent", () => { test("Genesis and Exodus are adjacent", () => { expect(isAdjacent("GEN", "EXO")).toBe(true); }); test("adjacency is symmetric", () => { expect(isAdjacent("EXO", "GEN")).toBe(true); }); test("Malachi and Matthew are adjacent across testament boundary", () => { expect(isAdjacent("MAL", "MAT")).toBe(true); // 39, 40 }); test("Jude and Revelation are adjacent", () => { expect(isAdjacent("JUD", "REV")).toBe(true); // 65, 66 }); test("same book is not adjacent to itself", () => { expect(isAdjacent("GEN", "GEN")).toBe(false); }); test("books two apart are not adjacent", () => { expect(isAdjacent("GEN", "LEV")).toBe(false); // 1, 3 }); test("returns false for invalid IDs", () => { expect(isAdjacent("FAKE", "GEN")).toBe(false); }); }); describe("bookNumberToId / bookIdToNumber lookup tables", () => { test("bookNumberToId[1] is GEN", () => { expect(bookNumberToId[1]).toBe("GEN"); }); test("bookNumberToId[66] is REV", () => { expect(bookNumberToId[66]).toBe("REV"); }); test("bookIdToNumber['GEN'] is 1", () => { expect(bookIdToNumber["GEN"]).toBe(1); }); test("bookIdToNumber['REV'] is 66", () => { expect(bookIdToNumber["REV"]).toBe(66); }); test("round-trip: number → ID → number", () => { for (let i = 1; i <= 66; i++) { const id = bookNumberToId[i]; expect(bookIdToNumber[id]).toBe(i); } }); test("round-trip: ID → number → ID", () => { for (const book of bibleBooks) { const num = bookIdToNumber[book.id]; expect(bookNumberToId[num]).toBe(book.id); } }); });