Files
ObsiGate/tests/frontend/pretty.test.mjs
T
bruno bb0c8e7731
CI / lint (push) Successful in 1m18s
CI / security (push) Successful in 56s
CI / test (push) Successful in 2m57s
CI / build (push) Successful in 48s
CI / e2e (push) Successful in 10m47s
fix(viewer): pretty print fallback tokenizer quand highlight.js ne produit aucun token (txt/log/plaintext) (#89)
2026-09-14 19:43:50 -04:00

88 lines
3.9 KiB
JavaScript

/**
* Frontend tests for Pretty print helpers (#89).
* detectPrettyLang / buildPrettyHtml are pure functions extracted from
* frontend/js/viewer.js; they are evaluated in a sandbox to avoid importing
* the full viewer module chain (browser-only dependencies).
*/
import { strict as assert } from "node:assert";
import { readFileSync } from "node:fs";
import vm from "node:vm";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const src = readFileSync(path.join(__dirname, "..", "..", "frontend", "js", "viewer.js"), "utf8");
function extractFn(name) {
const start = src.indexOf(`function ${name}(`);
assert.ok(start !== -1, `function ${name} not found in viewer.js`);
let depth = 0;
let i = src.indexOf("{", start);
const begin = i;
for (; i < src.length; i++) {
if (src[i] === "{") depth++;
else if (src[i] === "}") {
depth--;
if (depth === 0) break;
}
}
return src.slice(start, i + 1);
}
function escapeHtml(s) {
return String(s)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
const sandbox = { escapeHtml };
vm.createContext(sandbox);
vm.runInContext(
`${extractFn("detectPrettyLang")}\n${extractFn("buildPrettyHtml")}\n${src.slice(src.indexOf("const PP_TOKEN_RE"), src.indexOf("function applyPrettyHighlight"))}\nglobalThis.fallbackTokenize = fallbackTokenize;`,
sandbox,
);
const { detectPrettyLang, buildPrettyHtml, fallbackTokenize } = sandbox;
console.log("Testing detectPrettyLang...");
assert.equal(detectPrettyLang({ is_json: true }), "json");
assert.equal(detectPrettyLang({ extension: ".json" }), "json");
assert.equal(detectPrettyLang({ extension: ".py", html: '<pre><code class="language-python">x</code></pre>' }), "python");
assert.equal(detectPrettyLang({ extension: ".sh", html: '<pre><code class="language-bash">x</code></pre>' }), "bash");
assert.equal(detectPrettyLang({ extension: ".txt", html: "<pre><code>x</code></pre>" }), "plaintext");
console.log("Testing buildPrettyHtml (json reformat)...");
const jsonOut = buildPrettyHtml({ is_json: true }, '{"a":1,"b":[2,3]}');
assert.ok(jsonOut.includes("pretty-view"), "wrapper class present");
assert.ok(jsonOut.includes("pp-gutter"), "gutter present");
assert.ok(jsonOut.includes('class="language-json"'), "language class present");
// 4 formatted lines: {, "a": 1, "b": [...], } -> gutter must show 4 numbers at least
assert.ok(/<span>4<\/span>/.test(jsonOut), "line numbers computed on formatted text");
assert.ok(jsonOut.includes("&quot;a&quot;"), "HTML-escaped quotes");
console.log("Testing buildPrettyHtml (invalid json falls back to raw)...");
const bad = buildPrettyHtml({ is_json: true }, "{not valid json}");
assert.ok(bad.includes("{not valid json}"), "raw content displayed when JSON invalid");
console.log("Testing buildPrettyHtml (xss escaped)...");
const xss = buildPrettyHtml({ extension: ".py", html: "" }, 'print("<script>alert(1)</script>")');
assert.ok(!xss.includes("<script>"), "no raw script tag injected");
assert.ok(xss.includes("&lt;script&gt;"), "script tag escaped");
console.log("Testing fallbackTokenize (log levels, strings, comments)...");
const fb = fallbackTokenize('2026-09-14 ERROR failed to open "/var/db"\n# note simple\nvalue=42');
assert.ok(fb.includes("pp-err"), "ERROR level colored");
assert.ok(fb.includes("hljs-string"), "quoted string colored");
assert.ok(fb.includes("hljs-comment"), "comment colored");
assert.ok(fb.includes("hljs-number"), "number colored");
assert.ok(fb.includes("hljs-attr"), "key= colored");
console.log("Testing fallbackTokenize (no html injection)...");
const fbXss = fallbackTokenize('bad <img src=x onerror="alert(1)">');
assert.ok(!/<img/.test(fbXss), "no raw img tag");
assert.ok(fbXss.includes("&lt;img"), "img escaped");
console.log("✅ All pretty-print tests passed successfully!");