Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

ngkhang/unit-test-reactjs-course

Repository files navigation

Unit Test with ReactJS - TypeScript

This a repository about learning to write Unit Tests in React.js with TypeScript. The tutorial and codebase were created by TrungQuanDev.

Requirements

* nodejs >= v22.12.2
* npm >= v10.5.0
* yarn >= v1.22.19

Notes

  • Test File Naming:
    • *.test.ts / *.test.tsx - Standard convention
    • *.spec.ts / *.spec.tsx - Alternative convention
    • Place alongside source files or in __tests__ folder

JavaScript

  • globalThis: global variable (ES2020)

Jest

Globals

Jest: Globals

Jest provides global functions (describe, it, expect, etc.) - no imports needed.

  • Lifecycle hooks

    • beforeAll(fn, timeout) - Runs once before all tests in the file
    • afterAll(fn, timeout) - Runs once after all tests in the file
    • beforeEach(fn, timeout) - Runs before each test
    • afterEach(fn, timeout) - Runs after each test
    • timeout: optional, default 5s (milliseconds)
    • All wait for promises/generators to resolve
  • describe(name, fn)

    • Groups related tests into a block
    • Optional but recommended
    • Can nest for test hierarchies
  • test(name, fn, timeout) / it(name, fn, timeout)

    • Runs a test
    • timeout: Optional, default 5s (milliseconds)
  • test.each(table)(name, fn, timeout) / it.each(table)(name, fn, timeout)

    • Run the same test with different data
    • table: Array of Arrays with test arguments
    • name: Supports printf formatting for parameter injection (%s, %d, %i, %f, %j, %o, %#)
    • fn: Receives each row as arguments

Expect

Jest: Expect

Used to test values with "matcher" functions

  • Provides assertions like toBe(), toEqual(), toContain(), etc.

Mock Function

Jest: Mock Function

Mock functions (also called "spies") track function calls and control behavior

  • Creating Mocks: e.g. jest.fn(), jest.fn(), ...
  • Return Values: e.g. mockFn.mockResolvedValueOnce(value), mockFn.mockRejectedValueOnce(value), mockFn.mockImplementation(), ...
  • Reset/Restore: e.g. mockFn.mockReset(), mockFn.mockRestore(), ...
  • Assertions: e.g. .toHaveBeenCalled(), .toHaveBeenCalledTimes(), .toHaveBeenCalledWith(), ...

The Jest object

Jest: The Jest Object

The jest object is automatically in scope within every test file. It provides methods to create mocks and control Jest's behavior.

  • Mock Functions

    • jest.fn(): Returns a new, unused mock function
    • jest.spyOn(object, methodName):
      • Creates a mock function similar to jest.fn() but also tracks calls to object[methodName].
      • Returns a Jest mock function.
    • jest.clearAllMocks()
      • Clear all mock history (calls, instances, results).
      • Equivalent to calling .mockClear() on every mocked function.
    • jest.restoreAllMocks()
      • Restore all mocks to original values.
      • Equivalent to calling .mockRestore() on every mocked function and .restore() on every replaced property.
    • jest.resetAllMocks()
      • Reset all mocks (clears history and implementations).
      • Equivalent to calling .mockReset() on every mocked function.
  • Module Mocking

    • jest.resetModules()
      • Reset module registry cache.
      • Useful to isolate modules where local state might conflict between tests.
  • Fake Timers

    • jest.useFakeTimers()
      • Fake timers for all tests in file until restored with jest.useRealTimers().
      • This is a global operation affecting other tests in the same file.
    • jest.useRealTimers()
      • Restore original implementations of global date, performance, time and timer APIs
    • jest.runOnlyPendingTimers()
      • Executes only macro-tasks currently pending (queued by setTimeout() or setInterval()).
      • New tasks scheduled by pending tasks won't execute.
    • jest.advanceTimersByTime(msToRun)
      • Fast-forward time by specified milliseconds.
      • Executes all macro-tasks queued by setTimeout(), setInterval(), and setImmediate().

Testing Library

Queries

Testing Library: Queries

  • screen

    • Pre-bound to document.body with all query methods
    • Access rendered elements
  • Types of Queries

    • Single: getBy..., queryBy..., findBy...
    • Multiple: getAllBy..., queryAllBy..., findAllBy...
  • When to use

    • getBy... - Element expected (throws if not found)
    • queryBy... - Element may not exist (returns null)
    • findBy... - Element appears asynchronously (returns Promise, default 1000ms timeout)
  • Priority Order (most accessible → least)

    1. Queries Accessible to Everyone
      • getByRole (best - includes accessibility)
      • getByLabelText, getByPlaceholderText, getByText, getByDisplayValue, etc.
    2. Semantic Queries
      • getByAltText, getByTitle
    3. Test IDs
      • getByTestId

User Actions

  • Async Methods
    • findBy queries are a combination of getBy queries and waitFor
      • Usage: Expect an element to appear but the DOM change might not happen immediately (e.g., API calls, setTimeout, animations)
      • Can specify custom timeout: findByText('text', {}, { timeout: 3000 })

User Interactions

Testing Library: User Event

userEvent: Simulates real browser user interactions (preferred over fireEvent for more realistic behavior).

  • Setup

    • userEvent.setup() - Initialize user instance (required before interactions)
  • Common Interactions

    • user.click(element) - Click element
    • user.type(element, text, options?) - Type text into input
    • ...etc

React Testing Library

Testing Library: React Testing

  • render(component)

    • Mounts component into virtual DOM for testing
    • Returns queries bound to container and utility functions
  • act(callback):

    • Light wrapper around React's act function
    • Forwards all arguments to act if React version supports it
    • All it does is forward all arguments to the act function if your version of react supports act
  • renderHook(callback, option?)

    • Convenience wrapper around render with custom test component
    • Used for testing custom hooks in isolation

Coverage Metrics

Target Coverage: Aim for 80%+ coverage, but focus on testing critical paths and edge cases rather than chasing 100%.

Metric Name Meaning
% Stmts Statements Percentage of executable statements covered
% Branch Branches Percentage of code branches executed (if-else, switch-case)
% Funcs Functions Percentage of functions called at least once
% Lines Lines Percentage of source code lines executed

AAA Pattern (Arrange-Act-Assert)

  • Standard structure for organizing unit tests:

    • Arrange - Setup: mock data, dependencies, render components
    • Act - Execute: perform the action being tested
    • Assert - Verify: check expected outcomes with matchers
  • Example:

    // Example: Complete AAA pattern
    it('submits form with user data', async () => {
      // Arrange
      const user = userEvent.setup();
      const mockSubmit = jest.fn();
      render(<LoginForm onSubmit={mockSubmit} />);
    
      // Act
      await user.type(screen.getByLabelText(/email/i), 'user@example.com');
      await user.type(screen.getByLabelText(/password/i), 'password123');
      await user.click(screen.getByRole('button', { name: /submit/i }));
    
      // Assert
      expect(mockSubmit).toHaveBeenCalledTimes(1);
      expect(mockSubmit).toHaveBeenCalledWith({
        email: 'user@example.com',
        password: 'password123',
      });
    });

Author

  • TrungQuanDev
  • Khang Nguyen

References

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published