tests/libraryShelf.test.ts
Rama main · réplica de lectura del repositorio original.
// THE SHELF, WORKED OUT IN THE PANEL (client/libraryShelf.ts).
//
// The settings panel has to answer three questions before the owner saves: which
// folders a root would claim, what each of them would be called, and which rows
// the root has made redundant. The third one decides whether a row is DELETED,
// so it is a rule about losing the owner's typing and it belongs under a test —
// the module shipped with none, and the one defect the browser found was on the
// exact boundary these cases guard: a row's cover counts as "said by the folder"
// only when something actually says it.
//
// Pure: no store, no fetch, no DOM.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
addressProblem,
leafOf,
parentOf,
publishedChildFolders,
rootOf,
rootOffers,
rowIsFoldable,
} from "../client/libraryShelf.ts";
import type { LibraryPathRef, LibraryRoot } from "../shared/types.ts";
const BOOKS = "1 - Source Material/Books";
const LECTURES = "1 - Source Material/Lectures";
const row = (over: Partial<LibraryPathRef> & { folder: string }): LibraryPathRef => ({
id: `l${over.folder.length}${over.slug ?? ""}`,
slug: "",
kind: "book",
title: leafOf(over.folder),
...over,
});
describe("a folder split into its parent and its leaf", () => {
it("keeps the leaf whole — eight books under one parent differ only there", () => {
assert.equal(parentOf(`${BOOKS}/Calculus`), `${BOOKS}/`);
assert.equal(leafOf(`${BOOKS}/Calculus`), "Calculus");
});
it("answers for a folder at the vault's top level", () => {
assert.equal(parentOf("مكاتيب"), "");
assert.equal(leafOf("مكاتيب"), "مكاتيب");
});
});
describe("the children a root would claim", () => {
const published = new Set([
`${BOOKS}/Calculus/Chapter 1/One.md`,
`${BOOKS}/Calculus/Chapter 2/Two.md`,
`${BOOKS}/Zeno/Chapter 1/Three.md`,
`${BOOKS}/A Reader.md`,
`${LECTURES}/PLSC 114/L1/Four.md`,
]);
it("is every immediate subfolder holding a published note, by title", () => {
assert.deepEqual(publishedChildFolders(BOOKS, published), [`${BOOKS}/Calculus`, `${BOOKS}/Zeno`]);
});
it("leaves a note sitting directly in the root a post, not a path", () => {
// `Books/A Reader.md` is a note in a folder the owner chose to hold books.
assert.equal(publishedChildFolders(BOOKS, published).includes(`${BOOKS}/A Reader.md`), false);
});
it("does not answer a sibling whose name merely starts the same way", () => {
// The boundary is the slash: `Books/Z` must never claim `Books/Zeno`.
assert.deepEqual(publishedChildFolders(`${BOOKS}/Z`, published), []);
});
it("says nothing at all before the published set has loaded", () => {
assert.deepEqual(publishedChildFolders(BOOKS, null), []);
assert.deepEqual(publishedChildFolders("", published), []);
});
});
describe("which root a folder hangs from", () => {
const roots: LibraryRoot[] = [
{ id: "r1", folder: BOOKS, kind: "book" },
{ id: "r2", folder: LECTURES, kind: "course" },
];
it("names the parent, for an immediate child only", () => {
assert.equal(rootOf(`${BOOKS}/Calculus`, roots)?.id, "r1");
assert.equal(rootOf(`${LECTURES}/PLSC 114`, roots)?.kind, "course");
// A grandchild is a unit of a path, not a path of a root.
assert.equal(rootOf(`${BOOKS}/Calculus/Chapter 1`, roots), null);
assert.equal(rootOf("مكاتيب", roots), null);
});
});
describe("why a folder the panel expected is not on the shelf", () => {
it("says the title makes no address when it makes none", () => {
assert.deepEqual(addressProblem(`${BOOKS}/التفكير العلمي`, new Map()), { kind: "noAddress" });
});
it("names the path holding the address it wanted", () => {
const taken = new Map([["calculus", "Calculus (Michael Spivak)"]]);
assert.deepEqual(addressProblem(`${BOOKS}/Calculus`, taken), {
kind: "taken",
by: "Calculus (Michael Spivak)",
});
});
it("stays silent when it can prove nothing — a folder note may have hidden it", () => {
assert.equal(addressProblem(`${BOOKS}/Calculus`, new Map()), null);
});
});
describe("whether a row says anything the root and the folder would not", () => {
const folder = `${BOOKS}/Twilight of the Idols`;
const plain = row({ folder, slug: "twilight-of-the-idols", title: "Twilight of the Idols" });
it("folds a row that is the folder's own name and the address it suggests", () => {
assert.equal(rowIsFoldable(plain, "book", new Set()), true);
});
it("keeps a row whose title, address or kind is the owner's own word", () => {
assert.equal(rowIsFoldable({ ...plain, title: "Twilight (Nietzsche)" }, "book", new Set()), false);
assert.equal(rowIsFoldable({ ...plain, slug: "twilight" }, "book", new Set()), false);
assert.equal(rowIsFoldable(plain, "course", new Set()), false);
});
it("keeps a row carrying a blurb, a source or a take-down", () => {
assert.equal(rowIsFoldable({ ...plain, blurb: "Nietzsche in a hurry." }, "book", new Set()), false);
assert.equal(rowIsFoldable({ ...plain, source: "https://example.org" }, "book", new Set()), false);
assert.equal(rowIsFoldable({ ...plain, hidden: true }, "book", new Set()), false);
});
// THE ONE THE BROWSER CAUGHT. A cover counts as "said by the folder" only
// when a Media tracker LENDS one, and the server lends only from a tracker
// that has both a `folder:` and a `cover:`. A caller that fed in every
// tracker with a folder made this row look foldable, folding it deleted the
// row, and the book lost its picture on the public shelf.
it("keeps a row whose cover nothing else supplies", () => {
const withCover = { ...plain, cover: "Attachments/twilight.png" };
assert.equal(rowIsFoldable(withCover, "book", new Set()), false);
assert.equal(rowIsFoldable(withCover, "book", new Set([folder])), true);
// And the lender has to be THIS folder.
assert.equal(rowIsFoldable(withCover, "book", new Set([`${BOOKS}/Calculus`])), false);
});
});
describe("the one offer the panel makes", () => {
const rows: LibraryPathRef[] = [
row({ folder: `${BOOKS}/Calculus`, slug: "calculus-spivak", title: "Calculus (Michael Spivak)" }),
row({ folder: `${BOOKS}/Zeno`, slug: "zeno", title: "Zeno" }),
row({ folder: `${BOOKS}/Twilight of the Idols`, slug: "twilight-of-the-idols", title: "Twilight of the Idols" }),
row({ folder: `${LECTURES}/PLSC 114`, slug: "plsc-114", title: "PLSC 114", kind: "course" }),
];
it("offers the parent holding the most rows, with the kind they mostly are", () => {
const offer = rootOffers(rows, [], new Set());
assert.equal(offer?.parent, BOOKS);
assert.equal(offer?.kind, "book");
assert.equal(offer?.rows.length, 3);
});
it("offers only the rows that say nothing — the hand-typed title stays", () => {
const offer = rootOffers(rows, [], new Set());
assert.deepEqual(offer?.foldable.map((r) => r.title), ["Zeno", "Twilight of the Idols"]);
});
it("says nothing about a parent that is already a root", () => {
const offer = rootOffers(rows, [{ id: "r1", folder: BOOKS, kind: "book" }], new Set());
// Lectures holds one row, and one row is not a shape worth a question.
assert.equal(offer, null);
});
it("says nothing when no parent holds two rows", () => {
assert.equal(rootOffers([rows[3]], [], new Set()), null);
assert.equal(rootOffers([], [], new Set()), null);
});
it("never offers the vault itself as a root", () => {
const top = [row({ folder: "مكاتيب", slug: "makatib" }), row({ folder: "Orbits", slug: "orbits" })];
assert.equal(rootOffers(top, [], new Set()), null);
});
});