Find asset types below the fold of the + menu in e2e #331
Since the Instrument joined the + menu, its last entries can sit
below the fold of the test window. CI for 8a4e4a6 stopped in step 12
with 'widget with text "Texture" not found', and every step after it
was skipped.
- pickAssetType looked first with locate, which throws on a row
scrolled out of its list. So it never reached its own scroll. It
now looks with find and scrolls when the hit is not in the menu.
- A hit outside the menu counts as a miss, so the centre tab
"Texture" cannot take the click meant for the entry.
- Steps 12, 26 and 28 picked their entry by hand and now go through
pickAssetType ("Texture", "State machine", "Shader").
Tests:
- e2e 1-12, 26, 28 (melektaus-atx): ALL PASSED, 635 checks.
Before the fix step 12 failed there as in CI.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
144dee0a97
commit
6f1f31516f
4 files changed
+17
-16
No files matched your search
@@ -1,5 +1,5 @@
|
|||||||
import { colourDistance } from '../lib/harness.mjs';
|
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
|
* 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) {
|
export async function textures(t) {
|
||||||
const { check, sleep, json, evaluate, shot, mutate, press } = 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
|
// 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.
|
// 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 evaluate('__gm.console.clear()');
|
||||||
await clickText('+');
|
await clickText('+');
|
||||||
// By position, not by text: the menu entry "Texture" shares its label with the centre tab, and
|
// 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.
|
// `locate` would hand back whichever it walked into first. The menu scrolls once it outgrows the
|
||||||
const entry = await locate('Texture', true);
|
// screen, and "Texture" sits near its end.
|
||||||
await click(entry.x, entry.y);
|
await pickAssetType(t, 'Texture');
|
||||||
await sleep(1500);
|
await sleep(1500);
|
||||||
const picker = await json('__gm.imagePicker()');
|
const picker = await json('__gm.imagePicker()');
|
||||||
const stored = (await api('textures')).map((item) => item.file);
|
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
|
// 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.
|
// picture would disagree about its filter.
|
||||||
await clickText('+');
|
await clickText('+');
|
||||||
const entryAgain = await locate('Texture', true);
|
await pickAssetType(t, 'Texture');
|
||||||
await click(entryAgain.x, entryAgain.y);
|
|
||||||
await sleep(1500);
|
await sleep(1500);
|
||||||
const reopened = await json('__gm.imagePicker()');
|
const reopened = await json('__gm.imagePicker()');
|
||||||
check(
|
check(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { edge, node } from '../lib/builders.mjs';
|
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
|
* 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.
|
// 26a. The + menu creates a state machine; selected, it opens its own tab.
|
||||||
await clickText('+');
|
await clickText('+');
|
||||||
await clickLast('State machine');
|
await pickAssetType(t, 'State machine');
|
||||||
const made = (await machines())[0];
|
const made = (await machines())[0];
|
||||||
check(
|
check(
|
||||||
'the + menu creates a state machine asset',
|
'the + menu creates a state machine asset',
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
PASTE_DOT,
|
PASTE_DOT,
|
||||||
PASTE_HALVES,
|
PASTE_HALVES,
|
||||||
} from './lib/pictures.mjs';
|
} 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
|
* 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),
|
JSON.stringify(seeded),
|
||||||
);
|
);
|
||||||
await clickText('+');
|
await clickText('+');
|
||||||
await clickLast('Shader');
|
await pickAssetType(t, 'Shader');
|
||||||
const made = (await shaders()).find((s) => s.id !== ADJUST);
|
const made = (await shaders()).find((s) => s.id !== ADJUST);
|
||||||
const selection = await json('__gm.state.selection');
|
const selection = await json('__gm.state.selection');
|
||||||
check(
|
check(
|
||||||
|
|||||||
@@ -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
|
* 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
|
* the canvas, and since the Instrument (#331) its last entries can sit below the fold of this
|
||||||
* insurance for a shorter window, where entries below the mask edge are still found by `locate`
|
* window (`Texture` in step 12). `locate` refuses a row scrolled out of its list, so the first look is `find`,
|
||||||
* but a click there lands on nothing. That is what the fourteenth type (`Variables`, #91) did to
|
* and a hit outside the menu (the centre tab "Texture") counts as a miss.
|
||||||
* `Font` and to step 30.
|
|
||||||
*/
|
*/
|
||||||
export async function pickAssetType(t, label) {
|
export async function pickAssetType(t, label) {
|
||||||
const box = await t.json('__gm.overlayRect()');
|
const box = await t.json('__gm.overlayRect()');
|
||||||
let p = await t.locate(label, true);
|
let p = await t.find(label, true);
|
||||||
let scrolled = false;
|
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);
|
await t.wheel(box.x + box.w / 2, box.y + box.h / 2, 300);
|
||||||
p = await t.locate(label, true);
|
p = await t.locate(label, true);
|
||||||
scrolled = true;
|
scrolled = true;
|
||||||
|
|||||||
Reference in new issue
Block a user