diff --git a/tools/e2e/13-frames.mjs b/tools/e2e/13-frames.mjs index 2a6d03d7..75de3b46 100644 --- a/tools/e2e/13-frames.mjs +++ b/tools/e2e/13-frames.mjs @@ -1,4 +1,5 @@ import { colourDistance } from '../lib/harness.mjs'; +import { openTab } from './lib/scaffold.mjs'; /** * The Texture tab: cutting frames out of a sheet, and a sprite wearing one. @@ -41,8 +42,8 @@ export async function frames(t) { await evaluate('__gm.state.select(null)'); const texture = await json("(__gm.state.project.assets.find((a) => a.type === 'texture') ?? {}).id ?? ''"); await evaluate(`__gm.state.select({ kind: 'asset', assetId: ${JSON.stringify(texture)} })`); - await clickText('Texture'); - await sleep(600); + await openTab(t, 'texture'); + await sleep(400); check('the Texture tab opens', (await json('__gm.tab()')) === 'texture'); check( 'and shows the selected sheet', diff --git a/tools/e2e/14-overflow.mjs b/tools/e2e/14-overflow.mjs index 6403c09d..9dd9e8ba 100644 --- a/tools/e2e/14-overflow.mjs +++ b/tools/e2e/14-overflow.mjs @@ -1,3 +1,5 @@ +import { TAB_LABELS } from './lib/scaffold.mjs'; + /** * Labels must be shortened to fit their control, not written past it. Runs last because it renames * assets to absurd lengths to provoke the case. @@ -6,20 +8,6 @@ /** A name far wider than any 200 px picker, so a control that does not truncate must spill. */ const LONG_NAME = 'Player movement with jumping and coyote time'; -/** What the tab buttons read, to find one in the overflow menu. */ -const LABELS = { - scene: 'Scene', - game: 'Game', - graph: 'Behavior', - statemachine: 'State machine', - shader: 'Shader', - texture: 'Texture', - animation: 'Animation', - container: 'Container', - list: 'List', - particles: 'Particles', -}; - export async function overflow(t) { const { check, sleep, json, evaluate, shot, mutate, drag, clickText } = t; @@ -105,14 +93,14 @@ export async function overflow(t) { const offered = await json('__gm.overlayTexts()'); check( 'the overflow button offers every tab that had to go', - narrow.hidden.every((tab) => offered.includes(LABELS[tab])), + narrow.hidden.every((tab) => offered.includes(TAB_LABELS[tab])), JSON.stringify({ offered, hidden: narrow.hidden }), ); - await clickText(LABELS[wanted]); + await clickText(TAB_LABELS[wanted]); await sleep(400); const picked = await json('__gm.tabRow()'); check( - `picking ${LABELS[wanted]} from the overflow menu opens it and puts it in the row`, + `picking ${TAB_LABELS[wanted]} from the overflow menu opens it and puts it in the row`, (await json('__gm.tab()')) === wanted && picked.shown.some((b) => b.tab === wanted), JSON.stringify({ tab: await json('__gm.tab()'), shown: picked.shown.map((b) => b.tab) }), ); diff --git a/tools/e2e/16-container.mjs b/tools/e2e/16-container.mjs index b89b9d74..4dded399 100644 --- a/tools/e2e/16-container.mjs +++ b/tools/e2e/16-container.mjs @@ -1,4 +1,5 @@ import { instanceChild } from '../lib/builders.mjs'; +import { openTab } from './lib/scaffold.mjs'; /** * The Container tab: editing a template with the scene view's tools. Relies on the container step @@ -38,8 +39,8 @@ export async function containerTab(t) { await sleep(200); // 16a. The tab opens on the container the project has, and its header says which one. - await clickText('Container'); - await sleep(500); + await openTab(t, 'container'); + await sleep(300); const template = await json(`__gm.state.project.assets.find(a => a.id === '${containerId}').objects`); const count = template.length; check( diff --git a/tools/e2e/25-animation.mjs b/tools/e2e/25-animation.mjs index 3d41a63d..a221ab44 100644 --- a/tools/e2e/25-animation.mjs +++ b/tools/e2e/25-animation.mjs @@ -1,6 +1,6 @@ import { colourDistance } from '../lib/harness.mjs'; import { edge, node, propertiesOf, variable, written } from '../lib/builders.mjs'; -import { MAKE_OBJECT } from './lib/scaffold.mjs'; +import { MAKE_OBJECT, openTab } from './lib/scaffold.mjs'; /** * Animations: made from a texture, edited in their own tab, worn by a sprite through `texture`, @@ -132,8 +132,8 @@ export async function animation(t) { // 25c. The Animation tab shows it and plays it; the inspector keeps its two properties. await evaluate(`__gm.state.select({ kind: 'asset', assetId: ${JSON.stringify(walk.id)} })`); - await clickText('Animation'); - await sleep(500); + await openTab(t, 'animation'); + await sleep(300); check( 'the inspector edits frames per second and playback', (await t.has('Frames per second')) && (await t.has('Playback')) && (await t.has('Loop')), diff --git a/tools/e2e/lib/scaffold.mjs b/tools/e2e/lib/scaffold.mjs index 8e3b3b2b..c367ed4f 100644 --- a/tools/e2e/lib/scaffold.mjs +++ b/tools/e2e/lib/scaffold.mjs @@ -100,3 +100,32 @@ export async function scaffoldBehavior(t, options) { }, }; } + +/** What each tab button reads – the text a check has to click to open it. */ +export const TAB_LABELS = { + scene: 'Scene', + game: 'Game', + graph: 'Behavior', + statemachine: 'State machine', + shader: 'Shader', + texture: 'Texture', + animation: 'Animation', + container: 'Container', + list: 'List', + particles: 'Particles', +}; + +/** + * Opens a tab by clicking it, through the `»` menu when the row had to hide it. Since the tenth tab + * (#73) that is the normal case at the test window's width: a plain `clickText('Container')` found + * nothing and took the whole suite down with it. + */ +export async function openTab(t, tab) { + const row = await t.json('__gm.tabRow()'); + if (row.hidden.includes(tab)) { + await t.clickText('»'); + await t.sleep(300); + } + await t.clickText(TAB_LABELS[tab]); + await t.sleep(400); +}