Implementing Unit Testing in JavaScript with Jest
Guidelines on setting up and writing unit tests using Jest to ensure code reliability and maintainability in JavaScript projects.
0 likes
197 views
Rule Content
{
"title": "Implementing Unit Testing in JavaScript with Jest",
"description": "Guidelines on setting up and writing unit tests using Jest to ensure code reliability and maintainability in JavaScript projects.",
"category": "JavaScript Cursor Rules",
"rules": [
{
"name": "Use Descriptive Test Names",
"description": "Ensure each test name clearly describes the functionality being tested and the expected outcome.",
"examples": [
{
"bad": "test('works correctly', () => { /* test implementation */ });",
"good": "test('should return the sum of two numbers', () => { /* test implementation */ });"
}
]
},
{
"name": "Follow the Arrange-Act-Assert Pattern",
"description": "Structure tests into three distinct sections: setup (Arrange), execution (Act), and verification (Assert).",
"examples": [
{
"bad": "test('should add numbers', () => { const result = add(1, 2); expect(result).toBe(3); });",
"good": "test('should add numbers', () => { // Arrange const num1 = 1; const num2 = 2; // Act const result = add(num1, num2); // Assert expect(result).toBe(3); });"
}
]
},
{
"name": "Keep Tests Isolated and Independent",
"description": "Ensure each test is self-contained and does not depend on the state or results of other tests.",
"examples": [
{
"bad": "test('should increment counter', () => { counter.increment(); expect(counter.value).toBe(1); }); test('should decrement counter', () => { expect(counter.value).toBe(0); counter.decrement(); expect(counter.value).toBe(-1); });",
"good": "test('should increment counter', () => { const counter = new Counter(); counter.increment(); expect(counter.value).toBe(1); }); test('should decrement counter', () => { const counter = new Counter(); counter.decrement(); expect(counter.value).toBe(-1); });"
}
]
},
{
"name": "Use Mocks and Spies Appropriately",
"description": "Mock external dependencies and use spies to verify interactions, ensuring tests focus on the unit under test.",
"examples": [
{
"bad": "test('should fetch user data', () => { const data = fetchData(); expect(data).toEqual({ id: 1, name: 'John Doe' }); });",
"good": "test('should fetch user data', async () => { const mockFetch = jest.fn().mockResolvedValue({ id: 1, name: 'John Doe' }); const data = await fetchData(mockFetch); expect(mockFetch).toHaveBeenCalled(); expect(data).toEqual({ id: 1, name: 'John Doe' }); });"
}
]
},
{
"name": "Avoid Testing Implementation Details",
"description": "Focus on testing the output and behavior of functions rather than their internal implementation.",
"examples": [
{
"bad": "test('should call helper function', () => { const spy = jest.spyOn(module, 'helperFunction'); mainFunction(); expect(spy).toHaveBeenCalled(); });",
"good": "test('should return correct result', () => { const result = mainFunction(); expect(result).toBe('expected result'); });"
}
]
},
{
"name": "Utilize Setup and Teardown Methods",
"description": "Use Jest's lifecycle methods to set up and clean up resources before and after tests to maintain a consistent test environment.",
"examples": [
{
"bad": "test('should process data', () => { const db = new Database(); db.connect(); const result = processData(db); expect(result).toBe('processed data'); db.disconnect(); });",
"good": "describe('Data Processing', () => { let db; beforeAll(() => { db = new Database(); db.connect(); }); afterAll(() => { db.disconnect(); }); test('should process data', () => { const result = processData(db); expect(result).toBe('processed data'); }); });"
}
]
},
{
"name": "Ensure Tests Are Deterministic",
"description": "Write tests that produce the same results every time they are run, regardless of external factors.",
"examples": [
{
"bad": "test('should return current date', () => { const result = getCurrentDate(); expect(result).toBe(new Date().toISOString()); });",
"good": "test('should return current date', () => { const mockDate = new Date('2025-06-03T00:00:00Z'); jest.useFakeTimers().setSystemTime(mockDate); const result = getCurrentDate(); expect(result).toBe('2025-06-03'); jest.useRealTimers(); });"
}
]
},
{
"name": "Maintain High Test Coverage",
"description": "Aim for comprehensive test coverage to ensure all code paths are tested, enhancing code reliability.",
"examples": [
{
"bad": "test('should add numbers', () => { const result = add(1, 2); expect(result).toBe(3); }); // No tests for subtract function",
"good": "test('should add numbers', () => { const result = add(1, 2); expect(result).toBe(3); }); test('should subtract numbers', () => { const result = subtract(2, 1); expect(result).toBe(1); });"
}
]
},
{
"name": "Use Snapshot Testing for UI Components",
"description": "Employ snapshot testing to capture the rendered output of UI components and detect unintended changes.",
"examples": [
{
"bad": "test('should render component', () => { const component = render(<MyComponent />); expect(component).toBeDefined(); });",
"good": "test('should match snapshot', () => { const component = render(<MyComponent />); expect(component).toMatchSnapshot(); });"
}
]
},
{
"name": "Run Tests in Continuous Integration",
"description": "Integrate tests into the CI/CD pipeline to automatically run them on code changes, ensuring ongoing code quality.",
"examples": [
{
"bad": "// No CI integration for tests",
"good": "// .github/workflows/ci.yml name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install dependencies run: npm install - name: Run tests run: npm test"
}
]
}
]
}