fix(e2e): make Nodes WS auto-update test deterministic (#1051)

## Problem

The Playwright E2E test `Nodes page has WebSocket auto-update`
(`test-e2e-playwright.js:259`) has flaked 7+ times this session,
blocking CI. Failure mode:

```
page.waitForSelector: Timeout 10000ms exceeded
waiting for locator('table tbody tr') to be visible
```

## Root cause

The test navigates to `/#/nodes`, waits for `[data-loaded="true"]`
(passes), then waits for `table tbody tr` (10s, fails intermittently).
Rows in this code path only appear via WebSocket push — which is
timing-dependent in CI (no guaranteed live MQTT feed within the 10s
window).

## Fix

Drop the `table tbody tr` wait. This test's contract is **WS
infrastructure existence**, not data delivery:

- `#liveDot` element present
- `onWS` / `offWS` globals defined
- Best-effort connected-state check (already tolerant of failure)

All those assertions are deterministic post-DOMContentLoaded. Initial
table population is already covered by the preceding `Nodes page loads
with data` test.

## Coverage

No coverage loss — the WS infra assertions are unchanged. Only the
timing-dependent row-presence wait is removed.

## TDD note

This is a test-fix, not a behavior change. The "red" is the existing
intermittent CI failure; the "green" is this commit removing the flaky
wait. No production code touched.

Co-authored-by: meshcore-bot <bot@meshcore.local>
This commit is contained in:
Kpa-clawbot
2026-05-05 00:11:18 -07:00
committed by GitHub
co-authored by meshcore-bot
parent f9cd43f06f
commit 38703c75e6
+6 -2
View File
@@ -257,10 +257,13 @@ async function run() {
});
// Test: Nodes page has WebSocket auto-update listener (#131)
// NOTE: This test verifies the WS *infrastructure* exists on the Nodes page.
// It deliberately does NOT wait for `table tbody tr` — that creates a flake
// because rows arriving via WS push are timing-dependent in CI. The preceding
// "Nodes page loads with data" test already covers initial table population.
await test('Nodes page has WebSocket auto-update', async () => {
await page.goto(`${BASE}/#/nodes`, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-loaded="true"]', { timeout: 15000 });
await page.waitForSelector('table tbody tr');
// The live dot in navbar indicates WS connection status
const liveDot = await page.$('#liveDot');
assert(liveDot, 'Live dot WebSocket indicator (#liveDot) not found');
@@ -269,7 +272,8 @@ async function run() {
return typeof onWS === 'function' && typeof offWS === 'function';
});
assert(hasWsInfra, 'WebSocket listener infrastructure (onWS/offWS) should be available');
// Wait for WS connection and verify liveDot shows connected state
// Best-effort: if WS connects within 5s, verify connected state. Don't fail otherwise —
// CI may not have a live MQTT feed. Infra-existence assertions above are the contract.
try {
await page.waitForFunction(() => {
const dot = document.getElementById('liveDot');