From 80dd82349d6c5c514f63c3b77f515599bfb60fdc Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Mon, 14 Sep 2026 19:14:57 +0200 Subject: [PATCH] The + menu holds fourteen types now, so scrolling one into view belongs to the scaffold (#91) `Variables` pushed `Font` under the menu's mask edge: `locate` still finds the entry, a click there lands on nothing, `__gm.fontPicker()` is null and reading `.captions` throws. Only step 31 carried the scroll workaround, so step 30 fell. The helper moves to `lib/scaffold.mjs` as `pickAssetType()` and both steps use it. Co-Authored-By: Claude Opus 5 --- tools/e2e/30-font.mjs | 4 ++-- tools/e2e/31-particles.mjs | 24 +++--------------------- tools/e2e/lib/scaffold.mjs | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/tools/e2e/30-font.mjs b/tools/e2e/30-font.mjs index 3036cf3f..1e293834 100644 --- a/tools/e2e/30-font.mjs +++ b/tools/e2e/30-font.mjs @@ -1,4 +1,4 @@ -import { LANES } from './lib/scaffold.mjs'; +import { LANES, pickAssetType } from './lib/scaffold.mjs'; /** * Font assets (#74): uploaded like a picture – picked from what the server holds through "+ → Font", @@ -67,7 +67,7 @@ export async function font(t) { await evaluate('__gm.console.clear()'); await clickText('+'); await sleep(200); - await clickLast('Font'); + await pickAssetType(t, 'Font'); await sleep(500); const picker = await json('__gm.fontPicker()'); check( diff --git a/tools/e2e/31-particles.mjs b/tools/e2e/31-particles.mjs index 53c0435b..32a611ff 100644 --- a/tools/e2e/31-particles.mjs +++ b/tools/e2e/31-particles.mjs @@ -1,5 +1,5 @@ import { colourDistance } from '../lib/harness.mjs'; -import { LANES } from './lib/scaffold.mjs'; +import { LANES, pickAssetType } from './lib/scaffold.mjs'; /** * Particle assets (#73): a graph that says what one particle *is* as a function of its age and of a @@ -17,7 +17,7 @@ const RATE = 20; export async function particles(t) { const { check, sleep, json, evaluate, mutate, click, clickText, locate, typeText, press, shot } = t; - const { wheel, drag } = t; + const { drag } = t; const { select } = t; /** Freeze, restart every source's clock, then step the clock to `seconds` and let it redraw. */ const at = async (seconds) => { @@ -40,24 +40,6 @@ export async function particles(t) { await click(p.x, p.y); await sleep(200); }; - /** - * The `+` menu has one entry per asset type and scrolls past 320 px, so the last of them sits - * under the mask: `locate` still finds it, but a click there lands on nothing. Scroll it in first. - */ - const pickFromMenu = async (label) => { - const box = await json('__gm.overlayRect()'); - let p = await locate(label, true); - let scrolled = false; - if (box && (!p || p.y > box.y + box.h - 4)) { - await wheel(box.x + box.w / 2, box.y + box.h / 2, 300); - await sleep(250); - p = await locate(label, true); - scrolled = true; - } - await click(p.x, p.y); - await sleep(250); - return { box, p, scrolled }; - }; /** Places a node from the palette. The list scrolls, so the name is searched into view first. */ const placeNodeAt = async (label, point) => { await click(point.x, point.y, 'right'); @@ -105,7 +87,7 @@ export async function particles(t) { await evaluate('__gm.console.clear()'); await clickText('+'); await sleep(200); - const picked = await pickFromMenu('Particles'); + const picked = await pickAssetType(t, 'Particles'); await sleep(400); const created = await json(`{ tab: __gm.tab(), diff --git a/tools/e2e/lib/scaffold.mjs b/tools/e2e/lib/scaffold.mjs index c367ed4f..eae48742 100644 --- a/tools/e2e/lib/scaffold.mjs +++ b/tools/e2e/lib/scaffold.mjs @@ -129,3 +129,24 @@ export async function openTab(t, tab) { await t.clickText(TAB_LABELS[tab]); await t.sleep(400); } + +/** + * Picks an asset type from the already-open `+` menu. The menu has one entry per type and scrolls + * past 320 px, so the last of them sit under the mask: `locate` still finds them, but a click there + * lands on nothing. The fourteenth type (`Variables`, #91) pushed `Font` under that edge and took + * step 30 down with it, because only step 31 had scrolled first. + */ +export async function pickAssetType(t, label) { + const box = await t.json('__gm.overlayRect()'); + let p = await t.locate(label, true); + let scrolled = false; + if (box && (!p || p.y > box.y + box.h - 4)) { + await t.wheel(box.x + box.w / 2, box.y + box.h / 2, 300); + await t.sleep(250); + p = await t.locate(label, true); + scrolled = true; + } + await t.click(p.x, p.y); + await t.sleep(250); + return { box, p, scrolled }; +}