Write unit tests for Excel and CSV generators
epic-bufdir-reporting-export-processing-services-task-013 — 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.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
BufdirExcelCsvGenerator likely wraps a Dart Excel/CSV library (e.g., excel package or csv package). Test at the public API boundary β call generate(List
For CSV BOM: assert output bytes start with [0xEF, 0xBB, 0xBF] when Excel-compatibility mode is enabled. Use a ColumnOrderValidator helper that extracts row 0 header values and compares against an ordered const list β this makes column-order failures self-documenting. Avoid mocking the Excel library itself; test integration of generator + library together.
Testing Requirements
Unit tests only β no external dependencies. Use flutter_test with fake data factories to construct BufdirActivityRecord instances. Implement golden file tests using dart:typed_data to compare byte-level output against committed reference files for both .xlsx and .csv formats. Cover: (1) happy path with 1, 10, and 100 activity records; (2) Norwegian character encoding roundtrip; (3) number formatting for counts and hours; (4) empty input; (5) single-activity edge case; (6) column order validation by header name comparison.
Use group() blocks to separate Excel and CSV concerns. Aim for 90%+ coverage on the generator class.
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.
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.
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.