56 lines
3.7 KiB
JavaScript
56 lines
3.7 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const modulePath = process.env.PLAYWRIGHT_MODULE;
|
|
const url = process.env.XYZAC_PANEL_URL ?? "https://49.232.250.35:58010/";
|
|
if (!modulePath) {
|
|
console.log(JSON.stringify({ schema: "axis-control-inventory-browser.v1", status: "blocked", code: "playwright_unavailable" }));
|
|
process.exit(0);
|
|
}
|
|
const contract = await readFile(new URL("../docs/linuxcnc-axis-web-control-panel-source-logic.md", import.meta.url), "utf8");
|
|
const imported = await import(pathToFileURL(modulePath).href);
|
|
const playwright = imported.default ?? imported;
|
|
const browser = await playwright.chromium.launch({ headless: true, executablePath: process.env.BROWSER_EXECUTABLE_PATH ?? "/usr/bin/google-chrome", args: ["--ignore-certificate-errors", "--disable-gpu"] });
|
|
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 }, ignoreHTTPSErrors: true });
|
|
const browserErrors = [];
|
|
page.on("pageerror", (error) => browserErrors.push(`pageerror:${error.message}`));
|
|
page.on("console", (message) => { if (message.type() === "error") browserErrors.push(`console:${message.text()}`); });
|
|
await page.goto(`${url}${url.includes("?") ? "&" : "?"}control-inventory=1`, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
const main = page.locator("main.axis-app");
|
|
await main.waitFor({ state: "visible" });
|
|
for (let index = 0; index < 600; index += 1) {
|
|
if (await main.getAttribute("data-axis-program-loading") === "false") break;
|
|
await page.waitForTimeout(100);
|
|
}
|
|
|
|
await main.locator('[data-axis-control="menu-help"]').click();
|
|
await main.locator('[data-axis-control="menu-help-about"]').click();
|
|
await main.locator('[data-axis-control="about-close"]').waitFor({ state: "visible" });
|
|
const aboutClosePresent = await main.locator('[data-axis-control="about-close"]').count() === 1;
|
|
await main.locator('[data-axis-control="about-close"]').click();
|
|
|
|
const inventory = await main.locator("button,input,select,summary,textarea").evaluateAll((nodes) => nodes
|
|
.filter((node) => !(node instanceof HTMLTextAreaElement && node.readOnly))
|
|
.map((node) => ({
|
|
tag: node.tagName.toLowerCase(),
|
|
id: node.getAttribute("data-axis-control"),
|
|
text: (node.textContent ?? "").trim().replace(/\s+/g, " ").slice(0, 80),
|
|
aria: node.getAttribute("aria-label"),
|
|
disabled: "disabled" in node ? Boolean(node.disabled) : false,
|
|
hidden: node instanceof HTMLInputElement && node.type === "file",
|
|
})));
|
|
const missingIds = inventory.filter((entry) => !entry.id);
|
|
assert.deepEqual(missingIds, [], `actionable controls without data-axis-control: ${JSON.stringify(missingIds)}`);
|
|
const ids = inventory.map((entry) => entry.id);
|
|
for (const id of ids) assert.ok(contract.includes(`\`${id}\``), `runtime control missing from contract: ${id}`);
|
|
assert.equal(new Set(ids).size, ids.length, `duplicate control IDs: ${JSON.stringify(ids.filter((id, index) => ids.indexOf(id) !== index))}`);
|
|
for (const removed of ["Prepare T1", "Change", "Arm Probe", "Disarm", "Reload editor"]) assert.equal(inventory.some((entry) => entry.text === removed), false, `removed control still rendered: ${removed}`);
|
|
assert.equal(await main.locator('[data-axis-control="menu-file-edit-tool-data"]').isDisabled(), true);
|
|
assert.equal(await main.locator('[data-axis-control="menu-file-quit"]').isDisabled(), true);
|
|
assert.equal(aboutClosePresent, true);
|
|
assert.deepEqual(browserErrors, []);
|
|
|
|
console.log(JSON.stringify({ schema: "axis-control-inventory-browser.v1", status: "verified", url, actionable_controls: inventory.length + 1, static_control_ids: ids.length, dynamic_controls: ["about-close", "mdi-history-select"], disabled_host_boundaries: ["menu-file-edit-tool-data", "menu-file-quit"], browser_errors: browserErrors }));
|
|
await browser.close();
|