high priority medium complexity testing pending testing specialist Tier 3

Acceptance Criteria

Test suite contains at least one test group per organisation (NHF, Blindeforbundet, HLF) using their actual production column schema configs as test fixtures
Null value policy 'omit' test: a column with a null value is excluded from the mapped output row entirely
Null value policy 'default_value' test: a column with a null value is replaced by the configured default and included in the output
Null value policy 'placeholder' test: a column with a null value is replaced by the configured placeholder string (e.g., 'N/A') in the output
Missing optional field test: a row lacking an optional field produces a valid mapped row without throwing
Required field validation test: a row missing a required field causes mapRow to throw RequiredFieldMissingException with the field name included in the message
Configuration override precedence test: an org-level override for a specific column takes precedence over the global default config
All test fixtures (column configs and activity rows) are defined as static const or final variables in a test helper file, not inline in each test
Tests achieve ≥90% line coverage as verified by running flutter test --coverage and inspecting lcov output for the mapper file
No test uses real Supabase connections — all data is provided via in-memory fixtures

Technical Requirements

frameworks
Flutter
flutter_test
Dart
data models
BufdirColumnSchema
NullValuePolicy (enum)
ActivityRow
MappedColumnRow
OrganisationColumnConfig
RequiredFieldMissingException
performance requirements
Full test suite must complete in under 10 seconds
Each individual test must run in under 500ms
security requirements
Test fixtures must not contain real member data — use anonymised synthetic data only

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Begin by reading the actual BufdirColumnMapper implementation to identify every branch: the null value policy switch, the required-field guard, and the override-merge logic. Write one test per branch to maximise coverage efficiency. For the 'omit' policy test, assert that the output map does not contain the key at all (using expect(result.containsKey('fieldName'), isFalse)). For 'default_value' and 'placeholder', assert the exact value.

For RequiredFieldMissingException, use throwsA(isA().having((e) => e.fieldName, 'fieldName', 'expectedField')). Avoid testing private methods directly — test via the public mapRow interface and verify outcomes. If the mapper has a mapBatch method, add a batch test that verifies partial failure isolation (one bad row does not prevent good rows from being mapped).

Testing Requirements

Pure unit tests using flutter_test. Organise tests into group() blocks: 'NHF config', 'Blindeforbundet config', 'HLF config', 'null value policies', 'required field validation', 'override precedence'. Use setUp() to instantiate a fresh BufdirColumnMapper for each test. Define fixture helpers in test/fixtures/bufdir_column_mapper_fixtures.dart exporting nhfConfig, blindeforbundetConfig, hlfConfig, sampleActivityRow, rowWithNullOptionalField, rowMissingRequiredField, and rowWithOverriddenColumn.

Run flutter test --coverage after writing tests and confirm ≥90% line coverage; document any intentionally excluded lines with // coverage:ignore-line comments and a reason.

Component
Bufdir Column Mapper
service high
Epic Risks (2)
medium impact medium prob scope

Bufdir's column schema may have per-field business rules (conditional required fields, cross-field validation, organisation-specific category taxonomies) that cannot be expressed in a simple key-value mapping configuration. If the configuration model is too simple, supporting NHF's specific requirements will require hardcoded organisation logic, undermining the configuration-driven design.

Mitigation & Contingency

Mitigation: Design the column configuration schema as a full JSON document supporting field-level transformation rules, conditional expressions, and org-specific value enumerations. Validate the design against a real NHF Bufdir Excel template before implementation begins.

Contingency: If the configuration model cannot express all required rules, implement a thin transformation plugin interface where org-specific logic can be added as a named Dart class registered against the organisation ID, with the JSON config covering only the common cases.

high impact medium prob technical

For large organisations like NHF with potentially tens of thousands of activity records, the full export pipeline (query + map + generate + bundle + upload) may exceed Supabase Edge Function execution time limits (typically 150s), causing silent timeouts that leave audit records in a pending state indefinitely.

Mitigation & Contingency

Mitigation: Implement the orchestrator as a background Dart isolate with progress streaming rather than a synchronous Edge Function call. Use chunked processing for the query and mapping phases to reduce peak memory usage. Profile against realistic NHF data volumes in a staging environment.

Contingency: If processing time cannot be reduced below the timeout threshold, implement an asynchronous job model where the export is queued, processed in the background, and the user is notified via push notification when the download is ready — treating it as an eventual rather than synchronous operation.