242 lines
7.4 KiB
Dart
242 lines
7.4 KiB
Dart
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<void> ensureBackendIdentity() async {}
|
|
|
|
final _states = StreamController<AuthState>.broadcast();
|
|
AuthUser? user;
|
|
|
|
_FakeAuth({this.user});
|
|
|
|
@override
|
|
Stream<AuthState> 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<void> deleteCurrentUser() async {}
|
|
|
|
@override
|
|
void dispose() => _states.close();
|
|
|
|
@override
|
|
Future<String?> getIdToken([bool forceRefresh = false]) async => 'token';
|
|
|
|
@override
|
|
Future<void> reauthenticate({String? password}) async {}
|
|
|
|
@override
|
|
Future<void> reloadCurrentUser() async {}
|
|
|
|
@override
|
|
Future<void> sendEmailVerification() async {}
|
|
|
|
@override
|
|
Future<void> sendPasswordResetEmail(String email) async {}
|
|
|
|
@override
|
|
Future<void> signInAnonymously() async {}
|
|
|
|
@override
|
|
Future<void> signInWithEmailAndPassword(String email, String password) async {}
|
|
|
|
@override
|
|
Future<void> createUserWithEmailAndPassword(String email, String password,
|
|
{String? displayName}) async {}
|
|
|
|
@override
|
|
Future<void> signInWithGoogle() async {}
|
|
|
|
@override
|
|
Future<void> signOut() async {}
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
late SharedPreferences prefs;
|
|
|
|
setUp(() async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
prefs = await SharedPreferences.getInstance();
|
|
});
|
|
|
|
Widget buildTestable(Widget child, List<Override> 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);
|
|
});
|
|
});
|
|
}
|