Skip to content

test(chat): wait for each throttled delivery in the jump-to-latest test - #327

Merged
dovvnloading merged 1 commit into
mainfrom
fix/jump-to-latest-test-race
Oct 17, 2026
Merged

dovvnloading merged 1 commit into
mainfrom
fix/jump-to-latest-test-race

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Problem

ChatPage.renderCost.test.tsx > "follows streamed output instantly, and animates only the jump the reader asks for" fails intermittently with AssertionError: expected "vi.fn()" to be called 1 times, but got 2 times:

It blocks merging unrelated pull requests.

Root cause

The streaming bubble shows text through useThrottledText, which delivers each change from a setTimeout. The test:

  1. called stream("more ");
  2. cleared the mock;
  3. clicked "Jump to latest" as soon as the button existed.

The button already exists after the earlier "tok " delivery, so the "more " delivery could still be pending at the click. When that delivery's render landed in the same act as the click, it ran after jumpToLatest had set the reader back at the end. followStreamedOutput then, correctly, followed the new text with an instant scroll, and the test counted two scrolls.

The product behaves as designed: a reader who jumped to the end is followed when new text arrives. Only the test's timing assumption was wrong.

Change

Test-only. Each step waits until its text is in the bubble before going on, so nothing is pending at the click. The mock is cleared right after scrolling away, and a new assertion checks that delivering "more " while scrolled away scrolls nothing. The existing assertions are unchanged:

  • every follow is { behavior: "instant" };
  • the click causes exactly one { behavior: "smooth" } scroll.

Checks

  • npx vitest run src/features/chat/ChatPage.renderCost.test.tsx, 10 consecutive runs: 10 passed, 0 failed.
  • npx eslint on the file: clean. npx tsc --noEmit -p .: clean.
  • Pre-push hook (scripts/check.ps1 quick tier): all checks passed. Backend 3071 passed; vitest 77 files, 1047 tests passed.

Limits

  • Root cause is from reading, not a reproduction. The intermittent failure was not reproduced on demand on a quiet machine. The cause follows from the throttle's timer and the order of work inside the click's act.
  • A product observation, not changed here. While a reply streams, the next delivery after a jump follows with an instant scroll. That can cut the smooth jump animation short. It is a cosmetic matter of animation, not a defect in following.

Plan item: none (flaky test)

🤖 Generated with Claude Code

The test failed intermittently under load ("expected to be called 1
times, but got 2"), on a loaded local machine and in CI on #325. The
streaming bubble delivers text through useThrottledText's timer. The
test clicked "Jump to latest" while the delivery of "more " could still
be pending; when that delivery landed in the same act as the click, it
ran after jumpToLatest had marked the reader as back at the end, so
followStreamedOutput correctly followed it with an instant scroll, and
the test counted two scrolls.

Each step now waits until its text is in the bubble, so nothing is
pending at the click. The test also checks one more thing than before:
no scroll at all happens while the reader is scrolled away. The
assertions on what it protects are unchanged: following is instant and
only the reader's jump is smooth.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dovvnloading
dovvnloading merged commit eec0fc0 into main Oct 17, 2026
11 checks passed
@dovvnloading
dovvnloading deleted the fix/jump-to-latest-test-race branch October 17, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant