high priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

Test file located at test/features/mileage/domain/services/mileage_calculation_service_test.dart
All tests pass with flutter test — no skipped or pending tests
Norwegian rounding: calculate(1.0, 4.505) == 4.51 (half-up)
Norwegian rounding: calculate(1.0, 4.504) == 4.50 (half-down)
Zero distance: calculate(0.0, 5.0) == 0.00
Zero rate: calculate(10.0, 0.0) == 0.00
Fractional km: calculate(0.5, 4.0) == 2.00
Large distance: calculate(10000.0, 4.5) == 45000.00 with no overflow
Sub-øre accumulation: calculate(3.0, 1.001) rounds correctly
Minimum meaningful values: calculate(0.001, 0.01) returns valid double >= 0.00
Result is always rounded to exactly 2 decimal places (no trailing floating-point noise)
Test suite completes in under 500 ms

Technical Requirements

frameworks
Flutter
flutter_test
Dart
data models
MileageCalculationService
performance requirements
Full test suite executes in < 500 ms
No setUp/tearDown involving async operations

Execution Context

Execution Tier
Tier 2

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.

Epic Risks (3)
high impact medium prob security

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.

medium impact low prob scope

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.

low impact low prob technical

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.