A test that waits for a deadline somebody guessed is waiting for the wrong thing, so it waits for the editor (#93)
game-maker / suite (push) Successful in 6m48s
game-maker / suite (push) Successful in 6m48s
The suite spent 88% of its step time asleep: 564 s of steps, 496 s of
them in sleep(n) - fixed spans estimated by hand and then copied from
step to step. That is why it was slow, and why it flickered.
The signal is afterFrames(count, timeout) in ui/render.ts, exposed as
__gm.afterFrames(). It wakes the loop itself, because an editor that
draws nothing would never redeem a promise of a frame, and it gives up
after a timeout instead of hanging the run. settle() in the harness
waits two drawn frames (~32 ms) instead of 150-300 ms and falls back to
sleep(150) when the hook is missing (an old build): silently not
waiting would make every later check a coin toss.
Every action goes through it now - click, doubleClick, wheel, drag,
dragAsset, press, typeText, select, mutate, undo, redo - and with that
about 550 sleep() calls behind those actions became redundant, helpers
that are nothing but a mutate in a coat included. What a frame cannot
answer got its own condition instead: waitUntil(expr), play()/stop()
waiting on __gm.state.mode rather than on 300 ms, saved() for the
autosave (the two hand-written polling loops sampled at 300 ms for
something that arrives after a second), and showTab() as a real tool -
47 places called evaluate("__gm.showTab(...)") raw, and 24 of them
waited for nothing at all and read the old panel.
564 s -> 243 s of step time, the waiting share 88% -> 76%. Three kinds
of wait were kept, and each one bit when it was taken away: loading
bytes (textures, fonts), game time that a repaint cannot stand in for
(time scale, shader and particle clocks, the live values a running
graph carries), and the inertia the scroll step measures on purpose.
Two things the new speed uncovered, both real: 25-animation read the
frame menu unfiltered and had frozen an incomplete list (the CI failure
on c990dbc), and 33-render-on-change measured idleness while the
autosave of the step before was still painting - it waits for
saveStatus to leave dirty/saving now, so it measures that nothing
happens any more instead of that it waited long enough.
This commit is contained in:
1 parent
c990dbcb26
commit
7e5003b590
41 files changed
+362
-732
No files matched your search
@@ -8,7 +8,6 @@ import { same } from '../lib/harness.mjs';
|
||||
export async function parenting(t) {
|
||||
const {
|
||||
check,
|
||||
sleep,
|
||||
json,
|
||||
shot,
|
||||
click,
|
||||
@@ -36,7 +35,6 @@ export async function parenting(t) {
|
||||
const redRow = await locate('Red crate');
|
||||
const blueRow = await locate('Blue crate');
|
||||
await drag(blueRow.x, blueRow.y, redRow.x, redRow.y);
|
||||
await sleep(100);
|
||||
let o2 = await object('o2');
|
||||
check(
|
||||
'dropping a row onto another parents it, keeping the world position',
|
||||
@@ -60,7 +58,6 @@ export async function parenting(t) {
|
||||
await press('a', { ctrl: true });
|
||||
await typeText('-50');
|
||||
await press('Enter');
|
||||
await sleep(200);
|
||||
o2 = await object('o2');
|
||||
const parent = await object('o2').then((o) => object(o.parentId));
|
||||
const worldOfO2 = { x: o2.position.x + parent.position.x, y: o2.position.y + parent.position.y };
|
||||
@@ -73,7 +70,6 @@ export async function parenting(t) {
|
||||
// 7c. Play: entities mirror the hierarchy; undo restores parent and position.
|
||||
await select(null);
|
||||
await press('Enter', { ctrl: true });
|
||||
await sleep(300);
|
||||
const e2 = await entity('o2');
|
||||
check(
|
||||
'play instantiates the parent link and world positions',
|
||||
@@ -100,7 +96,6 @@ export async function parenting(t) {
|
||||
JSON.stringify(entries),
|
||||
);
|
||||
await typeText('red');
|
||||
await sleep(150);
|
||||
const filtered = await json('__gm.overlayTexts()');
|
||||
check(
|
||||
'typing filters the picker down to the matching entries',
|
||||
@@ -109,7 +104,6 @@ export async function parenting(t) {
|
||||
);
|
||||
await shot('30-parent-search');
|
||||
await press('Enter'); // takes the first match
|
||||
await sleep(150);
|
||||
o2 = await object('o2');
|
||||
check(
|
||||
'inspector Parent menu parents the object',
|
||||
@@ -120,7 +114,6 @@ export async function parenting(t) {
|
||||
const blueRow2 = await locate('Blue crate');
|
||||
await click(blueRow2.x, blueRow2.y, 'right');
|
||||
await clickText('Unparent (move to top level)');
|
||||
await sleep(100);
|
||||
o2 = await object('o2');
|
||||
check(
|
||||
'Unparent moves the object to the top level, keeping its world position',
|
||||
@@ -140,7 +133,6 @@ export async function parenting(t) {
|
||||
const blueRow3 = await locate('Blue crate');
|
||||
// 10 px above the centre of a 26 px row is its top quarter – the gap, not the row.
|
||||
await drag(blueRow3.x, blueRow3.y, redRow3.x, redRow3.y - 10);
|
||||
await sleep(150);
|
||||
const rowsAfter = await json('__gm.hierarchyOrder()');
|
||||
o2 = await object('o2');
|
||||
check(
|
||||
@@ -155,7 +147,6 @@ export async function parenting(t) {
|
||||
);
|
||||
await shot('31-reordered');
|
||||
await undo();
|
||||
await sleep(150);
|
||||
check(
|
||||
'undo puts the order back',
|
||||
same(await json('__gm.hierarchyOrder()'), rowsBefore),
|
||||
|
||||
Reference in new issue
Block a user