diff --git a/tools/e2e/12-textures.mjs b/tools/e2e/12-textures.mjs index a8b60f60..57ba5fab 100644 --- a/tools/e2e/12-textures.mjs +++ b/tools/e2e/12-textures.mjs @@ -1,5 +1,5 @@ import { colourDistance } from '../lib/harness.mjs'; -import { inView } from './lib/scaffold.mjs'; +import { inView, pickAssetType } from './lib/scaffold.mjs'; /** * Uploading a picture and wearing it. Runs last because it adds an asset and repaints the @@ -41,7 +41,7 @@ const PASTE_SPARE = `(async () => { export async function textures(t) { const { check, sleep, json, evaluate, shot, mutate, press } = t; - const { api, click, clickText, doubleClick, locate, undo, play, stop } = t; + const { api, click, clickText, doubleClick, undo, play, stop } = t; // The previous step leaves a picker open and a text field focused, and paste is deliberately // ignored while an input has focus, so that Ctrl+V inside a field still edits text. @@ -327,9 +327,9 @@ export async function textures(t) { await evaluate('__gm.console.clear()'); await clickText('+'); // By position, not by text: the menu entry "Texture" shares its label with the centre tab, and - // `locate` would hand back whichever it walked into first. - const entry = await locate('Texture', true); - await click(entry.x, entry.y); + // `locate` would hand back whichever it walked into first. The menu scrolls once it outgrows the + // screen, and "Texture" sits near its end. + await pickAssetType(t, 'Texture'); await sleep(1500); const picker = await json('__gm.imagePicker()'); const stored = (await api('textures')).map((item) => item.file); @@ -429,8 +429,7 @@ export async function textures(t) { // Reusing a file already in the project must not make a second asset on it – two assets on one // picture would disagree about its filter. await clickText('+'); - const entryAgain = await locate('Texture', true); - await click(entryAgain.x, entryAgain.y); + await pickAssetType(t, 'Texture'); await sleep(1500); const reopened = await json('__gm.imagePicker()'); check( diff --git a/tools/e2e/26-state-machine.mjs b/tools/e2e/26-state-machine.mjs index a131c47b..b3cc2cd7 100644 --- a/tools/e2e/26-state-machine.mjs +++ b/tools/e2e/26-state-machine.mjs @@ -1,5 +1,5 @@ import { edge, node } from '../lib/builders.mjs'; -import { LANES, scaffoldBehavior } from './lib/scaffold.mjs'; +import { LANES, pickAssetType, scaffoldBehavior } from './lib/scaffold.mjs'; /** * State machines: an asset made from the + menu, its states edited as nodes in the State machine @@ -51,7 +51,7 @@ export async function stateMachine(t) { // 26a. The + menu creates a state machine; selected, it opens its own tab. await clickText('+'); - await clickLast('State machine'); + await pickAssetType(t, 'State machine'); const made = (await machines())[0]; check( 'the + menu creates a state machine asset', diff --git a/tools/e2e/28-shader.mjs b/tools/e2e/28-shader.mjs index 1d538acf..652994b4 100644 --- a/tools/e2e/28-shader.mjs +++ b/tools/e2e/28-shader.mjs @@ -7,6 +7,7 @@ import { PASTE_DOT, PASTE_HALVES, } from './lib/pictures.mjs'; +import { pickAssetType } from './lib/scaffold.mjs'; /** * Shader assets: made from the + menu, built from nodes in the Shader tab, worn by a sprite through @@ -67,7 +68,7 @@ export async function shader(t) { JSON.stringify(seeded), ); await clickText('+'); - await clickLast('Shader'); + await pickAssetType(t, 'Shader'); const made = (await shaders()).find((s) => s.id !== ADJUST); const selection = await json('__gm.state.selection'); check( diff --git a/tools/e2e/lib/scaffold.mjs b/tools/e2e/lib/scaffold.mjs index 48970222..e3e98a30 100644 --- a/tools/e2e/lib/scaffold.mjs +++ b/tools/e2e/lib/scaffold.mjs @@ -203,16 +203,17 @@ export async function clickDocumentTab(t, doc) { /** * Picks an asset type from the already-open `+` menu. Since #43 the menu may grow to the height of - * the canvas, so on this window every type is usually on screen at once; the scroll stays in as - * insurance for a shorter window, where entries below the mask edge are still found by `locate` - * but a click there lands on nothing. That is what the fourteenth type (`Variables`, #91) did to - * `Font` and to step 30. + * the canvas, and since the Instrument (#331) its last entries can sit below the fold of this + * window (`Texture` in step 12). `locate` refuses a row scrolled out of its list, so the first look is `find`, + * and a hit outside the menu (the centre tab "Texture") counts as a miss. */ export async function pickAssetType(t, label) { const box = await t.json('__gm.overlayRect()'); - let p = await t.locate(label, true); + let p = await t.find(label, true); let scrolled = false; - if (box && (!p || p.y > box.y + box.h - 4)) { + const inMenu = (at) => + at && at.x >= box.x && at.x <= box.x + box.w && at.y >= box.y && at.y <= box.y + box.h - 4; + if (box && !inMenu(p)) { await t.wheel(box.x + box.w / 2, box.y + box.h / 2, 300); p = await t.locate(label, true); scrolled = true;