Skip to content

test(playground): exercise SSE reconnect Last-Event-ID replay#451

Open
MarioCadenas wants to merge 1 commit into
mainfrom
tests/reconnect-replay-e2e
Open

test(playground): exercise SSE reconnect Last-Event-ID replay#451
MarioCadenas wants to merge 1 commit into
mainfrom
tests/reconnect-replay-e2e

Conversation

@MarioCadenas

Copy link
Copy Markdown
Collaborator

Why

The existing reconnect E2E tests in apps/dev-playground/tests/reconnect.spec.ts only cover the happy path. They install setupMockAPI, which fulfills /api/reconnect/stream with a static SSE body delivering all 5 messages at once — the connection is never actually dropped. As a result, the real server reconnection path (StreamManager ring-buffer replay via Last-Event-ID, packages/appkit/src/stream/stream-manager.ts) was never exercised end-to-end. That blind spot is exactly why a real reconnect regression could survive ~6 weeks: a broken replay would still pass every existing test.

What

Adds one recovery test (kept alongside, not replacing, the happy-path tests) in a separate describe block so it runs against the real dev-playground server (no stream mock):

  • Loads /reconnect, waits until some (≥1, <5) messages have arrived.
  • Forces a client-side disconnect mid-stream with context.setOffline(true) then setOffline(false), which aborts the in-flight SSE fetch and triggers the client's reconnect with a Last-Event-ID header against the same streamId.
  • Asserts the stream completes with all 5 messages (headline reads 5), status never reaches Error, and the rendered list contains exactly one Message k/5 card for each k in 1..5 — i.e. no gaps and no duplicates, which is what proves the server replayed the buffered events the client missed.

Assertions use Playwright web-first / expect.poll with generous timeouts (no arbitrary sleeps beyond the brief offline window) to keep the SSE timing robust. The test is annotated scenario: reconnect-replay for triage.

Verification

Ran locally against the real server (reproducing CI env: APPKIT_E2E_TEST=true + mock workspace vars), Playwright auto-starting the server:

  • Full reconnect.spec.ts: 4 passed (new recovery test ~13s).
  • Recovery test --repeat-each=3: 3/3 passed, stable ~12.8s — no flakiness observed.
  • False-green check: temporarily disabled the missed-event replay loop in StreamManager._attachToExistingStream and confirmed the new test fails (stalls at 4 messages, never reaches 5), proving it genuinely catches a replay regression. Reverted afterwards.

Biome clean; no new lint errors. The playground-integration-test CI job will also execute this.

This pull request and its description were written by Isaac.

The existing reconnect E2E tests only cover the happy path (mocked
stream, all 5 messages delivered at once), so a Last-Event-ID replay
regression in the StreamManager ring buffer could go undetected. This
adds a recovery test that runs against the real server, drops the
network mid-stream via context.setOffline, and asserts the client ends
with all 5 messages and exactly one card per message (no gaps, no
duplicates) — proving buffered events were replayed on reconnect.

Co-authored-by: Isaac
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
@MarioCadenas MarioCadenas requested a review from a team as a code owner June 13, 2026 19:33
@MarioCadenas MarioCadenas requested a review from calvarjorge June 13, 2026 19:33
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