feat: Introduce comprehensive unit tests for models and BLoCs using mockito and bloc_test, and refine TripBloc error handling.
Some checks failed
Deploy to Play Store / build_and_deploy (push) Has been cancelled

This commit is contained in:
Van Leemput Dayron
2025-12-05 11:55:20 +01:00
parent 9b11836409
commit cac0770467
17 changed files with 1608 additions and 48 deletions

View File

@@ -31,14 +31,18 @@ import '../../services/notification_service.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
/// Repository for authentication operations.
final AuthRepository _authRepository;
final NotificationService _notificationService;
/// Creates an [AuthBloc] with the provided [authRepository].
///
/// The bloc starts in the [AuthInitial] state and registers event handlers
/// for all supported authentication events.
AuthBloc({required AuthRepository authRepository})
: _authRepository = authRepository,
super(AuthInitial()) {
AuthBloc({
required AuthRepository authRepository,
NotificationService? notificationService,
}) : _authRepository = authRepository,
_notificationService = notificationService ?? NotificationService(),
super(AuthInitial()) {
on<AuthCheckRequested>(_onAuthCheckRequested);
on<AuthSignInRequested>(_onSignInRequested);
on<AuthSignUpRequested>(_onSignUpRequested);
@@ -71,7 +75,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
if (user != null) {
// Save FCM Token on auto-login
await NotificationService().saveTokenToFirestore(user.id!);
await _notificationService.saveTokenToFirestore(user.id!);
emit(AuthAuthenticated(user: user));
} else {
emit(AuthUnauthenticated());

View File

@@ -103,7 +103,12 @@ class TripBloc extends Bloc<TripEvent, TripState> {
'Error loading trips: $error',
stackTrace,
);
emit(const TripError('Impossible de charger les voyages'));
add(
const _TripsUpdated(
[],
error: 'Impossible de charger les voyages',
),
);
},
);
}
@@ -117,7 +122,11 @@ class TripBloc extends Bloc<TripEvent, TripState> {
/// [event]: The _TripsUpdated event containing the updated trip list
/// [emit]: State emitter function
void _onTripsUpdated(_TripsUpdated event, Emitter<TripState> emit) {
emit(TripLoaded(event.trips));
if (event.error != null) {
emit(TripError(event.error!));
} else {
emit(TripLoaded(event.trips));
}
}
/// Handles [TripCreateRequested] events.
@@ -234,16 +243,11 @@ class TripBloc extends Bloc<TripEvent, TripState> {
///
/// This internal event is used to process updates from the trip stream
/// subscription and emit appropriate states based on the received data.
/// internal event
class _TripsUpdated extends TripEvent {
/// List of trips received from the stream
final List<Trip> trips;
/// Creates a _TripsUpdated event.
///
/// Args:
/// [trips]: List of trips from the stream update
const _TripsUpdated(this.trips);
final String? error;
const _TripsUpdated(this.trips, {this.error});
@override
List<Object?> get props => [trips];
List<Object?> get props => [trips, error];
}

View File

@@ -23,8 +23,8 @@ class NotificationService {
factory NotificationService() => _instance;
NotificationService._internal();
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
final FlutterLocalNotificationsPlugin _localNotifications =
late final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
late final FlutterLocalNotificationsPlugin _localNotifications =
FlutterLocalNotificationsPlugin();
bool _isInitialized = false;