3.4 KiB
3.4 KiB
TT-013 — Widget Tests
Type: Task
Priority: Medium
Labels: testing, widget-tests
Depends on: TT-006, TT-007, TT-008, TT-009, TT-010, TT-011
Blocks: —
Summary
Write widget tests for each feature screen. Tests verify correct rendering
of UI states, user interactions, and provider integration. All provider
dependencies are overridden with mocks via mocktail.
Scope
| Test file | Screen | Key scenarios |
|---|---|---|
test/features/timer/timer_screen_test.dart |
TimerScreen | idle state, running state, start tap, stop tap |
test/features/entries/entries_screen_test.dart |
EntriesScreen | empty state, list renders, swipe delete, add form |
test/features/projects/projects_screen_test.dart |
ProjectsScreen | empty state, tile renders, create form, archive |
test/features/reports/reports_screen_test.dart |
ReportsScreen | week tab, period navigation, chart renders |
test/features/settings/settings_screen_test.dart |
SettingsScreen | theme picker, language picker, export sheet opens |
Widget Test Pattern
Widget buildTestApp({List<Override> overrides = const []}) {
return ProviderScope(
overrides: overrides,
child: MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const TimerScreen(),
),
);
}
testWidgets('shows START button when idle', (tester) async {
when(() => mockTimerNotifier.build()).thenReturn(const TimerState.idle());
await tester.pumpWidget(buildTestApp(overrides: [
timerNotifierProvider.overrideWith(() => mockTimerNotifier),
]));
expect(find.text('Start'), findsOneWidget);
expect(find.text('Stop'), findsNothing);
});
Key Widget Test Cases per Screen
TimerScreen
- Idle: START visible, STOP hidden, elapsed shows
00:00:00 - Running: STOP visible, DISCARD visible, project name shown
- Tap START without project → button remains disabled
- Tap STOP →
timerNotifier.stop()called once - Tap DISCARD → confirmation dialog appears
EntriesScreen
- Empty: placeholder text visible
- With entries:
EntryListTilerendered for each - Swipe left on entry → delete action visible
- Tap "+" →
EntryFormSheetappears - Date filter chip "Today" → filters visible entries
ProjectsScreen
- Empty Active tab: "No projects yet" visible
- Tile shows project name and color dot
- Tap tile → edit form opens pre-filled
- Archive action → tile moves to Archived tab
ReportsScreen
- Week tab shows 7 bar groups
- Tap ▶ → period label advances by one week
- Total duration card shows formatted duration
SettingsScreen
- Theme dropdown shows current selection
- Changing theme →
themeModeProviderupdated - Tap "Export data" →
ExportSheetbottom sheet appears
Acceptance Criteria
- All listed widget test files exist and pass with
flutter test - Each screen has ≥ 3 test cases
- No test relies on real DB or real providers
- Tests run in < 30 seconds total (no
sleep/ real async delays) pumpAndSettleused after async interactions
Notes
- Use
find.byType(),find.text(),find.byKey()— avoid pixel-exact finders - Add semantic labels / keys to interactive widgets to simplify test selectors
- Golden tests (screenshot comparison) are optional for v1