high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

ActivityChartWidget tests cover: daily granularity renders bar chart mode (assert bar chart widget type present), weekly/monthly granularity renders line chart mode, switching granularity re-renders the correct chart type
ActivityChartWidget tooltip test: simulating a tap on a chart segment causes a tooltip widget to appear containing the segment's data label — verified via widget tree inspection after pump
ActivityChartWidget Semantics test: each chart segment has a Semantics widget with a non-empty label describing the data point (e.g., 'Monday: 5 activities')
ActivityChartWidget empty data test: when data list is empty, an empty state widget is rendered and no chart widget is present
PeerMentorStatsList row rendering test: with two mocked peer mentors each assigned to multiple chapters, the chapter labels are rendered correctly (e.g., 'Chapter A, Chapter B') in the row widget
PeerMentorStatsList onTap test: tapping a row fires the onTap callback with the correct (userId, timeWindow) pair for the tapped row — verified with a callback collector
PeerMentorStatsList empty state test: with an empty list, the empty state widget is rendered
PeerMentorStatsList loading skeleton test: in loading state, skeleton/shimmer rows are rendered and no real data rows are present
All tests are isolated from real Supabase calls and pass in CI

Technical Requirements

frameworks
Flutter
flutter_test
Riverpod (ProviderScope overrides)
data models
ActivityChartData
ChartGranularity
PeerMentorListItem
Chapter
TimeWindow
performance requirements
Full test suite for both widgets completes in under 15 seconds
ui components
ActivityChartWidget (bar and line modes)
ChartTooltip
PeerMentorStatsList
PeerMentorStatsRow
LoadingSkeleton/Shimmer

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

If the chart library (e.g., fl_chart) renders into a canvas, direct widget-tree assertions for individual bar/line types may not be possible — in that case, assert the chart widget's `barGroups` or `lineBarsData` parameter values via widget property inspection rather than pixel-level checks. Expose a `testKey` property on chart segments if tooltip testing requires a stable finder target. For PeerMentorStatsList, if the chapter label rendering logic is non-trivial (joining chapter names with separator), extract it to a pure function and add dedicated unit tests for the formatting edge cases (empty chapter list, single chapter, five chapters). Avoid testing third-party chart library internals; test only the integration layer (data passed in, output rendered correctly).

Testing Requirements

All tests are Flutter widget tests. For ActivityChartWidget, pass chart data via widget constructor or provider override; use `find.byType(BarChart)` and `find.byType(LineChart)` (or equivalent chart library widget types) to assert mode switching. For tooltip tests, use `tester.tap(find.byKey(segmentKey))` followed by `tester.pump()` and assert tooltip widget presence. For Semantics, use `tester.getSemantics()` with a finder targeting individual chart segments.

For PeerMentorStatsList, build the widget with a list of mock `PeerMentorListItem` objects. Organise with descriptive `group()` blocks. Cover at least one multi-chapter row and one single-chapter row in rendering tests. Add regression test for the exact callback signature emitted on tap.

Component
Peer Mentor Stats List
ui medium
Epic Risks (4)
high impact high prob technical

fl_chart renders chart elements on a Canvas, making individual bars and data points invisible to the Flutter Semantics tree by default. Without explicit Semantics wrappers, VoiceOver and TalkBack users receive no chart information, violating the WCAG 2.2 AA requirement mandated by all three partner organizations.

Mitigation & Contingency

Mitigation: Wrap the fl_chart widget in a Semantics node with a dynamically generated textual description of the chart data (e.g., 'Bar chart: January 12, February 8, March 15 sessions'). Implement a collapsible data table alternative beneath the chart that screen readers can navigate row by row. Validate with VoiceOver on iOS and TalkBack on Android before the epic is marked complete.

Contingency: If fl_chart's Canvas rendering cannot be made accessible within the epic timeline, ship the chart hidden from the Semantics tree with ExcludeSemantics and promote the data table alternative to first-class UI so screen reader users have full access to the information. Log a tech-debt item to revisit native chart accessibility in a future sprint.

medium impact medium prob scope

Coordinators managing up to 5 chapters (NHF requirement) require the PeerMentorStatsList to display chapter affiliation labels for each row. With large chapter lists and many peer mentors, the list could become overwhelming and cause layout overflow or scrolling performance issues on lower-end Android devices.

Mitigation & Contingency

Mitigation: Implement chapter filtering as a segmented control above the list so coordinators can scope the list to one chapter at a time. Use ListView.builder (lazy rendering) rather than a Column of all rows. Profile scroll performance on a low-end Android device (Pixel 4a equivalent) with 50 peer mentors in scope during development.

Contingency: If multi-chapter display causes unacceptable performance, ship with single-chapter scope as the default view and a chapter switcher dropdown, deferring the combined cross-chapter list to a follow-up sprint.

low impact low prob technical

Summary cards and the chart widget rebuilding simultaneously on provider state change could cause a visible jank frame on slower devices, degrading perceived quality especially since this screen is intended to feel motivating and polished for gamification purposes.

Mitigation & Contingency

Mitigation: Use AnimatedSwitcher with a short fade transition (150ms) on the stats cards and chart so that data replacement feels intentional rather than jarring. Profile with Flutter DevTools on a mid-range device and ensure no frame exceeds 16ms during a time-window switch.

Contingency: If animation introduces complexity that delays delivery, ship without animation and use a loading skeleton (shimmer effect) during re-fetch instead, which is simpler and equally effective at masking the data swap.

high impact low prob security

If the role-based screen dispatch is misconfigured, a peer mentor could navigate to the coordinator stats screen and see aggregated chapter data for all peer mentors, which is a data privacy violation and a compliance risk for all three organizations.

Mitigation & Contingency

Mitigation: Implement role guard at the router level using an existing role-route-guard component so the coordinator screen route is unreachable for peer mentor roles. Add a widget test that mounts the coordinator screen with a peer mentor session token and asserts that the guard redirects to the no-access screen.

Contingency: If a bypass is found in QA, add a secondary in-screen role assertion in the coordinator screen's initState that throws an AuthorizationException and navigates to the error screen, ensuring defence in depth regardless of router configuration.