tests: give the 17 bare dwell markers their documented why (determinism lint)
Some checks failed
wasm-build.yml / tests: give the 17 bare dwell markers their documented why (determinism lint) (push) Failing after 0s
CI full build + e2e (Ubicloud) / build (push) Has been cancelled
CI full build + e2e (Ubicloud) / Build all tools + KiCad e2e (Ubicloud) (push) Has been cancelled

The findings-E branch tightened lint:determinism to require
"documented interaction dwell: <why>" on every dwell marker; these six
specs landed on staging after that branch was cut, so the two only met
at merge time and the first staging CI run went red. Comment-only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Istvan Matejcsok 2026-09-01 09:36:26 +02:00
commit 766e2f409f
6 changed files with 17 additions and 17 deletions

View file

@ -126,7 +126,7 @@ test.describe('3D viewer close and reopen', () => {
// ...then let the wx-side op (wx_window_move → wxWindow::Move) fully land before // ...then let the wx-side op (wx_window_move → wxWindow::Move) fully land before
// close saves the frame position from the wx side (documented interaction dwell — // close saves the frame position from the wx side (documented interaction dwell —
// the DOM moves before the wx op completes; see 3d-viewer.spec.ts titlebar test). // the DOM moves before the wx op completes; see 3d-viewer.spec.ts titlebar test).
await page.waitForTimeout(500); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(500); // eslint-disable-line -- documented interaction dwell: the DOM observable fires before wx_window_move lands wx-side; close must save the settled wx position
const posBefore = await windowPos(page, winId); const posBefore = await windowPos(page, winId);
expect(posBefore, 'the 3D viewer window should have a position').not.toBeNull(); expect(posBefore, 'the 3D viewer window should have a position').not.toBeNull();

View file

@ -348,18 +348,18 @@ async function getPos(page: Page, id: string) {
async function moveWithM(page: Page, at: { x: number; y: number }, nudges: number) { async function moveWithM(page: Page, at: { x: number; y: number }, nudges: number) {
await page.mouse.move(at.x, at.y); await page.mouse.move(at.x, at.y);
await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell: pointer hover must settle so the tool picks the item under the cursor
await page.mouse.down(); await page.mouse.down();
await page.mouse.up(); await page.mouse.up();
await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell: click-select commit has no DOM observable
await page.keyboard.press("m"); await page.keyboard.press("m");
await page.waitForTimeout(400); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(400); // eslint-disable-line -- documented interaction dwell: move-tool activation has no DOM observable
for (let i = 0; i < nudges; i++) { for (let i = 0; i < nudges; i++) {
await page.keyboard.press("ArrowRight"); await page.keyboard.press("ArrowRight");
await page.waitForTimeout(150); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(150); // eslint-disable-line -- documented interaction dwell: each nudge repaint must land before the next key
} }
await page.keyboard.press("Enter"); await page.keyboard.press("Enter");
await page.waitForTimeout(500); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(500); // eslint-disable-line -- documented interaction dwell: move commit repaint has no DOM observable
} }
test.describe("P-3 `m` move twice per page", () => { test.describe("P-3 `m` move twice per page", () => {
@ -386,12 +386,12 @@ test.describe("P-3 `m` move twice per page", () => {
const mid = { x: Math.round((p0.x + p1.x) / 2), y: p0.y }; const mid = { x: Math.round((p0.x + p1.x) / 2), y: p0.y };
for (const p of [p0, p1]) { for (const p of [p0, p1]) {
await page.mouse.move(p.x, p.y); await page.mouse.move(p.x, p.y);
await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell: pointer hover must settle so the tool picks the item under the cursor
await page.mouse.down(); await page.mouse.down();
await page.mouse.up(); await page.mouse.up();
await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(350); // eslint-disable-line -- documented interaction dwell: click-select commit has no DOM observable
} }
await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell: the second selection must commit before Escape clears the tool
await page.keyboard.press("Escape"); await page.keyboard.press("Escape");
await page.keyboard.press("Escape"); await page.keyboard.press("Escape");
await expect.poll(async () => (await snapshotItems(page)).filter((i) => !idsBefore.has(i.id)).length, await expect.poll(async () => (await snapshotItems(page)).filter((i) => !idsBefore.has(i.id)).length,

View file

@ -109,9 +109,9 @@ async function loadEcc83(page: Page, testLogger: { consoleLogs: string[]; errors
}); });
if (!input) throw new Error('filename input not found'); if (!input) throw new Error('filename input not found');
await page.mouse.click(input.x, input.y); await page.mouse.click(input.x, input.y);
await page.waitForTimeout(200); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(200); // eslint-disable-line -- documented interaction dwell: focus caret must land in the wx text ctrl before typing
await page.keyboard.type(`${STEM}.kicad_pcb`); await page.keyboard.type(`${STEM}.kicad_pcb`);
await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell: typed filename must flush to the wx text ctrl before Enter confirms
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
const result = await waitForBoardLoaded(page, testLogger, 60000); const result = await waitForBoardLoaded(page, testLogger, 60000);
console.log(`[TEST] ecc83 board-ready result: ${result}`); console.log(`[TEST] ecc83 board-ready result: ${result}`);

View file

@ -116,9 +116,9 @@ async function loadOldBoard(page: Page, testLogger: { consoleLogs: string[]; err
}); });
if (!input) throw new Error('filename input not found'); if (!input) throw new Error('filename input not found');
await page.mouse.click(input.x, input.y); await page.mouse.click(input.x, input.y);
await page.waitForTimeout(200); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(200); // eslint-disable-line -- documented interaction dwell: focus caret must land in the wx text ctrl before typing
await page.keyboard.type(`${STEM}.kicad_pcb`); await page.keyboard.type(`${STEM}.kicad_pcb`);
await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell: typed filename must flush to the wx text ctrl before Enter confirms
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
const result = await waitForBoardLoaded(page, testLogger, 60000); const result = await waitForBoardLoaded(page, testLogger, 60000);
console.log(`[TEST] old board-ready result: ${result}`); console.log(`[TEST] old board-ready result: ${result}`);

View file

@ -168,14 +168,14 @@ for (const kind of ["selection", "xsel"] as const) {
expect(await removeItem(page, WIRE1)).toBe(true); expect(await removeItem(page, WIRE1)).toBe(true);
// Documented interaction dwell: the overlay repaint has no observable signal // Documented interaction dwell: the overlay repaint has no observable signal
// — settledShot below compares stable frames, this only lets it queue. // — settledShot below compares stable frames, this only lets it queue.
await page.waitForTimeout(1500); // eslint-disable-line -- documented interaction dwell await page.waitForTimeout(1500); // eslint-disable-line -- documented interaction dwell: the overlay repaint after delete has no observable; settledShot below only compares stable frames
const afterDelete = await settledShot(canvas); const afterDelete = await settledShot(canvas);
// Ground truth for "what the overlay should look like now": force the // Ground truth for "what the overlay should look like now": force the
// overlay to rebuild from the SAME peer snapshot — WIRE1 no longer // overlay to rebuild from the SAME peer snapshot — WIRE1 no longer
// resolves, so nothing is drawn for it. // resolves, so nothing is drawn for it.
await setRemote(page, { peers: [peer] }); await setRemote(page, { peers: [peer] });
await page.waitForTimeout(1500); // eslint-disable-line -- documented interaction dwell (overlay rebuild, no observable) await page.waitForTimeout(1500); // eslint-disable-line -- documented interaction dwell: the overlay rebuild from the pushed peer snapshot has no observable
const afterRepush = await settledShot(canvas); const afterRepush = await settledShot(canvas);
expect( expect(

View file

@ -90,10 +90,10 @@ test('P-1 standalone: fit lands after a keyboard rotate of a clicked footprint',
const sx = box.x + (fp.x - vp.cx) * vp.scale + vp.w / 2; const sx = box.x + (fp.x - vp.cx) * vp.scale + vp.w / 2;
const sy = box.y + (fp.y - vp.cy) * vp.scale + vp.h / 2; const sy = box.y + (fp.y - vp.cy) * vp.scale + vp.h / 2;
await page.mouse.move(sx, sy); await page.mouse.move(sx, sy);
await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell (pointer hover before press) await page.waitForTimeout(300); // eslint-disable-line -- documented interaction dwell: pointer hover must settle before press so the tool picks the item under the cursor
await page.mouse.down(); await page.mouse.down();
await page.mouse.up(); await page.mouse.up();
await page.waitForTimeout(400); // eslint-disable-line -- documented interaction dwell (selection tool commit) await page.waitForTimeout(400); // eslint-disable-line -- documented interaction dwell: selection-tool commit has no DOM observable
return (await selection()).includes(fp.id); return (await selection()).includes(fp.id);
}, { timeout: 15000, intervals: [500], message: 'click-select of the first footprint' }).toBe(true) }, { timeout: 15000, intervals: [500], message: 'click-select of the first footprint' }).toBe(true)
.then(() => true, () => false); .then(() => true, () => false);