103 lines
5.6 KiB
JavaScript
103 lines
5.6 KiB
JavaScript
const assert = require("node:assert/strict");
|
|
const { test } = require("node:test");
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
const { loadApplication, composeScript } = require("./support/application.cjs");
|
|
const { createDebugDom } = require("./support/debug-dom.cjs");
|
|
|
|
function fixture() {
|
|
const dom = createDebugDom();
|
|
const app = loadApplication("content", { document: dom.document });
|
|
const add = (id, name, second, status = "success") => app.debugContentLog.appendBackgroundRequestLog([{
|
|
debugKey: id, name, status, startedAt: `2026-09-18T12:00:${String(second).padStart(2, "0")}.000Z`,
|
|
metadata: name === "requestOpptyProducts" ? { optyNumber: "SYNTH-1", offset: 0 } : {},
|
|
requestHeaders: { Authorization: "synthetic-private" }
|
|
}]);
|
|
const nodes = () => dom.descendants(dom.panel);
|
|
const tab = category => nodes().find(node => node.getAttribute("data-debug-category") === category);
|
|
const ids = () => nodes().filter(node => node.tag === "details").map(node => node.getAttribute("data-request-id"));
|
|
const select = category => { const button = tab(category); button.focus(); button.listeners.click(); };
|
|
return { ...dom, app, add, nodes, tab, ids, select };
|
|
}
|
|
|
|
test("request categories cover every current family and unknown requests stay visible", () => {
|
|
const h = fixture();
|
|
for (const [name, category] of Object.entries({
|
|
requestTokenRelay: "authentication", requestTokenRelaySalesCommon: "authentication",
|
|
requestConsumerTokenService: "authentication", requestCustomerTokenService: "authentication",
|
|
requestOpportunities: "opportunities", requestOpptyProducts: "products", requestGenerateAiSummary: "ai",
|
|
requestAccountSummary: "consumption", requestAccountPlans: "consumption",
|
|
requestInstallBase: "installBase", requestCustomerServiceRequest: "serviceRequests",
|
|
requestConsumptionPlanDetail: "consumption",
|
|
requestConsumptionServiceQuarterly: "consumption", requestConsumptionServiceMonthly: "consumption",
|
|
requestConsumptionServiceWeekly: "consumption", requestConsumptionServiceDaily: "consumption", futureRequest: "other"
|
|
})) assert.equal(h.app.debugContentView.getRequestCategory({ name }), category, name);
|
|
h.app.debugContentView.renderDebugPanel();
|
|
assert.ok(h.tab("all"));
|
|
assert.equal(h.tab("products"), undefined);
|
|
h.add("future", "futureRequest", 0);
|
|
h.select("other");
|
|
assert.deepEqual(h.ids(), ["1"]);
|
|
});
|
|
|
|
test("All and category views sort by start time, preserve original ids and leave the log untouched", () => {
|
|
const h = fixture();
|
|
h.add("p-late", "requestOpptyProducts", 30, "pending");
|
|
h.add("auth", "requestTokenRelay", 10);
|
|
h.add("p-early", "requestOpptyProducts", 20);
|
|
assert.deepEqual(h.ids(), ["2", "3", "1"]);
|
|
assert.deepEqual(Array.from(h.app.debugState.requestLog, entry => entry.id), [1, 2, 3]);
|
|
h.select("products");
|
|
assert.deepEqual(h.ids(), ["3", "1"]);
|
|
assert.equal(h.tab("products").textContent, "Products (2) / 1 running");
|
|
assert.equal(h.nodes().filter(node => node.tag === "time").length, 2);
|
|
h.select("all");
|
|
assert.deepEqual(h.ids(), ["2", "3", "1"]);
|
|
assert.equal(h.tab("all").textContent, "All (3) / 1 running");
|
|
});
|
|
|
|
test("category, expansion, focus and hidden credentials survive asynchronous updates", () => {
|
|
const h = fixture();
|
|
h.add("p", "requestOpptyProducts", 10, "pending");
|
|
h.add("auth", "requestTokenRelay", 5);
|
|
h.select("products");
|
|
h.nodes().find(node => node.tag === "details").open = true;
|
|
h.select("authentication");
|
|
h.add("p", "requestOpptyProducts", 10);
|
|
assert.deepEqual(h.ids(), ["2"]);
|
|
assert.equal(h.tab("authentication").getAttribute("aria-selected"), "true");
|
|
assert.equal(h.document.activeElement, h.tab("authentication"));
|
|
h.select("products");
|
|
assert.equal(h.nodes().find(node => node.tag === "details").open, true);
|
|
assert.equal(h.tab("products").textContent, "Products (1)");
|
|
assert.ok(!h.nodes().some(node => node.text.includes("synthetic-private")));
|
|
h.nodes().find(node => node.tag === "details").open = false;
|
|
h.app.debugContentView.renderDebugPanel();
|
|
assert.equal(h.nodes().find(node => node.tag === "details").open, false);
|
|
});
|
|
|
|
test("tabs support arrows, Home and End with a single selected tab and labelled panel", () => {
|
|
const h = fixture();
|
|
h.add("auth", "requestTokenRelay", 1);
|
|
h.add("p", "requestOpptyProducts", 2);
|
|
h.select("all");
|
|
for (const [key, expected] of [["ArrowRight", "authentication"], ["End", "products"], ["ArrowRight", "all"], ["ArrowLeft", "products"], ["Home", "all"]]) {
|
|
let prevented = false;
|
|
h.document.activeElement.listeners.keydown({ key, preventDefault() { prevented = true; } });
|
|
assert.equal(prevented, true);
|
|
const selected = h.nodes().filter(node => node.getAttribute("aria-selected") === "true");
|
|
assert.equal(selected.length, 1);
|
|
assert.equal(selected[0], h.tab(expected));
|
|
assert.equal(h.document.activeElement, selected[0]);
|
|
assert.equal(h.nodes().find(node => node.getAttribute("role") === "tabpanel").getAttribute("aria-labelledby"), selected[0].id);
|
|
}
|
|
});
|
|
|
|
test("scoped debug styles are packaged after the unchanged main stylesheet", () => {
|
|
const root = path.join(__dirname, "..");
|
|
const css = ["src/content/styles/redwood.css", "src/features/debug/styles.css", "src/features/opportunities/styles.css", "src/features/install-base/styles.css", "src/features/service-requests/styles.css", "src/features/consumption/plan-detail.css"]
|
|
.map(file => fs.readFileSync(path.join(root, file), "utf8")).join("\n");
|
|
assert.ok(composeScript("content").includes(`const redwoodStyles = ${JSON.stringify(css)};`));
|
|
assert.ok(!composeScript("background").includes("opportunities-extension-debug-tabs"));
|
|
});
|