Skip to content

Instantly share code, notes, and snippets.

@cvan
Last active June 23, 2023 15:40
Show Gist options
  • Save cvan/576eb41ab5d382660c14e3831c33c6ea to your computer and use it in GitHub Desktop.
Save cvan/576eb41ab5d382660c14e3831c33c6ea to your computer and use it in GitHub Desktop.
cypress disable basic css transitions + animations
// Custom Cypress No-Motion helper
//
// To reduce flakiness in Cypress tests caused by motion,
// force disable all CSS transitions and animations.
//
// revised: 2023-03-15
// credits: @ypresto
function disableMotion(win) {
const injectedStyleEl = win.document.getElementById('__cy_disable_motion__');
if (injectedStyleEl) {
return;
}
win.document.head.insertAdjacentHTML(
'beforeend',
`
<style id="__cy_disable_motion__">
/* Disable CSS transitions. */
*, *::before, *::after { -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; -ms-transition: none !important; transition: none !important; }
/* Disable CSS animations. */
*, *::before, *::after { -webkit-animation: none !important; -moz-animation: none !important; -o-animation: none !important; -ms-animation: none !important; animation: none !important; }
</style>
`.trim()
);
}
function revertDisableMotion(win) {
const injectedStyleEl = win.document.getElementById('__cy_disable_motion__');
if (!injectedStyleEl) {
return;
}
injectedStyleEl.parentNode.removeChild(injectedStyleEl);
}
// to disable CSS transitions and animations:
Cypress.on('window:before:load', (cyWindow) => {
disableMotion(cyWindow);
});
// if you need to revert, uncomment the three lines below:
// Cypress.on('window:before:load', (cyWindow) => {
// revertDisableMotion(cyWindow);
// });
// Original version (do not use):
//
// tip: If the app uses a JS-based
// animation library, such as
// `framer-motion`, evaluate whether
// the last two CSS overrides in
// this version may still be helpful.
//
// Realistically, the animation library
// offers a `prefers-reduced-motion`
// (or similar) hook/helper function
// that can conditionally disable animations
// globally (check for `window.Cypress`).
/*
Cypress.Commands.add('cssDisableMotion', (selector = 'head') => {
cy.get('html').then(() => {
document.querySelector(selector).insertAdjacentHTML('beforeend', `
<style>
/* Disable CSS transitions. */
* { -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; transition: none !important; }
/* Disable CSS animations. */
* { -webkit-animation: none !important; -moz-animation: none !important; -o-animation: none !important; animation: none !important; }
/* Reset values on non-opaque/offscreen framer-motion components. */
*[style*="opacity"] { opacity: 1 !important; }
*[style*="transform"] { transform: none !important; }
</style>
`);
});
});
*/
@simonsmith
Copy link

This should use cy.document() otherwise it won't inject the styles into the app, but the test instead

@ypresto
Copy link

ypresto commented Mar 15, 2023

* selector does not include ::before and ::after pseudo elements.

Cypress.on('window:before:load', window => {
  window.document.head.insertAdjacentHTML(
    'beforeend',
    `
    <style>
      /* Disable CSS transitions. */
      *, *::before, *::after { -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; transition: none !important; }
      /* Disable CSS animations. */
      *, *::before, *::after { -webkit-animation: none !important; -moz-animation: none !important; -o-animation: none !important; animation: none !important; }
    </style>
  `
  )
})

@cvan
Copy link
Author

cvan commented Mar 16, 2023

* selector does not include ::before and ::after pseudo elements.

excellent observation. the snippet above has been updated now. thank you!

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