Repository navigation
A browser test proves an idle console stays quiet on a 50-worker fleet #918
Description
Part of #905.
Scope
A browser-lane test proves that an idle console tab on a 50-worker fleet stays at or under 40 requests a minute on every page, so a return to per-second polling fails CI.
In short
The test opens each of the seven pages against a gateway whose /v1/workers answer is stubbed with 50 workers and 500 devices and whose /v1/leases answer is stubbed with 300 leases. Once the page's first reads have answered, it counts the requests to /v1 over the next 60 s, the event stream not counted.
flowchart LR
P[Playwright page] --> F["stubs: 50 workers, 500 devices, 300 leases"] --> D[real gateway daemon]
P --> C["request counter (new)"]
If it goes wrong: the test is flaky on a slow CI machine, or passes while a page still polls fast.
Technical spec
Facts
| # | Fact | Source |
|---|---|---|
| F1 | long-lists.spec.ts stubs a route's answer on top of the daemon's own response with page.route + route.fulfill({ json, response }), keeping real headers; its answer helper is local to that file. |
e2e/console/long-lists.spec.ts:115-127 |
| F2 | startDaemon("gateway") starts a real gateway with HTTP on a free loopback port and no workers, so its own /v1/workers answer is empty. |
e2e/console/fixtures.ts:229-300, 426-484 |
| F3 | NAV lists the seven pages; openFromNav opens one; settled waits only for the page's slide and fade animations. |
e2e/console/fixtures.ts:748-781, 765-772 |
| F4 | The configured test timeout is 60 s per test. | playwright.config.ts:13 |
| F5 | The console casts /v1/workers without validating it. |
ui/src/data/api.ts:147-151 |
| F6 | The idle ceiling and its window. | #905 Shared values "Idle ceiling" |
| F7 | The poll intervals live in ui/src/state/queries.ts after #914. |
#914 Modules touched |
Modules touched
e2e/console/big-fleet.spec.ts (new: one test that visits the seven pages in turn, with test.setTimeout(10 * 60_000)), e2e/console/stub-answers.ts (new: answer moved out of long-lists.spec.ts, dropping If-None-Match before route.fetch() so a stub always edits a full answer, as #916 does for the other stubs), e2e/console/long-lists.spec.ts (imports it), a 50-worker builder typed as WorkerView from src/contract/worker-view.ts (F5). Searches: page.route( and function answer in e2e/console.
Contract and event changes
None.
Other code on the same state
None: the stubs and the counter live in the test's own page. Searches: page.on("request" in e2e/ (none to share).
Failure modes
| Call | Outcome | What happens | Limit, counted from |
|---|---|---|---|
| page load | slow, or never quiet | the 60 s window starts once no /v1 request other than the stream has been sent for 2 s, or 15 s after navigation, whichever comes first; so a page that polls every second fails on the count, not on a timeout |
10 min for the test (F4 overridden) |
| stubbed read | the daemon answers 304 | cannot happen: the stub drops If-None-Match |
— |
Rules in play
- Testing rules: browser lane, no devices; stubs keep the daemon's real headers and a contract-typed body (F1, F5).
Tests
Seam: the console browser lane, modelled on e2e/console/long-lists.spec.ts.
- An idle console on a big fleet stays quiet: for each of the seven pages (Overview, Inbox, Fleet, Leases, Queue, Activity, Usage), in the 60 s after its first reads → at most 40 requests to
/v1other than/v1/events/stream.
Done when
- The console browser lane passes with
big-fleet.spec.ts. - Setting the intervals in
ui/src/state/queries.ts(F7) back to 1 s makes it fail (reviewer may check locally).
Out of scope
CPU or render-time budgets; event bursts (proven in #914's unit tests).
Depends on
Written by an agent.
Activity
[-]One shared recent-events list, bounded history, and a cheaper clock[/-][+]A browser test proves an idle console stays quiet on a 50-worker fleet[/+]test(console): an idle console on a 50-worker fleet stays under 40 re…