critical priority high complexity testing pending backend specialist Tier 4

Acceptance Criteria

Integration test suite connects to a dedicated test Supabase project (separate from dev/prod) configured via environment variables
Seed data is inserted before each test and torn down after, ensuring test isolation and repeatability
For a canonical seed dataset (e.g., 1 org, 3 peer mentors, 15 activities across 2 chapters), the pipeline produces exactly 4 artifacts: Excel, CSV, PDF, and ZIP
Excel artifact row count matches seeded activity count; totals row values match expected aggregates
CSV artifact parsed record count matches seeded activity count
PDF artifact is a valid PDF document containing the organization name and reporting period from seed data
ZIP artifact contains all seeded attachment files and a valid manifest.json
All 4 artifacts are stored in Supabase Storage export bucket and return valid signed URLs with expiry > 1 hour
Signed URLs are accessible (HTTP 200) when fetched within the test — confirming actual storage write
Pipeline completes for the canonical seed dataset in under 30 seconds total
Test environment setup/teardown scripts are documented in the test README

Technical Requirements

frameworks
flutter_test
Supabase Dart SDK
archive
http (for signed URL verification)
apis
Supabase Database API
Supabase Storage API
Supabase Auth API
data models
BufdirActivityRecord
BufdirOrganizationReport
BufdirExportArtifact
BufdirBundleManifest
performance requirements
Full pipeline for canonical 15-activity seed completes in under 30 seconds
Signed URL HTTP verification request must complete in under 5 seconds
security requirements
Test Supabase project credentials stored in .env.test — never committed to version control
Test storage bucket uses separate path prefix (test/) to prevent collision with dev data
Service role key used for seeding/teardown; anon key used for pipeline execution to test realistic permissions

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Integration tests require a dedicated CI Supabase project — provision one via Supabase Management API or use the CLI (supabase start for local Docker). Store project URL and service_role_key in GitHub Actions secrets mapped to environment variables read in test setup. The TestSupabaseHelper should use the service_role_key (bypassing RLS) for seeding and teardown, while the pipeline under test should use a test user's JWT to exercise real RLS policies. Use unique organization IDs per test run (UUID.v4()) to ensure parallel CI runs don't interfere.

Teardown should use ON DELETE CASCADE on seed records or explicit deletion in reverse dependency order. For the signed URL verification step, generate signed URLs with 2-hour expiry and use Dart's http package to assert HTTP 200 — this confirms the storage write actually succeeded. Document the test Supabase project setup in test/integration/README.md including required table schemas, RLS policies, and storage bucket configuration.

Testing Requirements

Integration tests using flutter_test with a real test Supabase instance. Use a TestSupabaseHelper class to manage seed data lifecycle: insertSeedActivities(), insertSeedAttachments(), tearDownTestData(). Each test should call setUp/tearDown via flutter_test hooks. Seed data constants defined in test/fixtures/bufdir_seed_data.dart.

Test scenarios: (1) canonical pipeline — 15 activities, 3 attachments, verify all 4 artifacts; (2) zero-activity organization — verify pipeline completes and produces valid empty-state artifacts; (3) large dataset smoke test — 200 activities, verify completion without timeout or error. Use http package to verify signed URLs return HTTP 200. Parse artifact contents using archive (ZIP), csv parser, and PDF byte inspection utilities from prior unit test tasks.

Component
Bufdir Activity Query Service
service high
Dependencies (4)
Write unit tests for the BufdirExcelCsvGenerator covering correct column mapping to Bufdir's required layout, Norwegian character encoding in both Excel and CSV output, correct number formatting for participant counts and hours, and output file structure validation. Include golden file tests comparing generated output against reference Bufdir template files. epic-bufdir-reporting-export-processing-services-task-013 Write unit tests for the BufdirPdfGenerator verifying correct page layout structure, presence of all required Bufdir template sections, proper Norwegian date and number formatting, and that the generated PDF is a valid parseable document. Include rendering tests for edge cases such as organizations with zero activities and organizations with very large activity counts causing multi-page reports. epic-bufdir-reporting-export-processing-services-task-014 Write unit tests for the BufdirAttachmentBundler covering attachment collection from database, ZIP directory structure correctness, handling of missing or inaccessible attachments, filename collision resolution, and correct manifest generation. Mock Supabase Storage interactions to ensure tests run without external dependencies. epic-bufdir-reporting-export-processing-services-task-015 Write comprehensive unit tests for the BufdirActivityQueryService covering multi-chapter deduplication scenarios including: peer mentor registered in two chapters with same activity, same activity submitted by both coordinator and peer mentor, boundary cases where activities have identical timestamps, and correct handling of activities that legitimately span multiple chapters. epic-bufdir-reporting-export-processing-services-task-012
Epic Risks (3)
high impact medium prob technical

NHF contacts can belong to up to five local chapters simultaneously. If the deduplication logic in the activity query service incorrectly attributes cross-chapter activities, organisations will either under-report or over-report to Bufdir, which could trigger grant clawback or compliance investigations.

Mitigation & Contingency

Mitigation: Implement deduplication using the existing multi-chapter membership service as the source of truth for chapter affiliation. Write test fixtures covering all known multi-chapter edge cases and validate outputs against manually prepared reference exports from NHF.

Contingency: If deduplication cannot be made deterministic for complex hierarchies before release, gate the export behind an org-level feature flag and require NHF to validate a preview export against their manual Excel before enabling in production.

medium impact medium prob dependency

Server-side Dart libraries for Excel generation are less mature than equivalents in Node.js or Python. The chosen library may lack support for Bufdir-required formatting features (merged cells, data validation, specific date formats), requiring significant workaround effort or a library switch mid-implementation.

Mitigation & Contingency

Mitigation: Evaluate the top two Dart xlsx libraries (excel, spreadsheet_decoder) against a Bufdir template sample file before committing. Identify all required formatting features and verify library support in a spike.

Contingency: If no Dart library meets requirements, implement the Excel generation as a Supabase Edge Function in TypeScript using the well-supported ExcelJS library, exposing it to the Dart backend via an internal RPC call.

medium impact medium prob integration

The attachment bundler must retrieve documents from Supabase Storage that were uploaded by the document attachments feature. If storage paths, RLS policies, or signed URL expiry have not been standardised across features, the bundler may fail to retrieve attachments at export time.

Mitigation & Contingency

Mitigation: Audit the document attachments feature's storage schema and RLS policies before implementing the bundler. Agree on a stable internal service-account access pattern for cross-feature storage reads.

Contingency: If cross-feature storage access cannot be made reliable, implement the bundler to include only attachments that can be retrieved successfully and produce a manifest listing any attachments that could not be bundled, rather than failing the entire export.