import assert from "node:assert/strict"; import test from "node:test"; import { fileURLToPath } from "node:url"; import { build } from "esbuild"; // Bundle React together with the code under test so that both share one React instance. async function load(entry) { const result = await build({ stdin: { contents: entry, resolveDir: fileURLToPath(new URL("../src/", import.meta.url)), loader: "tsx" }, bundle: true, write: false, format: "esm", platform: "node", jsx: "automatic", logLevel: "silent", banner: { js: "import { createRequire } from \"node:module\"; const require = createRequire(process.cwd() + \"/package.json\");" }, }); const code = Buffer.from(result.outputFiles[0].text).toString("base64"); return import(`data:text/javascript;base64,${code}`); } const { renderToStaticMarkup, h, ProgressBar, highlight } = await load(` export { renderToStaticMarkup } from "react-dom/server"; export { createElement as h } from "react"; export { ProgressBar, highlight } from "./pages/TranslationParts"; `); const stats = { lines: 10, translated: 5, progress: 0.5, strings: 4, stringsTranslated: 2, states: { untranslated: 5, outdated: 1, translated: 3, fuzzy: 0, machine: 0, approved: 1 }, }; test("ProgressBar renders counts and only non-empty segments", () => { const html = renderToStaticMarkup(h(ProgressBar, { stats })); assert.match(html, /5 из 10 реплик \(50%\)/); assert.match(html, /устарело 1/); assert.match(html, /seg-approved/); assert.doesNotMatch(html, /seg-warn/); }); test("highlight wraps glossary terms case-insensitively and escapes regex characters", () => { const terms = [{ src: "Eileen", t: "Эйлин", note: "" }, { src: "a+b", t: "x", note: "" }]; const html = renderToStaticMarkup(h("p", null, highlight("eileen met a+b", terms))); assert.match(html, /eileen<\/mark>/); assert.match(html, /a\+b<\/mark>/); assert.equal(highlight("plain", []), "plain"); });