high priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

sessionCount equals the number of activity rows returned by the mocked repository
averageDurationMinutes is correctly computed as total duration / session count, rounded to the appropriate precision
Empty activity list returns ActivitySummary with sessionCount=0 and averageDurationMinutes=0 (or null per contract) without throwing
Activities with null or missing duration are excluded from the average calculation (not treated as zero) and a corresponding field (e.g., sessionsWithoutDuration) is incremented if such a field exists in ActivitySummary
When a date range is provided, the exact DateTimeRange (or equivalent) is forwarded to the repository mock without modification
When no date range is provided, the repository is called with a null/absent filter
The aggregator makes exactly one repository call per aggregation request — no direct Supabase references exist in the service class
All edge cases (single activity, all activities missing duration, very large session count) pass without overflow or exception
Tests are isolated with setUp/tearDown and complete without real database connections

Technical Requirements

frameworks
flutter_test
mocktail
data models
ActivitySummary
ActivityRecord
ActivityRepository
performance requirements
Tests complete in under 500ms total
Aggregation logic is O(n) — no quadratic test scenarios needed
security requirements
Test fixtures must not contain real peer mentor identifiers or personal data

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Build a small list of ActivityRecord fixtures with varying durations (some null) using a factory function to keep test data consistent and readable. For average calculation assertions, use closeTo matcher (e.g., closeTo(expectedAvg, 0.01)) to handle floating-point precision. When testing date range forwarding, use an ArgumentCaptor equivalent (mocktail's captureAny) to capture the argument and assert its startDate/endDate. Ensure the aggregator class does NOT import Supabase directly — if it does, that is an architecture violation that should be flagged and fixed before the tests are merged.

Testing Requirements

Async unit tests using flutter_test and mocktail. Create a mock for the ActivityRepository interface. Structure tests in four groups: (1) correct aggregation from a typical multi-row result, (2) empty result set handling, (3) date range filter forwarding, (4) partial data / missing duration handling. Use factory helpers to build ActivityRecord test fixtures.

Verify repository call arguments using captureAny/verify. Aim for 100% branch coverage of the aggregator service. Place test file at test/services/activity_summary_aggregator_test.dart.

Component
Activity Summary Aggregator
service low
Epic Risks (2)
medium impact medium prob integration

Supabase organisation configuration table may not yet have the five multiplier columns, requiring a migration. If the migration is not coordinated with other teams touching the same table, schema conflicts could delay delivery.

Mitigation & Contingency

Mitigation: Add multiplier columns in a dedicated, non-destructive ALTER TABLE migration script. Review the organisation config table schema with the backend team before writing the migration. Use nullable columns with defaults so existing rows are unaffected.

Contingency: If the migration cannot be deployed in time, stub the repository to return hardcoded default multiplier values from a local config file, allowing parallel development. Swap in the real Supabase fetch once the migration is live.

low impact medium prob scope

The ActivitySummaryAggregator depends on activity records already persisted in the database. For newly onboarded peer mentors with no activity history, the aggregator will return zero counts, which could make the calculator appear broken on first use.

Mitigation & Contingency

Mitigation: Design the pre-fill value object to distinguish between 'no data yet' and 'zero activities'. The calculator input panel should display empty inputs (not zero) when no history exists, with placeholder text guiding the user to enter values manually.

Contingency: If the distinction cannot be surfaced cleanly in the UI timeline, fall back to always showing empty inputs and document the manual-entry path as the primary UX until activity data accumulates.