# testing-patterns > Testing strategies for animations and motion. Use for visual regression testing, timing verification, reduced motion compliance, and performance profiling to ensure animations work correctly. - Author: Edison - Repository: soilmass/motion-design-agent - Version: 20260124075058 - Stars: 1 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/soilmass/motion-design-agent - Web: https://mule.run/skillshub/@@soilmass/motion-design-agent~testing-patterns:20260124075058 --- --- name: testing-patterns description: Testing strategies for animations and motion. Use for visual regression testing, timing verification, reduced motion compliance, and performance profiling to ensure animations work correctly. --- # Animation Testing Patterns Systematic approaches to testing animations for correctness, accessibility, and performance. ## Testing Categories | Category | What to Test | Tools | |----------|-------------|-------| | Visual regression | Animation appearance | Playwright, Percy | | Timing | Duration, delays, easing | Jest timers, Playwright | | Accessibility | Reduced motion, focus | Playwright, axe | | Performance | Frame rate, paint times | Chrome DevTools, Lighthouse | ## Visual Regression Testing ### Playwright Setup ```typescript import { test, expect } from '@playwright/test'; test.describe('Button animations', () => { test('hover state animation', async ({ page }) => { await page.goto('/components/button'); const button = page.locator('.animated-button'); await expect(button).toHaveScreenshot('button-idle.png'); await button.hover(); await page.waitForTimeout(300); await expect(button).toHaveScreenshot('button-hover.png'); }); }); ``` ## Timing Verification ### Jest Timer Tests ```typescript import { render, screen, act } from '@testing-library/react'; describe('Animation timing', () => { beforeEach(() => jest.useFakeTimers()); afterEach(() => jest.useRealTimers()); test('fade-in completes in 300ms', () => { render(); const element = screen.getByTestId('animated-element'); expect(element).toHaveStyle({ opacity: 0 }); act(() => jest.advanceTimersByTime(300)); expect(element).toHaveStyle({ opacity: 1 }); }); }); ``` ## Reduced Motion Testing ### Playwright Reduced Motion ```typescript test.describe('Reduced motion compliance', () => { test('respects prefers-reduced-motion', async ({ page }) => { await page.emulateMedia({ reducedMotion: 'reduce' }); await page.goto('/components/animated-list'); await page.click('[data-add-item]'); const item = page.locator('.list-item').last(); const animationDuration = await item.evaluate( el => getComputedStyle(el).animationDuration ); expect(animationDuration).toBe('0s'); }); }); ``` ### Jest Reduced Motion ```typescript describe('Reduced motion', () => { beforeEach(() => { Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation(query => ({ matches: query === '(prefers-reduced-motion: reduce)', media: query, addEventListener: jest.fn(), removeEventListener: jest.fn(), })), }); }); test('uses instant transition when reduced motion preferred', () => { render(); const element = screen.getByTestId('animated'); expect(element).toHaveClass('reduced-motion'); }); }); ``` ## Performance Testing ### Frame Rate Testing ```typescript test('maintains 60fps during animation', async ({ page }) => { await page.goto('/components/heavy-animation'); await page.tracing.start({ categories: ['devtools.timeline'] }); await page.click('[data-start-animation]'); await page.waitForTimeout(1000); const traceBuffer = await page.tracing.stop(); const trace = JSON.parse(traceBuffer.toString()); // Analyze frame times - 60fps = 16.67ms per frame const frames = trace.traceEvents .filter(e => e.name === 'FrameCommittedInBrowser') .map(e => e.ts); const frameTimes = frames.slice(1).map((ts, i) => ts - frames[i]); const avgFrameTime = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length; expect(avgFrameTime).toBeLessThan(20000); // 20ms average }); ``` ## CI Integration ```yaml name: Animation Tests on: [push, pull_request] jobs: visual-regression: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 - run: npm ci - run: npx playwright install --with-deps - run: npm run test:animations - uses: actions/upload-artifact@v3 if: failure() with: name: animation-test-results path: test-results/ ``` ## Common Testing Mistakes 1. **Not waiting for animation completion** - Use proper timeouts 2. **Ignoring reduced motion** - Always test both preferences 3. **Screenshot timing issues** - Capture at consistent animation points 4. **Missing performance baseline** - Establish fps expectations 5. **Flaky visual tests** - Allow reasonable pixel tolerance ## Related Skills - `motion-audit/` - Comprehensive audit checklists - `accessibility/` - WCAG compliance requirements - `remotion/` - Testing Remotion compositions See `references/` for complete Playwright and Jest test examples.