This document outlines the testing principles, structure, and practices used in the Yapli project.
The Yapli test suite follows these core principles:
- Component Isolation: Each component is tested in isolation to ensure it functions correctly regardless of its context.
- Behavior-Driven: Tests focus on the behavior of components and functions rather than implementation details.
- Comprehensive Coverage: We aim to test all critical paths and edge cases.
- Maintainability: Tests are structured to be easy to understand and maintain.
The test suite is organized into the following directories:
test/components/: Tests for React componentstest/lib/: Tests for utility functions and libraries
Yapli uses the following testing tools:
- Jest: As the test runner and assertion library
- React Testing Library: For rendering and testing React components
- jest-dom: For additional DOM-specific assertions
Component tests follow this pattern:
- Render the component with specific props
- Query the rendered output using screen queries
- Make assertions about the component's behavior and appearance
- Test interactions like clicks using fireEvent
Example:
import { render, screen, fireEvent } from '@testing-library/react';
import Component from '@/components/Component';
describe('Component', () => {
it('renders correctly with default props', () => {
render(<Component />);
expect(screen.getByText('Expected Text')).toBeInTheDocument();
});
it('handles user interactions', () => {
const handleClick = jest.fn();
render(<Component onClick={handleClick} />);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalled();
});
});Utility function tests follow this pattern:
- Call the utility function with specific inputs
- Make assertions about the return values
- Test edge cases and invalid inputs
Example:
import { utilityFunction } from '@/lib/utilities';
describe('utilityFunction', () => {
it('returns expected output for valid input', () => {
expect(utilityFunction('valid input')).toBe('expected output');
});
it('handles edge cases', () => {
expect(utilityFunction('')).toBe(null);
expect(utilityFunction(null)).toThrow();
});
});You can run the tests using the following npm scripts:
npm test: Run all testsnpm run test:watch: Run tests in watch mode, which will rerun tests when files change
The Jest configuration is defined in jest.config.ts and includes:
- Test environment setup with jsdom for DOM testing
- Module mappers for handling CSS and image imports
- Coverage collection settings
- Test file patterns
Additional setup is performed in jest.setup.ts, which includes:
- DOM testing extensions from @testing-library/jest-dom
- Mocks for browser APIs not available in jsdom (matchMedia, IntersectionObserver)
When writing new tests:
- Place component tests in
test/components/ - Place utility function tests in
test/lib/ - Follow the established patterns for each type of test
- Ensure tests are isolated and don't depend on other tests
- Focus on testing behavior, not implementation details