"use strict"; // Zero-dependency browser calculation regressions (run: node tests/cache_outcomes.cjs). const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const vm = require("node:vm"); const root = path.join(__dirname, ".."); const src = fs.readFileSync(path.join(root, "src/admin/web/app/runtime.js"), "utf8"); const begin = src.indexOf("function cacheOutcomeMix(totals) {"); const renderBegin = src.indexOf("\nfunction renderCacheMix(mix, totalRequests) {", begin); const end = src.indexOf("\nfunction renderDiagnostics(", renderBegin); assert.ok(begin >= 0 && renderBegin > begin && end > renderBegin, "production cumulative widget functions exist"); const mix = vm.runInNewContext(`${src.slice(begin, renderBegin)}; cacheOutcomeMix;`); const result = mix([10, 4, 2, 3]); assert.deepEqual(Array.from(result.counts), [4, 2, 3, 1]); assert.deepEqual(Array.from(result.percentages), [40, 20, 30, 10]); assert.equal(result.requests, 10); assert.deepEqual(Array.from(mix([12, 0, 0, 0]).counts), [0, 0, 0, 12]); assert.deepEqual(Array.from(mix([9, 0, 0, 9]).counts), [0, 0, 9, 0]); for (const invalid of [[0, 0, 0, 0], [1, 2, 0, 0], [10, -1, 0, 0], [NaN, 0, 0, 0], [10.1, 2, 0, 0], [Number.MAX_SAFE_INTEGER + 1, 0, 0, 0], [], null]) { assert.equal(mix(invalid), null, `invalid lifetime counters ${invalid} are not charted`); } // Ensure the panel uses all-time counters straight from the status payload, on every render. const diagnostic = src.slice(end, src.indexOf("\nfunction ", end + 1)); assert.match(diagnostic, /const counters = \[m\.requests, c\.hits, c\.misses, c\.bypasses\]/); assert.match(diagnostic, /renderCacheMix\(cacheOutcomeMix\(counters\), counters\[0\]\);/); assert.doesNotMatch(src, /cacheMixLastCounters|cacheMixLastShares|cacheMixLastTotal/); const translations = ["en_US", "pl_pl"].map(language => JSON.parse(fs.readFileSync(path.join(root, `langs/${language}.json`), "utf8")).translations); const nodes = new Map(); const dom = id => { if (!nodes.has(id)) { const node = { style: {}, textContent: "", attributes: {}, setAttribute(name, value) { this.attributes[name] = value; } }; nodes.set(id, node); } return nodes.get(id); }; const english = translations[0]; const render = vm.runInNewContext(`${src.slice(renderBegin + 1, end)}; renderCacheMix;`, { $: dom, t: key => english[key], fmt: (value, digits = 0) => Number(value).toFixed(digits), }); render(result, 10); assert.equal(dom("cache-mix-headline").textContent, "40.0% HIT"); assert.equal(dom("cache-mix-caption").textContent, "10"); assert.equal(dom("cache-mix-caption").attributes.title, "Since service start · 10 HTTP requests"); assert.equal(dom("cache-mix-caption").attributes["aria-label"], "Since service start · 10 HTTP requests"); for (const [name, count, percent] of [["hit", 4, 40], ["miss", 2, 20], ["bypass", 3, 30], ["other", 1, 10]]) { assert.equal(dom(`cache-mix-${name}-count`).textContent, String(count)); assert.equal(dom(`cache-mix-${name}-percent`).textContent, `${percent.toFixed(1)}%`); assert.equal(dom(`cache-mix-${name}`).style.width, `${percent}%`); } assert.match(dom("cache-mix-bar").attributes["aria-label"], /4 HIT, 2 MISS, 3 BYPASS, 1 OTHER/); render(null, 0); assert.equal(dom("cache-mix-caption").textContent, "0"); assert.equal(dom("cache-mix-caption").attributes.title, "Since service start · 0 HTTP requests"); assert.equal(dom("cache-mix-hit-count").textContent, "-"); assert.equal(dom("cache-mix-hit").style.width, "0%"); render(null, 10); assert.equal(dom("cache-mix-caption").textContent, "10"); assert.equal(dom("cache-mix-caption").attributes.title, "Since service start · 10 HTTP requests"); assert.equal(dom("cache-mix-bar").attributes["aria-label"], english.cacheMixInvalid); render(null, NaN); assert.equal(dom("cache-mix-caption").textContent, "-"); assert.equal(dom("cache-mix-caption").attributes.title, english.cacheMixInvalid); const widgets = JSON.parse(fs.readFileSync(path.join(root, "src/admin/web/dashboard-widgets.json"), "utf8")); const defaults = JSON.parse(fs.readFileSync(path.join(root, "src/admin/web/dashboard-defaults.json"), "utf8")); assert.equal(widgets.filter(widget => widget.id === "cache_outcomes").length, 1); assert.equal(defaults.dashboard_widgets.filter(id => id === "cache_outcomes").length, 1); assert.equal(widgets.find(widget => widget.id === "cache_outcomes").default_hidden, true, "cache outcomes is opt-in"); assert.equal(defaults.dashboard_hidden_widgets.filter(id => id === "cache_outcomes").length, 1, "hidden in factory layout"); const html = fs.readFileSync(path.join(root, "src/admin/web/partials/overview-metrics.html"), "utf8"); assert.match(html, /data-dashboard-widget="cache_outcomes"/); assert.match(html, /class="cache-mix-header">\s*[^<]+<\/span>\s*