From a40e629fde12badd6a298de6fbf6a3bd19eb9745 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Sat, 3 Oct 2026 18:16:59 +0200 Subject: [PATCH] Make e2e 56 pass on its own, not only after module 55 (#307) Check 56a-ii clicks the read-only value of a private variable and types into it. A read-only field takes no focus, so typeText found no input and threw when the module ran alone. In the full run the keystroke went into whatever input an earlier module had left focused, and the check was green by luck. - New harness helper typeBlind sends the keystrokes without checking where they land. It is meant for keystrokes that should be refused. - 56a-ii now also checks that no field holds the focus after the click (__gm.focusedRect() is null), the same way module 28 checks its read-only Asset row. - No other module types into a field that is meant to be locked. Tests: - e2e 56 alone: ALL PASSED, 10 checks (was E2E EXIT 1 before) - e2e 55,56: ALL PASSED, 27 checks - Counter-check with the second lock click left out: 56a-ii fails with a focused field and timer 9, three later checks follow - Gate: 229 files, 3514 tests, CHECK EXIT 0 Co-Authored-By: Claude Opus 5.5 --- tools/e2e/56-private-variables.mjs | 12 +++++++----- tools/lib/harness.mjs | 6 ++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/e2e/56-private-variables.mjs b/tools/e2e/56-private-variables.mjs index fb6fd060..886456af 100644 --- a/tools/e2e/56-private-variables.mjs +++ b/tools/e2e/56-private-variables.mjs @@ -97,10 +97,12 @@ export async function privateVariables(t) { ); await press_((await locks())[1], 'the lock of timer, again'); - // 56a-ii. While locked the value is read-only: typing into it changes nothing, hp still takes a value. + // 56a-ii. While locked the value is read-only: a click into it leaves no field focused, so typing + // changes nothing. hp still takes a value. await sleep(150); await press_(await json("__gm.inspectorField('timer')"), 'timer value'); - await typeText('9'); + const focusedAfter = await json('__gm.focusedRect()'); + await t.typeBlind('9'); await press('Enter'); await press_(await json("__gm.inspectorField('hp')"), 'hp value'); await press('a', { ctrl: true }); @@ -109,9 +111,9 @@ export async function privateVariables(t) { await sleep(150); const defaults = (await brain()).props; check( - 'the value of the private timer is read-only, hp still takes a new one', - defaults.timer === 42 && defaults.hp === 8, - JSON.stringify(defaults), + 'the value of the private timer is read-only and takes no focus, hp still takes a new one', + focusedAfter === null && defaults.timer === 42 && defaults.hp === 8, + JSON.stringify({ focusedAfter, ...defaults }), ); // 56b. The placed object shows hp only; its Variables tab builds the same rows. diff --git a/tools/lib/harness.mjs b/tools/lib/harness.mjs index e1ebc7f1..73a1c2ac 100644 --- a/tools/lib/harness.mjs +++ b/tools/lib/harness.mjs @@ -363,6 +363,11 @@ function makeTools({ cdp, projectId, baseUrl, consoleLog, check, shotPrefix }) { ); await settle(); }; + /** Types without checking where it lands, for keystrokes that are meant to be refused. */ + const typeBlind = async (text) => { + for (const ch of text) await cdp.send('Input.insertText', { text: ch }); + await settle(); + }; const undo = async () => { await press('z', { ctrl: true }); }; @@ -517,6 +522,7 @@ function makeTools({ cdp, projectId, baseUrl, consoleLog, check, shotPrefix }) { keyDown, keyUp, typeText, + typeBlind, undo, redo, state,