mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-09-14 13:25:35 +00:00
Closes #1923.
## What was wrong
`test-slideover-1056-e2e.js` runs twice in CI: inside the main E2E
suite, and again as the #1616 flake-gate, which is the last step before
coverage collection. That second run starts roughly 20 minutes after
`tools/freshen-fixture.sh` set the fixture's newest packet to "now".
The packets page defaults to a 15-minute time window
(`DEFAULT_TIME_WINDOW`, `public/packets.js:746`). By the time the
flake-gate runs, every fixture packet is outside it, the table renders
zero data rows, and `packets@800: page renders + first row exists` times
out after 30s. The two tests that need a row to click fail with it, so
one expired window reports as three failures.
Whether it fires depends on how long the preceding suite took, which is
why it read as flake and hit PRs that cannot have caused it. #1760 (a
frontend analytics tab, 2026-07-09) and #1872 (Go-only, deletes a dead
struct field, 2026-07-28) failed on the identical three tests three
weeks apart, and neither touches the packets page.
## The change
Pin `?timeWindow=1440` on both packets navigations in that file, so it
tests the slide-over rather than the clock. Two lines plus the comment
explaining why, no product code touched.
The value must be greater than 0. `public/packets.js:1092` reads the
parameter under `_urlTimeWindow > 0`, so `timeWindow=0` does **not**
disable the filter, it silently leaves the 15-minute default in place.
That is worth knowing before anyone "simplifies" it to zero.
## Verification
Reproduced first, then fixed. All against `upstream/master` a06ac8ac
with the server on the committed fixture:
| fixture age | change | result |
|---|---|---|
| 22 min | without | the exact three CI failures, verbatim |
| 26 min | with | 27 passed, 0 failed |
| 186 min | with | 27 passed, 0 failed |
| 186 min | with, 3 consecutive runs on one backend (as the flake-gate
does) | 27 passed each time |
| unaged | with | 27 passed, 0 failed |
## What this does not do
Two adjacent problems, both pre-existing and both left alone so this
stays reviewable:
- `wide@1440 packets` waits on `#pktTable tbody tr`, which also matches
the virtual-scroll spacer row, so it passed even when there were zero
data rows. It was testing nothing on every affected run.
- The two dependent steps fail rather than skip when the first step
found no row. That is what turns one root cause into three reported
failures.
Happy to take either as a follow-up. Should they be one PR or two?
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Wzwr3eXseyNM7Xj598djjE
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,8 +38,24 @@ step.skip = function (name, reason, fn) {
|
||||
};
|
||||
function assert(c, m) { if (!c) throw new Error(m || 'assertion failed'); }
|
||||
|
||||
// The packets page defaults to a 15-minute time window (DEFAULT_TIME_WINDOW in
|
||||
// public/packets.js). CI freshens the fixture once at the start of the e2e job,
|
||||
// and this file runs twice: inside the main suite, and again as the #1616
|
||||
// flake-gate AFTER every other E2E — roughly 20 minutes later. By then every
|
||||
// fixture packet is older than 15 minutes, the packets table renders zero data
|
||||
// rows, and `packets@800: page renders + first row exists` times out after 30s.
|
||||
// The two tests that need a row to click then fail with it, so one expired
|
||||
// window reports as three failures. Whether it fires depends on how long the
|
||||
// preceding suite took, which is why it looked like flake and hit unrelated PRs.
|
||||
//
|
||||
// Pin an explicit window so this file tests the slide-over rather than the
|
||||
// clock. The value must be > 0: packets.js only reads the param under
|
||||
// `_urlTimeWindow > 0`, so `timeWindow=0` does NOT disable the filter, it
|
||||
// silently leaves the 15-minute default in place.
|
||||
const PACKETS_QUERY = '?timeWindow=1440';
|
||||
|
||||
const PAGES = [
|
||||
{ hash: '#/packets', tableSel: '#pktTable', rowSel: '#pktTable tbody tr[data-hash]', name: 'packets' },
|
||||
{ hash: '#/packets' + PACKETS_QUERY, tableSel: '#pktTable', rowSel: '#pktTable tbody tr[data-hash]', name: 'packets' },
|
||||
{ hash: '#/nodes', tableSel: '#nodesTable', rowSel: '#nodesTable tbody tr[data-value]', name: 'nodes' },
|
||||
{ hash: '#/observers', tableSel: '#obsTable', rowSel: '#obsTable tbody tr[data-action="navigate"]', name: 'observers' },
|
||||
];
|
||||
@@ -701,7 +717,7 @@ const PAGES = [
|
||||
page.setDefaultTimeout(8000);
|
||||
|
||||
await step('wide@1440 packets: row click does NOT open slide-over', async () => {
|
||||
await page.goto(BASE + '/#/packets', { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(BASE + '/#/packets' + PACKETS_QUERY, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForSelector('#pktTable', { timeout: 8000 });
|
||||
await page.waitForFunction(() => document.querySelectorAll('#pktTable tbody tr').length > 0, null, { timeout: 8000 });
|
||||
await page.evaluate(() => {
|
||||
|
||||
Reference in New Issue
Block a user