You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
9.3 KiB
252 lines
9.3 KiB
import 'package:flutter/material.dart';
|
|
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';
|
|
import 'package:app_boilerplate/data/sync/sync_engine.dart';
|
|
import 'package:app_boilerplate/data/session/session_service.dart';
|
|
import 'package:app_boilerplate/data/firebase/firebase_service.dart';
|
|
import 'package:app_boilerplate/core/service_locator.dart';
|
|
|
|
import 'main_navigation_scaffold_test.mocks.dart';
|
|
|
|
@GenerateMocks([
|
|
LocalStorageService,
|
|
NostrService,
|
|
SyncEngine,
|
|
SessionService,
|
|
FirebaseService,
|
|
])
|
|
void main() {
|
|
late MockLocalStorageService mockLocalStorageService;
|
|
late MockNostrService mockNostrService;
|
|
late MockSyncEngine mockSyncEngine;
|
|
late MockSessionService mockSessionService;
|
|
late MockFirebaseService mockFirebaseService;
|
|
|
|
setUp(() {
|
|
mockLocalStorageService = MockLocalStorageService();
|
|
mockNostrService = MockNostrService();
|
|
mockSyncEngine = MockSyncEngine();
|
|
mockSessionService = MockSessionService();
|
|
mockFirebaseService = MockFirebaseService();
|
|
|
|
// Set default return values for mocks
|
|
when(mockSessionService.isLoggedIn).thenReturn(false);
|
|
when(mockSessionService.currentUser).thenReturn(null);
|
|
when(mockFirebaseService.isEnabled).thenReturn(false);
|
|
when(mockNostrService.getRelays()).thenReturn([]);
|
|
|
|
// Stub NostrService methods that might be called by UI
|
|
final mockKeyPair = NostrKeyPair.generate();
|
|
when(mockNostrService.generateKeyPair()).thenReturn(mockKeyPair);
|
|
|
|
// Register services with ServiceLocator
|
|
ServiceLocator.instance.registerServices(
|
|
localStorageService: mockLocalStorageService,
|
|
nostrService: mockNostrService,
|
|
syncEngine: mockSyncEngine,
|
|
sessionService: mockSessionService,
|
|
firebaseService: mockFirebaseService,
|
|
);
|
|
});
|
|
|
|
tearDown(() {
|
|
// Reset ServiceLocator after each test
|
|
ServiceLocator.instance.reset();
|
|
});
|
|
|
|
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 with correct tabs', (WidgetTester tester) async {
|
|
await tester.pumpWidget(createTestWidget());
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for navigation icons (custom bottom nav, not standard BottomNavigationBar)
|
|
expect(find.byIcon(Icons.home), findsWidgets);
|
|
expect(find.byIcon(Icons.menu_book), findsWidgets);
|
|
expect(find.byIcon(Icons.favorite), findsWidgets);
|
|
expect(find.byIcon(Icons.person), 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 should appear in AppBar
|
|
expect(find.text('Home'), findsWidgets);
|
|
expect(find.byIcon(Icons.home), findsWidgets);
|
|
});
|
|
|
|
testWidgets('can navigate to Recipes screen', (WidgetTester tester) async {
|
|
await tester.pumpWidget(createTestWidget());
|
|
await tester.pumpAndSettle();
|
|
|
|
// Tap Recipes tab
|
|
final recipesTab = find.text('Recipes');
|
|
expect(recipesTab, findsWidgets);
|
|
await tester.tap(recipesTab);
|
|
await tester.pumpAndSettle();
|
|
|
|
// Verify Recipes screen is shown
|
|
expect(find.text('Recipes Screen'), findsOneWidget);
|
|
expect(find.text('Recipes'), findsWidgets);
|
|
});
|
|
|
|
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();
|
|
|
|
// 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('Add Recipe button navigates to Add Recipe screen', (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();
|
|
|
|
// 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 all main screens correctly', (WidgetTester tester) async {
|
|
await tester.pumpWidget(createTestWidget());
|
|
await tester.pumpAndSettle();
|
|
|
|
// 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('all screens have settings icon in AppBar', (WidgetTester tester) async {
|
|
await tester.pumpWidget(createTestWidget());
|
|
await tester.pumpAndSettle();
|
|
|
|
// 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);
|
|
});
|
|
});
|
|
}
|