high priority medium complexity testing pending testing specialist Tier 10

Acceptance Criteria

All 5 workflow scenarios are implemented as separate named integration test cases (not monolithic)
Test 1: Admin screen mounted with empty database shows empty-state illustration and 'No activity types yet' message
Test 2: Full create flow — open form, enter display_name, set duration, select Bufdir category, tap submit, verify new item appears in the list with correct title and Bufdir badge
Test 3: Full edit flow — tap existing item, change display_name and one metadata flag, submit, verify card reflects updated values without navigating away and re-entering
Test 4: Archive flow — archive item via overflow menu, confirm in bottom sheet, verify item removed from active list; toggle 'Show archived', verify archived item appears with grey badge
Test 5: RLS test — authenticate as peer_mentor role, navigate to admin screen route, assert access is denied (no-access screen or 403 error state shown, not the list)
All form validation error paths are triggered and asserted: empty name, duration too low (4 min), duration too high (481 min), missing Bufdir category
Tests run successfully against Supabase local emulator with seeded test data (seed script included in test setup)
No test relies on hardcoded Supabase record IDs — all IDs are resolved dynamically during the test run
Test suite completes within 3 minutes on CI (parallel execution or optimised setup/teardown)

Technical Requirements

frameworks
Flutter
flutter_test
integration_test package
Riverpod (provider overrides for test isolation)
apis
Supabase local emulator REST API
ActivityTypeService (real implementation, not mocked)
Supabase Auth (test user creation via admin API)
data models
ActivityType
Organisation
UserRole
performance requirements
Each individual test case must complete within 60 seconds including setup and teardown
Database seed/reset between tests must complete within 5 seconds
security requirements
Test credentials (Supabase local emulator keys) must be stored in environment variables, not hardcoded in test files
RLS test must use a real JWT for the peer_mentor role — do not simulate by modifying client-side state

Execution Context

Execution Tier
Tier 10

Tier 10 - 11 tasks

Can start after Tier 9 completes

Implementation Notes

Structure the test file as `test/integration/activity_type_crud_test.dart`. Use a shared `TestSupabaseClient` singleton initialised once per suite (not per test) to avoid connection overhead — reset data between tests using a SQL truncate via the Supabase admin REST endpoint. Override Riverpod providers in tests using `ProviderScope(overrides: [...])` to inject the test Supabase client. For the RLS peer_mentor test, call `supabaseAdmin.auth.admin.createUser({email, password, role: 'peer_mentor'})` in setUp, sign in as that user in the app, and attempt navigation to the admin route.

Use `flutter drive` or the `integration_test` runner for CI. Add a `Makefile` target `make test-integration` that starts the Supabase emulator, runs the suite, and tears down — document this in the feature README. Avoid `Future.delayed` in tests; use `pumpAndSettle` or `pump(Duration)` with explicit tick counts for snackbar timing assertions.

Testing Requirements

This task IS the testing deliverable. Use `flutter_test` with the `integration_test` package. Structure tests using `group()` with `setUp` (seed database, authenticate user) and `tearDown` (reset database to clean state). Use `WidgetTester.pumpAndSettle()` after async operations.

Use `find.byType()`, `find.text()`, and `find.byKey()` for element location — add `Key` annotations to key widgets if missing. For RLS testing, call the Supabase admin API to create a peer_mentor-scoped JWT. Include a `test_helpers/seed_activity_types.dart` utility that inserts known test records. Verify coverage with `flutter test --coverage`; target 100% on all form validation branches.

Component
Activity Type Admin Screen
ui medium
Epic Risks (3)
high impact medium prob dependency

The Bufdir reporting category list is defined externally by Bufdir and may change between reporting years. If the dropdown in ActivityTypeFormScreen is hardcoded, existing activity type mappings could become invalid after a Bufdir schema update, breaking export validation for all organisations.

Mitigation & Contingency

Mitigation: Store the valid Bufdir category list in a Supabase configuration table (bufdir_categories) rather than as a Dart constant, so it can be updated by an admin without a mobile app release. Load the list in the form screen via a lightweight repository call cached locally.

Contingency: If the Bufdir category list cannot be externalised before the admin screen ships, expose a manual override field that allows coordinators to enter a raw Bufdir category code as a fallback, and schedule the configuration table migration as a follow-up task.

medium impact medium prob technical

Reusing ActivityTypeFormScreen for both creation and editing requires careful Riverpod provider scoping. If the form provider is not properly reset between navigation events, stale values from a previously edited type may pre-populate a new creation form, leading to incorrect data being saved.

Mitigation & Contingency

Mitigation: Scope the form state provider to the route using Riverpod's autoDispose modifier, ensuring the state is torn down when the screen is popped. Write a widget test that navigates to edit type A, pops, navigates to create new, and asserts all fields are empty.

Contingency: If provider scoping proves complex with the current router setup, fall back to separate widget implementations for create and edit that share a common form widget but maintain independent provider instances.

high impact low prob integration

Archiving an activity type must not break historical Bufdir export queries that filter activities by type. If the export pipeline performs an INNER JOIN against only active activity types, archived types will cause historical activities to be silently excluded from exports, producing incorrect reporting data.

Mitigation & Contingency

Mitigation: Audit all downstream query builders (Bufdir export, stats aggregation) before shipping the archive feature to confirm they join against all activity types regardless of is_active status. Add an integration test that archives a type, then asserts historical activity records for that type still appear in export queries.

Contingency: If a downstream query is discovered to filter on is_active post-launch, apply a targeted Supabase view fix that unions active and archived types for export contexts without requiring a mobile app update.