import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:provider/provider.dart'; import 'package:fuel_tax_tracker/screens/main_shell.dart'; import 'package:fuel_tax_tracker/services/app_state.dart'; /// Confirms the bottom nav actually switches between the four tabs and /// that each one builds without crashing against a freshly-constructed, /// not-yet-synced [AppState] — the same "no cloud connected, no vehicles /// yet" state a real fresh install starts in. void main() { testWidgets('bottom nav switches between all four tabs', (tester) async { final appState = AppState()..isLoading = false; await tester.pumpWidget( ChangeNotifierProvider.value( value: appState, child: const MaterialApp(home: MainShell()), ), ); // Receipts is the default tab. expect(find.widgetWithText(AppBar, 'Receipts'), findsOneWidget); await tester.tap(find.widgetWithText(NavigationDestination, 'Vehicles')); await tester.pumpAndSettle(); expect(find.widgetWithText(AppBar, 'Vehicles'), findsOneWidget); await tester.tap(find.widgetWithText(NavigationDestination, 'Reports')); await tester.pumpAndSettle(); expect(find.widgetWithText(AppBar, 'Fuel Report'), findsOneWidget); await tester.tap(find.widgetWithText(NavigationDestination, 'Settings')); await tester.pumpAndSettle(); expect(find.widgetWithText(AppBar, 'Settings'), findsOneWidget); await tester.tap(find.widgetWithText(NavigationDestination, 'Receipts')); await tester.pumpAndSettle(); expect(find.widgetWithText(AppBar, 'Receipts'), findsOneWidget); }); testWidgets('Receipts tab shows an empty state with no fuel entries yet', (tester) async { final appState = AppState()..isLoading = false; await tester.pumpWidget( ChangeNotifierProvider.value( value: appState, child: const MaterialApp(home: MainShell()), ), ); expect(find.textContaining('No fuel entries'), findsOneWidget); }); testWidgets('a right-to-left swipe on the body advances to the next tab', (tester) async { final appState = AppState()..isLoading = false; await tester.pumpWidget( ChangeNotifierProvider.value( value: appState, child: const MaterialApp(home: MainShell()), ), ); expect(find.widgetWithText(AppBar, 'Receipts'), findsOneWidget); await tester.fling(find.byType(PageView), const Offset(-400, 0), 1000); await tester.pumpAndSettle(); expect(find.widgetWithText(AppBar, 'Vehicles'), findsOneWidget); // And a left-to-right swipe goes back. await tester.fling(find.byType(PageView), const Offset(400, 0), 1000); await tester.pumpAndSettle(); expect(find.widgetWithText(AppBar, 'Receipts'), findsOneWidget); }); testWidgets( "swiping away from Receipts and back preserves its selected date range " '(AutomaticKeepAliveClientMixin keeping the tab alive across the PageView, ' 'not just the old IndexedStack)', (tester) async { final appState = AppState()..isLoading = false; await tester.pumpWidget( ChangeNotifierProvider.value( value: appState, child: const MaterialApp(home: MainShell()), ), ); await tester.tap(find.text('Last 3 Months')); await tester.pumpAndSettle(); // Swipe all the way to Settings and back. await tester.tap(find.widgetWithText(NavigationDestination, 'Settings')); await tester.pumpAndSettle(); await tester.tap(find.widgetWithText(NavigationDestination, 'Receipts')); await tester.pumpAndSettle(); final selectedLabel = tester.widget(find.text('Last 3 Months')); expect((selectedLabel.style?.fontWeight), FontWeight.w800, reason: 'still the active range'); }); }