Skip to content

Testing

The mobile app has two testing tiers: Jest unit tests for component and logic verification, and Detox end-to-end tests for full interaction flows on simulators and emulators.

Unit Tests

Unit tests use Jest with @testing-library/react-native for component rendering and interaction testing.

Test Locations

Tests are colocated with the code they test, in __tests__/ directories:

DirectoryCoverage
lib/__tests__/Utility functions, store logic
components/mail/__tests__/Email list item component
components/ui/__tests__/Avatar, button, card, empty state, input, loading components

Running Unit Tests

bash
cd mobile

# Single run
npm test

# Watch mode (re-runs on file changes)
npm run test:watch

# With coverage report
npm run test:coverage

Coverage Thresholds

The project enforces minimum coverage thresholds:

  • Statements: 50%
  • Branches: 40%
  • Functions: 50%
  • Lines: 50%

The coverage report is generated by Jest's built-in coverage reporter. Builds will fail in CI if coverage drops below these thresholds.

What to Test

UI components -- Each component in components/ui/ has a corresponding test file verifying:

  • Rendering with default and custom props
  • Visual states (loading, error, disabled)
  • User interactions (press, input)
  • Accessibility labels

Mail components -- The email-list-item.test.tsx tests verify:

  • Correct display of email metadata (sender, subject, date)
  • Unread indicator visibility
  • Attachment icon visibility
  • Swipe action triggers

Library utilities -- The lib/__tests__/utils.test.ts tests cover shared utility functions used across the app.

Test Configuration

The Jest configuration uses jest-expo as its preset, which provides React Native module mocking and transformer configuration. Native modules that cannot run in the Jest environment (such as expo-secure-store and expo-local-authentication) are mocked automatically or via manual mocks.

End-to-End Tests

E2E tests use Detox to run automated interaction tests on iOS simulators and Android emulators.

Test Location

E2E tests live in the e2e/ directory:

  • e2e/auth.e2e.js -- Authentication flow tests (login, account creation, logout)
  • e2e/jest.config.js -- Detox Jest configuration

Running E2E Tests

E2E tests require a built app binary and a running simulator or emulator.

bash
cd mobile

# Build the app for testing (first time or after native changes)
npx expo prebuild
# Then build with Detox or use EAS

# Run on iOS simulator
npm run test:e2e:ios

# Run on Android emulator
npm run test:e2e:android

Detox Configurations

The Detox configuration defines two test targets:

ConfigurationPlatformDevice
ios.sim.debugiOSSimulator (debug build)
android.emu.debugAndroidEmulator (debug build)

Prerequisites

  • iOS: Xcode with a configured iOS simulator (requires macOS)
  • Android: Android Studio with an AVD (Android Virtual Device) configured
  • Detox CLI: Install globally with npm install -g detox-cli
  • The Expo dev server does not need to be running -- Detox tests use a pre-built app binary

CI Integration

Both test tiers run in the GitHub Actions CI pipeline (mobile-build.yml):

  1. Lint -- ESLint checks run first
  2. Unit tests -- Jest with coverage reporting
  3. EAS builds -- Cloud builds for iOS and Android (separate from E2E)

E2E tests are not currently run in CI due to simulator/emulator requirements but can be integrated with a macOS runner and Detox's CI-friendly configuration.

Released under the MIT License.