@ -3,6 +3,7 @@ import 'package:flutter_test/flutter_test.dart';
import ' package:mockito/annotations.dart ' ;
import ' package:mockito/mockito.dart ' ;
import ' package:app_boilerplate/ui/navigation/main_navigation_scaffold.dart ' ;
import ' package:app_boilerplate/ui/navigation/app_router.dart ' ;
import ' package:app_boilerplate/data/local/local_storage_service.dart ' ;
import ' package:app_boilerplate/data/nostr/nostr_service.dart ' ;
import ' package:app_boilerplate/data/nostr/models/nostr_keypair.dart ' ;
@ -34,7 +35,7 @@ void main() {
mockSessionService = MockSessionService ( ) ;
mockFirebaseService = MockFirebaseService ( ) ;
/ / Set default return values for mocks - use getter stubbing
/ / Set default return values for mocks
when ( mockSessionService . isLoggedIn ) . thenReturn ( false ) ;
when ( mockSessionService . currentUser ) . thenReturn ( null ) ;
when ( mockFirebaseService . isEnabled ) . thenReturn ( false ) ;
@ -60,92 +61,191 @@ void main() {
} ) ;
Widget createTestWidget ( ) {
final appRouter = AppRouter (
sessionService: mockSessionService ,
localStorageService: mockLocalStorageService ,
nostrService: mockNostrService ,
syncEngine: mockSyncEngine ,
firebaseService: mockFirebaseService ,
) ;
return MaterialApp (
onGenerateRoute: appRouter . generateRoute ,
home: const MainNavigationScaffold ( ) ,
) ;
}
group ( ' MainNavigationScaffold - Navigation ' , ( ) {
testWidgets ( ' displays bottom navigation bar ' , ( WidgetTester tester ) async {
testWidgets ( ' displays bottom navigation bar with correct tabs ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
expect ( find . byType ( BottomNavigationBar ) , findsOneWidget ) ;
/ / Check for icons in bottom nav
/ / Check for navigation icons ( custom bottom nav , not standard BottomNavigationBar )
expect ( find . byIcon ( Icons . home ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . photo_library ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . cloud ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . menu_book ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . favorite ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . person ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . settings ) , findsWidgets ) ;
/ / Check for labels
expect ( find . text ( ' Home ' ) , findsWidgets ) ;
expect ( find . text ( ' Recipes ' ) , findsWidgets ) ;
expect ( find . text ( ' Favourites ' ) , findsWidgets ) ;
expect ( find . text ( ' User ' ) , findsWidgets ) ;
} ) ;
testWidgets ( ' displays Add Recipe button in center of bottom nav ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Find the add icon in the bottom navigation ( should be in center )
expect ( find . byIcon ( Icons . add ) , findsWidgets ) ;
/ / The add button is now part of the custom bottom nav , not a FloatingActionButton
} ) ;
testWidgets ( ' renders Home screen by default ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Home text might appear in AppBar and body , so check for at least one
/ / Home text should appear in AppBar
expect ( find . text ( ' Home ' ) , findsWidgets ) ;
expect ( find . byIcon ( Icons . home ) , findsWidgets ) ;
} ) ;
testWidgets ( ' can navigate between screens ' , ( WidgetTester tester ) async {
testWidgets ( ' can navigate to Recipes screen ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify Home is shown initially ( might appear multiple times )
expect ( find . text ( ' Home ' ) , findsWidgets ) ;
/ / Tap Recipes tab
final recipesTab = find . text ( ' Recipes ' ) ;
expect ( recipesTab , findsWidgets ) ;
await tester . tap ( recipesTab ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify navigation structure allows switching
expect ( find . byType ( BottomNavigationBar ) , findsOneWidget ) ;
/ / Navigation functionality is verified by the scaffold structure existing
/ / Verify Recipes screen is shown
expect ( find . text( ' Recipes Screen ' ) , findsOneWidget ) ;
expect ( find . text ( ' Recipes ' ) , findsWidgets ) ;
} ) ;
} ) ;
group ( ' MainNavigationScaffold - Route Guards ' , ( ) {
testWidgets ( ' route guards exist and scaffold renders ' , ( WidgetTester tester ) async {
/ / Mock not logged in
when ( mockSessionService . isLoggedIn ) . thenReturn ( false ) ;
testWidgets ( ' can navigate to Favourites screen ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Tap Favourites tab
final favouritesTab = find . text ( ' Favourites ' ) ;
expect ( favouritesTab , findsWidgets ) ;
await tester . tap ( favouritesTab ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify Favourites screen is shown
expect ( find . text ( ' Favourites Screen ' ) , findsOneWidget ) ;
expect ( find . text ( ' Favourites ' ) , findsWidgets ) ;
} ) ;
testWidgets ( ' can navigate to User/Session screen ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify scaffold structure exists - route guards are implemented in _buildScreen
expect ( find . byType ( BottomNavigationBar ) , findsOneWidget ) ;
expect ( find . byType ( Scaffold ) , findsWidgets ) ;
/ / Tap User tab
final userTab = find . text ( ' User ' ) ;
expect ( userTab , findsWidgets ) ;
await tester . tap ( userTab ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify User screen is shown
expect ( find . text ( ' User ' ) , findsWidgets ) ;
} ) ;
testWidgets ( ' route guards work with authentication ' , ( WidgetTester tester ) async {
/ / Mock logged in
when ( mockSessionService . isLoggedIn ) . thenReturn ( true ) ;
testWidgets ( ' Add Recipe button navigates to Add Recipe scree n' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Find all add icons ( Home screen has its own FAB , bottom nav has the Add Recipe button )
final addButtons = find . byIcon ( Icons . add ) ;
expect ( addButtons , findsWidgets ) ;
/ / The bottom nav add button is in a Material widget with CircleBorder
/ / Find it by looking for Material widgets with CircleBorder that contain add icons
/ / We ' ll tap the last add icon found (should be the bottom nav one, after Home screen ' s FAB )
final allAddIcons = addButtons . evaluate ( ) . toList ( ) ;
if ( allAddIcons . length > 1 ) {
/ / Tap the last one ( bottom nav button )
await tester . tap ( find . byIcon ( Icons . add ) . last ) ;
} else {
/ / Only one found , tap it
await tester . tap ( addButtons . first ) ;
}
await tester . pump ( ) ; / / Initial pump
await tester . pumpAndSettle ( const Duration ( seconds: 1 ) ) ; / / Wait for navigation
/ / Verify Add Recipe screen is shown ( check for AppBar title )
/ / If navigation worked , we should see " Add Recipe " in the AppBar
expect ( find . text ( ' Add Recipe ' ) , findsWidgets ) ;
} ) ;
testWidgets ( ' settings icon appears in AppBar ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify scaffold renders correctly
expect ( find . byType ( BottomNavigationBar ) , findsOneWidget ) ;
expect ( find . byType ( Scaffold ) , findsWidgets ) ;
/ / Settings icon should be in AppBar actions
expect ( find . byIcon ( Icons . settings ) , findsWidgets ) ;
} ) ;
testWidgets ( ' settings icon is tappable and triggers navigation ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Find settings icon in AppBar
final settingsIcons = find . byIcon ( Icons . settings ) ;
expect ( settingsIcons , findsWidgets ) ;
/ / Verify we ' re on Home screen initially
expect ( find . text ( ' Home ' ) , findsWidgets ) ;
/ / Tap the first settings icon ( should be in AppBar )
/ / This should trigger navigation to Relay Management
await tester . tap ( settingsIcons . first ) ;
await tester . pump ( ) ; / / Just pump once to trigger navigation
/ / Verify navigation was attempted ( no errors thrown )
/ / The actual screen content depends on service availability in test environment
} ) ;
} ) ;
group ( ' MainNavigationScaffold - Screen Rendering ' , ( ) {
testWidgets ( ' renders Home screen correctly ' , ( WidgetTester tester ) async {
testWidgets ( ' renders all main screens correctly' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
expect ( find . text ( ' Home ' ) , findsWidgets ) ; / / AppBar title and / or body
/ / Verify scaffold structure exists
/ / Custom bottom nav ( not standard BottomNavigationBar )
expect ( find . byType ( Scaffold ) , findsWidgets ) ;
expect ( find . byType ( IndexedStack ) , findsOneWidget ) ;
/ / Verify navigation icons are present
expect ( find . byIcon ( Icons . home ) , findsWidgets ) ;
} ) ;
testWidgets ( ' renders navigation scaffold structure ' , ( WidgetTester tester ) async {
testWidgets ( ' all screens have settings icon in AppBar ' , ( WidgetTester tester ) async {
await tester . pumpWidget ( createTestWidget ( ) ) ;
await tester . pumpAndSettle ( ) ;
/ / Verify scaffold structure exists
expect ( find . byType ( BottomNavigationBar ) , findsOneWidget ) ;
expect ( find . byType ( Scaffold ) , findsWidgets ) ;
/ / IndexedStack is internal - verify it indirectly by checking scaffold renders
expect ( find . text ( ' Home ' ) , findsWidgets ) ; / / Home screen should be visible
/ / Check Home screen
expect ( find . byIcon ( Icons . settings ) , findsWidgets ) ;
/ / Navigate to Recipes
await tester . tap ( find . text ( ' Recipes ' ) ) ;
await tester . pumpAndSettle ( ) ;
expect ( find . byIcon ( Icons . settings ) , findsWidgets ) ;
/ / Navigate to Favourites
await tester . tap ( find . text ( ' Favourites ' ) ) ;
await tester . pumpAndSettle ( ) ;
expect ( find . byIcon ( Icons . settings ) , findsWidgets ) ;
/ / Navigate to User
await tester . tap ( find . text ( ' User ' ) ) ;
await tester . pumpAndSettle ( ) ;
expect ( find . byIcon ( Icons . settings ) , findsWidgets ) ;
} ) ;
} ) ;
}