import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:glp1_companion/core/platform/notification_service.dart'; import 'package:glp1_companion/features/auth/presentation/controllers/dev_auth_bypass.dart'; import 'package:glp1_companion/features/auth/presentation/screens/login_screen.dart'; import 'package:glp1_companion/features/medication/domain/entities/dose_entry.dart'; import 'package:glp1_companion/features/medication/domain/repositories/medication_repository.dart'; import 'package:glp1_companion/features/medication/presentation/controllers/medication_controller.dart'; import 'package:glp1_companion/main.dart'; /// Empty history so the medication shell renders without touching drift. class _EmptyMedicationRepository implements IMedicationRepository { @override Stream> watchDoseEntries({int limit = 500}) => Stream.value(const []); @override Future> getDoseEntries({int limit = 500}) async => const []; @override Future saveDoseEntry(DoseEntry entry) async => entry; @override Future deleteDoseEntry(int id) async {} @override Future getLatestAdministeredDose() async => null; } class _NoopNotificationService implements INotificationService { @override Future initialize() async {} @override Future requestPermissions() async => false; @override Future scheduleDoseReminder({ required DateTime scheduledAt, required String title, required String body, int id = kDoseReminderNotificationId, String? payload, }) async => false; @override Future cancelReminder(int id) async {} @override Future cancelAllReminders() async {} } Widget _buildApp() => ProviderScope( overrides: [ medicationRepositoryProvider .overrideWithValue(_EmptyMedicationRepository()), notificationServiceProvider .overrideWithValue(_NoopNotificationService()), ], child: const GLP1CompanionApp(), ); void main() { testWidgets('unauthenticated sessions land on the login screen', (tester) async { await tester.pumpWidget(_buildApp()); await tester.pumpAndSettle(); expect(find.byType(LoginScreen), findsOneWidget); }); testWidgets('dev bypass button skips sign-in and opens the medication shell', (tester) async { // A tall phone-like viewport keeps the whole login column on-screen. tester.view.physicalSize = const Size(1080, 2400); tester.view.devicePixelRatio = 1.0; addTearDown(tester.view.reset); await tester.pumpWidget(_buildApp()); await tester.pumpAndSettle(); // Debug builds expose the bypass affordance on the login screen. final bypassButton = find.text('Continue Without Signing In'); expect(bypassButton, findsOneWidget); await tester.tap(bypassButton); await tester.pumpAndSettle(); // The guard admits the session and routes into the protected shell. expect(find.byType(LoginScreen), findsNothing); expect(find.text('Medication Tracker'), findsOneWidget); // The dev banner marks the session as not signed in. expect(find.text('Development mode - not signed in'), findsOneWidget); }); testWidgets('bypass resets to disabled on every cold start', (tester) async { await tester.pumpWidget( const ProviderScope(child: SizedBox()), ); final container = ProviderScope.containerOf( tester.element(find.byType(SizedBox)), ); expect(container.read(devAuthBypassProvider), isFalse); }); }