Integration and widget tests for resolution flows
epic-duplicate-activity-detection-ui-task-014 — Write widget tests for DuplicateWarningBottomSheet covering all three resolution paths (proceed, merge, cancel), including state verification after each action. Write integration tests for the DeduplicationQueueScreen covering list rendering with pagination, filter/sort behavior, detail view navigation, coordinator resolution actions, and badge count reactivity.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 8 - 48 tasks
Can start after Tier 7 completes
Implementation Notes
Structure tests in two files: `duplicate_warning_bottom_sheet_test.dart` (widget) and `deduplication_queue_screen_test.dart` (integration). Use a shared `test/fixtures/duplicate_activity_fixtures.dart` file for reusable mock data — this prevents drift between widget and integration tests. For BLoC state verification after bottom sheet actions, wrap the widget under test in a `BlocProvider` with a `MockBloc` and use `verify(() => mockBloc.add(ProceedResolutionEvent()))`. For badge count reactivity, simulate a Supabase realtime event by emitting a new state from the mock provider rather than connecting to a real stream.
Pay attention to async gaps when the bottom sheet dismisses — use `await tester.pumpAndSettle()` only after `Navigator.pop` completes. For the pagination integration test, inject a mock repository that returns two pages of data and assert the 'Load more' trigger fires at scroll bottom.
Testing Requirements
Use flutter_test for all widget tests with `testWidgets()`. Use `WidgetTester.pump()` and `pumpAndSettle()` appropriately — avoid over-relying on `pumpAndSettle` for BLoC streams; use `pump(Duration)` to advance specific timers. Mock the BLoC/Riverpod providers using `MockBloc` (bloc_test package) or `ProviderScope` overrides. For integration tests, use flutter_test integration_test package with a fake Supabase client.
Verify state transitions with `expect(bloc.state, isA
The merge resolution path requires identifying which fields from the draft differ from the existing record, applying those differences to the existing record, and cancelling the draft — all as an atomic operation. Partial failures (e.g., update succeeds but draft cancellation fails) could leave the system in an inconsistent state.
Mitigation & Contingency
Mitigation: Implement the merge path as a Supabase RPC transaction that updates the existing record and soft-deletes the draft in a single atomic call. The DuplicateResolutionHandler should never attempt field-level merge at the application layer.
Contingency: If the atomic RPC approach proves too complex for the initial release, simplify the merge path to: mark existing record as the canonical record and cancel the new submission without field merging, displaying a message to the user to manually verify the existing record's fields. Log a follow-up ticket for full field-merge in a later sprint.
The DuplicateWarningBottomSheet must intercept the activity wizard's save action without disrupting the wizard's existing navigation stack. If the bottom sheet is implemented as a separate route rather than an overlay, back navigation could break the wizard's step state.
Mitigation & Contingency
Mitigation: Use a `showModalBottomSheet` overlay pattern so the bottom sheet sits above the wizard route without pushing a new route onto the Navigator stack. The wizard's CuBit/BLoC retains all draft state while the sheet is visible. Test this integration with the existing activity-registration-cubit before merging.
Contingency: If the overlay approach causes Z-order or focus issues with the wizard's keyboard-aware layout, route the duplicate check result back to the wizard as a state event (DuplicateDetected), and let the wizard render a local inline warning banner instead of a bottom sheet.
The bottom sheet and comparison panel involve complex layouts with multiple interactive elements. Screen reader users (particularly relevant for Blindeforbundet) may struggle with the side-by-side comparison layout if semantics are not carefully ordered.
Mitigation & Contingency
Mitigation: Design the comparison panel with a single-column semantic order (read record A fully, then record B fully) regardless of visual layout. Use Flutter's `Semantics` widget with `sortKey` to enforce correct traversal order. Test with TalkBack and VoiceOver against the WCAG 2.2 AA reading order criteria.
Contingency: If side-by-side layout cannot achieve acceptable screen reader ordering, switch to a stacked tab layout (Tab A / Tab B) for the comparison panel that is semantically simple even if less visually immediate for sighted users.