End-to-end test: proxy activity wizard flow
epic-bulk-and-proxy-registration-bulk-ui-task-015 — Write integration tests for the complete proxy activity wizard flow: select proxy mode → select peer mentor → complete wizard steps with attribution banner visible → submit proxy payload → verify recorded_by_user_id and peer_mentor_id are present in the submitted data. Include widget tests for the attribution banner persistence across steps and BLoC unit tests for payload assembly.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Structure tests in three files: proxy_activity_cubit_test.dart, proxy_activity_wizard_widget_test.dart, and proxy_wizard_flow_integration_test.dart. Use mocktail for service mocks; register fakes for complex types like ProxyActivityPayload to avoid registration errors. For the integration test, use a test-specific ProviderScope / BlocProvider override to inject mocked services into the widget tree — do not rely on global singletons. The attribution banner persistence test should use a PageController or equivalent to navigate between wizard pages and call pumpAndSettle() after each transition before asserting banner presence.
Capture the exact argument passed to ActivityService.submitProxyActivity using mocktail's verify(mockService.submitProxyActivity(captureAny())).captured pattern. Ensure tests clean up any StreamSubscriptions from cubits in tearDown to prevent test pollution.
Testing Requirements
Three test layers required: (1) BLoC unit tests — test ProxyActivityCubit.selectMentor(mentor), navigateToNextStep(), assemblePayload() produce correct ProxyActivityPayload with both IDs; test payload is immutable across multiple step navigations; test failure state on service rejection. (2) Widget tests — mount ProxyActivityWizard with mocked cubit; navigate through all steps using WidgetTester; assert attribution banner text on each step; assert banner text updates when selectMentor emits new state. (3) Integration test — use flutter_test integration test runner; stub ActivityService at the repository layer; drive full flow from proxy mode selection to submission; capture the payload passed to ActivityService.submitProxyActivity and assert field values.
If the batch insert RPC returns a mix of successes and failures (e.g., 3 of 10 mentors fail due to constraint violations that slipped through application-level duplicate detection), the confirmation screen result state becomes ambiguous. A coordinator who sees '7 of 10 succeeded' may not know whether to manually register the 3 failures, retry, or escalate — leading to either duplicate registrations or silent underreporting.
Mitigation & Contingency
Mitigation: Design the Bulk Registration Service to return a strongly typed BulkRegistrationResult with per-mentor RegistrationOutcome (success | duplicate_detected | constraint_violation | permission_denied). Design the result screen to list each failed mentor with a specific, plain-language reason and a one-tap 'Retry for this mentor' action that pre-fills the activity wizard with the batch template for that individual.
Contingency: If per-mentor retry UI is too complex to deliver within the epic scope, fall back to displaying failed mentors with their error codes and instructing coordinators to use single-proxy mode for the failures. Document this as a known limitation in release notes and create a follow-up ticket for per-mentor retry in the next sprint.
The Proxy Activity Wizard must reuse the existing activity wizard step widgets (type, date, duration, notes) while injecting a proxy attribution banner and a different submission payload builder. If the existing wizard is not designed for composability, the proxy variant may require forking the widget tree, creating two maintenance-diverging codebases that will drift out of sync when the base wizard is updated (e.g., new activity types added, new mandatory fields).
Mitigation & Contingency
Mitigation: Before implementing the Proxy Activity Wizard, audit the existing activity wizard's architecture. If steps are already extracted as independent StatelessWidget/ConsumerWidget classes, compose them directly with a wrapping Column that injects the attribution banner. If they are tightly coupled inside a parent widget, refactor the existing wizard to accept a nullable ProxyContext parameter before starting the proxy variant — this refactor should be a prerequisite task in this epic.
Contingency: If refactoring the base wizard is blocked by unrelated in-flight work on that component, implement the proxy wizard as a full fork but create a shared StepWidgets library file that both the base wizard and proxy wizard import. Schedule a deduplication refactor as a tech-debt ticket in the next planning cycle.
The bulk registration flow spans three sequential screens (multi-select → activity form → confirmation → result) with shared mutable state: the selected mentor list, the activity template, the per-mentor duplicate warnings, and the final submission result. Managing this state across screens without a well-designed Bloc risks state leaks, stale duplicate warning data after mentor removal, and confirmation screen inconsistencies if the user navigates back and changes the mentor selection.
Mitigation & Contingency
Mitigation: Define a single BulkRegistrationBloc (or Cubit) with explicit state transitions covering: MentorsSelected → ActivityTemplateCompleted → DuplicatesChecked → ConfirmationReady → Submitting → SubmissionResult. Each backward navigation event (e.g., 'Back' from confirmation to mentor selection) dispatches a ResetToMentorSelection event that clears downstream state. Unit test every state transition with edge cases including empty mentor list, all mentors having duplicates, and network failure during submission.
Contingency: If state management complexity causes persistent bugs in testing, simplify by passing state explicitly through Navigator arguments (immutable snapshots per screen) rather than a shared Bloc. This reduces flexibility but eliminates cross-screen state mutation bugs.