high priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

A test iterates all ExpenseType enum values via ExpenseType.values and asserts that ExpenseTypeConfig.forType(variant) returns a non-null entry for each — zero missing variants allowed
Each config entry's rate field is asserted to be strictly greater than 0.0
Each config entry's threshold field is asserted to be greater than or equal to 0.0
A JSON round-trip test serialises each config to JSON via toJson() and deserialises via fromJson(), asserting deep equality (==) with the original — no field loss permitted
The full test suite completes in under 200 ms as verified by flutter test --reporter expanded showing elapsed time
No network calls, file I/O, or platform channel invocations occur — confirmed by absence of MethodChannel mocking requirements
All ExpenseType enum variants introduced in task-002 are covered — adding a new variant without a config entry must cause at least one test to fail
Test file is located under test/expense_type/ and follows the project's existing test naming convention

Technical Requirements

frameworks
flutter_test
Flutter
data models
ExpenseType
ExpenseTypeConfig
ExpenseTypePair
performance requirements
Full test suite completes in < 200 ms (no I/O, no platform channels)
Tests are purely in-memory with no setUp async overhead
security requirements
No real expense data or PII used in test fixtures — use symbolic placeholder values only

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

The most robust pattern for exhaustive enum coverage in Dart is to iterate ExpenseType.values in a loop inside the test rather than listing variants explicitly — this way adding a new enum value without a config entry automatically fails the test without requiring test updates. For the JSON round-trip, ensure the toJson/fromJson cycle preserves double precision for rate and threshold (avoid int/double coercion). If ExpenseTypeConfig uses freezed or json_serializable, confirm the generated code is committed before this test runs. Keep test fixtures as const maps defined at the top of the file for readability.

Testing Requirements

Unit tests only using flutter_test. Use group() blocks to organise: 'completeness' (every enum variant has a config), 'business constraints' (rate/threshold ranges), and 'serialisation' (JSON round-trip). Use expect(ExpenseType.values, everyElement(predicate(...))) for exhaustive enum coverage. Assert serialisation with expect(decoded, equals(original)) leveraging Equatable or a manual == override on ExpenseTypeConfig.

No mocking required. Run with: flutter test test/expense_type/expense_type_config_test.dart

Component
Expense Type Configuration
data low
Epic Risks (2)
high impact medium prob scope

The compatibility matrix might be under-specified in source documentation. If a new organisation adds expense types or redefines rules, hardcoded pairwise logic becomes a maintenance liability and can silently allow previously excluded combinations.

Mitigation & Contingency

Mitigation: Model the matrix as a const Map<ExpenseType, Set<ExpenseType>> rather than if-else chains; add a unit test that exhaustively asserts every pair combination so any future matrix change forces explicit test updates.

Contingency: If per-organisation matrix variants are requested before the epic closes, extract matrix loading into expense-type-config with an org-override slot and defer per-org configuration to the repository epic.

medium impact medium prob technical

VoiceOver (iOS) and TalkBack (Android) handle Semantics widget announcements differently in Flutter. Live-region behaviour for disabled state changes is inconsistent across Flutter versions and may require platform-specific workarounds that are not yet documented.

Mitigation & Contingency

Mitigation: Write accessibility integration tests using Flutter's SemanticsController targeting both iOS and Android simulators from the outset; pin to a Flutter version known to handle Semantics.liveRegion correctly.

Contingency: If platform parity is unachievable before release, ship with a known gap documented in the WCAG audit log and schedule a dedicated accessibility sprint; do not block other epics.