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
14 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" } ] } ] }