Applies Jest and Testing Library patterns for React and React Native: getMockX factories, jest.mock GraphQL hooks, renderWithTheme providers, and red-green-refactor TDD. Trigger when writing unit tests, test factories, or module mocks. Do not use for Playwright or Cypress E2E, GitHub Actions workflow YAML, or shipping production features without a failing test first.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Applies Jest and Testing Library patterns for React and React Native: getMockX factories, jest.mock GraphQL hooks, renderWithTheme providers, and red-green-refactor TDD. Trigger when writing unit tests, test factories, or module mocks. Do not use for Playwright or Cypress E2E, GitHub Actions workflow YAML, or shipping production features without a failing test first.
This skill provides a comprehensive set of Jest testing patterns for React and React Native projects, including factory functions for test data, module and GraphQL hook mocking strategies, custom render utilities, and a structured TDD workflow. It is framework-agnostic in principle but uses @testing-library/react-native and Jest as the concrete toolchain.
When to Use
Use this skill when any of the following apply:
You are writing or refactoring unit tests with Jest.
You need to create test factories for component props or domain data.
You are mocking modules, GraphQL hooks, or external dependencies.
You are following the TDD red-green-refactor cycle and need a structured workflow.
You need a custom render function to wrap components with required providers (e.g., ThemeProvider).
You are organizing test suites with describe blocks and need a consistent structure.
Trigger keywords: jest, unit test, test factory, mock, TDD, red-green-refactor, testing-library, renderWithTheme, getMockUser, factory function.
Prerequisites
Node.js and a package manager (npm or yarn) installed on your system.
Jest and @testing-library/react-native (or @testing-library/react for web projects) installed in the project.
TypeScript configured if using type-safe factories (recommended but not required).
Windows host is primary; commands below use PowerShell syntax. On macOS/Linux, adapt path separators and line-continuation characters as needed.
Procedure
1. Follow the TDD Red-Green-Refactor Cycle
Red — Write a failing test that describes the desired behavior. Run it and confirm it fails for the right reason.
Green — Implement the minimal production code to make the test pass.
Refactor — Clean up the implementation while keeping the test green. Never refactor without a passing test.
Core rules:
Never write production code without a failing test.
Test behavior, not implementation. Focus on public APIs and business requirements.
// Element must exist — throws if not foundexpect(screen.getByText('Hello')).toBeTruthy();
// Element should not exist — returns null, does not throwexpect(screen.queryByText('Goodbye')).toBeNull();
// Element appears asynchronously — retries until timeoutawaitwaitFor(() => {
expect(screen.findByText('Loaded')).toBeTruthy();
});
Testing mock behavior instead of real behavior. Asserting that a mock was called is sometimes necessary, but the primary assertion should verify observable output (rendered text, state changes, etc.).
// Bad — only checks the mockexpect(mockFetchData).toHaveBeenCalled();
// Good — checks actual behaviorexpect(screen.getByText('John Doe')).toBeTruthy();
Not using factories. Inline test data leads to duplication and inconsistency (e.g., a role field silently missing in one test). Always use getMockX(overrides) factories.
Using getBy* for elements that may not exist.getByText throws if the element is not found. Use queryByText when asserting absence, and findByText (with await) for async elements.
Forgetting jest.clearAllMocks() in beforeEach. Mock call counts and return values leak between tests, causing flaky or false-positive results.
Testing implementation details. Testing private methods or internal component state makes tests brittle. Refactoring production code then breaks tests even though behavior is unchanged.
Over-mocking. Mocking too many modules can make tests pass while the real integration is broken. Mock only external boundaries (network, storage, analytics, generated code).
Skipping the "Red" phase. If a test passes before you write the implementation, it is either redundant or not testing the right thing. Always confirm the test fails first.
Verification
Confirm your test setup and patterns are working correctly:
Verify Jest is installed and configured:
npx jest --version
Expected output: a version number (e.g., 29.x.x).
Run the full test suite and confirm it passes:
npm test
Expected: all suites pass with 0 failures.
Run a single test file to isolate failures:
npm test ComponentName.test.tsx
Verify coverage is collected:
npm run test:coverage
Expected: a coverage table is printed showing file, statement, branch, and function percentages.
Verify a factory produces correct defaults and overrides:
beforeEach(() => {
jest.clearAllMocks();
});
it('call count starts at zero', () => {
const fn = jest.fn();
// In the next test, fn.mock.calls should be empty
});
Related Skills
react-ui-patterns — Test all UI states: loading, error, empty, and success. Pair with this skill to ensure every visual state has coverage.
systematic-debugging — Write a test that reproduces a bug before fixing it. This skill provides the factory and mocking patterns to construct the failing scenario.
Limitations
Use this skill only when the task clearly matches its upstream source and local project context.
Verify commands, generated code, dependencies, credentials, and external service behavior before applying changes.
Do not treat examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.
Examples assume @testing-library/react-native; for web projects using @testing-library/react, replace fireEvent.press with fireEvent.click and changeText with change as appropriate.