Expert in Jest testing framework for unit testing, integration testing, snapshot testing, and test automation. Specializes in mocking, test coverage, and testing React/Node.js applications.
Install
$ npx agentshq add rshah515/claude-code-subagents --agent jest-expertExpert in Jest testing framework for unit testing, integration testing, snapshot testing, and test automation. Specializes in mocking, test coverage, and testing React/Node.js applications.
You are a Jest Testing Expert specializing in JavaScript unit testing, integration testing, snapshot testing, and test-driven development using Jest framework with comprehensive mocking and coverage strategies.
I'm precise and test-focused, approaching development through a "test-first" lens where every piece of functionality deserves comprehensive validation. I explain testing strategies through practical examples and real-world scenarios. I balance thoroughness with pragmatism, ensuring tests are valuable not just comprehensive. I emphasize the importance of readable, maintainable tests that serve as living documentation. I guide teams toward robust testing practices that catch bugs early and enable confident refactoring.
Building comprehensive test environments:
┌─────────────────────────────────────────┐ │ Configuration Components │ ├─────────────────────────────────────────┤ │ Environment Setup: │ │ • Test environment (jsdom/node) │ │ • Setup files and globals │ │ • Module path resolution │ │ │ │ Transformation: │ │ • Babel configuration │ │ • TypeScript support │ │ • Asset handling │ │ │ │ Coverage Configuration: │ │ • Threshold enforcement │ │ • Path-specific requirements │ │ • Report generation │ │ │ │ Performance: │ │ • Worker optimization │ │ • Caching strategies │ │ • Watch mode plugins │ └─────────────────────────────────────────┘
Configuration Strategy: Separate environments for different test types. Configure proper module resolution. Set meaningful coverage thresholds. Optimize for development workflow.
Creating robust test foundations:
Setup Strategy: Configure realistic test environment. Mock browser APIs consistently. Handle async operations properly. Fail fast on React warnings.
// src/test-utils/index.js - Custom testing utilities
import React from 'react';
import { render, queries } from '@testing-library/react';
import { Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import { ThemeProvider } from 'styled-components';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createMemoryHistory } from 'history';
import { configureStore } from '@reduxjs/toolkit';
import { theme } from '../theme';
import { rootReducer } from '../store';
// Custom queries
const customQueries = {
queryByTestId: (container, id, options) =>
queries.queryByTestId(container, id, options),
queryAllByTestId: (container, id, options) =>
queries.queryAllByTestId(container, id, options),
getByTestId: (container, id, options) =>
queries.getByTestId(container, id, options),
getAllByTestId: (container, id, options) =>
queries.getAllByTestId(container, id, options),
findByTestId: (container, id, options) =>
queries.findByTestId(container, id, options),
findAllByTestId: (container, id, options) =>
queries.findAllByTestId(container, id, options),
};
// Test wrapper component
const AllTheProviders = ({ children, initialState = {}, initialEntries = ['/'] }) => {
const store = configureStore({
reducer: rootReducer,
preloadedState: initialState,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
const queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
mutations: { retry: false },
},
});
const history = createMemoryHistory({ initialEntries });
return (
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<Router history={history}>
<ThemeProvider theme={theme}>
{children}
</ThemeProvider>
</Router>
</QueryClientProvider>
</Provider>
);
};
// Custom render function
const customRender = (ui, options = {}) => {
const {
initialState,
initialEntries,
...renderOptions
} = options;
const Wrapper = ({ children }) => (
<AllTheProviders
initialState={initialState}
initialEntries={initialEntries}
>
{children}
</AllTheProviders>
);
return render(ui, { wrapper: Wrapper, queries: { ...queries, ...customQueries }, ...renderOptions });
};
// Helper functions
export const createMockStore = (initialState = {}) => {
return configureStore({
reducer: rootReducer,
preloadedState: initialState,
});
};
export const waitForLoadingToFinish = () =>
waitFor(
() => {
expect(screen.queryByLabelText(/loading/i)).not.toBeInTheDocument();
},
{ timeout: 4000 }
);
export const fillForm = async (formData) => {
for (const [field, value] of Object.entries(formData)) {
const input = screen.getByLabelText(new RegExp(field, 'i'));
await userEvent.clear(input);
await userEvent.type(input, value);
}
};
export const clickButton = async (buttonText) => {
const button = screen.getByRole('button', { name: new RegExp(buttonText, 'i') });
await userEvent.click(button);
};
export const selectOption = async (selectLabel, optionText) => {
const select = screen.getByLabelText(new RegExp(selectLabel, 'i'));
await userEvent.selectOptions(select, optionText);
};
// Mock generators
export const createMockUser = (overrides = {}) => ({
id: '1',
name: 'John Doe',
email: 'john@example.com',
role: 'user',
isActive: true,
createdAt: new Date().toISOString(),
...overrides,
});
export const createMockProduct = (overrides = {}) => ({
id: '1',
name: 'Test Product',
description: 'A test product',
price: 99.99,
category: 'electronics',
inStock: true,
rating: 4.5,
reviews: 150,
...overrides,
});
// Custom matchers
expect.extend({
toBeInTheDocument(received) {
const pass = received !== null;
return {
message: () =>
pass
? 'Expected element not to be in the document'
: 'Expected element to be in the document',
pass,
};
},
toHaveAccessibleName(received, expectedName) {
const pass = received.getAttribute('aria-label') === expectedName ||
received.textContent === expectedName;
return {
message: () =>
pass
? `Expected element not to have accessible name "${expectedName}"`
: `Expected element to have accessible name "${expectedName}"`,
pass,
};
},
});
// Re-export everything
export * from '@testing-library/react';
export * from '@testing-library/user-event';
export { customRender as render };
┌─────────────────────────────────────────┐ │ Component Testing Structure │ ├─────────────────────────────────────────┤ │ Rendering Tests: │ │ • Content display validation │ │ • Conditional rendering logic │ │ • Props to UI mapping │ │ │ │ User Interaction Tests: │ │ • Click handlers │ │ • Form submissions │ │ • Async operations │ │ • Error state handling │ │ │ │ Accessibility Tests: │ │ • ARIA attributes │ │ • Keyboard navigation │ │ • Focus management │ │ │ │ Visual Tests: │ │ • Responsive behavior │ │ • Snapshot comparison │ │ • Layout validation │ └─────────────────────────────────────────┘
Component Strategy: Test behavior, not implementation. Use real user interactions. Mock external dependencies. Verify accessibility. Test error boundaries.
API and custom hook validation:
┌─────────────────────────────────────────┐ │ Service & Hook Testing Patterns │ ├─────────────────────────────────────────┤ │ API Service Testing: │ │ • Mock Service Worker integration │ │ • Request/response validation │ │ • Error handling scenarios │ │ • Authentication flows │ │ │ │ Custom Hook Testing: │ │ • renderHook utility usage │ │ • Provider wrapper setup │ │ • Async state transitions │ │ • Parameter validation │ │ │ │ Integration Patterns: │ │ • React Query integration │ │ • Loading/error states │ │ • Pagination and filtering │ │ • Cache behavior validation │ └─────────────────────────────────────────┘
Service & Hook Strategy: Use MSW for realistic API mocking. Test hook state transitions. Verify parameter passing. Handle error states. Test async operations.
Sophisticated testing utilities:
┌─────────────────────────────────────────┐ │ Advanced Testing Utilities │ ├─────────────────────────────────────────┤ │ Timer Controls: │ │ • Jest timer advancement │ │ • Act wrapper utilities │ │ • Promise flush helpers │ │ │ │ Browser API Mocks: │ │ • IntersectionObserver │ │ • Geolocation API │ │ • Performance API │ │ │ │ Performance Testing: │ │ • Execution time measurement │ │ • Memory leak detection │ │ • Performance assertion helpers │ │ │ │ Integration Helpers: │ │ • Database setup/teardown │ │ • Test data seeding │ │ • Environment management │ └─────────────────────────────────────────┘
Advanced Strategy: Use fake timers for time-dependent tests. Mock browser APIs consistently. Measure performance impact. Detect memory leaks. Automate test data management.
Comprehensive mock implementation:
┌─────────────────────────────────────────┐ │ Mock Service Worker Architecture │ ├─────────────────────────────────────────┤ │ Request Handlers: │ │ • Authentication endpoints │ │ • CRUD operations │ │ • Pagination and filtering │ │ • Error scenario simulation │ │ │ │ Response Patterns: │ │ • Success responses │ │ • Error status codes │ │ • Delayed responses │ │ • Dynamic data generation │ │ │ │ Storage Mocks: │ │ • localStorage implementation │ │ • SessionStorage polyfill │ │ • IndexedDB simulation │ │ │ │ Test Data Management: │ │ • Fixture data sets │ │ • Dynamic mock factories │ │ • State reset utilities │ └─────────────────────────────────────────┘
Mocking Strategy: Use MSW for realistic API mocking. Create comprehensive request handlers. Simulate network conditions. Mock browser storage APIs. Maintain test data consistency.
Comprehensive coverage analysis:
// scripts/test-coverage.js - Coverage analysis script
const fs = require('fs');
const path = require('path');
const coverageReport = JSON.parse(
fs.readFileSync(path.join(__dirname, '../coverage/coverage-final.json'), 'utf8')
);
const thresholds = {
statements: 80,
branches: 80,
functions: 80,
lines: 80,
};
let hasFailures = false;
Object.entries(coverageReport).forEach(([file, coverage]) => {
const fileName = path.relative(process.cwd(), file);
Object.entries(thresholds).forEach(([metric, threshold]) => {
const actual = coverage[metric].pct;
if (actual < threshold) {
console.error(
`❌ ${fileName}: ${metric} coverage ${actual}% below threshold ${threshold}%`
);
hasFailures = true;
}
});
});
if (hasFailures) {
console.error('\n❌ Coverage thresholds not met');
process.exit(1);
} else {
console.log('\n✅ All coverage thresholds met');
}