diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76018d4..aee5a55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: env: CARTOLITE_BASE_URL: http://127.0.0.1:39476 PLAYWRIGHT_HTML_OUTPUT_DIR: focused-playwright-report - run: npm run test:e2e -- --grep '@terrain|@world' --output focused-test-results + run: npm run test:e2e -- --grep '@terrain|@world|@regions' --output focused-test-results - name: Complete desktop and mobile browser suite if: matrix.arch == 'amd64' working-directory: web @@ -170,7 +170,7 @@ jobs: ) & publisher_pid=$! trap 'kill "$publisher_pid" >/dev/null 2>&1 || true' EXIT - npm run test:e2e -- --grep-invert '@terrain|@world' + npm run test:e2e -- --grep-invert '@terrain|@world|@regions' - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: scan-type: image diff --git a/web/e2e/netgraph-regions.spec.ts b/web/e2e/netgraph-regions.spec.ts index b840644..80460e5 100644 --- a/web/e2e/netgraph-regions.spec.ts +++ b/web/e2e/netgraph-regions.spec.ts @@ -34,7 +34,7 @@ async function layoutPanel(page: Page) { await page.locator('.graph-layout > summary').click(); } -test('spacing and dragging survive refresh while live packets keep their routes and clock', async ({ page, context }, info) => { +test('spacing and dragging survive refresh while live packets keep their routes and clock @regions', async ({ page, context }, info) => { if (info.project.name === 'mobile') await page.setViewportSize({ width: 320, height: 640 }); await fixture(page); await page.emulateMedia({ reducedMotion: 'reduce' }); await page.goto('/netgraph/'); const stage = page.locator('#netgraph-stage'); @@ -55,6 +55,7 @@ test('spacing and dragging survive refresh while live packets keep their routes await expect.poll(() => stage.getAttribute('data-view-tilt').then(Number)).toBeCloseTo(Math.PI / 4, 3); const code = Object.keys(first.centres)[0]!; const point = await page.evaluate(code => (window as unknown as { regionHandles: Record }).regionHandles[code]!, code); + expect(point).toBeTruthy(); expect(Number.isFinite(point.x) && Number.isFinite(point.y)).toBe(true); const camera = await stage.getAttribute('data-view-center'); const touch = info.project.name !== 'desktop' ? await context.newCDPSession(page) : null; if (touch) { @@ -103,7 +104,7 @@ test('spacing and dragging survive refresh while live packets keep their routes expect(page.url()).toContain('/netgraph/'); }); -test('checkbox regions filter topology, search and Follow and retain their device selection', async ({ page }, info) => { +test('checkbox regions filter topology, search and Follow and retain their device selection @regions', async ({ page }, info) => { await fixture(page); await page.emulateMedia({ reducedMotion: 'reduce' }); await page.goto('/netgraph/'); const stage = page.locator('#netgraph-stage'); await expect(stage).toHaveAttribute('data-render-state', 'idle'); await page.locator('#find-button').click(); await page.locator('#node-search').fill('Visual Charlie'); diff --git a/web/src/netgraph/regionControls.ts b/web/src/netgraph/regionControls.ts index a367145..d01e64c 100644 --- a/web/src/netgraph/regionControls.ts +++ b/web/src/netgraph/regionControls.ts @@ -5,7 +5,7 @@ export function mountRegionControls(graph: NetgraphRenderer, host: HTMLElement, const stage = document.getElementById('netgraph-stage')!; const navigate = () => stage.dispatchEvent(new Event('graphnavigate')); const measure = () => document.documentElement.style.setProperty('--graph-controls-bottom', `${Math.ceil(host.getBoundingClientRect().bottom)}px`); - const resize = new ResizeObserver(measure); resize.observe(host); + const resize = typeof ResizeObserver === 'function' ? new ResizeObserver(measure) : undefined; resize?.observe(host); window.addEventListener('resize', measure); measure(); const menu = graphTemplate('graph-regions-ui'); const summary = menu.querySelector('summary')!, search = menu.querySelector('input')!, list = menu.querySelector('.region-checks')!; @@ -70,5 +70,5 @@ export function mountRegionControls(graph: NetgraphRenderer, host: HTMLElement, } } sync(); - return { sync, destroy() { resize.disconnect(); window.removeEventListener('resize', measure); document.removeEventListener('pointerdown', dismiss); menu.remove(); routes.remove(); layout.remove(); } }; + return { sync, destroy() { resize?.disconnect(); window.removeEventListener('resize', measure); document.removeEventListener('pointerdown', dismiss); menu.remove(); routes.remove(); layout.remove(); } }; }