import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:motorcycle_dash/features/records/records_service.dart'; import 'package:motorcycle_dash/features/social/friends_screen.dart'; import 'package:motorcycle_dash/features/social/rider_profile_screen.dart'; import 'package:motorcycle_dash/services/auth/auth_providers.dart'; import 'package:motorcycle_dash/services/auth/auth_service.dart'; import 'package:motorcycle_dash/services/auth/auth_state.dart'; import 'package:motorcycle_dash/services/auth/auth_user.dart'; import 'package:motorcycle_dash/services/social/rider_profile_models.dart'; import 'package:motorcycle_dash/services/social/social_providers.dart'; import 'package:shared_preferences/shared_preferences.dart'; class _FakeAuth implements AuthService { @override Future ensureBackendIdentity() async {} final _states = StreamController.broadcast(); AuthUser? user; _FakeAuth({this.user}); @override Stream get authStateChanges => _states.stream; @override AuthState get currentState => user == null ? const AuthState.unauthenticated(isFirebaseConfigured: true) : (user!.isAnonymous ? AuthState.anonymous(user!, isFirebaseConfigured: true) : AuthState.authenticated(user!, isFirebaseConfigured: true)); @override AuthUser? get currentUser => user; @override bool get isConfigured => true; @override bool get isEmailVerified => true; @override Future deleteCurrentUser() async {} @override void dispose() => _states.close(); @override Future getIdToken([bool forceRefresh = false]) async => 'token'; @override Future reauthenticate({String? password}) async {} @override Future reloadCurrentUser() async {} @override Future sendEmailVerification() async {} @override Future sendPasswordResetEmail(String email) async {} @override Future signInAnonymously() async {} @override Future signInWithEmailAndPassword(String email, String password) async {} @override Future createUserWithEmailAndPassword(String email, String password, {String? displayName}) async {} @override Future signInWithGoogle() async {} @override Future signOut() async {} } void main() { TestWidgetsFlutterBinding.ensureInitialized(); late SharedPreferences prefs; setUp(() async { SharedPreferences.setMockInitialValues({}); prefs = await SharedPreferences.getInstance(); }); Widget buildTestable(Widget child, List overrides) { return ProviderScope( overrides: [ sharedPreferencesProvider.overrideWithValue(prefs), ...overrides, ], child: MaterialApp(home: child), ); } group('RiderProfileScreen Widget Tests', () { testWidgets('shows account required notice when signed out', (tester) async { final fakeAuth = _FakeAuth(user: null); await tester.pumpWidget( buildTestable( const RiderProfileScreen(), [authServiceProvider.overrideWithValue(fakeAuth)], ), ); await tester.pumpAndSettle(); expect(find.text('MOTORCLOUD ACCOUNT REQUIRED'), findsOneWidget); expect(find.text('SIGN IN OR REGISTER'), findsOneWidget); }); testWidgets('renders profile form and privacy controls when authenticated', (tester) async { final user = const AuthUser( uid: 'pilot_1', email: 'pilot@example.com', displayName: 'Test Pilot', ); final fakeAuth = _FakeAuth(user: user); final existingProfile = RiderProfile( uid: 'pilot_1', handle: 'test_pilot', displayName: 'Test Pilot', bio: 'Speed and curves.', region: 'Tail of the Dragon', avatarPreset: 'helmet_cyan', createdAt: DateTime.now(), updatedAt: DateTime.now(), ); await tester.pumpWidget( buildTestable( const RiderProfileScreen(), [ authServiceProvider.overrideWithValue(fakeAuth), myRiderProfileProvider.overrideWith((ref) => Stream.value(existingProfile)), ], ), ); await tester.pumpAndSettle(); expect(find.text('Rider Profile'), findsOneWidget); expect(find.text('@test_pilot'), findsWidgets); expect(find.text('Test Pilot'), findsWidgets); expect(find.text('Speed and curves.'), findsWidgets); expect(find.text('Tail of the Dragon'), findsWidgets); // Privacy switches expect(find.text('PRIVACY CONTROLS'), findsOneWidget); expect(find.text('Discoverable by Handle'), findsOneWidget); expect(find.text('Public Profile'), findsOneWidget); expect(find.text('Allow Friend Requests'), findsOneWidget); // Save button expect(find.text('SAVE PROFILE'), findsOneWidget); }); }); group('FriendsScreen Widget Tests', () { testWidgets('shows account required notice when signed out', (tester) async { final fakeAuth = _FakeAuth(user: null); await tester.pumpWidget( buildTestable( const FriendsScreen(), [authServiceProvider.overrideWithValue(fakeAuth)], ), ); await tester.pumpAndSettle(); expect(find.text('MOTORCLOUD ACCOUNT REQUIRED'), findsOneWidget); }); testWidgets('renders tabs and empty states when authenticated', (tester) async { final user = const AuthUser( uid: 'rider_1', email: 'rider@example.com', displayName: 'Rider One', ); final fakeAuth = _FakeAuth(user: user); await tester.pumpWidget( buildTestable( const FriendsScreen(), [ authServiceProvider.overrideWithValue(fakeAuth), myFriendsProvider.overrideWith((ref) => Stream.value([])), myIncomingRequestsProvider.overrideWith((ref) => Stream.value([])), myOutgoingRequestsProvider.overrideWith((ref) => Stream.value([])), ], ), ); await tester.pumpAndSettle(); expect(find.text('Friends (0)'), findsOneWidget); expect(find.text('Requests'), findsOneWidget); expect(find.text('Find Riders'), findsOneWidget); expect(find.text('NO FRIENDS ADDED YET'), findsOneWidget); }); testWidgets('displays friend item with action menu', (tester) async { final user = const AuthUser( uid: 'rider_1', email: 'rider@example.com', displayName: 'Rider One', ); final fakeAuth = _FakeAuth(user: user); final friendsList = [ FriendSummary( uid: 'friend_99', handle: 'corner_carver', displayName: 'Corner Carver', avatarPreset: 'tach_neon', friendedAt: DateTime.now(), ), ]; await tester.pumpWidget( buildTestable( const FriendsScreen(), [ authServiceProvider.overrideWithValue(fakeAuth), myFriendsProvider.overrideWith((ref) => Stream.value(friendsList)), myIncomingRequestsProvider.overrideWith((ref) => Stream.value([])), myOutgoingRequestsProvider.overrideWith((ref) => Stream.value([])), ], ), ); await tester.pumpAndSettle(); expect(find.text('Friends (1)'), findsOneWidget); expect(find.text('Corner Carver'), findsOneWidget); expect(find.text('@corner_carver'), findsOneWidget); }); }); }