Skip to content

test(e2e): read recorded animations instead of racing getAnimations() - #169

Merged
jjeff merged 1 commit into
mainfrom
fix/flip-animation-race
Sep 4, 2026
Merged

jjeff merged 1 commit into
mainfrom
fix/flip-animation-race

Conversation

@jjeff

@jjeff jjeff commented Aug 30, 2026

Copy link
Copy Markdown
Owner

The failure

tests/e2e/animation.spec.ts blocked PR #166 — release retry and 3.0.0 notes on WebKit in run 33324767753:

Error: expect(received).not.toBeNull()
Received: null
  at tests/e2e/animation.spec.ts:145:22

PR #166 changes only release.yml and CHANGELOG.md. The same test passed on two other PRs branched from the same commit, and passed on re-run.

The cause

flipInfo and animatingCount read getAnimations() after page.dragAndDrop() returned. That list only holds animations that are still running, so the read raced the 150ms animation it was inspecting — on a loaded runner the FLIP finished before the page.evaluate round-trip landed, and the call came back empty.

Because the race is load-dependent, all three Playwright retries lose together on a slow machine, so it presents as a hard failure rather than an obvious flake.

A longer timeout cannot fix it. The observation window opens when the animation starts and closes when it ends; waiting only moves the read further past the close.

The change

recordAnimations patches Element.prototype.animate via addInitScript, so every Animation is stored on the element that created it. flipInfo and animatingCount read that record, which outlives the animation. The reads no longer depend on when they land.

That also removes the reason for the 500ms widening in should animate items affected by reordering — it existed only to hold the window open, and the test asserts which items animate, not for how long. It now runs at the default duration.

Verified

Forcing a full waitForAnimations ahead of every read reproduces the worst case deterministically — the animations are guaranteed finished before the assertion:

Result
Before this change 4 failed, 4 passed — Received: null, Received: undefined, Received: 0
After this change 8 passed

Both runs on Chromium. Unmodified, the file also passes 8/8 after the change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JktBrqK6LaxcbiiTfDyUC7

🔖 Claude agent: M2:Resortable Release
session id: 4abbd3dd-78c3-4334-a069-05481c380a2f

`tests/e2e/animation.spec.ts` inspected FLIP animations by calling
`getAnimations()` after `page.dragAndDrop()` returned. That list only holds
animations still running, so the read raced the 150ms animation it was
inspecting: on a loaded runner the FLIP finished before the `page.evaluate`
round-trip landed and the call came back empty.

Because the race is load-dependent, all three Playwright retries lose
together on a slow machine, so it surfaces as a hard failure rather than an
obvious flake. Seen on WebKit in run 33324767753:

  Error: expect(received).not.toBeNull()
  Received: null
    at tests/e2e/animation.spec.ts:145:22

A longer timeout cannot fix this. The observation window opens when the
animation starts and closes when it ends, and waiting only moves the read
further past the close.

`recordAnimations` patches `Element.prototype.animate` through
`addInitScript` so every `Animation` is stored on the element that created
it. `flipInfo` and `animatingCount` now read that record, which outlives the
animation, so the assertions no longer depend on when the read lands.

That also removes the reason for the 500ms widening in 'should animate items
affected by reordering'. It was there to hold the window open long enough to
observe, and the test asserts which items animate, not for how long. The
test now runs at the default duration.

Verified: all 8 tests in the file pass on Chromium, and still pass when a
full `waitForAnimations` is forced ahead of every read — the worst case for
the old approach.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JktBrqK6LaxcbiiTfDyUC7
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@jjeff
jjeff merged commit 788765e into main Sep 4, 2026
16 checks passed
@jjeff
jjeff deleted the fix/flip-animation-race branch September 4, 2026 00:36
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 3.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant