Skip to content

fix: pause animations during screenshots#33582

Open
adamalston wants to merge 13 commits into
cypress-io:developfrom
adamalston:29144-pixar
Open

fix: pause animations during screenshots#33582
adamalston wants to merge 13 commits into
cypress-io:developfrom
adamalston:29144-pixar

Conversation

@adamalston
Copy link
Copy Markdown
Contributor

@adamalston adamalston commented Apr 9, 2026

Additional details

  • cy.screenshot() did not pause animations created via the Web Animations API (document.getAnimations()), which allowed elements using element.animate() to continue changing during capture.
  • I updated the animation disabler to pause and resume animations, while keeping nested disable and cleanup calls balanced.
  • I adjusted screenshot cleanup so onAfterScreenshot runs only after timers and animations are restored.

Note

Medium Risk
Changes how Cypress disables animations during cy.screenshot() by pausing/resuming Web Animations API animations with nested-call reference counting, which could impact timing-sensitive tests or leave animations paused if edge cases are missed.

Overview
Fixes cy.screenshot() flake potential by extending the animation disabler to pause running Web Animations API animations (document.getAnimations()) during capture and resume them afterward, while keeping nested add/remove calls balanced and ensuring the injected CSS disabler style is only added/removed once per document.

Adds a new unit test suite for dom/animation covering resume/pause behavior, nesting, missing getAnimations fallback, and error handling, plus an e2e screenshot test asserting onAfterScreenshot runs before timers are resumed. Updates the CLI changelog to note the screenshot/animation bugfix.

Reviewed by Cursor Bugbot for commit 39c66c1. Bugbot is set up for automated code reviews on this repo. Configure here.

Steps to test

# Tests should pass.
yarn workspace @packages/driver test test/unit/dom/animation.spec.ts
yarn workspace @packages/driver cypress:run --spec cypress/e2e/commands/screenshot.cy.js
# Revert the fix.
git restore --source=develop --staged --worktree \
  packages/driver/src/dom/animation.ts \
  packages/driver/src/cy/commands/screenshot.ts
# Tests should fail.
yarn workspace @packages/driver test test/unit/dom/animation.spec.ts
# Restore the fix.
git restore --source=HEAD --staged --worktree \
  packages/driver/src/dom/animation.ts \
  packages/driver/src/cy/commands/screenshot.ts
# Tests should pass again.
yarn workspace @packages/driver test test/unit/dom/animation.spec.ts
yarn workspace @packages/driver cypress:run --spec cypress/e2e/commands/screenshot.cy.js

How has the user experience changed?

Before, screenshot capture could leave animations running. Based on the code, nested cleanup calls could also result in animations remaining paused after capture, and there was no post-cleanup hook for screenshot callbacks to safely inspect or preserve the final animation state.

After, Cypress pauses running animations during screenshot capture, restores them after the final cleanup call, and calls onAfterScreenshot only after timers and animations have been restored. That should improve the stability of screenshot comparisons for apps that include animations.

PR Tasks

@cypress-app-bot
Copy link
Copy Markdown
Collaborator

@adamalston adamalston marked this pull request as ready for review April 9, 2026 02:04
@mschile mschile requested a review from cacieprins April 9, 2026 14:24
Comment thread packages/driver/src/dom/animation.ts Outdated
return playState === 'running'
}) ?? []

pausedAnimations.forEach((animation) => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for ... of is more idiomatic


return automateScreenshot(state, automationOptions)
})
.then((props) => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change in behavior fix something? Before, onAfterScreenshot would be invoked while animations were still paused.

Copy link
Copy Markdown
Contributor Author

@adamalston adamalston Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was intended to address an issue. With the original ordering, onAfterScreenshot runs while Cypress still has timers paused and animations disabled, so callback code appears to see a temporary screenshot state rather than the restored page state.

I've reverted the change because it introduces a behavior change that is separate from the main screenshot fix in this pull request.

@adamalston adamalston requested a review from cacieprins April 25, 2026 17:19
Comment thread packages/driver/src/dom/animation.ts
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e3987aa. Configure here.

Comment thread packages/driver/src/dom/animation.ts
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.

Cypress Test Occasionally Fails Due to Minor Image Differences With Animation Disabled

4 participants