Write unit tests for ActivityTypeService validation logic
epic-activity-type-configuration-business-logic-task-008 — Write unit tests covering: org-scoped fetching returns only types for the authenticated org, triggersReimbursementWorkflow/isTravelExpenseEligible flag combination validation throws the expected error for invalid states, cache invalidation is called after create/update/deactivate mutations, and label resolution falls back gracefully on missing keys. Mock the repository and cache provider using mocktail.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Mock both ActivityTypeRepository and ActivityTypeCacheProvider using mocktail's Mock class. Register fallback values for any complex argument types using registerFallbackValue() in setUpAll(). For cache invalidation verification, use mocktail's verify(() => mockCache.invalidate(any())).called(1) pattern. For the flag combination validation, the service should validate before any repository call — verify this by asserting the repository mock was never called when validation fails.
Label resolution fallback should be implemented as a try/catch or null-coalescing pattern in the service itself, not in the repository. Keep each test focused on a single behavior — avoid multi-assertion tests that obscure failure location.
Testing Requirements
Pure Dart unit tests using flutter_test and mocktail. No widget tree required. Use setUp() to construct a fresh service instance with fresh mocks before each test. Use verify() and verifyNever() from mocktail to assert cache invalidation call counts.
Use throwsA(isA
Metadata flag combination rules differ between organisations (e.g., Blindeforbundet honorarium thresholds, HLF mutual exclusion of km and transit). Encoding these as generic service-level validation may be insufficient, forcing organisation-specific branching inside the service that becomes unmaintainable as new organisations are onboarded.
Mitigation & Contingency
Mitigation: Model flag validation as a pure function that accepts an ActivityTypeMetadata object and an org configuration record, making org-specific rules data-driven rather than hardcoded. Establish the validation contract in the foundation epic so the service just delegates to the validator.
Contingency: Defer complex cross-flag validation to a lightweight edge function that can be updated without a mobile app release, accepting that initial validation in the mobile service layer is permissive and corrected server-side.
Blindeforbundet users rely on VoiceOver and JAWS. If the selection screen is built with non-semantic widgets that fail accessibility audit late in the sprint, a significant rework of the widget tree may be required, blocking the registration wizard integration.
Mitigation & Contingency
Mitigation: Build the selection screen against the project's established accessibility design tokens and semantics wrapper conventions from the start. Run Flutter's semantic tree inspector and a manual VoiceOver pass before marking any widget task complete.
Contingency: Wrap all tappable items in the project's SemanticsWrapperWidget and schedule a dedicated accessibility review session with a screen reader user from Blindeforbundet before the epic is closed.