test(#1923 follow-up): pin the packets window in the munger slide-over step (#1942)

Follow-up to #1923/#1924 — one of the row-dependent packets navigations
the pin sweep did not reach.

## The gap

`test-slideover-1168-munger-e2e.js` navigates to bare `#/packets` and
waits for `#pktTable tbody tr[data-action]` with an 8 s budget, on the
default client-side window (`since = now − 15 min`). It is one of the
row-dependent packets navigations #1924 did not reach. Most are already
immune: #1924 pinned `?timeWindow=1440` in `test-slideover-1056-e2e.js`,
`test-e2e-playwright.js` sets `meshcore-time-window=525600` in
`gotoPackets()` and in the #1791 Group-Data step, and
`test-issue-1122`/`1128` widen the window through the UI dropdown.

Three other row-dependent packets navigations in the same job share the
exposure and are **not** in this PR, to keep it to one file:
- `test-gestures-1062-e2e.js` and `test-touch-gestures-coverage-e2e.js`
also assert on the URL after in-app navigation, so a bare `?timeWindow=`
query leaks into those assertions (`#/packets?hash=…` becomes
`#/packets?timeWindow=1440&hash=…`); they want the localStorage window
path.
- the mobile branch of `test-observer-iata-1188-e2e.js` pins via
localStorage, which `packets.js:736` clamps back to 15 min above 180 on
a mobile viewport; switching it to the URL-param idiom this PR uses
(which is applied after that clamp) would fix it, but it is a separate
file.

I can send those separately.

(This step itself runs at an 800px viewport — `isMobile`, since the
breakpoint is `innerWidth <= 1024` — and the pin still works precisely
because the URL param is read after the mobile clamp, at
`packets.js:1091-1094`, not from the clamped localStorage value.)

## Why it matters now, with numbers

On two of the four master runs of 2026-09-02 this step executed at
**freshen+8:06** (run 33678488159) and **freshen+10:13** (run
33684614144) — margins of 6:54 and 4:47 before the fixture's newest rows
age out of the window. Every test added ahead of it shrinks that. The
suite as a whole is closer still: in run 33684614144 the third
repetition of the #1616 flake-gate ran **21:48:21→21:48:45 =
freshen+14:45→+15:09**, i.e. already past the 15-minute mark — it
survives only because of the #1924 pin.

## Verification

Reproduced without waiting for the clock: shift the freshened fixture 20
minutes back (`first_seen` and `observations.timestamp`) and start the
server on it —

| | aged fixture | fresh fixture |
|---|---|---|
| step without the pin (master) | **fails** (selector timeout) | passes
|
| step with the pin (this PR) | passes | passes 3/3 |

Same idiom and value as #1924, same caveat baked into the comment: the
value must be > 0, because `packets.js` only reads the param under
`_urlTimeWindow > 0`, so `timeWindow=0` silently keeps the default.

One observation from the same investigation, offered separately from
this PR: `tools/freshen-fixture.sh` computes its shift as `now −
MAX(first_seen)`; if the max ever sits in the future, the offset goes
negative and `printf('+%d seconds')` produces the invalid `'+-N
seconds'`. On the NOT NULL `transmissions.first_seen` that aborts the
script (set -e); on the nullable columns (`nodes.last_seen`, observers,
neighbor_edges) `strftime` silently returns NULL. A one-line clamp to ≥0
would make it safe to run around an insert. Happy to send that
separately if wanted.
This commit is contained in:
TeTeHacko
2026-09-03 18:21:47 +02:00
committed by GitHub
parent ab62e86d2d
commit f167d6f338
+8 -1
View File
@@ -121,7 +121,14 @@ function assert(c, m) { if (!c) throw new Error(m || 'assertion failed'); }
const page = await ctx.newPage();
page.setDefaultTimeout(8000);
page.on('pageerror', (e) => console.error('[pageerror]', e.message));
await page.goto(BASE + '/#/packets', { waitUntil: 'domcontentloaded' });
// #1923 follow-up: pin an explicit window so this step tests the munger
// slide-over rather than the clock, the same way #1924 pinned
// test-slideover-1056-e2e.js. The packets page defaults to
// `since = now - 15 min` client-side, and the freshened fixture's newest
// rows age out of that window ~15 minutes after freshen-fixture.sh runs.
// Must be > 0: packets.js reads the param only under `_urlTimeWindow > 0`,
// so `timeWindow=0` silently keeps the default.
await page.goto(BASE + '/#/packets?timeWindow=1440', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('#pktTable tbody tr[data-action]', { timeout: 8000 });
await step('hashchange: navigating away closes slide-over + releases scroll-lock', async () => {