medium priority medium complexity testing pending testing specialist Tier 5

Acceptance Criteria

Golden files are committed to the repository under test/goldens/ with a clear naming convention (e.g. stat_card_locked_light.png)
StatCardWidget: golden files for locked, counting (mid-animation frame), and completed states in both light and dark themes (6 golden files minimum)
StatCardWidget reduced-motion: golden file for completed state with reduced-motion enabled (no animation artefacts — counter shows final value) in both themes (2 files)
MilestoneBadgeWidget: golden files for locked and unlocked states in both themes (4 files)
ActivityTypeBreakdownWidget: golden files for 3-segment and 6-segment variants in both themes (4 files); reduced-motion variant for each (4 files)
SummaryShareOverlay: golden file for open state (preview visible, share button enabled) in both themes (2 files)
All golden tests pass on CI with matchesGoldenFile() — pixel tolerance set to 1% to handle sub-pixel font rendering differences across platforms
A README or inline comment in the test file documents how to regenerate golden files (flutter test --update-goldens)
Reduced-motion variants visually confirm that animations are paused at their final resting frame — no partial progress states visible
Tests are isolated: each test pumps a fresh widget tree with deterministic data (no random values)

Technical Requirements

frameworks
Flutter
flutter_test (matchesGoldenFile)
golden_toolkit (optional, for easier multi-theme/multi-size pumping)
BLoC test stubs for providing widget state
apis
matchesGoldenFile() (flutter_test)
tester.pumpWidget() with fixed-size SizedBox wrapper for deterministic layout
ThemeData / design token injection for light/dark switching
SummaryAccessibilityProvider with reducedMotionEnabled flag
data models
SummaryStatCardData (deterministic fixture: fixed numbers, no random)
MilestoneBadgeData (locked fixture and unlocked fixture)
ActivityTypeBreakdownData (3-segment fixture and 6-segment fixture with fixed percentages summing to 100%)
performance requirements
Golden test suite must complete in under 60 seconds on CI
Each golden image must be under 500KB (use PNG with default compression)
security requirements
Golden fixtures must not include real user data — use synthetic placeholder values (e.g. '42 activities', 'Test User')
ui components
StatCardWidget
MilestoneBadgeWidget
ActivityTypeBreakdownWidget
SummaryShareOverlay
Design token ThemeData wrappers (light + dark)

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Wrap each widget under test in a MaterialApp with the appropriate ThemeData (light/dark design tokens injected). Fix the widget size with SizedBox(width: 375, height: X) to match the iPhone SE viewport width for consistency. Use a FakeAsync or explicit pump durations rather than pumpAndSettle for animation states — pumpAndSettle will skip to the end, so use tester.pump(const Duration(milliseconds: 300)) for the mid-animation counting state. Store all golden files in test/goldens/ with snake_case names.

If using golden_toolkit, use loadAppFonts() in setUpAll to ensure text renders correctly. For the share overlay golden, mock ScreenshotCaptureUtility to return a fixed 1x1 transparent image so the preview renders without async gaps.

Testing Requirements

All tests use flutter_test's matchesGoldenFile. Use tester.pump(Duration.zero) to advance to the initial frame, and for mid-animation state use tester.pump(animationDuration * 0.5) to capture counting state. For completed state use tester.pumpAndSettle(). For reduced-motion, inject SummaryAccessibilityProvider with reducedMotionEnabled: true and use tester.pumpAndSettle() — the widget should immediately show final state.

Run golden tests on a Linux CI runner (Flutter's canonical golden comparison platform) to ensure deterministic rendering. Document the update command: flutter test --update-goldens test/goldens/. Enforce that golden files are never committed with --update-goldens in CI — use a diff check on PRs.

Component
Animated Stat Card Widget
ui medium
Epic Risks (2)
medium impact medium prob technical

Simultaneous count-up animations across multiple stat cards and chart draw-in animations on lower-end Android devices may cause frame drops below 60fps, degrading the premium Wrapped experience and making the feature feel unpolished.

Mitigation & Contingency

Mitigation: Stagger animation starts using AnimationController with staggered intervals rather than starting all animations simultaneously. Use RepaintBoundary around each animated widget to isolate rasterisation. Profile on a mid-range Android device (e.g., equivalent to Pixel 4a) during development, not just at QA.

Contingency: If frame rate targets cannot be met on low-end devices, implement a device-capability check at startup and substitute simpler fade-in animations for the count-up and chart draw-in on devices below a CPU performance threshold.

medium impact low prob integration

The activity-type-breakdown-widget must render organisation-specific activity type labels sourced from the terminology system. If the terminology provider is not yet integrated at the time this widget is built, the widget will display hardcoded system labels, which is a regression risk for multi-org support.

Mitigation & Contingency

Mitigation: Accept activity type labels as a typed parameter in the widget constructor rather than reading from the terminology provider directly inside the widget. The BLoC or repository layer resolves labels before passing them to the widget, maintaining clean separation and testability.

Contingency: If terminology resolution is unavailable at widget integration time, display internal activity type keys as a temporary fallback with a localised suffix '(label pending)' visible only in non-production builds so QA can identify unresolved labels.