Unit and integration tests for API client
epic-bufdir-report-export-api-integration-task-009 — Write comprehensive tests for the bufdir-api-client: unit tests for the request mapper covering all required and optional payload fields, unit tests for authentication token refresh and error handling, integration tests using a mock Bufdir API server to validate the full submission flow (success, 422 validation error, 500 retry), and tests confirming the bufdir_reference_number is correctly persisted. Target 90%+ coverage on the client module.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Handles integration between different epics or system components. Requires coordination across multiple development streams.
Implementation Notes
Structure tests in three files mirroring the production structure: `bufdir_request_mapper_test.dart` (pure unit, no I/O), `bufdir_auth_handler_test.dart` (unit with mocked token store), `bufdir_api_client_integration_test.dart` (mock HTTP server). Use Dart's `http` package MockClient for HTTP stubbing — avoid real HttpServer unless response streaming behaviour must be tested. For the retry integration test, use a stateful counter in the mock handler that returns 500 for the first N calls then 200, and assert the counter reached the expected value. For Supabase persistence assertions, inject a mock repository implementing the same interface as the real one (follow the repository pattern already established in the codebase).
Keep test data in `test/fixtures/bufdir/` as JSON files to keep test methods readable. Do not use `print` in tests — use `fail()` with descriptive messages instead.
Testing Requirements
Unit tests: cover every public method on the API client class using flutter_test with mocked HTTP and mocked Supabase repository. Integration tests: spin up a local MockClient or dart:io HttpServer that returns scripted HTTP responses (200 with reference number, 422 with validation body, 500 then 200 on retry). Use setUp/tearDown to isolate test state. Assert both the returned Dart objects and side-effects (repository.persist called with correct reference number).
Coverage: run `flutter test --coverage` and use lcov or the built-in reporter to confirm the 90% threshold. Failure modes to test: network timeout, malformed JSON response body, missing reference_number field in success response.
Norse Digital Products has not yet completed API negotiations with Bufdir. If negotiations stall or Bufdir's API design diverges significantly from expectations, the API client may need substantial rework, or the epic may be blocked indefinitely.
Mitigation & Contingency
Mitigation: Implement the client against a locally defined stub of the expected Bufdir API schema. Isolate all Bufdir-specific schema mapping in a single adapter class so that changes to the actual API schema require changes in only one place. Keep the epic in 'interface-ready' status until real API credentials are available for integration testing.
Contingency: If API negotiations are not completed within the planned window, defer this epic without impact on any other epic — the PDF/CSV fallback path from Epics 1–4 delivers full standalone value. Mark the epic as blocked and resurface when negotiations conclude.
Bufdir API credentials stored in the application or edge function environment could be exposed through misconfigured secrets management, log leakage, or a compromised deployment pipeline, allowing unauthorised Bufdir submissions on behalf of the organisation.
Mitigation & Contingency
Mitigation: Store all Bufdir API credentials exclusively in Supabase Vault (or the integration credential vault component), never in client-side code or environment variables accessible to the Flutter app. Transmit credentials only from within the edge function, not from the Flutter client. Implement credential rotation support from the outset.
Contingency: If a credential leak is detected, immediately revoke and rotate the affected API credentials through Bufdir's credential management portal, audit submission logs for any unauthorised calls, and notify Bufdir's technical contact per the API agreement's security incident clause.