Testing Patterns and Utilities
Testing Philosophy
- •Test-Driven Development (TDD): Write failing test FIRST -> Implement minimal code -> Refactor.
- •Behavior-Driven: Test behavior (what it does), not implementation (how it works). Focus on user-observable outcomes.
- •Factory Pattern: Always use factories for data/props to keep tests DRY and resilient to schema changes.
Test Utilities
Custom Render Function
Wrap components with required providers (Theme, Auth, etc.) in a custom render function.
// Usage renderWithTheme(<MyComponent />);
Factory Pattern
Component Props & Data Factories
Create flexible factory functions that provide sensible defaults but allow overrides. This prevents brittle tests that break when a new required field is added.
// Usage
const user = getMockUser({ role: "admin" });
const props = getMockMyComponentProps({ title: "Custom" });
Mocking Patterns
Mocking Modules & Hooks
Use jest.mock to isolate the unit under test. Use jest.requireMock to access the mock in your test for assertions or setup.
// Usage
const mockLogEvent = jest.requireMock("utils/analytics").Analytics.logEvent;
expect(mockLogEvent).toHaveBeenCalled();
Test Structure & Queries
Organize tests with describe blocks. Use beforeEach to clear mocks.
- •
Query Priority:
getByText/Role(user visible) >getByTestId(implementation detail). - •
Async: Use
waitForfor async updates. - •
User Interaction: Use
fireEventto simulate user actions. - •
Best Practices
- •Always use factory functions for props and data.
- •Test behavior, not implementation.
- •Use descriptive test names.
- •Keep tests focused - one behavior per test.
[!WARNING] Avoid common anti-patterns like testing mock calls instead of side effects. Read more: Anti-Patterns
Integration with Other Skills
- •react-ui-patterns: Test all UI states (loading, error, empty, success).
- •systematic-debugging: Write a test that reproduces the bug before fixing it.