tests/hadithRefs.test.ts
Rama main · réplica de lectura del repositorio original.
// Hadith references (shared/hadithRefs.ts): the callout's text and the corpus
// note's frontmatter must fold to ONE key, or a callout that names the right
// hadith renders as a quote with no way to tell why. Every claim here is
// about that agreement, plus the chain/matn split the card draws from.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
collectionKey,
collectionLabel,
hadithKey,
hadithKeyOfFrontmatter,
parseHadithRef,
splitHadith,
} from "../shared/hadithRefs.ts";
describe("collectionKey", () => {
it("files the six books and their Arabic names under one key each", () => {
for (const spelling of ["Bukhari", "bukhari", "al-Bukhari", "Sahih al-Bukhari", "Sahih Bukhari", "البخاري", "صحيح البخاري", "بخاري"]) {
assert.equal(collectionKey(spelling), "bukhari", spelling);
}
assert.equal(collectionKey("Muslim"), "muslim");
assert.equal(collectionKey("صحيح مسلم"), "muslim");
assert.equal(collectionKey("Abu Dawud"), "abudawud");
assert.equal(collectionKey("سنن أبي داود"), "abudawud");
assert.equal(collectionKey("Tirmidhi"), "tirmidhi");
assert.equal(collectionKey("الترمذي"), "tirmidhi");
assert.equal(collectionKey("Nasa'i"), "nasai");
assert.equal(collectionKey("النسائي"), "nasai");
assert.equal(collectionKey("Ibn Majah"), "ibnmajah");
assert.equal(collectionKey("ابن ماجه"), "ibnmajah");
});
it("keeps a book it has never heard of, folded to itself", () => {
assert.equal(collectionKey("Ibn Hibban"), "ibnhibban");
assert.equal(collectionKey("ibn-hibban"), "ibnhibban");
assert.equal(collectionKey("صحيح ابن حبان"), "ابنحبان");
assert.equal(collectionKey(""), "");
assert.equal(collectionKey(" , "), "");
});
});
describe("parseHadithRef", () => {
it("reads a collection and a number with any separator", () => {
assert.deepEqual(parseHadithRef("Bukhari 1"), { collection: "bukhari", number: 1 });
assert.deepEqual(parseHadithRef("Bukhari:1"), { collection: "bukhari", number: 1 });
assert.deepEqual(parseHadithRef("Bukhari #1"), { collection: "bukhari", number: 1 });
assert.deepEqual(parseHadithRef("Sahih Muslim 2564"), { collection: "muslim", number: 2564 });
assert.deepEqual(parseHadithRef("البخاري ١"), { collection: "bukhari", number: 1 });
assert.deepEqual(parseHadithRef("صحيح البخاري، ٥٢"), { collection: "bukhari", number: 52 });
assert.deepEqual(parseHadithRef("Ibn Hibban 12"), { collection: "ibnhibban", number: 12 });
});
it("refuses text with no number or no collection", () => {
assert.equal(parseHadithRef("Bukhari"), null);
assert.equal(parseHadithRef("1"), null);
assert.equal(parseHadithRef(""), null);
assert.equal(parseHadithRef("Bukhari 0"), null);
});
});
describe("the key, from both sides", () => {
it("is the same string from the callout and from the frontmatter", () => {
const fromCallout = parseHadithRef("Sahih al-Bukhari 52")!;
assert.equal(hadithKey(fromCallout.collection, fromCallout.number), "bukhari#52");
assert.equal(hadithKeyOfFrontmatter({ collection: "البخاري", number: 52 }), "bukhari#52");
assert.equal(hadithKeyOfFrontmatter({ collection: "Bukhari", number: "52" }), "bukhari#52");
assert.equal(hadithKeyOfFrontmatter({ collection: "Bukhari", number: "٥٢" }), "bukhari#52");
});
it("is null for a note that is not a corpus note", () => {
assert.equal(hadithKeyOfFrontmatter({}), null);
assert.equal(hadithKeyOfFrontmatter({ collection: "Bukhari" }), null);
assert.equal(hadithKeyOfFrontmatter({ number: 1 }), null);
// A tag page's `collection: true` is a different feature's key entirely.
assert.equal(hadithKeyOfFrontmatter({ collection: true, number: 1 }), null);
assert.equal(hadithKeyOfFrontmatter({ collection: "Bukhari", number: 1.5 }), null);
});
});
describe("collectionLabel", () => {
it("names a known book in the chrome's language and a custom one as written", () => {
assert.equal(collectionLabel("bukhari", "ar", "Bukhari"), "صحيح البخاري");
assert.equal(collectionLabel("bukhari", "en", "البخاري"), "Sahih al-Bukhari");
assert.equal(collectionLabel("ibnhibban", "en", "Ibn Hibban"), "Ibn Hibban");
});
});
describe("splitHadith", () => {
it("takes a first paragraph that opens like an isnad for the chain", () => {
const body = "حَدَّثَنَا الحُمَيْدِيُّ عَبْدُ اللَّهِ بْنُ الزُّبَيْرِ، قَالَ: حَدَّثَنَا سُفْيَانُ\n\nإِنَّمَا الأَعْمَالُ بِالنِّيَّاتِ";
const { chain, matn } = splitHadith(body);
assert.ok(chain?.startsWith("حَدَّثَنَا"));
assert.equal(matn, "إِنَّمَا الأَعْمَالُ بِالنِّيَّاتِ");
});
it("is all matn when nothing opens like an isnad", () => {
assert.deepEqual(splitHadith("The deeds are by intentions.\n\nSecond paragraph."), {
chain: null,
matn: "The deeds are by intentions.\n\nSecond paragraph.",
});
});
it("lets the frontmatter's own chain win", () => {
assert.deepEqual(splitHadith("إِنَّمَا الأَعْمَالُ", "عن عمر رضي الله عنه"), {
chain: "عن عمر رضي الله عنه",
matn: "إِنَّمَا الأَعْمَالُ",
});
});
});