Files
linuxcncWebWASM/scripts/test_machine_dialog_browser.mjs

92 lines
7.1 KiB
JavaScript

import assert from 'node:assert/strict';
import { mkdir, writeFile } from 'node:fs/promises';
import { pathToFileURL } from 'node:url';
const { chromium } = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href);
const output = new URL('../coverage/glb-machine/dialogs/', import.meta.url); await mkdir(output, { recursive: true });
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({ viewport: { width: 1440, height: 900 } });
const errors = []; page.on('pageerror', (e) => errors.push(e.message));
const control = (id) => page.locator(`[data-axis-control="${id}"]`);
const settled = () => page.waitForFunction(() => document.querySelector('main')?.dataset.axisProgramLoading === 'false');
const report = { report_id: 'machine-dialog-browser-v1', status: 'running', layouts: [], dialogs: [] };
const bounds = (selector) => page.locator(selector).boundingBox();
async function drag(dialog, dx, dy) {
const title = await page.locator(`${dialog} .machine-dialog-titlebar strong`).boundingBox();
await page.mouse.move(title.x + 15, title.y + title.height / 2); await page.mouse.down();
await page.mouse.move(title.x + 15 + dx, title.y + title.height / 2 + dy, { steps: 8 }); await page.mouse.up();
}
async function within(selector) {
const b = await bounds(selector); const viewport = page.viewportSize();
assert.ok(b.x >= 7 && b.y >= 7 && b.x + b.width <= viewport.width - 7 && b.y + b.height <= viewport.height - 7, JSON.stringify({ b, viewport }));
return b;
}
try {
await page.goto('http://127.0.0.1:5174/'); await settled();
assert.equal(await page.locator('dialog[open]').count(), 0);
await control('machine-glb-settings').click();
await control('machine-glb-bc').click(); await settled();
assert.ok(await page.locator('.xyzac-machine-view').getAttribute('data-machine-glb'));
await page.keyboard.press('Escape');
assert.equal(await page.locator('dialog[open]').count(), 0);
assert.equal(await control('machine-glb-settings').evaluate((e) => e === document.activeElement), true);
for (const [button, selector] of [['machine-glb-settings', '.model-dialog'], ['geometry-settings', '.geometry-dialog']]) {
const canvasBefore = await bounds('.xyzac-machine-view canvas');
await control(button).click();
const before = await within(selector);
await drag(selector, 110, 60); const after = await within(selector);
assert.ok(Math.abs(after.x - before.x - 110) < 2 && Math.abs(after.y - before.y - 60) < 2);
assert.deepEqual(await bounds('.xyzac-machine-view canvas'), canvasBefore);
await page.keyboard.press('F2');
assert.equal(await control('machine-glb-import').isDisabled(), false, 'dialog key must not power on the machine');
for (let i = 0; i < 12; i++) { await page.keyboard.press('Tab'); assert.ok(await page.locator(selector).evaluate((e) => e.contains(document.activeElement))); }
await drag(selector, -2000, -2000); await within(selector);
await drag(selector, 4000, 4000); await within(selector);
await page.screenshot({ path: new URL(`${button}-dragged.png`, output).pathname });
await page.keyboard.press('Escape'); assert.equal(await page.locator('dialog[open]').count(), 0);
assert.equal(await control(button).evaluate((e) => e === document.activeElement), true);
report.dialogs.push({ button, before, after, focus_contained: true, keyboard_ignored: true, edge_clamped: true });
}
await control('geometry-settings').click(); await page.getByLabel('x-rot-point', { exact: true }).fill('31');
await page.keyboard.press('Escape'); await control('geometry-settings').click();
assert.equal(await page.getByLabel('x-rot-point', { exact: true }).inputValue(), '31');
await page.keyboard.press('Escape');
await control('toolbar-power').click();
await page.waitForFunction(() => document.querySelector('[data-axis-control="machine-glb-import"]').disabled);
await control('geometry-settings').click(); assert.ok(await page.getByLabel('x-rot-point', { exact: true }).isDisabled()); await page.keyboard.press('Escape');
await control('toolbar-power').click();
for (const [width, height] of [[2048, 859], [1440, 900], [390, 844]]) {
await page.setViewportSize({ width, height });
await page.locator('.xyzac-machine-view').scrollIntoViewIfNeeded();
await page.waitForTimeout(150);
const machine = await bounds('.xyzac-machine-view'), path = await bounds('.axis-preview-toolpath'), pane = await bounds('.axis-preview-machine');
assert.ok(machine.height >= 250, JSON.stringify(machine));
assert.ok(machine.height / pane.height > .85, JSON.stringify({ machine, pane }));
if (width > 900) assert.ok(path.height - machine.height < 50, JSON.stringify({ machine, path }));
await page.locator('.axis-preview-machine').screenshot({ path: new URL(`preview-${width}.png`, output).pathname });
await control('geometry-settings').click(); await within('.geometry-dialog');
await page.screenshot({ path: new URL(`parameters-${width}.png`, output).pathname });
const fields = await page.locator('.geometry-dialog input:not([hidden])').evaluateAll((nodes) => nodes.map((e) => { const r = e.getBoundingClientRect(); return { x: r.x, right: r.right }; }));
assert.ok(fields.every((r) => r.x >= 0 && r.right <= width));
await page.keyboard.press('Escape');
await control('machine-glb-settings').click(); await within('.model-dialog');
if (width === 390) {
const cdp = await page.context().newCDPSession(page);
const b = await bounds('.model-dialog .machine-dialog-titlebar strong');
const before = await bounds('.model-dialog');
await cdp.send('Input.dispatchTouchEvent', { type: 'touchStart', touchPoints: [{ x: b.x + 10, y: b.y + 8 }] });
await cdp.send('Input.dispatchTouchEvent', { type: 'touchMove', touchPoints: [{ x: b.x + 10, y: b.y + 58 }] });
await cdp.send('Input.dispatchTouchEvent', { type: 'touchEnd', touchPoints: [] });
const after = await within('.model-dialog'); assert.ok(after.y - before.y > 30);
report.touch_drag = { before, after };
}
await page.keyboard.press('Escape');
report.layouts.push({ width, height, machine, path, pane });
}
await page.setViewportSize({ width: 1440, height: 900 }); await control('geometry-settings').click(); await drag('.geometry-dialog', 150, 160);
await page.setViewportSize({ width: 390, height: 500 }); await page.waitForTimeout(150); await within('.geometry-dialog');
await page.keyboard.press('Escape');
assert.deepEqual(errors, []); report.status = 'verified';
} catch (e) { report.status = 'failed'; report.error = String(e.stack ?? e); await page.screenshot({ path: new URL('failure.png', output).pathname }); throw e; }
finally { report.browser_errors = errors; await writeFile(new URL('dialog.report.json', output), JSON.stringify(report, null, 2) + '\n'); await browser.close(); }
console.log(JSON.stringify({ report_id: report.report_id, status: report.status, layouts: report.layouts.map(({ width, machine }) => ({ width, canvas_height: machine.height })) }));