import assert from "node:assert/strict"; import { pathToFileURL } from "node:url"; const playwright = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href); const { chromium } = playwright.default ?? playwright; const browser = await chromium.launch({ executablePath: "/usr/bin/google-chrome", headless: true, args: ["--no-sandbox", "--use-angle=swiftshader", "--enable-unsafe-swiftshader"] }); const page = await browser.newPage(); try { await page.goto(process.env.MACHINE_MANAGER_URL ?? "http://127.0.0.1:5173/"); const report = await page.evaluate(async () => { const { GLTFLoader } = await import("/node_modules/three/examples/jsm/loaders/GLTFLoader.js"); const { analyzeGlbFiveAxisScene } = await import("/src/glb-five-axis-analyzer.ts"); const response = await fetch("/@fs/home/mes006/linuxcncWebWASM/glb/m1.glb"); if (!response.ok) throw new Error(`m1.glb HTTP ${response.status}`); const gltf = await new GLTFLoader().parseAsync(await response.arrayBuffer(), ""); return analyzeGlbFiveAxisScene(gltf.scene, "m1.glb"); }); assert.deepEqual(report.axes.map(({ axis }) => axis), ["X", "Y", "Z", "A", "C"]); assert.equal(report.suggestedCoordinates, "XYZAC"); assert.equal(report.suggestedKinematics, "xyzac-trt-kins"); assert.equal(report.rtcp.mode, "native-trt"); assert.ok(report.boundsMm.size.every((value) => value > 100)); await page.locator('[data-axis-control="machine-glb-settings"]').click(); await page.locator('[data-axis-control="machine-glb-file"]').setInputFiles("/home/mes006/linuxcncWebWASM/glb/m1.glb"); await page.waitForFunction(() => document.querySelector(".xyzac-machine-view")?.getAttribute("data-xyzac-model-source") === "glb-axis-analysis/linuxcnc-wasm", undefined, { timeout: 30000 }); const runtime = await page.locator(".xyzac-machine-view").evaluate((element) => ({ source: element.getAttribute("data-xyzac-model-source"), bindings: JSON.parse(element.getAttribute("data-xyzac-axis-bindings") || "[]") })); assert.equal(runtime.source, "glb-axis-analysis/linuxcnc-wasm"); assert.deepEqual(runtime.bindings.map(({ axis }) => axis), ["X", "Y", "Z", "A", "C"]); const driven = await page.evaluate(async () => { const { loadImportedMachine, buildImportedMachine } = await import("/src/imported-machine.ts"); const bytes = await (await fetch("/@fs/home/mes006/linuxcncWebWASM/glb/m1.glb")).arrayBuffer(); const asset = await loadImportedMachine(bytes, "m1.glb"); const assembly = buildImportedMachine(asset); assembly.update({ joints: [12, 23, 34, 10, 40], offsets: { x_rot_point: 0, y_rot_point: 0, z_rot_point: 0, x_offset: 0, y_offset: 0, z_offset: 0, tool_offset: 0 } }); const nodes = Object.fromEntries(["JT_X", "JT_Y", "JT_Z", "JT_A", "JT_C"].map((name) => { const node = assembly.machine.getObjectByName(name); return [name, { position: node?.position.toArray(), quaternion: node?.quaternion.toArray() }]; })); assembly.dispose(); return nodes; }); assert.ok(Math.abs(driven.JT_X.position[0] - 0.12007432234287262) < 1e-9); assert.ok(Math.abs(driven.JT_A.quaternion[0]) > 0.01); assert.ok(Math.abs(driven.JT_C.quaternion[2]) > 0.01); console.log(JSON.stringify({ report_id: "glb-five-axis-analyzer-v1", status: "verified", axes: report.axes.map(({ axis, nodeName }) => ({ axis, nodeName })), suggested: report.suggestedCoordinates, kinematics: report.suggestedKinematics, bounds_mm: report.boundsMm, runtime, driven })); } finally { await browser.close(); }