critical priority medium complexity testing pending testing specialist Tier 3

Acceptance Criteria

Test suite contains at minimum 9 test cases covering all named comparison scenarios
Exact date match (delta = 0) with matching activity_type returns a non-null DuplicateActivityWarning
Delta of +1 day with matching activity_type returns a non-null DuplicateActivityWarning
Delta of -1 day with matching activity_type returns a non-null DuplicateActivityWarning
Delta of +2 days with matching activity_type returns null
Delta of -2 days with matching activity_type returns null
Delta of 0 days with different activity_type returns null
Empty activity list from CrossChapterActivityQuery returns null
When a warning is returned, DuplicateActivityWarning.chapterName equals the chapter name from the mock data
When a warning is returned, DuplicateActivityWarning.dateDeltaDays equals the expected signed integer value
When a warning is returned, DuplicateActivityWarning.activityTypeLabel is the display string (not the raw code)
When a warning is returned, DuplicateActivityWarning.conflictingActivityId equals the ID from the mock StoredActivity
All tests are async (use async/await), make no real network calls, and pass with flutter test

Technical Requirements

frameworks
Flutter
flutter_test
apis
CrossChapterActivityQuery (mocked)
data models
PendingActivity
StoredActivity
DuplicateActivityWarning
ActivityType
performance requirements
Full test suite runs in under 5 seconds

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Parameterise date-delta test cases using a local helper that creates a StoredActivity offset by N days from a base date, reducing copy-paste. For the field-population tests (chapterName, activityTypeLabel etc.), use a single rich mock StoredActivity with all fields populated and assert every field of the returned warning in one test case labelled 'fully populates all warning fields for dialog rendering'. This avoids spreading field assertions across multiple tests and makes the spec easy to read. Ensure the mock for CrossChapterActivityQuery is reset between tests using setUp().

Testing Requirements

All tests are pure async unit tests using flutter_test. Mock CrossChapterActivityQuery using mockito or a hand-written fake that returns a configurable List. Use fixed reference dates (e.g., DateTime(2025, 6, 15)) rather than DateTime.now() to make tests deterministic. Assert return value is null using expect(result, isNull) and non-null using expect(result, isNotNull) followed by field-level assertions.

Group tests under a single group('DuplicateActivityDetectionService') block with nested groups per scenario category (e.g., 'date tolerance', 'activity type mismatch', 'empty results'). Verify CrossChapterActivityQuery is called once per test using mockito verify().

Component
Duplicate Activity Detection Service
service high
Epic Risks (2)
medium impact medium prob scope

The ±1 day duplicate detection tolerance is specified in the acceptance criteria but timezone handling is not defined. A coordinator in UTC+2 submitting at 23:00 and another in UTC+0 submitting at 01:00 the next calendar day could trigger or miss a duplicate depending on which timezone the comparison uses.

Mitigation & Contingency

Mitigation: Define and document the authoritative timezone for all date comparisons (UTC stored in Supabase, all comparisons performed in UTC). Add timezone boundary unit tests covering the ambiguous ±1 day edges.

Contingency: If false positives or false negatives are reported in production, provide a coordinator-visible audit trail of duplicate detections so erroneous flags can be investigated and cleared manually.

medium impact medium prob technical

The Duplicate Activity Detection Service performs a cross-chapter join query synchronously during the activity submission flow. On slow mobile connections this could cause a perceptible stall on the submission confirmation step, degrading user experience.

Mitigation & Contingency

Mitigation: Pre-fetch the cross-chapter activity dataset for the selected contact immediately when the contact is selected in the activity wizard (not only at submit time), storing the result in the state manager for instant comparison at submission.

Contingency: If latency is still unacceptable, implement a loading indicator on the submit action and add a configurable server-side timeout with graceful degradation: if the check times out, allow submission with a logged 'check skipped' audit entry rather than blocking the user.