Testing
How to run and write tests for Turbo Themes.
Testing
Turbo Themes uses multiple testing strategies to ensure quality.
Running Tests
All Tests
bun run test
Specific Test Suites
# Unit tests
bun run test:unit
# E2E tests
bun run test:e2e
# Visual regression tests
bun run test:visual
Test Types
Unit Tests
Unit tests for individual functions and components.
Location: packages/*/test/
# Run unit tests
bun run test:unit
# Run with coverage
bun run test:coverage
Example test:
// packages/theme-selector/test/storage.test.ts
import { describe, it, expect, beforeEach } from 'bun:test';
import { getStoredTheme, setStoredTheme } from '../src/storage';
describe('storage', () => {
beforeEach(() => {
localStorage.clear();
});
it('returns default theme when nothing stored', () => {
expect(getStoredTheme()).toBe('catppuccin-mocha');
});
it('returns stored theme', () => {
localStorage.setItem('turbo-theme', 'dracula');
expect(getStoredTheme()).toBe('dracula');
});
it('stores theme in localStorage', () => {
setStoredTheme('github-dark');
expect(localStorage.getItem('turbo-theme')).toBe('github-dark');
});
});
End-to-End Tests
E2E tests using Playwright.
Location: e2e/
# Run E2E tests
bun run test:e2e
# Run in headed mode (see browser)
bun run test:e2e -- --headed
# Run specific test file
bun run test:e2e -- e2e/theme-switching.spec.ts
Example E2E test:
// e2e/theme-switching.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Theme Switching', () => {
test('changes theme when selecting from dropdown', async ({ page }) => {
await page.goto('/');
// Open theme dropdown
await page.click('[data-testid="theme-trigger"]');
// Select Dracula theme
await page.click('[data-theme="dracula"]');
// Verify theme applied
const html = page.locator('html');
await expect(html).toHaveAttribute('data-theme', 'dracula');
});
test('persists theme across page reload', async ({ page }) => {
await page.goto('/');
// Change theme
await page.click('[data-testid="theme-trigger"]');
await page.click('[data-theme="dracula"]');
// Reload page
await page.reload();
// Theme should still be Dracula
const html = page.locator('html');
await expect(html).toHaveAttribute('data-theme', 'dracula');
});
});
Visual Regression Tests
Visual tests to catch unintended UI changes.
# Run visual tests
bun run test:visual
# Update snapshots
bun run test:visual -- --update-snapshots
Accessibility Tests
Automated accessibility checks:
bun run test:a11y
Writing Tests
Test File Naming
- Unit tests:
*.test.ts - E2E tests:
*.spec.ts - Visual tests:
*.visual.ts
Test Structure
Follow the AAA pattern (Arrange, Act, Assert):
it('applies theme class to document', () => {
// Arrange
const doc = createMockDocument();
// Act
applyTheme(doc, 'dracula');
// Assert
expect(doc.documentElement.getAttribute('data-theme')).toBe('dracula');
});
Mocking
import { mock, spyOn } from 'bun:test';
// Mock localStorage
const mockStorage = {
getItem: mock(() => 'catppuccin-mocha'),
setItem: mock(() => {}),
};
globalThis.localStorage = mockStorage;
// Spy on function
const spy = spyOn(console, 'log');
Test Coverage
Check test coverage:
bun run test:coverage
Coverage report is generated in coverage/.
Coverage Requirements
- Minimum overall coverage: 80%
- New code should have tests
- Critical paths should have 100% coverage
CI/CD Tests
Tests run automatically on:
- Pull requests
- Pushes to main
CI runs:
- Linting
- Type checking
- Unit tests
- E2E tests
- Visual regression tests
- Accessibility tests
Debugging Tests
Unit Tests
# Run with verbose output
bun run test:unit -- --verbose
# Run single test
bun run test:unit -- --filter "storage"
E2E Tests
# Debug mode
bun run test:e2e -- --debug
# Headed mode (see browser)
bun run test:e2e -- --headed
# Slow motion
bun run test:e2e -- --headed --slow-mo=500
Next Steps
- Understand the Release Process
- Review Contributing Guidelines
- Set up your Development Environment