Ilya Ashikhmin dd547f7ea1 fix(sim): exclude power lines from fluid routing
Power and signal edges no longer act as fluid paths in the mock solver
(a water demand was previously routed through the pump's power cable).

Also: bundled demo diagram, visual e2e script with dev-mode editor hook,
plan checklist completed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:34:44 +02:00

75 lines
2.5 KiB
JavaScript

/**
* Visual verification: loads the demo document through the dev hook,
* captures screenshots of (1) the routed diagram with jumpover arcs,
* (2) simulation running, (3) arcs disabled, (4) dark color scheme.
* Run: node e2e/visual.mjs (starts the dev server if needed)
*/
import { chromium } from 'playwright';
import { spawn } from 'node:child_process';
import { setTimeout as sleep } from 'node:timers/promises';
import { readFileSync } from 'node:fs';
const URL = 'http://localhost:1420';
let devServer = null;
async function serverUp() {
try {
return (await fetch(URL)).ok;
} catch {
return false;
}
}
async function main() {
if (!(await serverUp())) {
devServer = spawn('npm', ['run', 'dev'], { stdio: 'ignore', detached: true });
for (let i = 0; i < 60 && !(await serverUp()); i += 1) await sleep(500);
}
const doc = readFileSync(new globalThis.URL('../examples/demo.pipeline.json', import.meta.url), 'utf8');
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1500, height: 950 } });
page.on('pageerror', (e) => console.error('[pageerror]', String(e)));
await page.goto(URL);
await page.waitForSelector('[data-testid="canvas"] svg');
await page.waitForFunction(() => !!window.__editor);
await page.evaluate((json) => {
window.__editor.loadDocumentJSON(json);
window.__editor.zoomToFit();
}, doc);
await sleep(600);
await page.screenshot({ path: 'e2e/visual-routing.png' });
console.log('✓ e2e/visual-routing.png (manhattan routing + jumpover arcs)');
await page.click('[data-testid="simulate-button"]');
await sleep(900);
await page.screenshot({ path: 'e2e/visual-simulation.png' });
console.log('✓ e2e/visual-simulation.png (animated flow, labels)');
await page.click('[data-testid="simulate-button"]');
await page.evaluate(() => {
window.__editor.applyConfig({ ...window.__editor.config, arcOnIntersections: false });
});
await sleep(500);
await page.screenshot({ path: 'e2e/visual-no-arcs.png' });
console.log('✓ e2e/visual-no-arcs.png (arcs disabled)');
await page.evaluate(() => {
window.__editor.applyConfig({ ...window.__editor.config, arcOnIntersections: true, colorScheme: 'dark' });
});
await sleep(500);
await page.screenshot({ path: 'e2e/visual-dark.png' });
console.log('✓ e2e/visual-dark.png (dark scheme)');
await browser.close();
if (devServer) process.kill(-devServer.pid);
}
main().catch((e) => {
console.error(e);
if (devServer) process.kill(-devServer.pid);
process.exit(1);
});