Unit test MileageCalculationService rounding and edge cases
epic-mileage-reimbursement-entry-infrastructure-task-008 — Write comprehensive unit tests for MileageCalculationService covering Norwegian rounding rules, zero distance, fractional km values, very large distances, and minimum/maximum rate scenarios. Tests must be deterministic and run without any external dependencies.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use flutter_test's group() to organise test cases: group('Norwegian rounding', ...), group('edge cases', ...), group('large values', ...). For rounding assertions, use expect(result, equals(expected)) rather than closeTo() — the integer-arithmetic implementation in task-006 should produce exact results. If the implementation uses doubles internally, document the acceptable epsilon in the test. Include a test that verifies the return type is double (not int) and that negative inputs either throw ArgumentError or return 0.00 (document the chosen contract explicitly in the test description).
Testing Requirements
Pure unit tests using flutter_test. Group tests by category: rounding behaviour, zero/boundary inputs, large values, fractional inputs. Use expect() with closeTo() only when documenting floating-point tolerance is intentional; prefer exact equality for the integer-arithmetic implementation. No mocks needed — the service is dependency-free.
Aim for 100% branch coverage of the calculate() method.
Supabase Row Level Security policies for mileage_claims may require complex join conditions to distinguish peer mentor (own claims only) from coordinator (chapter-scoped claims) access. If the RLS policy is misconfigured, coordinators could see claims outside their chapter scope or peer mentors could read other users' data, causing a data privacy incident.
Mitigation & Contingency
Mitigation: Write RLS policy SQL as part of this epic with explicit test cases for each role. Use Supabase's built-in policy testing tools and add integration tests that assert cross-user data isolation before merging.
Contingency: If RLS configuration proves too complex to test reliably within the epic, add an application-layer guard in the adapter that filters query results by authenticated user ID as a defence-in-depth measure while the policy is corrected.
Norwegian tax authority reimbursement rounding rules may change or may not be publicly documented in machine-readable form. Using the wrong rounding convention could cause systematic over- or under-payment, leading to compliance issues for the organisation.
Mitigation & Contingency
Mitigation: Source the exact rounding specification from HLF's finance team before implementing MileageCalculationService. Document the rule as a comment in the source code and link to the authoritative reference.
Contingency: If the rule is ambiguous, implement both truncation and half-up rounding behind a configuration flag so the organisation can switch without a code release.
SharedPreferences reads and writes are asynchronous. If the distance prefill service (built in the next epic) calls LocalDistanceCache concurrently with a post-submission write, a race condition could result in the cache returning a stale or partially written value, causing the next form load to show an incorrect default.
Mitigation & Contingency
Mitigation: Wrap all SharedPreferences access in LocalDistanceCache with sequential async operations and document the non-concurrent usage contract in the class API.
Contingency: If race conditions are observed in testing, introduce a simple mutex pattern using a Completer to serialise cache operations.