forked from eatvio/eatvio_app
199 lines
8.0 KiB
Dart
199 lines
8.0 KiB
Dart
import 'dart:async';
|
||
import 'package:eatvio_app/core/enums/base_state.dart';
|
||
import 'package:eatvio_app/core/models/pagination_model.dart';
|
||
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
||
import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart';
|
||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
|
||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_state.dart';
|
||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||
import 'package:flutter_test/flutter_test.dart';
|
||
import 'package:mockito/annotations.dart';
|
||
import 'package:mockito/mockito.dart';
|
||
import 'package:dart_pusher_channels/dart_pusher_channels.dart';
|
||
import 'chats_cubit_test.mocks.dart';
|
||
|
||
@GenerateNiceMocks([MockSpec<ChatRepository>(), MockSpec<ProfileRepository>(), MockSpec<WsManager>(), MockSpec<StreamSubscription>()])
|
||
void main() {
|
||
TestWidgetsFlutterBinding.ensureInitialized();
|
||
group('ChatsCubit', () {
|
||
late ChatsCubit chatsCubit;
|
||
late MockChatRepository mockChatRepository;
|
||
late MockProfileRepository mockProfileRepository;
|
||
late MockWsManager mockWsManager;
|
||
|
||
const testChatRoomsPagination = ChatRoomPaginationModel(
|
||
data: [],
|
||
unreadChatsCount: 0,
|
||
meta: Meta(currentPage: 1, from: null, lastPage: 1, links: [], perPage: 10, to: null, total: 0),
|
||
);
|
||
|
||
setUp(() {
|
||
mockChatRepository = MockChatRepository();
|
||
mockProfileRepository = MockProfileRepository();
|
||
mockWsManager = MockWsManager();
|
||
chatsCubit = ChatsCubit(chatRepository: mockChatRepository, wsManager: mockWsManager, profileRepository: mockProfileRepository);
|
||
});
|
||
|
||
tearDown(() async {
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
if (!chatsCubit.isClosed) {
|
||
await chatsCubit.close();
|
||
}
|
||
});
|
||
|
||
test('начальное состояние - initial', () {
|
||
expect(chatsCubit.state, isA<ChatsState>());
|
||
expect(chatsCubit.state.state, BaseState.initial);
|
||
});
|
||
|
||
test('getChatRoomsWithLoading - загружает комнаты с loading состоянием', () async {
|
||
when(mockChatRepository.getChatRooms(query: null)).thenAnswer((_) async => testChatRoomsPagination);
|
||
|
||
await chatsCubit.getChatRoomsWithLoading();
|
||
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
expect(chatsCubit.state.state, BaseState.success);
|
||
verify(mockChatRepository.getChatRooms(query: null)).called(1);
|
||
});
|
||
|
||
test('getChatRoomsWithLoading - обрабатывает ошибку', () async {
|
||
when(mockChatRepository.getChatRooms(query: null)).thenThrow(Exception('Network error'));
|
||
|
||
await chatsCubit.getChatRoomsWithLoading();
|
||
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
expect(chatsCubit.state.state, BaseState.error);
|
||
expect(chatsCubit.state.errorMessage, isNotNull);
|
||
});
|
||
|
||
test('getChatRooms - загружает комнаты без loading состояния', () async {
|
||
when(mockChatRepository.getChatRooms(query: null)).thenAnswer((_) async => testChatRoomsPagination);
|
||
|
||
await chatsCubit.getChatRooms();
|
||
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
expect(chatsCubit.state.state, BaseState.success);
|
||
verify(mockChatRepository.getChatRooms(query: null)).called(1);
|
||
});
|
||
|
||
test('getChatRooms - загружает комнаты с запросом', () async {
|
||
const query = 'test query';
|
||
when(mockChatRepository.getChatRooms(query: query)).thenAnswer((_) async => testChatRoomsPagination);
|
||
|
||
await chatsCubit.getChatRooms(query: query);
|
||
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
expect(chatsCubit.state.state, BaseState.success);
|
||
verify(mockChatRepository.getChatRooms(query: query)).called(1);
|
||
});
|
||
|
||
test('loadMoreChatRooms - загружает больше комнат', () async {
|
||
// Create pagination with lastPage > 1 so loadMoreChatRooms doesn't return early
|
||
const paginationPage1 = ChatRoomPaginationModel(
|
||
data: [],
|
||
unreadChatsCount: 0,
|
||
meta: Meta(
|
||
currentPage: 1,
|
||
from: null,
|
||
lastPage: 3, // Set to 3 so we can load more
|
||
links: [],
|
||
perPage: 10,
|
||
to: null,
|
||
total: 30,
|
||
),
|
||
);
|
||
|
||
const paginationPage2 = ChatRoomPaginationModel(
|
||
data: [],
|
||
unreadChatsCount: 0,
|
||
meta: Meta(currentPage: 2, from: null, lastPage: 3, links: [], perPage: 10, to: null, total: 30),
|
||
);
|
||
|
||
when(mockChatRepository.getChatRooms(query: null, page: 1)).thenAnswer((_) async => paginationPage1);
|
||
|
||
// Сначала загружаем первую страницу
|
||
await chatsCubit.getChatRooms();
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
|
||
// Затем загружаем следующую страницу
|
||
when(mockChatRepository.getChatRooms(query: null, page: 2)).thenAnswer((_) async => paginationPage2);
|
||
|
||
await chatsCubit.loadMoreChatRooms();
|
||
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
verify(mockChatRepository.getChatRooms(query: null, page: 2)).called(1);
|
||
});
|
||
|
||
test('loadMoreChatRooms - не загружает если уже загружается', () async {
|
||
when(mockChatRepository.getChatRooms(query: null)).thenAnswer((_) async => testChatRoomsPagination);
|
||
|
||
await chatsCubit.getChatRooms();
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
|
||
// Устанавливаем isLoadingMoreChats в true
|
||
chatsCubit.emit(chatsCubit.state.copyWith(isLoadingMoreChats: true));
|
||
|
||
await chatsCubit.loadMoreChatRooms();
|
||
|
||
// Не должно вызывать репозиторий
|
||
verifyNever(mockChatRepository.getChatRooms(query: null, page: 2));
|
||
});
|
||
|
||
test('reduceUnreadMessagesCount - уменьшает количество непрочитанных сообщений', () {
|
||
const chatId = 'chat-id';
|
||
const count = 2;
|
||
|
||
const chatRoom = ChatRoom(
|
||
id: chatId,
|
||
lastMessage: null,
|
||
users: Users(
|
||
fromChatUser: ChatUser(id: 1, name: 'User 1', profilePhotoPath: null, profilePhotoUrl: ''),
|
||
toChatUser: ChatUser(id: 2, name: 'User 2', profilePhotoPath: null, profilePhotoUrl: ''),
|
||
),
|
||
unreadMessagesCount: 5,
|
||
chosenPlan: null,
|
||
);
|
||
|
||
const pagination = ChatRoomPaginationModel(
|
||
data: [chatRoom],
|
||
unreadChatsCount: 1,
|
||
meta: Meta(currentPage: 1, from: null, lastPage: 1, links: [], perPage: 10, to: null, total: 1),
|
||
);
|
||
|
||
chatsCubit.emit(ChatsState(state: BaseState.success, chatRooms: pagination.data, chatsWithUnreadMessagesCount: 1));
|
||
|
||
chatsCubit.reduceUnreadMessagesCount(chatId: chatId, count: count);
|
||
|
||
final updatedState = chatsCubit.state;
|
||
final updatedRoom = updatedState.chatRooms.firstWhere((r) => r.id == chatId);
|
||
expect(updatedRoom.unreadMessagesCount, 3);
|
||
});
|
||
|
||
test('connectToWebSocket - подключается к WebSocket', () async {
|
||
const mockStream = Stream<ChannelReadEvent>.empty();
|
||
when(mockWsManager.newMessagesStream).thenAnswer((_) => mockStream);
|
||
|
||
await chatsCubit.connectToWebSocket();
|
||
|
||
verify(mockWsManager.newMessagesStream).called(1);
|
||
});
|
||
|
||
test('close - закрывает cubit и отписывается от подписок', () async {
|
||
final mockSubscription1 = MockStreamSubscription();
|
||
|
||
when(mockSubscription1.cancel()).thenAnswer((_) async => Future.value());
|
||
|
||
// Set newIncomingMessagesSubscription
|
||
chatsCubit.newIncomingMessagesSubscription = mockSubscription1;
|
||
|
||
await chatsCubit.close();
|
||
|
||
// Verify that cancel was called on newIncomingMessagesSubscription
|
||
verify(mockSubscription1.cancel()).called(1);
|
||
// newLastMessageSubscription is cancelled in super.close() which we can't easily verify
|
||
// but the test verifies that the method completes without error
|
||
});
|
||
});
|
||
}
|