Documentation Index Fetch the complete documentation index at: https://docs.thesozocrm.com/llms.txt
Use this file to discover all available pages before exploring further.
Testing Workflow
This guide covers how to write, run, and maintain tests in the Elevate CRM codebase.
Quick Start
Run Tests
# Run all tests
npm test
# Run specific test file
npm test -- RepManagement.test.jsx
# Run tests in watch mode
npm test -- --watch
# Run tests with coverage
npm test -- --coverage
Test Structure
Unit Tests
Location: src/**/__tests__/*.test.js or *.test.jsx
Example:
// src/shared/services/__tests__/regionService.test.js
import regionService from '../regionService' ;
describe ( 'regionService' , () => {
describe ( 'assignTeamToRegion' , () => {
it ( 'should assign team to region and sync rep regionIds' , async () => {
// Test implementation
});
});
});
Component Tests
Location: src/**/__tests__/*.test.jsx
Example:
// src/features/reps/components/__tests__/RepCard.test.jsx
import { render , screen } from '@testing-library/react' ;
import RepCard from '../RepCard' ;
describe ( 'RepCard' , () => {
it ( 'should display rep name and email' , () => {
const rep = { name: 'John Doe' , email: 'john@test.com' };
render ( < RepCard rep = { rep } /> );
expect ( screen . getByText ( 'John Doe' )). toBeInTheDocument ();
});
});
Writing Tests
Test-Driven Development (TDD)
Write Failing Test
Write a test that describes the behavior you want
Run Test
Verify the test fails (Red)
Write Minimal Code
Write just enough code to make the test pass (Green)
Refactor
Improve the code while keeping tests passing
Test Structure (AAA Pattern)
describe ( 'FeatureName' , () => {
it ( 'should do something when condition' , () => {
// Arrange - Set up test data
const input = { value: 10 };
// Act - Execute the function
const result = myFunction ( input );
// Assert - Verify the result
expect ( result ). toBe ( 20 );
});
});
Testing Patterns
Mocking Firebase
// Mock Firestore
jest . mock ( 'firebase/firestore' , () => ({
doc: jest . fn (),
getDoc: jest . fn (),
setDoc: jest . fn (),
updateDoc: jest . fn (),
collection: jest . fn (),
query: jest . fn (),
where: jest . fn (),
getDocs: jest . fn (),
}));
// In test
import { getDoc , setDoc } from 'firebase/firestore' ;
beforeEach (() => {
getDoc . mockResolvedValue ({
exists : () => true ,
data : () => ({ name: 'Test' })
});
});
Testing React Components
import { render , screen , fireEvent } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
test ( 'should handle user interaction' , async () => {
const user = userEvent . setup ();
render ( < MyComponent /> );
const button = screen . getByRole ( 'button' , { name: /click me/ i });
await user . click ( button );
expect ( screen . getByText ( 'Clicked!' )). toBeInTheDocument ();
});
Testing Hooks
import { renderHook , act } from '@testing-library/react' ;
import { useMyHook } from '../useMyHook' ;
test ( 'should update state' , () => {
const { result } = renderHook (() => useMyHook ());
act (() => {
result . current . updateValue ( 10 );
});
expect ( result . current . value ). toBe ( 10 );
});
Coverage Requirements
Minimum Coverage
Lines : ≥ 85%
Branches : ≥ 90% (for core modules)
Functions : ≥ 85%
Check Coverage
# Run with coverage report
npm test -- --coverage
# View HTML report
open coverage/lcov-report/index.html
Coverage Exclusions
Some files are excluded from coverage:
Configuration files
Test utilities
Legacy code (marked with // @ts-nocheck or similar)
Best Practices
Test Behavior, Not Implementation Test what the component does, not how it does it
One Assertion Per Test Each test should verify one thing
Use Descriptive Names Test names should read like specifications
Keep Tests Fast Unit tests should run in milliseconds
Isolate Tests Tests should not depend on each other
Mock External Dependencies Mock Firebase, APIs, and external services
Common Test Patterns
Testing Async Functions
test ( 'should handle async operation' , async () => {
const result = await myAsyncFunction ();
expect ( result ). toBeDefined ();
});
Testing Error Handling
test ( 'should handle errors gracefully' , async () => {
jest . spyOn ( console , 'error' ). mockImplementation (() => {});
await expect ( myFunction ()). rejects . toThrow ( 'Expected error' );
console . error . mockRestore ();
});
test ( 'should submit form with valid data' , async () => {
const user = userEvent . setup ();
const onSubmit = jest . fn ();
render ( < MyForm onSubmit = { onSubmit } /> );
await user . type ( screen . getByLabelText ( /email/ i ), 'test@test.com' );
await user . click ( screen . getByRole ( 'button' , { name: /submit/ i }));
expect ( onSubmit ). toHaveBeenCalledWith ({ email: 'test@test.com' });
});
Troubleshooting
Tests Failing After Changes
If you changed function signatures, update your mocks
Ensure all dependencies are properly mocked