import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:motorcycle_dash/database/database.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/sync/sync_manager.dart'; import 'package:motorcycle_dash/services/sync/sync_outbox.dart'; import 'package:motorcycle_dash/services/sync/sync_provider.dart'; import 'package:motorcycle_dash/services/sync/sync_models.dart'; import 'package:motorcycle_dash/services/sync/firebase_sync_provider.dart'; class _Auth implements AuthService { @override bool get isEmailVerified => false; @override Future sendEmailVerification() async {} @override Future reloadCurrentUser() async {} @override Future reauthenticate({String? password}) async {} @override Future deleteCurrentUser() async {} @override Future ensureBackendIdentity() async {} AuthUser? user; @override bool get isConfigured => true; @override AuthUser? get currentUser => user; @override AuthState get currentState => user == null ? const AuthState.unauthenticated() : AuthState.authenticated(user!); @override Stream get authStateChanges => Stream.value(currentState); @override Future createUserWithEmailAndPassword(String e, String p, {String? displayName}) async {} @override Future sendPasswordResetEmail(String email) async {} @override Future signInAnonymously() async {} @override Future signInWithEmailAndPassword(String e, String p) async {} @override Future signInWithGoogle() async {} @override Future getIdToken([bool forceRefresh = false]) async => user == null ? null : 'token'; @override Future signOut() async { user = null; } @override void dispose() {} } void main() { TestWidgetsFlutterBinding.ensureInitialized(); test('new rides are unclaimed and claim is immutable', () async { final db = AppDatabase.forTesting(NativeDatabase.memory()); addTearDown(db.close); final rideId = await db.startRide(); expect(await db.getCloudOwnerUid(rideId), isNull); expect(await db.claimRideForCloudOwner(rideId, 'user_a'), isTrue); expect(await db.getCloudOwnerUid(rideId), 'user_a'); expect(await db.claimRideForCloudOwner(rideId, 'user_b'), isFalse); expect(await db.getCloudOwnerUid(rideId), 'user_a'); expect(await db.getCloudRideId(rideId), startsWith('ride_')); }); test('authenticated enqueue claims only for the current permanent account', () async { SharedPreferences.setMockInitialValues({}); final prefs = await SharedPreferences.getInstance(); final db = AppDatabase.forTesting(NativeDatabase.memory()); addTearDown(db.close); final auth = _Auth()..user = const AuthUser(uid: 'user_a', email: 'a@test.com'); final rideId = await db.startRide(); final manager = SyncManager( SyncOutbox(prefs), db: db, authService: auth, initialProviders: [FakeSyncProvider(providerId: 'firebase')], defaultProviderId: 'firebase', ); addTearDown(manager.dispose); await manager.enqueueRide(rideId, autoProcess: false); expect(await db.getCloudOwnerUid(rideId), 'user_a'); auth.user = const AuthUser(uid: 'user_b', email: 'b@test.com'); await manager.enqueueRide(rideId, autoProcess: false); expect(await db.getCloudOwnerUid(rideId), 'user_a'); }); test('signed-out enqueue leaves ride unclaimed', () async { SharedPreferences.setMockInitialValues({}); final prefs = await SharedPreferences.getInstance(); final db = AppDatabase.forTesting(NativeDatabase.memory()); addTearDown(db.close); final rideId = await db.startRide(); final manager = SyncManager( SyncOutbox(prefs), db: db, authService: _Auth(), initialProviders: [FakeSyncProvider(providerId: 'firebase')], defaultProviderId: 'firebase', ); addTearDown(manager.dispose); await manager.enqueueRide(rideId, autoProcess: false); expect(await db.getCloudOwnerUid(rideId), isNull); }); test('Firebase provider rejects another account before any cloud call', () async { final db = AppDatabase.forTesting(NativeDatabase.memory()); addTearDown(db.close); final rideId = await db.startRide(); await db.claimRideForCloudOwner(rideId, 'user_a'); final auth = _Auth()..user = const AuthUser(uid: 'user_b', email: 'b@test.com'); final result = await FirebaseSyncProvider(db: db, authService: auth).uploadRide( SyncItem(localRideId: rideId, providerId: 'firebase', createdAt: DateTime.now()), ); expect(result.success, isFalse); expect(result.isRetryable, isFalse); expect(await db.getCloudOwnerUid(rideId), 'user_a'); }); }