Align AXIS control flow and fix pause and program rendering

Document source UI gates, explicit native live-plot clearing, and remaining parity boundaries. Fix pause/resume transport continuity, repeated stepping, coordinate previews, and spindle override state. Optimize large program snapshots and rendering, and cover the control flows with native Tcl, WASM, and browser checks.

Validation: 22 native tests and source/browser checks pass. Worker/App regression: 113 of 123 pass; 10 pre-existing failures remain documented with no new failures.
This commit is contained in:
2026-09-08 10:46:27 +08:00
parent 845075f4a3
commit bade560372
55 changed files with 2495 additions and 286 deletions

View File

@@ -0,0 +1,46 @@
import assert from "node:assert/strict";
import { pathToFileURL } from "node:url";
const { chromium } = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href);
const browser = await chromium.launch({ executablePath: "/usr/bin/google-chrome", headless: true, args: ["--disable-gpu"] });
const page = await browser.newPage({ viewport: { width: 390, height: 844 } });
const errors = [];
page.on("pageerror", (error) => errors.push(error.message));
const button = (id) => page.locator(`[data-axis-control="${id}"]`);
try {
await page.goto(process.env.XYZAC_PANEL_URL ?? "http://127.0.0.1:5175/");
await page.waitForFunction(() => document.querySelector("main")?.dataset.axisProgramLoading === "false");
await button("workspace-load-3d-chips").click();
await page.waitForFunction(() => document.querySelector("main")?.dataset.axisProgramPath === "linuxcnc/nc_files/3D_Chips.ngc" && document.querySelector("main")?.dataset.axisProgramLoading === "false");
const dimensions = [];
for (const width of [390, 768, 1440]) {
await page.setViewportSize({ width, height: width === 1440 ? 1000 : 844 });
await page.waitForTimeout(150);
const size = await page.evaluate(() => {
const editor = document.querySelector("#axis-program");
return { width: innerWidth, pageWidth: document.documentElement.scrollWidth, pageHeight: document.documentElement.scrollHeight, editorHeight: editor.clientHeight, editorScrollHeight: editor.scrollHeight, renderedLines: document.querySelectorAll(".program-gutter span").length };
});
assert.ok(size.pageWidth <= width + 1 && size.pageHeight < 5000, JSON.stringify(size));
assert.ok(size.editorHeight > 180 && size.editorHeight < 700 && size.editorScrollHeight > 80000, JSON.stringify(size));
assert.ok(size.renderedLines < 100, JSON.stringify(size));
await button("program-editor").evaluate((editor) => { editor.scrollTop = editor.scrollHeight; editor.dispatchEvent(new Event("scroll")); });
await page.waitForTimeout(100);
assert.ok((await page.locator(".program-gutter span").last().textContent()).includes("4712"));
await button("program-editor").evaluate((editor) => { editor.scrollTop = 0; editor.dispatchEvent(new Event("scroll")); });
dimensions.push(size);
}
await page.setViewportSize({ width: 390, height: 844 });
await button("toolbar-power").click(); await button("manual-home-all").click(); await button("toolbar-run").click();
await page.waitForFunction(() => document.querySelector("main")?.dataset.axisProgramStatus === "running");
const tick = () => page.locator("[data-xyzac-preview]").getAttribute("data-xyzac-tick").then(Number);
const start = await tick(); const wall = performance.now();
await page.waitForTimeout(3000);
const ratio = (await tick() - start) * 10 / (performance.now() - wall);
assert.ok(ratio > .75, `mobile simulation ratio ${ratio}`);
await button("toolbar-stop").click();
await page.waitForFunction(() => document.querySelector("main")?.dataset.axisProgramStatus === "aborted");
await button("toolbar-view-p").click();
await page.waitForTimeout(200);
await page.screenshot({ path: "/tmp/axis-chips-replacement-390.png", fullPage: true });
assert.deepEqual(errors, []);
console.log(JSON.stringify({ schema: "xyzac-chips-layout.v1", status: "verified", dimensions, mobile_simulation_ratio: ratio, browser_errors: errors }));
} finally { await browser.close(); }