high priority high complexity testing pending testing specialist Tier 5

Acceptance Criteria

Test scenario 1: Coordinator role renders only chapter-scoped scopes; org admin role renders all org scopes — verified via ProviderScope override with role fixture
Test scenario 2: requestPreview() invocation asserts zero calls to audit repository's persistAuditRecord and returns a BufdirPreviewResult with a non-empty temporaryFileUrl
Test scenario 3: requestFinalExport() invocation asserts exactly one call to audit repository's persistAuditRecord with metadata matching the request (scope, period, format, userId)
Test scenario 4a: Edge function returning HTTP 500 → BufdirServerException propagated to UI layer and displayed as error state
Test scenario 4b: Edge function timeout → BufdirTimeoutException propagated to UI layer and displayed as timeout error state
Test scenario 5a: PDF format request → PdfGenerationService.generate() called, CsvGenerationService.generate() not called
Test scenario 5b: CSV format request → CsvGenerationService.generate() called, PdfGenerationService.generate() not called
All HTTP interactions mocked at the http.Client level — no real network calls in tests
Tests run in CI without requiring a live Supabase instance
Test file structure follows project conventions (one describe block per scenario group)

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
apis
Supabase Edge Functions (mocked)
Supabase Storage (mocked)
Supabase Auth (mocked)
data models
bufdir_export_audit_log
bufdir_column_schema
performance requirements
Full test suite for this file must complete within 30 seconds in CI
No real HTTP calls — all network I/O mocked to prevent flakiness
security requirements
Test fixtures must not contain real personnummer, organisation credentials, or production JWTs
Fixture JWTs must be obviously fake (e.g., 'test-jwt-coordinator') and not parse as valid tokens
ui components
ExportScopeSelector (widget test)
InlineErrorBanner (widget test for error propagation)

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Structure the test file as `bufdir_export_orchestration_integration_test.dart`. Create a shared TestFixtures class with static factory methods: TestFixtures.coordinatorSession(), TestFixtures.orgAdminSession(), TestFixtures.validExportRequest(), TestFixtures.edgeFunctionSuccessResponse(format), TestFixtures.edgeFunctionErrorResponse(statusCode). Use ProviderContainer from Riverpod for service-level tests (no pumpWidget needed) — faster than widget pumping and sufficient for orchestration logic. For the audit record assertion, capture the argument passed to the mock's persistAuditRecord() and assert individual fields rather than full object equality to avoid fragility.

Separate the HTTP mock setup into a helper method configureHttpMock(responseCode, body) to avoid repetition across scenarios.

Testing Requirements

Use flutter_test with mockito for service mocks and http_mock_adapter (or nock equivalent) for HTTP-layer mocking. Organise tests in groups: 'scope selector rendering', 'preview flow', 'full export flow', 'error handling', 'file generator routing'. Each group should have a setUp() that establishes the correct ProviderScope with mocked dependencies. For widget-level tests use pumpWidget with ProviderScope.

For service-level tests instantiate BufdirExportService directly with injected mocks. Assert mock call counts and argument values using mockito's verify() and captor. Target: 100% branch coverage on BufdirExportService orchestration paths.

Component
Bufdir Export Service
service high
Epic Risks (2)
high impact medium prob security

The scope selector must accurately reflect each coordinator's access rights within the org hierarchy. If a coordinator can select a scope broader than their authorised access, the edge function's RLS enforcement must catch the attempt — but a permissive RLS policy or a bug in the scope resolver could allow unauthorised data to be exported.

Mitigation & Contingency

Mitigation: Implement permission enforcement at two independent layers: (1) the scope selector only renders options permitted by the user's role record, and (2) the edge function re-validates the requested scope against the user's JWT claims before executing any queries. Write integration tests that attempt to invoke the edge function with a scope beyond the user's permissions and assert rejection.

Contingency: If a permission bypass is discovered post-launch, immediately disable the export feature via the org-level feature flag while the fix is deployed. Review all audit records for exports that may have included out-of-scope data and notify affected organisations.

medium impact medium prob technical

The export workflow has 7+ discrete states (idle, scope selected, period selected, preview loading, preview ready, confirming, exporting, complete, failed) and several conditional transitions. An incomplete BLoC state machine could allow duplicate submissions, stale preview data to be confirmed, or error states to be unrecoverable without a restart.

Mitigation & Contingency

Mitigation: Model the state machine explicitly as a sealed class hierarchy before coding. Review the state diagram against all user story acceptance criteria. Write bloc unit tests for every valid and invalid state transition, including the happy path and all documented error states.

Contingency: If the BLoC grows too complex to test reliably, decompose it into two cooperating blocs: one for configuration (scope + period selection) and one for execution (preview + confirm + export), linked by a coordinator object.