34 lines
4.4 KiB
JavaScript
34 lines
4.4 KiB
JavaScript
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: "xyzac-live-trace-replacement-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: ["--ignore-certificate-errors", "--disable-gpu"] });
|
|
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 }, ignoreHTTPSErrors: true });
|
|
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 main = page.locator("main.axis-app");
|
|
const state = () => main.evaluate((element) => ({ source: element.dataset.axisStateSource, machine: element.querySelector(".machine-state")?.textContent?.trim(), program: element.dataset.axisProgramStatus, line: element.dataset.axisCurrentLine, path: element.querySelector(".xyzac-tool-preview")?.dataset.xyzacToolpathCount, live: element.querySelector(".xyzac-tool-preview")?.dataset.xyzacLiveTraceCount, loading: element.querySelector(".case-status")?.getAttribute("aria-busy") === "true", command: element.querySelector(".command-status")?.textContent, error: element.querySelector(".diagnostic-error")?.textContent ?? null }));
|
|
const wait = async (predicate, label, timeout = 45000) => { const started = Date.now(); let last; while (Date.now() - started < timeout) { last = await state(); if (predicate(last)) return last; await page.waitForTimeout(100); } throw new Error(`${label}:${JSON.stringify(last)}`); };
|
|
const click = async (locator, label) => { for (let index = 0; index < 300; index += 1) { if (await locator.count() && !await locator.first().isDisabled()) { await locator.first().click(); return; } await page.waitForTimeout(100); } throw new Error(`${label}:disabled_or_missing`); };
|
|
const loadFile = async (name, source) => { const input = main.locator('input[type="file"][aria-label="Open G-code file"]'); await input.setInputFiles({ name, mimeType: "text/plain", buffer: Buffer.from(source) }); return wait((value) => value.program === "loaded" && !value.loading && value.error === null, `${name}_loaded`); };
|
|
const runUntilTrace = async () => { await click(main.locator('button[aria-label="Power on [F2]"]'), "power_on"); await click(main.locator('button[aria-label="Home all axes"]'), "home_all"); await click(main.getByRole("button", { name: /^Identity/ }), "identity"); await main.getByRole("tab", { name: "Manual Control [F3]" }).click(); await click(main.locator('button[aria-label="Begin executing current file [R]"]'), "run_first"); return wait((value) => Number(value.live) > 2, "first_live_trace"); };
|
|
try {
|
|
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
await wait((value) => value.source === "linuxcnc-wasm", "wasm_startup");
|
|
const first = await loadFile("live-first.ngc", "G21\nG90\nG1 X20 F120\nG1 Y20\nG1 X0\nG1 Y0\nM2\n");
|
|
const running = await runUntilTrace();
|
|
await click(main.locator('button[aria-label="Stop program execution [ESC]"]'), "stop_first");
|
|
await wait((value) => value.program === "aborted" || value.program === "loaded", "first_stop");
|
|
const second = await loadFile("live-second.ngc", "G21\nG90\nG1 X3 Y4 F120\nM2\n");
|
|
const after = await wait((value) => value.program === "loaded" && value.path === "1" && value.live === "0" && value.error === null, "second_replacement");
|
|
await page.screenshot({ path: "/tmp/xyzac-live-trace-replacement.png", fullPage: true });
|
|
console.log(JSON.stringify({ schema: "xyzac-live-trace-replacement-browser.v1", status: errors.length === 0 && Number(running.live) > 2 && Number(after.path) === 1 && after.live === "0" ? "verified" : "failed", url, first_loaded: first, first_running: running, second_loaded: second, after_replacement: after, browser_errors: errors, screenshot: "/tmp/xyzac-live-trace-replacement.png" }));
|
|
} catch (error) {
|
|
console.log(JSON.stringify({ schema: "xyzac-live-trace-replacement-browser.v1", status: "failed", url, reason: error?.message ?? String(error), browser_errors: errors, screenshot: "/tmp/xyzac-live-trace-replacement.png" }));
|
|
}
|
|
await browser.close();
|