Skip to content

Add frame-driven waitFor utility#30

Open
greatestape wants to merge 1 commit into
vadimdemedes:masterfrom
greatestape:feat/frame-driven-wait-for
Open

Add frame-driven waitFor utility#30
greatestape wants to merge 1 commit into
vadimdemedes:masterfrom
greatestape:feat/frame-driven-wait-for

Conversation

@greatestape
Copy link
Copy Markdown

@greatestape greatestape commented Apr 1, 2026

This introduces a waitFor function similar to the one in the react testing library.

I think it's convenient because it should guarantee that we don't miss frames, and it might make tests faster.

Arguably addresses #22

Usage:

  const {lastFrame, waitFor} = render(<MyComponent />);
  await waitFor(() => {
    if (lastFrame() !== 'expected output') {
      throw new Error('not yet');
    }
  });

One big caveat: as you can see in the change, waitFor isn't compatible with AVA tests. As I understand it this is because AVA stores test failures and reports them later, so the "keep trying until assertions pass or timeout" pattern doesn't work.

Emit a 'frame' event from Stdout and Stderr whenever a new frame is
written. Add a waitFor function, returned from render(), that listens
for these events and re-checks the assertion on each frame.

Unlike polling-based approaches (setInterval), this detects output
changes instantly — at the moment stdout.write() is called — with no
intermediate timer that can be delayed by event loop congestion.

This addresses the CI flakiness pattern where polling timers get
stretched under CPU load, causing tests to time out even though the
component's output was already available.

Closes vadimdemedes#22

Usage:
  const {lastFrame, waitFor} = render(<MyComponent />);
  await waitFor(() => {
    if (lastFrame() !== 'expected output') {
      throw new Error('not yet');
    }
  });
@greatestape greatestape force-pushed the feat/frame-driven-wait-for branch from 4fe54e1 to 6a59c9b Compare April 1, 2026 21:22
@greatestape greatestape marked this pull request as ready for review April 1, 2026 22:00
@sindresorhus
Copy link
Copy Markdown
Collaborator

A few things:

  1. This still doesn’t solve the coordination problem it’s trying to solve for input-driven tests. I manually removed the extra tick before stdin.write(...) and the test still failed with Expected "Hello World", got "". So users still need an extra tick just to avoid missing the event subscription.

  2. The timeout behavior, docs, and tests need tightening. The implementation always rejects with the last assertion error, not a generic timeout error, so the generic timeout fallback looks unreachable. The current timeout test also only checks that something was thrown, which hides that mismatch.

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.

2 participants