3-Tiered Testing Strategy

Overview

Testing ensures that our applications remain reliable, offline-first capabilities behave correctly, and changes do not break shared modules.

๐Ÿ› Test Levels & Scope

We test our codebase across three distinct levels:
LevelScopeTarget Areas
Unit TestsPure logic, helper functions, and data mappersModels, JSON parsing, result converters, and business logic
Widget TestsSingle screens, UI components, and state controllersBrand wrappers, form validation, and screen transitions
Integration TestsEnd-to-end user journeys and sync behaviorPowerSync data uploads, authentication cycles, and background tracking

๐Ÿงช Key Testing Rules

1. High Coverage on Shared Packages

Because the shared packages (packages/core_*) are load-bearing for all applications, they require the strictest test coverage. A regression in a core package could break multiple apps simultaneously.

2. Integration Testing for PowerSync

Since data sync is critical, we write integration tests to verify:
  • Upload Queue Replay: Testing that local writes are correctly uploaded when the network comes back online.
  • Sync Rules Bucket Correctness: Verifying that each user scenario replicates only the correct data partition to the device (ensuring user isolation).
  • Permanent Rejections: Verifying that when a write is rejected by the Go backend (e.g., validation failure), the queue does not wedge and the error surfaces reactively in the rejected_mutations table.

3. Widget testing for critical flows

Key user flows (like completing the verified-identity gate, clocking in, or viewing offline work orders) must have widget tests with mocked repositories.

๐Ÿƒ Running Tests

To run all tests across all monorepo packages and apps:
# Run from mobile/flutter workspace directory
melos run test
To run tests in a specific package:
cd packages/core_models
flutter test