Files
linuxcncWebWASM/scripts/test_rtcp_program_library_browser.mjs

102 lines
6.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { pathToFileURL } from "node:url";
const modulePath = process.env.PLAYWRIGHT_MODULE;
if (!modulePath) {
console.log(JSON.stringify({ schema: "rtcp-program-library-browser.v1", status: "blocked", code: "playwright_unavailable" }));
process.exit(0);
}
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: ["--no-sandbox", "--use-angle=swiftshader", "--enable-unsafe-swiftshader"] });
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
const errors = [];
page.on("pageerror", (error) => errors.push(`pageerror:${error.message}`));
page.on("console", (message) => { if (message.type() === "error") errors.push(`console:${message.text()}`); });
const control = (id) => page.locator(`[data-axis-control="${id}"]`);
const main = page.locator("main.axis-app");
const waitReady = () => page.waitForFunction(() => {
const element = document.querySelector("main.axis-app");
return element?.dataset.axisStateSource === "linuxcnc-wasm" && element?.dataset.axisProgramLoading === "false";
}, null, { timeout: 45000 });
const waitPath = (path) => page.waitForFunction((expected) => {
const element = document.querySelector("main.axis-app");
return element?.dataset.axisProgramLoading === "false" && element?.dataset.axisProgramPath === expected && element?.dataset.axisProgramStatus === "loaded";
}, path, { timeout: 45000 });
const report = { schema: "rtcp-program-library-browser.v1", status: "running", checks: [] };
try {
await page.goto(process.env.RTCP_LIBRARY_URL ?? "http://127.0.0.1:5174/", { waitUntil: "domcontentloaded", timeout: 30000 });
await waitReady();
assert.match(await control("workspace-rtcp-programs").textContent(), /AC(XYZAC) RTCP 程序 \(15\)/);
await control("workspace-rtcp-programs").click();
assert.equal(await control("rtcp-program-scope").inputValue(), "machine");
assert.equal(await control("rtcp-program-select").locator("option").count(), 15);
assert.deepEqual(await control("rtcp-program-select").locator("optgroup").evaluateAll((nodes) => nodes.map((node) => ({ label: node.label, count: node.querySelectorAll("option").length }))), [
{ label: "TRT 旋转倾斜台 XYZAC/XYZBC (12)", count: 12 },
{ label: "gmoccapy TRT 示例 (3)", count: 3 },
]);
report.checks.push("AC machine defaults to 15 XYZAC/common programs");
await control("rtcp-program-scope").selectOption("all");
assert.equal(await control("rtcp-program-select").locator("option").count(), 32);
assert.deepEqual(await control("rtcp-program-select").locator("optgroup").evaluateAll((nodes) => nodes.map((node) => ({ label: node.label, count: node.querySelectorAll("option").length }))), [
{ label: "TRT 旋转倾斜台 XYZAC/XYZBC (16)", count: 16 },
{ label: "gmoccapy TRT 示例 (5)", count: 5 },
{ label: "XYZAB 双旋转台 (3)", count: 3 },
{ label: "Bridge Mill / 5axiskins (4)", count: 4 },
{ label: "Hexapod genhexkins RTCP (3)", count: 3 },
{ label: "独立五轴动态刀长示例 (1)", count: 1 },
]);
report.checks.push("all-source scope retains 32 programs and 6 source groups");
await control("rtcp-program-select").selectOption("trt-remap-m428");
assert.equal(await control("rtcp-program-load").isDisabled(), true);
await control("rtcp-program-source").click();
await page.waitForFunction(() => document.querySelector(".rtcp-program-source")?.value.includes("motion.switchkins-type"));
report.checks.push("support remap is source-readable and execution-disabled");
await control("rtcp-program-select").selectOption("xyzab-tdr-demo");
assert.equal(await control("rtcp-program-load").isDisabled(), true);
assert.match(await page.locator(".rtcp-incompatible").textContent(), /需要 XYZAB/);
report.checks.push("mismatched XYZAB program is visible and execution-disabled");
const xyzacPath = "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_3.ngc";
await control("rtcp-program-select").selectOption("trt-xyzac-switchkins-test-3");
assert.equal(await control("rtcp-program-load").isDisabled(), false);
await control("rtcp-program-load").click();
await waitPath(xyzacPath);
assert.match(await main.getAttribute("data-axis-program-source-hash"), /^fnv1a64:/);
assert.ok(Number(await page.locator(".xyzac-tool-preview").getAttribute("data-xyzac-toolpath-count")) > 0);
report.checks.push("XYZAC switchkins test loaded through WASM with canonical source hash and preview");
await page.keyboard.press("Escape");
const xyzbcCase = "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini";
await control("workspace-case-select").selectOption(xyzbcCase);
await page.waitForFunction((expected) => document.querySelector('[data-axis-control="workspace-case-select"]')?.value === expected && document.querySelector("main.axis-app")?.dataset.axisProgramLoading === "false", xyzbcCase, { timeout: 45000 });
assert.match(await control("workspace-rtcp-programs").textContent(), /BC(XYZBC) RTCP 程序 \(9\)/);
await control("workspace-rtcp-programs").click();
assert.equal(await control("rtcp-program-scope").inputValue(), "machine");
assert.equal(await control("rtcp-program-select").locator("option").count(), 9);
const xyzbcPath = "linuxcnc/configs/sim/gmoccapy/non_trivial_kinematics/table-rotary-tilting/examples/boat-xyzbc.ngc";
await control("rtcp-program-select").selectOption("gmoccapy-boat-xyzbc");
assert.equal(await control("rtcp-program-load").isDisabled(), false);
await control("rtcp-program-load").click();
await waitPath(xyzbcPath);
assert.ok(Number(await page.locator(".xyzac-tool-preview").getAttribute("data-xyzac-toolpath-count")) > 0);
report.checks.push("BC machine defaults to 9 XYZBC/common programs and loads gmoccapy XYZBC through WASM");
assert.deepEqual(errors, []);
report.status = "verified";
} catch (error) {
report.status = "failed";
report.error = error instanceof Error ? error.stack : String(error);
await page.screenshot({ path: "/tmp/rtcp-program-library-failure.png", fullPage: true });
throw error;
} finally {
report.browser_errors = errors;
report.final = await main.evaluate((element) => ({ coordinates: element.querySelector('[data-axis-control="workspace-case-select"]')?.value, program_path: element.dataset.axisProgramPath, program_status: element.dataset.axisProgramStatus, source_hash: element.dataset.axisProgramSourceHash })).catch(() => null);
await browser.close();
}
console.log(JSON.stringify(report));