English spellcheck suggestions with Add-to-dictionary in the native context menu plus a Settings toggle. Typewriter caret-centering mode. OS file associations for .md/.txt and Open File wording. Updater: release URL surfaced, single progress listener, two-byte tarball check, installer wait guard. Search/installer test suites registered; chapter-list layout polish; ignore KDE .directory files.
41 lines
2 KiB
JavaScript
41 lines
2 KiB
JavaScript
// Standalone test for the whole-book search helpers (src/renderer/book/ui.ts).
|
|
// These pure functions power the Search modal: Markdown flattening, literal
|
|
// matching (phrases included), and result snippets.
|
|
// Run with: node tests/run-search-test.mjs
|
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
|
|
|
const { mod: ui, cleanupBundle } = await bundleForTest({
|
|
name: "folio-search-ui",
|
|
entryPoints: ["src/renderer/book/ui.ts"],
|
|
});
|
|
const { findMatches, markdownToPlain, makeSnippet, moveInList, escapeHtml } = ui;
|
|
|
|
let failures = 0;
|
|
function ok(cond, msg) {
|
|
if (cond) console.log(" ok -", msg);
|
|
else { failures++; console.error("FAIL -", msg); }
|
|
}
|
|
|
|
// markdown -> searchable plain text
|
|
ok(markdownToPlain("# Title\nSome **bold** text") === "Title\nSome bold text", "headings/emphasis flattened");
|
|
ok(markdownToPlain("[link](http://x)") === "link", "links flattened to text");
|
|
ok(markdownToPlain("`code`") === "code", "inline code flattened");
|
|
|
|
// literal matching incl. phrases, case handling
|
|
ok(JSON.stringify(findMatches("hello world hello", "hello", true)) === "[0,12]", "finds all occurrences");
|
|
ok(findMatches("Hello", "hello", true).length === 0, "match-case respected");
|
|
ok(findMatches("Hello", "hello", false).length === 1, "case-insensitive match");
|
|
ok(JSON.stringify(findMatches("the quick brown fox", "quick brown", false)) === "[4]", "phrase search works");
|
|
ok(findMatches("a.b", "a.b", false).length === 1, "regex chars treated literally");
|
|
|
|
// snippets highlight the match and escape HTML
|
|
const snip = makeSnippet("say <hi> & bye", 4, 4);
|
|
ok(snip.includes("<mark>") && snip.includes("<hi>"), "snippet highlights + escapes");
|
|
|
|
// shared reorder math used by drag + keyboard reorder
|
|
ok(JSON.stringify(moveInList([1, 2, 3], 0, 2)) === "[2,3,1]", "moveInList moves item");
|
|
ok(escapeHtml("<a>&") === "<a>&", "escapeHtml works");
|
|
|
|
cleanupBundle();
|
|
if (failures) { console.error(`${failures} search check(s) FAILED`); process.exit(1); }
|
|
console.log("All search checks passed.");
|