Public: anyone can read this; the crew can change it.

test/tui-size.test.ts waits for the frame a resize draws, not a timer, and passes on a loaded check machine #3018

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/3008-test-tui-size-test-ts-waits-for-the-fram → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/3008-test-tui-size-test-ts-waits-for-the-fram was merged into main as 8ca57f8.

Review

Sign in to review this change.
1 file changed +44 −4
test/tui-size.test.ts +44 −4
@@ -55,6 +55,9 @@ const SIZES: readonly [number, number][] = [
5555 [200, 60],
5656 ];
5757
58 /** How long a harness step waits for the frame it caused. */
59 const FRAME_WAIT_MS = 10_000;
60
5861 interface Harness {
5962 app: App;
6063 session: Session;
@@ -81,13 +84,48 @@ describe("the terminal lays out for the terminal it is in", () => {
8184 );
8285 app.start();
8386 await settleApp(app);
84 const settle = (): Promise<void> => settleApp(app);
87 /**
88 * Settle, then wait for a frame drawn after `since` at the wanted size.
89 * Bounded: it fails naming the size it was waiting for, not whatever
90 * assertion follows a half-drawn screen.
91 */
92 const framed = async (
93 since: number,
94 want: { cols: number; rows: number },
95 ): Promise<void> => {
96 const deadline = Date.now() + FRAME_WAIT_MS;
97 await settleApp(app);
98 for (;;) {
99 app.frame();
100 const { cols, rows } = app.screen;
101 if (
102 app.frameCount > since &&
103 cols === want.cols &&
104 rows === want.rows &&
105 terminal.toText() === app.screen.toText()
106 )
107 return;
108 if (Date.now() > deadline)
109 throw new Error(
110 `no frame at ${want.cols}×${want.rows} within ${FRAME_WAIT_MS}ms ` +
111 `(have ${cols}×${rows}, frames ${since}→${app.frameCount})\n${app.screen.toText()}`,
112 );
113 await settleApp(app);
114 }
115 };
116 const here = (): { cols: number; rows: number } => ({
117 cols: app.screen.cols,
118 rows: app.screen.rows,
119 });
85120 return {
86121 app,
87122 session,
88123 terminal,
89124 lines: () => app.screen.toText().split("\n"),
90125 async press(...keys) {
126 // A key that changes nothing draws nothing, so a press waits for
127 // the app to settle and the grid to agree, not for a new frame.

since = -1 makes frameCount > since vacuously true. Make since optional in framed() instead of passing a sentinel.

128 const since = -1;
91129 for (const key of keys)
92130 app.dispatch({
93131 type: "key",
@@ -96,15 +134,17 @@ describe("the terminal lays out for the terminal it is in", () => {
96134 alt: false,
97135 shift: false,
98136 });
99 await settle();
137 await framed(since, here());
100138 },
101139 async resize(c, r) {
140 const since = app.frameCount;
102141 terminal.resize(c, r);
103 await settle();
142 await framed(since, { cols: c, rows: r });
104143 },
105144 async push(screen) {
145 const since = app.frameCount;
106146 app.push(screen(session, app.ctx));
107 await settle();
147 await framed(since, here());
108148 },
109149 stop: () => app.stop(),
110150 };

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs