You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, the SwipeLab frontend relies heavily on end-to-end (E2E) testing via Playwright. While E2E tests are excellent for confidence, they are slow and brittle. To align with industry best practices, we should implement a robust lower-level testing strategy utilizing Jest and React Native Testing Library (RNTL).
Goal
Establish a testing pyramid where the bulk of our logic is tested quickly in isolation (Unit Tests), UI components are tested for rendering and interactions (Component Tests), and major screens are tested with mocked APIs (Integration Tests).
Proposed Architecture
We will introduce a __tests__ directory inside the frontend/ root (to separate them from E2E tests) structured as follows:
frontend/__tests__/
├── unit/ # Pure functions, utils, and Zustand stores
├── hooks/ # Custom React Query hooks and logic
├── components/ # Isolated UI component tests
└── integration/ # Full screen tests with mocked API
1. Unit Testing (Pure Logic & State)
Tools: Jest Focus: Fast, synchronous logic that does not depend on React components.
Utils & Helpers: Test formatting functions, validation logic, and data transformers (app/utils/).
Zustand Stores: Test global state mutations (app/stores/). We will render the store in isolation and assert that actions (e.g., setTokens, logout) correctly update the state.
API Clients: Mock the global fetch API to ensure app/api/ services correctly format headers and payloads.
2. Hook Testing (React Query)
Tools:@testing-library/react-native (renderHook) Focus: Validating data fetching and caching logic.
Use renderHook wrapped in a test QueryClientProvider to verify that custom hooks (like useTasks, useGamification) fetch, cache, and expose loading/error states correctly.
3. Component Testing (Isolated UI)
Tools: Jest + RNTL (render, fireEvent, screen) Focus: Ensuring UI components render correctly based on props, and that user interactions fire callbacks.
Dumb Components: Test reusable components in app/components/ui/ (e.g., Button, SwipeCard, NotificationBell).
Assertions: Verify styles, accessibility labels, and that callbacks (onPress, onSwipe) are triggered with correct arguments.
Mocking: Global state (Zustand) and API queries (React Query) will be mocked so the component can be tested in isolation.
4. Integration Testing (Screens)
Tools: RNTL + MSW (Mock Service Worker) or Jest fetch mocks Focus: Testing the interaction between components, hooks, and stores on a single screen without a real backend.
Screens: Test complex views like AdminDashboardScreen or CollectionScreen.
Flow: Mock the API response, render the screen, interact with elements, and assert that the UI updates (e.g., clicking a "Mark as Read" button optimistic-updates the UI).
Decisions Made
Note
API Mocking Strategy: We will use Jest global.fetch mocks (via jest.spyOn or jest-fetch-mock). This is the fastest approach to deliver, as it requires zero external setup compared to MSW in a React Native environment.
Coverage Goals: We will not enforce a strict CI coverage threshold initially. Instead, we will generate coverage reports to track progress and prevent the CI pipeline from arbitrarily blocking PRs while the suite is built up.
Writing sample tests for a Zustand Store.
Writing sample tests for a UI Component (e.g., SwipeCard).
(Optional) Integrating MSW for a Screen integration test.
Frontend Testing Strategy (Unit & Integration)
Currently, the SwipeLab frontend relies heavily on end-to-end (E2E) testing via Playwright. While E2E tests are excellent for confidence, they are slow and brittle. To align with industry best practices, we should implement a robust lower-level testing strategy utilizing Jest and React Native Testing Library (RNTL).
Goal
Establish a testing pyramid where the bulk of our logic is tested quickly in isolation (Unit Tests), UI components are tested for rendering and interactions (Component Tests), and major screens are tested with mocked APIs (Integration Tests).
Proposed Architecture
We will introduce a
__tests__directory inside thefrontend/root (to separate them from E2E tests) structured as follows:1. Unit Testing (Pure Logic & State)
Tools: Jest
Focus: Fast, synchronous logic that does not depend on React components.
app/utils/).app/stores/). We will render the store in isolation and assert that actions (e.g.,setTokens,logout) correctly update the state.fetchAPI to ensureapp/api/services correctly format headers and payloads.2. Hook Testing (React Query)
Tools:
@testing-library/react-native(renderHook)Focus: Validating data fetching and caching logic.
renderHookwrapped in a testQueryClientProviderto verify that custom hooks (likeuseTasks,useGamification) fetch, cache, and expose loading/error states correctly.3. Component Testing (Isolated UI)
Tools: Jest + RNTL (
render,fireEvent,screen)Focus: Ensuring UI components render correctly based on props, and that user interactions fire callbacks.
app/components/ui/(e.g.,Button,SwipeCard,NotificationBell).onPress,onSwipe) are triggered with correct arguments.4. Integration Testing (Screens)
Tools: RNTL + MSW (Mock Service Worker) or Jest fetch mocks
Focus: Testing the interaction between components, hooks, and stores on a single screen without a real backend.
AdminDashboardScreenorCollectionScreen.Decisions Made
Note
global.fetchmocks (viajest.spyOnorjest-fetch-mock). This is the fastest approach to deliver, as it requires zero external setup compared to MSW in a React Native environment.SwipeCard).