# 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.