Ctrl K
ComunidadGuías…

tests/hadithRefs.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// 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: "إِنَّمَا الأَعْمَالُ",
    });
  });
});