106 lines
4.8 KiB
Dart
106 lines
4.8 KiB
Dart
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<void> sendEmailVerification() async {}
|
|
@override Future<void> reloadCurrentUser() async {}
|
|
@override Future<void> reauthenticate({String? password}) async {}
|
|
@override Future<void> deleteCurrentUser() 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<AuthState> get authStateChanges => Stream.value(currentState);
|
|
@override Future<void> createUserWithEmailAndPassword(String e, String p, {String? displayName}) async {}
|
|
@override Future<void> sendPasswordResetEmail(String email) async {}
|
|
@override Future<void> signInAnonymously() async {}
|
|
@override Future<void> signInWithEmailAndPassword(String e, String p) async {}
|
|
@override Future<void> signInWithGoogle() async {}
|
|
@override Future<String?> getIdToken([bool forceRefresh = false]) async => user == null ? null : 'token';
|
|
@override Future<void> 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');
|
|
});
|
|
}
|