Skip to content

Commit 5426034

Browse files
committed
Settle markdown highlight tests on content, not a fixed sleep
Highlighting runs on a worker outside the render scheduler, so a quiet renderer or a fixed 250ms sleep does not reliably mean the highlighted frame has landed. Poll for the settled shape instead — every block present and the raw markdown marker gone — so each test returns as soon as it is true and tolerates slower runs instead of racing a guessed duration.
1 parent 0e6c3ce commit 5426034

1 file changed

Lines changed: 36 additions & 18 deletions

File tree

‎src/tui-opentui/markdown-rows.test.ts‎

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,22 @@ const shellOpts = {
2323
} as const
2424

2525
/**
26-
* Markdown blocks highlight asynchronously; settle before capturing a frame.
27-
* A row with several top-level blocks (heading, list, fence, link) resolves
28-
* its highlight promises one render at a time, so a fixed couple of ticks
29-
* that was enough for one block is not enough for several.
26+
* Highlighting runs on a worker outside the render scheduler, so the
27+
* scheduler goes idle before the highlighted frame lands. Pass a predicate
28+
* for the settled shape and get the frame back the moment it's true, rather
29+
* than gambling on a fixed sleep long enough to outrun load.
3030
*/
31-
async function settle(h: Harness): Promise<string> {
32-
for (let i = 0; i < 8; i += 1) {
33-
await new Promise((resolve) => setTimeout(resolve, 50))
31+
async function settle(h: Harness, isSettled: (frame: string) => boolean): Promise<string> {
32+
const deadline = Date.now() + 2000
33+
for (;;) {
3434
await h.renderOnce()
35+
const frame = h.captureCharFrame()
36+
if (isSettled(frame)) return frame
37+
if (Date.now() >= deadline) {
38+
throw new Error(`markdown row never settled; last frame:\n${frame}`)
39+
}
40+
await new Promise((resolve) => setTimeout(resolve, 20))
3541
}
36-
return h.captureCharFrame()
3742
}
3843

3944
describe("markdown transcript rows", () => {
@@ -68,7 +73,10 @@ describe("markdown transcript rows", () => {
6873
].join("\n"),
6974
})
7075

71-
const frame = await settle(h)
76+
const frame = await settle(
77+
h,
78+
(f) => f.includes("docs") && !f.includes("## Title") && !f.includes("**bolded**"),
79+
)
7280
expect(frame).toContain("Title")
7381
expect(frame).not.toContain("## Title")
7482
expect(frame).toContain("bolded")
@@ -94,7 +102,10 @@ describe("markdown transcript rows", () => {
94102
].join("\n"),
95103
})
96104

97-
const frame = await settle(h)
105+
const frame = await settle(
106+
h,
107+
(f) => f.includes("What the site is") && !f.includes("###") && !f.includes("**Hardware:**"),
108+
)
98109
expect(frame).toContain("What the site is")
99110
expect(frame).not.toContain("###")
100111
expect(frame).toContain("Hardware:")
@@ -108,7 +119,7 @@ describe("markdown transcript rows", () => {
108119
appendStreamRow(shell, { role: "tool", text: "## not a heading" })
109120
appendStreamRow(shell, { role: "system", text: "**raw**" })
110121

111-
const frame = await settle(h)
122+
const frame = await settle(h, (f) => f.includes("**raw**"))
112123
expect(frame).toContain("## not a heading")
113124
expect(frame).toContain("**raw**")
114125
}, WIDE)
@@ -123,7 +134,10 @@ describe("markdown transcript rows", () => {
123134
text: ["## Done", "", "```ts", "const partial = "].join("\n"),
124135
})
125136

126-
const frame = await settle(h)
137+
const frame = await settle(
138+
h,
139+
(f) => f.includes("Done") && !f.includes("## Done") && f.includes("const partial ="),
140+
)
127141
expect(frame).toContain("Done")
128142
expect(frame).not.toContain("## Done")
129143
expect(frame).toContain("const partial =")
@@ -143,7 +157,7 @@ describe("markdown transcript rows", () => {
143157
// literal text and the row paints the bare markers until the title's
144158
// first character lands. Held back instead, so the line's classification
145159
// cannot flip under text already on screen.
146-
const frame = await settle(h)
160+
const frame = await settle(h, (f) => f.includes("Some body text.") && !f.includes("####"))
147161
expect(frame).toContain("Some body text.")
148162
expect(frame).not.toContain("####")
149163

@@ -152,7 +166,7 @@ describe("markdown transcript rows", () => {
152166
streaming: true,
153167
text: ["Some body text.", "", "#### Title"].join("\n"),
154168
})
155-
const next = await settle(h)
169+
const next = await settle(h, (f) => f.includes("Title") && !f.includes("#### Title"))
156170
expect(next).toContain("Title")
157171
expect(next).not.toContain("#### Title")
158172
}, WIDE)
@@ -240,7 +254,7 @@ describe("markdown transcript rows", () => {
240254
role: "assistant",
241255
text: ["### Title", "", "Here is the list:", "- alpha", "- beta"].join("\n"),
242256
})
243-
const frame = await settle(h)
257+
const frame = await settle(h, (f) => f.includes("alpha"))
244258
const lines = frame.split("\n").map((line) => line.trimEnd())
245259
const listLine = lines.findIndex((line) => line.includes("Here is the list:"))
246260
expect(listLine).toBeGreaterThan(-1)
@@ -257,7 +271,7 @@ describe("markdown transcript rows", () => {
257271
role: "assistant",
258272
text: ["### Steps", "", ...items].join("\n"),
259273
})
260-
const frame = await settle(h)
274+
const frame = await settle(h, (f) => f.includes("10. item 10"))
261275
expect(frame).toContain("1. item 1")
262276
expect(frame).toContain("10. item 10")
263277
}, WIDE)
@@ -290,7 +304,8 @@ describe("markdown transcript rows", () => {
290304
})
291305
// Warm up once: the first highlight pass in a process loads the
292306
// tree-sitter grammar and is not itself part of what this test samples.
293-
const baseline = await settle(h).then(() => headingSpan(h))
307+
await settle(h, () => headingSpan(h) !== null)
308+
const baseline = headingSpan(h)
294309
expect(baseline).not.toBeNull()
295310

296311
for (let i = 2; i <= full.length; i += 1) {
@@ -375,7 +390,10 @@ describe("markdown transcript rows", () => {
375390
"more prose streaming in",
376391
].join("\n"),
377392
})
378-
const frame = await settle(h)
393+
const frame = await settle(
394+
h,
395+
(f) => f.includes("# this is a comment, not a heading") && f.includes("more prose streaming in"),
396+
)
379397
expect(frame).toContain("# this is a comment, not a heading")
380398
expect(frame).toContain("echo hi")
381399
expect(frame).toContain("more prose streaming in")

0 commit comments

Comments
 (0)