Playwright
// Emulate reduced motion preference
await page.emulateMedia({
reducedMotion: 'reduce'
});
// Verify animations are disabled using $eval
const spinner = page.getByTestId('spinner');
const animation = await spinner.$eval(
'self', el => getComputedStyle(el).animationName
);
expect(animation).toBe('none');
// Check for animation-duration
const duration = await spinner.$eval(
'self', el => getComputedStyle(el).animationDuration
);
// Should be 0 or very small
expect(parseFloat(duration)).toBeLessThan(0.1);
// Test both modes
for (const motion of ['reduce', 'no-preference']) {
await page.emulateMedia({ reducedMotion: motion });
// Test behavior...
}CSS Audit
// Find all animated elements using $$eval
const animated = await page.$$eval('*', els =>
els.filter(el => {
const style = getComputedStyle(el);
return style.animationName !== 'none' ||
parseFloat(style.transitionDuration) > 0.3;
}).map(el => ({
tag: el.tagName,
animation: getComputedStyle(el).animationName,
duration: getComputedStyle(el).animationDuration
}))
);
console.log('Elements with animation:', animated);
// Check if @media (prefers-reduced-motion)
// exists in stylesheets
const sheets = [...document.styleSheets];
const hasReducedMotionRule = sheets.some(sheet => {
try {
return [...sheet.cssRules].some(rule =>
rule.media?.mediaText.includes('prefers-reduced-motion')
);
} catch { return false; }
});