Skip to content

fix(utilities): stop Collapsible leaking its test waiter on a fast toggle - #621

Merged
josemarluedke merged 1 commit into
mainfrom
fix/collapsible-waiter-leak
Oct 14, 2026
Merged

josemarluedke merged 1 commit into
mainfrom
fix/collapsible-waiter-leak

Conversation

@josemarluedke

Copy link
Copy Markdown
Owner

Problem

does not leak a test waiter when toggled twice before the transition finishes failed once in CI (run 38483680687, on #620) after ~3s with the frontile:collapsible waiter still pending.

If a Collapsible is closed before the open's requestAnimationFrame callback has made it visible, the close's final frame sets opacity: 0 on an element whose opacity is already 0. No transition runs, so no transitionend fires — and onTransitionEnd is the only place a close ends the waiter. The same race also let the stale open frame set opacity: 1 on a panel that had just been closed.

Fix

  • expand/contract track the frames they schedule and cancel the other direction's pending frames (and all of them on teardown).
  • After applying the final styles, endWaiterUnlessTransitioning checks element.getAnimations() and ends the waiter immediately when no height/opacity transition is running. onTransitionEnd falls back to the same check, so a close where only height animates still settles once it finishes.

Tests

Two new tests stub requestAnimationFrame/cancelAnimationFrame with a manual queue so the race is deterministic. Both failed before the fix — the leak one with the same ~3s timeout signature as CI.

  • Collapsible module: 15/15, five consecutive runs
  • Full test-app suite: 2208 pass, 3 skip, 0 fail
  • ESLint, frontile lint:types, lint:hbs: clean for the touched files

🤖 Generated with Claude Code

…ggle

Closing a Collapsible before the open's requestAnimationFrame ran could
leave the `frontile:collapsible` waiter pending: opacity went 0 -> 0, so
no transitionend fired, and onTransitionEnd is the only place a close
ends the waiter. The stale open frame could also still set opacity 1 on
a panel that had just been closed.

- Track the frames expand/contract schedule and cancel them on the next
  toggle and on teardown.
- After applying the final styles, end the waiter immediately when
  getAnimations() shows no height/opacity transition running, and fall
  back to the same check in onTransitionEnd.

Adds deterministic tests that stub requestAnimationFrame to reproduce
both cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@netlify

netlify Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for frontile-next ready!

Name Link
🔨 Latest commit f6d43e9
🔍 Latest deploy log https://app.netlify.com/projects/frontile-next/deploys/6acf9cf11565b778db1f9528
😎 Deploy Preview https://deploy-preview-621--frontile-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@josemarluedke josemarluedke added the Type: Bug Something isn't working label Oct 14, 2026
@josemarluedke
josemarluedke merged commit 19ad8b2 into main Oct 14, 2026
5 checks passed
@josemarluedke
josemarluedke deleted the fix/collapsible-waiter-leak branch October 14, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant