high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

All five KPI computations are tested with at least two distinct mocked datasets (normal data + boundary data): active peer mentors count, activities this month, hours logged, reach (unique contacts), and Bufdir-reportable activities
Subtree scoping test: when a regional node ID is passed, KPIs reflect only activity within that subtree; activity from sibling or parent nodes does not appear in the result
Month-over-month trend tests: (a) positive trend — current month value > previous month value yields a positive percentage and 'up' direction; (b) negative trend — current < previous yields negative percentage and 'down' direction; (c) flat — equal values yield 0% and 'flat' direction
Trend magnitude accuracy: percentage change is computed as ((current - previous) / previous) × 100, rounded to one decimal place; test asserts exact rounded value
Cache TTL test: KPI results served from cache within TTL window; cache expired after TTL elapses (inject clock); post-expiry call re-fetches from repository
Edge case — empty org: all KPIs return 0, trend direction is 'flat', no exception thrown
Edge case — no previous month activity: month-over-month trend returns null or a documented sentinel value (not NaN or infinity); test asserts the documented behaviour
Edge case — org with activity only in previous month (current = 0): trend shows 100% decrease, direction 'down'
Test suite achieves ≥ 85% branch coverage on AdminStatisticsService

Technical Requirements

frameworks
flutter_test
mocktail for repository and OrgHierarchyService mocking
apis
AdminStatisticsService public API
AdminStatisticsRepository (mocked)
OrgHierarchyService.getSubtreeIds() (mocked)
data models
AdminKpiSnapshot (5 KPI fields)
MonthOverMonthTrend (direction, percentage)
OrgScopeFilter
performance requirements
All tests complete in < 5 s; no real-time waits or network I/O
security requirements
Verify that KPI computation never aggregates data outside the requested subtree IDs — confirm via mock assertion that repository is called with the correct ID filter

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

If AdminStatisticsService does not currently accept a clock/DateTime injection, coordinate with the implementation owner to add a ClockProvider parameter before writing cache TTL tests — avoid using real async delays (Future.delayed) in tests. For trend calculation edge cases, confirm with the team what the API contract is for 'previous month = 0' (division by zero): document this as a comment in the test regardless of outcome. Test subtree scoping by providing mock getSubtreeIds responses that return a specific list of IDs, then assert the repository's fetchActivities call receives exactly those IDs (via verify). Keep test data minimal — a handful of OrgNode stubs and a small set of activity records is sufficient; avoid generating large synthetic datasets that obscure intent.

Testing Requirements

Pure Dart unit tests (flutter_test). Mock AdminStatisticsRepository and OrgHierarchyService using mocktail. Use a FakeClock or injected DateTime for TTL tests to avoid real time delays. Organise in groups: 'KPI computations', 'subtree scoping', 'trend calculations', 'cache behaviour', 'edge cases'.

Each KPI should have its own dedicated test for clarity. Trend calculation tests should use fixed numeric inputs and assert exact output to catch rounding regressions. Run coverage report and enforce ≥ 85% branch coverage on the service class in CI.

Component
Admin Statistics Service
service high
Epic Risks (4)
medium impact high prob technical

OrgHierarchyNavigator rendering NHF's full 1,400-chapter tree in a single widget may cause Flutter frame-rate drops below 60 fps on mid-range devices, making the navigator unusable for NHF national admins.

Mitigation & Contingency

Mitigation: Implement lazy expansion: only load immediate children on node expand rather than the full tree upfront. Use virtual scrolling for long sibling lists. Test with a synthetic 1,400-node dataset on a low-end Android device during development.

Contingency: If lazy expansion is insufficient, replace the tree widget with a paginated drill-down navigator (select level → select child) that avoids rendering more than 50 nodes at a time.

medium impact medium prob dependency

Bufdir may update their required export column structure or file format during or after development. If the AdminExportService hardcodes the current Bufdir schema, any format change requires a code release rather than a config update.

Mitigation & Contingency

Mitigation: Drive the Bufdir column mapping from a configuration repository rather than hardcoded constants. Abstract column definitions into a named schema config so that format changes require only a config update and re-deployment without service logic changes.

Contingency: If Bufdir format changes post-launch, release a config update within one sprint. If the change is structural (new required sections), scope a targeted service update and communicate timeline to partner organisations.

high impact medium prob integration

Role transition side-effects in UserManagementService (e.g., certification expiry removing mentor from chapter listing, pause triggering coordinator notification) may interact with external services like HLF's website sync. Incomplete side-effect handling could leave the system in an inconsistent state.

Mitigation & Contingency

Mitigation: Model side-effects as explicit domain events published after the primary state change is persisted. Implement event handlers as idempotent operations so re-processing is safe. Write integration tests that assert all side-effects fire correctly for each role transition type.

Contingency: If a side-effect fails after the primary change is persisted, log the failure with full context and trigger a manual reconciliation alert to the on-call team. Provide an admin-accessible re-trigger action for failed side-effects.

medium impact medium prob scope

If AdminStatisticsService cache TTL is set too long, org_admin may see significantly stale KPI values (e.g., a mentor newly paused an hour ago still appears as active), undermining trust in the dashboard.

Mitigation & Contingency

Mitigation: Default cache TTL to 5 minutes with a manual refresh action on the dashboard. Implement cache invalidation triggered by UserManagementService write operations that affect counted entities.

Contingency: If staleness causes org admin complaints post-launch, reduce TTL to 60 seconds and introduce a real-time Supabase subscription for high-impact counters (paused mentors, expiring certifications).