75 lines
3.1 KiB
JavaScript
75 lines
3.1 KiB
JavaScript
import { same } from '../lib/harness.mjs';
|
||
|
||
/**
|
||
* Hierarchy folding. A freshly opened scene is fully collapsed, so only its top-level objects
|
||
* are listed (o4/oc1 hang under o1, oc2 under o2). The chevron folds a row open and shut
|
||
* without touching the selection, and selecting a nested object unfolds the way down to it.
|
||
*/
|
||
export async function hierarchy(t) {
|
||
const { check, evaluate, json, click, clickText, doubleClick, select, state, shot } = t;
|
||
const rowIds = () => json('__gm.hierarchyOrder()');
|
||
const rows = async () => JSON.stringify(await rowIds());
|
||
const selectionBefore = (await state()).selection;
|
||
|
||
check(
|
||
'hierarchy starts collapsed – only top-level objects are listed',
|
||
same(await rowIds(), ['o1', 'o2', 'o3', 'o5']),
|
||
await rows(),
|
||
);
|
||
check('a leaf row offers no chevron', (await evaluate(`__gm.hierarchyChevron('o3')`)) === null);
|
||
const chevron = await json(`__gm.hierarchyChevron('o2')`);
|
||
await click(chevron.x, chevron.y);
|
||
check(
|
||
'clicking the chevron unfolds the row, leaving the selection alone',
|
||
same(await rowIds(), ['o1', 'o2', 'oc2', 'o3', 'o5']) && same((await state()).selection, selectionBefore),
|
||
await rows(),
|
||
);
|
||
await shot('01a-hierarchy-unfolded');
|
||
await click(chevron.x, chevron.y);
|
||
check(
|
||
'clicking it again folds the subtree away',
|
||
same(await rowIds(), ['o1', 'o2', 'o3', 'o5']),
|
||
await rows(),
|
||
);
|
||
// The row itself folds on a double-click, the same as its chevron. Pixi leaves `detail` at 0 on
|
||
// a press, so this needs a real double-click from the harness, not two `click()` calls.
|
||
const row = await json(`__gm.hierarchyRow('o2')`);
|
||
await doubleClick(row.x, row.y);
|
||
check(
|
||
'double-clicking the row unfolds it as well',
|
||
same(await rowIds(), ['o1', 'o2', 'oc2', 'o3', 'o5']),
|
||
await rows(),
|
||
);
|
||
await doubleClick(row.x, row.y);
|
||
check(
|
||
'double-clicking it again folds the subtree away',
|
||
same(await rowIds(), ['o1', 'o2', 'o3', 'o5']),
|
||
await rows(),
|
||
);
|
||
|
||
await select({ kind: 'object', holderId: 'scene1', objectId: 'oc1' });
|
||
check(
|
||
'selecting a nested object unfolds its ancestors',
|
||
same(await rowIds(), ['o1', 'o4', 'oc1', 'o2', 'o3', 'o5']),
|
||
await rows(),
|
||
);
|
||
await evaluate('__gm.state.select(null); __gm.hierarchyCollapseAll()');
|
||
check('Collapse all folds everything back', same(await rowIds(), ['o1', 'o2', 'o3', 'o5']), await rows());
|
||
|
||
// Open asset in the row's menu does what a double-click in the asset panel does.
|
||
const spawnerRow = await json(`__gm.hierarchyRow('o5')`);
|
||
await click(spawnerRow.x, spawnerRow.y, 'right');
|
||
await clickText('Open asset');
|
||
const opened = await json('__gm.documents()');
|
||
const openedSelection = (await state()).selection;
|
||
check(
|
||
'Open asset in the row menu selects the asset and opens its tab',
|
||
opened.active === 'asset:spawner' &&
|
||
opened.docs.includes('asset:spawner') &&
|
||
openedSelection?.kind === 'asset' &&
|
||
openedSelection.assetId === 'spawner',
|
||
JSON.stringify({ opened, openedSelection }),
|
||
);
|
||
await evaluate(`__gm.closeDocument('asset:spawner'); __gm.state.select(null)`);
|
||
}
|