A step opens a tab the way a person has to, through the menu when it is hidden
CI run 35 was red: the suite died after step 15 with `widget with text "Container" not found`. Nothing in the editor broke — the tenth tab (#73) pushed Container behind the `»` button at the test window's 1280 px, exactly the case #84 was built for, and three steps still clicked the tab name directly. openTab(t, tab) in tools/e2e/lib/scaffold.mjs asks tabRow() whether the tab is hidden and goes through the menu when it is, so the fix lives in one place rather than in every step that opens a tab. The LABELS record moves there as TAB_LABELS, since both the helper and 14-overflow need it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0f9e1611d1
commit
4feb4c2cf6
5 files changed
+43
-24
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
import { colourDistance } from '../lib/harness.mjs';
|
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.
|
* 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)');
|
await evaluate('__gm.state.select(null)');
|
||||||
const texture = await json("(__gm.state.project.assets.find((a) => a.type === 'texture') ?? {}).id ?? ''");
|
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 evaluate(`__gm.state.select({ kind: 'asset', assetId: ${JSON.stringify(texture)} })`);
|
||||||
await clickText('Texture');
|
await openTab(t, 'texture');
|
||||||
await sleep(600);
|
await sleep(400);
|
||||||
check('the Texture tab opens', (await json('__gm.tab()')) === 'texture');
|
check('the Texture tab opens', (await json('__gm.tab()')) === 'texture');
|
||||||
check(
|
check(
|
||||||
'and shows the selected sheet',
|
'and shows the selected sheet',
|
||||||
|
|||||||
@@ -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
|
* 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.
|
* 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. */
|
/** 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';
|
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) {
|
export async function overflow(t) {
|
||||||
const { check, sleep, json, evaluate, shot, mutate, drag, clickText } = 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()');
|
const offered = await json('__gm.overlayTexts()');
|
||||||
check(
|
check(
|
||||||
'the overflow button offers every tab that had to go',
|
'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 }),
|
JSON.stringify({ offered, hidden: narrow.hidden }),
|
||||||
);
|
);
|
||||||
await clickText(LABELS[wanted]);
|
await clickText(TAB_LABELS[wanted]);
|
||||||
await sleep(400);
|
await sleep(400);
|
||||||
const picked = await json('__gm.tabRow()');
|
const picked = await json('__gm.tabRow()');
|
||||||
check(
|
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),
|
(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) }),
|
JSON.stringify({ tab: await json('__gm.tab()'), shown: picked.shown.map((b) => b.tab) }),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { instanceChild } from '../lib/builders.mjs';
|
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
|
* 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);
|
await sleep(200);
|
||||||
|
|
||||||
// 16a. The tab opens on the container the project has, and its header says which one.
|
// 16a. The tab opens on the container the project has, and its header says which one.
|
||||||
await clickText('Container');
|
await openTab(t, 'container');
|
||||||
await sleep(500);
|
await sleep(300);
|
||||||
const template = await json(`__gm.state.project.assets.find(a => a.id === '${containerId}').objects`);
|
const template = await json(`__gm.state.project.assets.find(a => a.id === '${containerId}').objects`);
|
||||||
const count = template.length;
|
const count = template.length;
|
||||||
check(
|
check(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { colourDistance } from '../lib/harness.mjs';
|
import { colourDistance } from '../lib/harness.mjs';
|
||||||
import { edge, node, propertiesOf, variable, written } from '../lib/builders.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`,
|
* 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.
|
// 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 evaluate(`__gm.state.select({ kind: 'asset', assetId: ${JSON.stringify(walk.id)} })`);
|
||||||
await clickText('Animation');
|
await openTab(t, 'animation');
|
||||||
await sleep(500);
|
await sleep(300);
|
||||||
check(
|
check(
|
||||||
'the inspector edits frames per second and playback',
|
'the inspector edits frames per second and playback',
|
||||||
(await t.has('Frames per second')) && (await t.has('Playback')) && (await t.has('Loop')),
|
(await t.has('Frames per second')) && (await t.has('Playback')) && (await t.has('Loop')),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user