Skip to content

Commit a29ac1f

Browse files
committed
test(chat): stabilize ChatView scroll debug repro flake
1 parent 4f118c7 commit a29ac1f

1 file changed

Lines changed: 38 additions & 12 deletions

File tree

webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,11 @@ const postState = (clineMessages: ClineMessage[]) => {
225225
},
226226
}
227227

228-
window.postMessage(message, "*")
228+
window.dispatchEvent(
229+
new MessageEvent("message", {
230+
data: message,
231+
}),
232+
)
229233
}
230234

231235
const renderView = () =>
@@ -240,20 +244,42 @@ const renderView = () =>
240244
const hydrate = async (atBottomAfterCalls: number) => {
241245
harness.atBottomAfterCalls = atBottomAfterCalls
242246
renderView()
247+
await act(async () => {
248+
await Promise.resolve()
249+
})
243250
await act(async () => {
244251
postState(buildMessages(Date.now() - 3_000))
245252
})
253+
await waitFor(() => {
254+
const list = document.querySelector("[data-testid='virtuoso-item-list']")
255+
expect(list).toBeTruthy()
256+
expect(list?.getAttribute("data-count")).toBe("2")
257+
})
246258
}
247259

248260
const waitForCalls = async (min: number, timeout = 1_500) => {
249261
await waitFor(() => expect(harness.scrollCalls).toBeGreaterThanOrEqual(min), { timeout })
250262
}
251263

252-
const expectCallsStable = async (ms = 120) => {
253-
await sleep(ms)
254-
const snapshot = harness.scrollCalls
255-
await sleep(ms)
256-
expect(harness.scrollCalls).toBe(snapshot)
264+
const waitForCallsSettled = async (idleMs = 80, timeoutMs = 2_000) => {
265+
const deadline = Date.now() + timeoutMs
266+
let lastSeen = harness.scrollCalls
267+
268+
while (Date.now() < deadline) {
269+
await sleep(idleMs)
270+
const current = harness.scrollCalls
271+
272+
if (current === lastSeen) {
273+
await sleep(idleMs)
274+
if (harness.scrollCalls === current) {
275+
return
276+
}
277+
}
278+
279+
lastSeen = current
280+
}
281+
282+
throw new Error(`Expected scroll calls to settle within ${timeoutMs}ms, last count: ${harness.scrollCalls}`)
257283
}
258284

259285
const getScrollable = (): HTMLElement => {
@@ -291,7 +317,7 @@ describe("ChatView scroll behavior regression coverage", () => {
291317
it("rehydration converges to bottom", async () => {
292318
await hydrate(6)
293319
await waitForCalls(6, 2_000)
294-
await expectCallsStable()
320+
await waitForCallsSettled()
295321
expect(document.querySelector(".codicon-chevron-down")).toBeNull()
296322
})
297323

@@ -302,7 +328,7 @@ describe("ChatView scroll behavior regression coverage", () => {
302328
expect(document.querySelector(".codicon-chevron-down")).toBeNull()
303329

304330
await waitForCalls(8, 2_000)
305-
await expectCallsStable()
331+
await waitForCallsSettled()
306332
expect(resolveFollowOutput(false)).toBe("auto")
307333
})
308334

@@ -327,7 +353,7 @@ describe("ChatView scroll behavior regression coverage", () => {
327353
it("non-wheel upward intent disengages sticky follow", async () => {
328354
await hydrate(4)
329355
await waitForCalls(4)
330-
await expectCallsStable()
356+
await waitForCallsSettled()
331357
expect(resolveFollowOutput(false)).toBe("auto")
332358

333359
const scrollable = getScrollable()
@@ -346,7 +372,7 @@ describe("ChatView scroll behavior regression coverage", () => {
346372
it("nested scroller scroll events do not falsely disengage sticky follow", async () => {
347373
await hydrate(4)
348374
await waitForCalls(4)
349-
await expectCallsStable()
375+
await waitForCallsSettled()
350376
expect(resolveFollowOutput(false)).toBe("auto")
351377

352378
const scrollable = getScrollable()
@@ -371,7 +397,7 @@ describe("ChatView scroll behavior regression coverage", () => {
371397
it("wheel-up intent disengages sticky follow", async () => {
372398
await hydrate(4)
373399
await waitForCalls(4)
374-
await expectCallsStable()
400+
await waitForCallsSettled()
375401
expect(resolveFollowOutput(false)).toBe("auto")
376402

377403
const scrollable = getScrollable()
@@ -413,7 +439,7 @@ describe("ChatView scroll behavior regression coverage", () => {
413439
it("scroll-to-bottom CTA re-anchors with one interaction", async () => {
414440
await hydrate(4)
415441
await waitForCalls(4)
416-
await expectCallsStable()
442+
await waitForCallsSettled()
417443
expect(resolveFollowOutput(false)).toBe("auto")
418444

419445
await act(async () => {

0 commit comments

Comments
 (0)