high priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

All tests are located in `test/notifications/pause_notification_payload_builder_test.dart`
Coordinator payload test: title contains peer mentor's display name, body contains effective date, data map has `type: 'pause_coordinator_alert'`, `assignment_id`, `peer_mentor_id`
Peer mentor confirmation payload test: title uses organisation-specific peer mentor label, body contains expected return date or 'no date' fallback phrase
Long-name truncation test: a name of 80 characters does not cause the final body string to exceed FCM body character limit
Missing return date test: payload is valid and body contains the configured fallback phrase when `expectedReturnDate` is null
Organisation terminology test: two calls with different `OrganisationLabels` maps produce body strings containing the respective custom labels
ArgumentError tests: null `peer_mentor_id` and null `assignment_id` each throw `ArgumentError` for both builder methods
All tests pass with `flutter test` in under 2 seconds total
Test file has no external dependencies — all inputs are in-memory stubs, no Supabase or FCM calls

Technical Requirements

frameworks
Flutter
Dart
flutter_test
data models
assignment
contact
performance requirements
Full test suite completes in under 2 seconds
security requirements
Test fixtures must not contain real personnummer, real email addresses, or real names from production data

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Organise tests in four `group` blocks: `coordinatorPayload`, `mentorConfirmationPayload`, `truncation`, and `errorHandling`. Create a shared `buildDefaultLabels()` helper inside the test file that returns a minimal `OrganisationLabels` map for reuse. For the terminology substitution tests, define two constant label maps (`labelsNhf`, `labelsHlf`) inline in the test file — do not read from files. Verify both `title` and `body` fields in every payload assertion, not just one.

Keep each test method under 20 lines.

Testing Requirements

Pure unit tests using flutter_test. Use `group` blocks to separate coordinator payload tests, mentor confirmation payload tests, truncation tests, and error tests. Use `expect` with `throwsArgumentError` matcher for error cases. Parameterise the long-name truncation test with boundary values (exactly at limit, one over limit, far over limit).

No mocking framework needed — builder is a pure function.

Component
Pause Notification Payload Builder
service low
Epic Risks (3)
high impact medium prob integration

The org membership table structure used to resolve coordinator relationships may differ from what the repository assumes, causing incorrect coordinator lookup or missing rows for mentors in multi-chapter scenarios.

Mitigation & Contingency

Mitigation: Review the existing org membership table schema and RLS policies before writing repository queries. Align query logic with the patterns already used by peer-mentor-status-repository and multi-chapter-membership-service.

Contingency: If schema differs, add an adapter layer in the repository that normalises the membership resolution and document the discrepancy for the data team. Fall back to coordinator lookup via the feature's own stored coordinator_id field if org membership join fails.

high impact medium prob technical

Device tokens stored in the database may be stale or unregistered, causing FCM dispatch failures that silently drop coordinator notifications — the primary coordination safeguard of this feature.

Mitigation & Contingency

Mitigation: Implement token validation on every dispatch call and handle FCM's NOT_REGISTERED error by flagging the token as invalid in the database. Reuse the token refresh pattern already established by fcm-token-manager.

Contingency: If push delivery fails after retry, ensure the in-app notification record is always written regardless of push outcome so coordinators can still see the event in the notification centre.

medium impact low prob technical

The optional reason field may contain special characters, emoji, or non-Latin scripts that exceed the 200-character byte limit when FCM encodes the payload, causing delivery failures.

Mitigation & Contingency

Mitigation: Enforce the 200-character limit on Unicode code point count, not byte count, in the payload builder. Add a unit test with multi-byte input strings.

Contingency: If an oversized payload is detected at dispatch time, strip the reason field from the push notification body and note 'See in-app notification for full reason' to preserve delivery.