timetracker/.tasks/done/TT-013-widget-tests.md
2026-08-03 21:51:48 +02:00

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: EntryListTile rendered for each
  • Swipe left on entry → delete action visible
  • Tap "+" → EntryFormSheet appears
  • 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 → themeModeProvider updated
  • Tap "Export data" → ExportSheet bottom 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)
  • pumpAndSettle used 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