Let's take a web application with beautiful CSS animations showing time of day. Each click of the button sets a different CSS class which triggers CSS transitions.
Time of day via CSS animations
🖼 You can find the example application in the repo bahmutov/css-animation-cypress-example. It is based on this Codepen created by Olivia Ng.
CSS Animations #
To create the transitions, the application sets a different CSS class name
1 | $('.option').on('click', function () { |
The application CSS specifies the transition duration applied to different elements. For example, to move the sun and the clouds, the application uses SVG shapes. Each shape will change its "fill" property in five seconds.
1 | path, |
Similarly, the ".sun" and other CSS classes will change its styles when applied in five seconds
1 | .sun { |
Cypress tests #
Ok, pretty slick. But how do the slow transitions affect the Cypress tests? Well, Cypress test does not "know" about five seconds it takes to finish the transition after clicking each button. Thus a typical test will show a weird start of the transition before abruptly starting a new one.
1 | const times = ['Day', 'Sunset', 'Night', 'Dusk'] |
The test only waits one second before the next step
We could slow down the test by waiting five seconds, but what if we could speed up the animations instead? Or disable them completely?
Cypress screenshots #
If you every used cy.screenshot command, you might have noticed the option disableTimersAndAnimations
in its documentation page:
The cy.screenshot command mentions CSS animations
Hmm, does cy.screenshot
know how to disable CSS animations?! Let's try it out.
1 | it('takes a screenshot', () => { |
Look at the screenshots - they all show the page as if the CSS animations ran to the finish!
Somehow cy.screenshot shows the final transition in each image
How does it do it? How does it bypass waiting 5 seconds?
Let's search the Cypress source code for "disableTimersAndAnimations". This search result seems very relevant.
Looks like cy.screenshot is injecting something into the application's frame to disable CSS animations
Let's click on the search result to find the utility method addCssAnimationDisabler
. It seems to just add a style to overwrite all CSS transitions in the page and set their duration to zero!
How Cypress skips CSS animations during screenshots
Disabling animations from out test #
Nice, we can do the same thing ourselves from the Cypress test. We can use jQuery bundled with Cypress under Cypress.$
to make the code simpler.
1 | it('disables animations', () => { |
The test shows the nice final state of each animation.
The Cypress test with disabled CSS animations
Note: I should record a video showing what I have explained in this blog post. Subscribe to my YouTube channel to find the video when it comes out.