Files
feuerwerk/tools/e2e/14-overflow.mjs
T
rootandClaude Fable 5.1 6471671f7d Refactor round: ship web/index.html, drop the remote browser, fix stale comments and README
- `.gitignore` said `index.html` unanchored, which also caught the Vite source page;
  a fresh clone could neither `dev` nor `build`. Anchored to `/index.html`, page added.
- Removed GM_REMOTE (tools/remote/gm-browser.ps1 and the ssh/scp branch in browser.mjs):
  the Windows test machine is gone and the only flaky check that lived on it is closed (#37).
- Removed `npm run preview`, undocumented and unused.
- Comments: wrong number in collider.test.ts (250 → 200), the "declarations used to…"
  history in listItems.ts and friends, the 24 px/28 contradiction, section banners in
  nodes/index.ts, node-catalog.test.ts and api/index.php, name paraphrases, and the stale
  step numbers in tools/e2e/11-…23- from the old global count.
- README: asset types include `animation`, kind order Number/Text/Boolean, tagged colour
  and texture items, 6/5 kinds, the `Texture` node, `./build.sh`, PROJECT_FORMAT_VERSION,
  and the file tree (kinds.ts, listItems.ts, propertyPorts.ts, Breadcrumb.ts, beads.ts,
  tools/assets/).
- tests/helpers.ts takes the duplicated `findObject` and `sceneWithCamera`.

Proof: ./check.sh 797 tests, full e2e ALL PASSED 633 checks against this bundle.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 15:44:05 +02:00

95 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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.
*/
/** 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';
export async function overflow(t) {
const { check, sleep, json, evaluate, shot, mutate } = t;
const pickerWidths = async () => {
const out = {};
for (const tab of ['graph', 'texture', 'container']) {
await evaluate(`__gm.showTab(${JSON.stringify(tab)})`);
await sleep(300);
out[tab] = await json(`__gm.${tab}.pickerWidth()`);
}
return out;
};
const before = await pickerWidths();
await mutate(`
for (const asset of __gm.state.project.assets) {
if (asset.type === 'behavior' || asset.type === 'texture' || asset.type === 'container')
asset.name = ${JSON.stringify(LONG_NAME)};
}
__gm.state.select(null)`);
await sleep(600);
// 14a. The pickers keep the width they were given instead of growing with the name they show.
const after = await pickerWidths();
for (const tab of ['graph', 'texture', 'container']) {
check(
`the ${tab} picker keeps its width when the name gets long`,
before[tab] === 200 && after[tab] === 200,
`before ${before[tab]}, after ${after[tab]}`,
);
}
// 14b. Every tab, because each one owns a different set of controls.
for (const tab of ['scene', 'graph', 'texture', 'game', 'container', 'list']) {
await evaluate(`__gm.showTab(${JSON.stringify(tab)})`);
await sleep(400);
const spills = await json('__gm.textOverflows()');
check(
`no label is drawn past its control in the ${tab} tab`,
spills.length === 0,
JSON.stringify(spills),
);
}
// 14c. Shortened, not simply dropped: the value must still be readable and marked as cut.
await evaluate("__gm.showTab('graph')");
await sleep(400);
const shown = (await json('__gm.textOverflows(true)')).find((e) => e.text.startsWith('Player movement'));
check(
'a value too wide for its dropdown is cut with an ellipsis',
Boolean(shown) && shown.text.endsWith('…') && shown.text.length > 8,
JSON.stringify(shown),
);
await shot('36-long-labels');
// 14d. An inspector full of dropdowns – the parent row and the enum fields – with a selection
// whose asset name is now overlong too.
await evaluate("__gm.showTab('scene')");
await sleep(300);
await evaluate("__gm.state.select({ kind: 'object', objectId: 'otex' })");
await sleep(500);
const inspector = await json('__gm.textOverflows()');
check('no label spills in the inspector', inspector.length === 0, JSON.stringify(inspector));
// 14e. The other direction: a control narrow enough to swallow its whole label draws nothing
// at all, which the overflow walk cannot see – an empty text spills over no edge.
for (const tab of ['scene', 'graph', 'texture', 'container', 'list']) {
await evaluate(`__gm.showTab(${JSON.stringify(tab)})`);
await sleep(400);
const dropped = await json('__gm.labelsDropped()');
check(
`no button is left without its label in the ${tab} tab`,
dropped.length === 0,
JSON.stringify(dropped),
);
}
// The narrowest buttons in the editor sit on a behaviour's variable rows.
await evaluate("__gm.state.select({ kind: 'asset', assetId: 'mover' })");
await sleep(400);
const onVariables = await json('__gm.labelsDropped()');
check(
'the variable rows keep their buttons labelled',
onVariables.length === 0,
JSON.stringify(onVariables),
);
}