import 'package:flutter_test/flutter_test.dart'; import 'package:bloc_test/bloc_test.dart'; import 'package:mockito/mockito.dart'; import 'package:mockito/annotations.dart'; import 'package:travel_mate/blocs/trip/trip_bloc.dart'; import 'package:travel_mate/blocs/trip/trip_event.dart'; import 'package:travel_mate/blocs/trip/trip_state.dart'; import 'package:travel_mate/repositories/trip_repository.dart'; import 'package:travel_mate/models/trip.dart'; import 'trip_bloc_test.mocks.dart'; @GenerateMocks([TripRepository]) void main() { group('TripBloc', () { late MockTripRepository mockTripRepository; late TripBloc tripBloc; final trip = Trip( id: 'trip1', title: 'Summer Vacation', description: 'Trip to the beach', location: 'Miami', startDate: DateTime(2023, 6, 1), endDate: DateTime(2023, 6, 10), createdBy: 'user1', createdAt: DateTime(2023, 1, 1), updatedAt: DateTime(2023, 1, 2), participants: ['user1'], status: 'active', ); setUp(() { mockTripRepository = MockTripRepository(); tripBloc = TripBloc(mockTripRepository); }); tearDown(() { tripBloc.close(); }); test('initial state is TripInitial', () { expect(tripBloc.state, TripInitial()); }); // LoadTripsByUserId blocTest( 'emits [TripLoading, TripLoaded] when LoadTripsByUserId is added', setUp: () { when( mockTripRepository.getTripsByUserId('user1'), ).thenAnswer((_) => Stream.value([trip])); }, build: () => tripBloc, act: (bloc) => bloc.add(const LoadTripsByUserId(userId: 'user1')), expect: () => [ TripLoading(), TripLoaded([trip]), ], ); blocTest( 'emits [TripLoading, TripError] when stream error', setUp: () { when( mockTripRepository.getTripsByUserId('user1'), ).thenAnswer((_) => Stream.error('Error loading trips')); }, build: () => tripBloc, act: (bloc) => bloc.add(const LoadTripsByUserId(userId: 'user1')), expect: () => [ TripLoading(), const TripError('Impossible de charger les voyages'), ], ); // TripCreateRequested blocTest( 'emits [TripLoading, TripCreated] when TripCreateRequested is added', setUp: () { when( mockTripRepository.createTrip(any), ).thenAnswer((_) async => 'trip1'); }, build: () => tripBloc, act: (bloc) => bloc.add(TripCreateRequested(trip: trip)), // Note: TripBloc automatically refreshes list if _currentUserId is set. // Here we haven't loaded trips so _currentUserId is null. expect: () => [TripLoading(), const TripCreated(tripId: 'trip1')], ); // TripDeleteRequested blocTest( 'emits [TripOperationSuccess] when TripDeleteRequested is added', setUp: () { when(mockTripRepository.deleteTrip('trip1')).thenAnswer((_) async {}); }, build: () => tripBloc, act: (bloc) => bloc.add(const TripDeleteRequested(tripId: 'trip1')), expect: () => [const TripOperationSuccess('Trip deleted successfully')], ); }); }