- NumberField takes a decimals option (default 3); frame rects and the slice dialog use 0, matching their integer model. - Button truncates its label to the drawn width; Dropdown reserves the chevron slot. NodeView reuses the shared truncate(). - Setting scaleMode leaves the style's shared resource id in place, so the old GPU sampler stayed in use until a reload. Call style.update(). - Graph gets a header bar like the Texture tab: GraphEditor is now the frame, the former editor is GraphCanvas. A selection the tab does not concern no longer unloads the behavior. - New e2e step 14 guards text overflow across all widgets. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
57 lines
2.4 KiB
JavaScript
57 lines
2.4 KiB
JavaScript
/**
|
||
* 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.
|
||
*
|
||
* `__gm.textOverflows()` is a general guard rather than a check on one widget: it walks every
|
||
* visible text and reports the ones drawn wider than the widget that owns them. It was verified
|
||
* to actually catch this class of bug – against a build without the fix it reported the graph
|
||
* picker at 106 px over, and nothing else.
|
||
*/
|
||
|
||
/** 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;
|
||
|
||
await mutate(`
|
||
for (const asset of __gm.state.project.assets) {
|
||
if (asset.type === 'behavior' || asset.type === 'texture') asset.name = ${JSON.stringify(LONG_NAME)};
|
||
}
|
||
__gm.state.select(null)`);
|
||
await sleep(600);
|
||
|
||
// 21. Every tab, because each one owns a different set of controls: the two header bars with
|
||
// their pickers, the inspector's dropdowns, and the toolbar.
|
||
for (const tab of ['scene', 'graph', 'texture', 'game']) {
|
||
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),
|
||
);
|
||
}
|
||
|
||
// 21a. 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');
|
||
|
||
// 21b. 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: 'o1' })");
|
||
await sleep(500);
|
||
const inspector = await json('__gm.textOverflows()');
|
||
check('no label spills in the inspector', inspector.length === 0, JSON.stringify(inspector));
|
||
}
|