/** * 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), ); }