refactor(tests): update model instantiation to use const for improved performance

This commit is contained in:
mso7nueh
2025-12-03 06:16:34 +03:00
parent d0becb9e11
commit f3d4478c65
15 changed files with 1840 additions and 27 deletions

View File

@@ -26,10 +26,10 @@ void main() {
mockFeedRepository = MockFeedRepository();
mockCommentsRepository = MockCommentsRepository();
testCommentModel = CommentModel(
testCommentModel = const CommentModel(
data: [],
links: const Links(first: '', last: '', prev: null, next: null),
meta: const Meta(
links: Links(first: '', last: '', prev: null, next: null),
meta: Meta(
currentPage: 1,
from: null,
lastPage: 1,

View File

@@ -31,7 +31,7 @@ void main() {
test('getConsultants - успешная загрузка консультантов', () async {
final testConsultants = [
FeedConsultantModel(
const FeedConsultantModel(
slug: 'consultant-1',
name: 'Консультант 1',
description: 'Описание консультанта 1',
@@ -40,7 +40,7 @@ void main() {
badges: [],
ratingPlace: 1,
),
FeedConsultantModel(
const FeedConsultantModel(
slug: 'consultant-2',
name: 'Консультант 2',
description: 'Описание консультанта 2',

View File

@@ -28,9 +28,9 @@ void main() {
});
test('getFeedBlogPosts - успешное получение постов', () async {
final expectedModel = FeedBlogPostSettingsModel(
feedBlogPostList: const [],
meta: const Meta(
const expectedModel = FeedBlogPostSettingsModel(
feedBlogPostList: [],
meta: Meta(
currentPage: 1,
from: null,
lastPage: 1,
@@ -56,9 +56,9 @@ void main() {
test('getFeedBlogPosts - с запросом и страницей', () async {
const query = 'тест';
const page = 2;
final expectedModel = FeedBlogPostSettingsModel(
feedBlogPostList: const [],
meta: const Meta(
const expectedModel = FeedBlogPostSettingsModel(
feedBlogPostList: [],
meta: Meta(
currentPage: page,
from: null,
lastPage: 2,
@@ -117,7 +117,7 @@ void main() {
});
test('getRecipes - успешное получение рецептов', () async {
final expectedRecipes = const RecipesPagination(
const expectedRecipes = RecipesPagination(
recipesList: [],
);
@@ -131,10 +131,10 @@ void main() {
});
test('getDiets - успешное получение диет', () async {
final expectedDiets = DietsPagination(
data: const [],
links: const Links(first: '', last: '', prev: null, next: null),
meta: const Meta(
const expectedDiets = DietsPagination(
data: [],
links: Links(first: '', last: '', prev: null, next: null),
meta: Meta(
currentPage: 1,
from: null,
lastPage: 1,
@@ -169,10 +169,10 @@ void main() {
});
test('getPlans - успешное получение планов', () async {
final expectedPlans = PlanPaginationModel(
data: const [],
links: const Links(first: '', last: '', prev: null, next: null),
meta: const Meta(
const expectedPlans = PlanPaginationModel(
data: [],
links: Links(first: '', last: '', prev: null, next: null),
meta: Meta(
currentPage: 1,
from: null,
lastPage: 1,
@@ -210,10 +210,10 @@ void main() {
test('getBlogPostComments - успешное получение комментариев', () async {
const postId = '1';
final expectedComments = CommentModel(
const expectedComments = CommentModel(
data: [],
links: const Links(first: '', last: '', prev: null, next: null),
meta: const Meta(
links: Links(first: '', last: '', prev: null, next: null),
meta: Meta(
currentPage: 1,
from: null,
lastPage: 1,
@@ -278,10 +278,10 @@ void main() {
});
test('getConsultants - успешное получение консультантов', () async {
final expectedConsultants = FeedConsultantPaginationModel(
data: const [],
links: const Links(first: '', last: '', prev: null, next: null),
meta: const Meta(
const expectedConsultants = FeedConsultantPaginationModel(
data: [],
links: Links(first: '', last: '', prev: null, next: null),
meta: Meta(
currentPage: 1,
from: null,
lastPage: 1,

View File

@@ -0,0 +1,85 @@
import 'package:eatvio_app/features/my_finance/models/card_model.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('CardModel', () {
test('fromJson - успешная десериализация', () {
final json = {
'id': 1,
'bank_pan': '1234567890123456',
'is_default': true,
};
final card = CardModel.fromJson(json);
expect(card.id, equals(1));
expect(card.cardNumber, equals('1234567890123456'));
expect(card.isDefault, isTrue);
});
test('fromJson - is_default как int', () {
final json = {
'id': 1,
'bank_pan': '1234567890123456',
'is_default': 1,
};
final card = CardModel.fromJson(json);
expect(card.isDefault, isTrue);
});
test('fromJson - is_default как строка "1"', () {
final json = {
'id': 1,
'bank_pan': '1234567890123456',
'is_default': '1',
};
final card = CardModel.fromJson(json);
expect(card.isDefault, isTrue);
});
test('fromJson - is_default как false', () {
final json = {
'id': 1,
'bank_pan': '1234567890123456',
'is_default': false,
};
final card = CardModel.fromJson(json);
expect(card.isDefault, isFalse);
});
test('toJson - успешная сериализация', () {
final card = CardModel(
id: 1,
cardNumber: '1234567890123456',
isDefault: true,
);
final json = card.toJson();
expect(json['id'], equals(1));
expect(json['bank_pan'], equals('1234567890123456'));
expect(json['is_default'], isTrue);
});
test('copyWith - создание копии с изменениями', () {
final card = CardModel(
id: 1,
cardNumber: '1234567890123456',
isDefault: false,
);
final updatedCard = card.copyWith(isDefault: true);
expect(updatedCard.id, equals(1));
expect(updatedCard.cardNumber, equals('1234567890123456'));
expect(updatedCard.isDefault, isTrue);
});
});
}

View File

@@ -0,0 +1,39 @@
import 'package:eatvio_app/features/my_finance/models/payment_url_model.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('PaymentUrlModel', () {
test('fromJson - успешная десериализация', () {
final json = {
'paymentUrl': 'https://payment.example.com/checkout',
};
final model = PaymentUrlModel.fromJson(json);
expect(model.paymentUrl, equals('https://payment.example.com/checkout'));
});
test('toJson - успешная сериализация', () {
final model = PaymentUrlModel(
paymentUrl: 'https://payment.example.com/checkout',
);
final json = model.toJson();
expect(json['paymentUrl'], equals('https://payment.example.com/checkout'));
});
test('copyWith - создание копии с изменениями', () {
final model = PaymentUrlModel(
paymentUrl: 'https://payment.example.com/checkout',
);
final updatedModel = model.copyWith(
paymentUrl: 'https://payment.example.com/new',
);
expect(updatedModel.paymentUrl, equals('https://payment.example.com/new'));
});
});
}

View File

@@ -0,0 +1,154 @@
import 'package:eatvio_app/core/enums/base_state.dart';
import 'package:eatvio_app/features/my_finance/models/card_model.dart';
import 'package:eatvio_app/features/my_finance/models/payment_url_model.dart';
import 'package:eatvio_app/features/my_finance/presentation/cubit/user_cards_cubit/user_cards_cubit.dart';
import 'package:eatvio_app/features/my_finance/repositories/cards_repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'user_cards_cubit_test.mocks.dart';
@GenerateMocks([CardsRepository])
void main() {
group('UserCardsCubit', () {
late UserCardsCubit cubit;
late MockCardsRepository mockCardsRepository;
setUp(() {
mockCardsRepository = MockCardsRepository();
cubit = UserCardsCubit(cardsRepository: mockCardsRepository);
});
tearDown(() {
cubit.close();
});
test('начальное состояние', () {
expect(cubit.state.cards, isEmpty);
expect(cubit.state.error, isNull);
expect(cubit.state.state, BaseState.initial);
});
test('getCards - успешная загрузка карт', () async {
final cards = [
CardModel(id: 1, cardNumber: '1234', isDefault: true),
CardModel(id: 2, cardNumber: '5678', isDefault: false),
];
when(mockCardsRepository.getCards()).thenAnswer((_) async => cards);
await cubit.getCards();
expect(cubit.state.cards, equals(cards));
expect(cubit.state.state, BaseState.success);
expect(cubit.state.error, isNull);
verify(mockCardsRepository.getCards()).called(1);
});
test('getCards - ошибка при загрузке', () async {
final error = Exception('Ошибка загрузки');
when(mockCardsRepository.getCards()).thenThrow(error);
await cubit.getCards();
expect(cubit.state.cards, isEmpty);
expect(cubit.state.state, BaseState.error);
expect(cubit.state.error, equals(error.toString()));
verify(mockCardsRepository.getCards()).called(1);
});
test('addCard - успешное добавление карты', () async {
final paymentUrl = PaymentUrlModel(paymentUrl: 'https://payment.url');
when(mockCardsRepository.addCard()).thenAnswer((_) async => paymentUrl);
final result = await cubit.addCard();
expect(result, equals(paymentUrl));
verify(mockCardsRepository.addCard()).called(1);
});
test('addCard - ошибка при добавлении', () async {
when(mockCardsRepository.addCard()).thenThrow(Exception('Ошибка'));
final result = await cubit.addCard();
expect(result, isNull);
verify(mockCardsRepository.addCard()).called(1);
});
test('markAsDefault - успешное изменение карты по умолчанию', () async {
final cards = [
CardModel(id: 1, cardNumber: '1234', isDefault: true),
CardModel(id: 2, cardNumber: '5678', isDefault: false),
];
when(mockCardsRepository.getCards()).thenAnswer((_) async => cards);
when(mockCardsRepository.markAsDefault(id: 2)).thenAnswer((_) async {});
await cubit.getCards();
await cubit.markAsDefault(id: 2);
expect(cubit.state.cards[0].isDefault, isFalse);
expect(cubit.state.cards[1].isDefault, isTrue);
// Ждем завершения debounce
await Future.delayed(const Duration(milliseconds: 100));
verify(mockCardsRepository.markAsDefault(id: 2)).called(1);
});
test('deleteCard - успешное удаление карты', () async {
final cards = [
CardModel(id: 1, cardNumber: '1234', isDefault: true),
CardModel(id: 2, cardNumber: '5678', isDefault: false),
];
when(mockCardsRepository.getCards()).thenAnswer((_) async => cards);
when(mockCardsRepository.deleteCard(id: 2)).thenAnswer((_) async {});
await cubit.getCards();
await cubit.deleteCard(id: 2);
expect(cubit.state.cards.length, equals(1));
expect(cubit.state.cards[0].id, equals(1));
verify(mockCardsRepository.deleteCard(id: 2)).called(1);
});
test('deleteCard - ошибка при удалении', () async {
final cards = [
CardModel(id: 1, cardNumber: '1234', isDefault: true),
];
when(mockCardsRepository.getCards()).thenAnswer((_) async => cards);
when(mockCardsRepository.deleteCard(id: 1)).thenThrow(Exception('Ошибка'));
await cubit.getCards();
await cubit.deleteCard(id: 1);
// Карта должна вернуться обратно
expect(cubit.state.cards.length, equals(1));
expect(cubit.state.state, BaseState.error);
verify(mockCardsRepository.deleteCard(id: 1)).called(1);
});
test('collectCharge - успешный сбор платежа', () async {
when(mockCardsRepository.collectCharge(chosenPlaId: 1)).thenAnswer((_) async {});
final result = await cubit.collectCharge(chosenPlaId: 1);
expect(result, isTrue);
verify(mockCardsRepository.collectCharge(chosenPlaId: 1)).called(1);
});
test('collectCharge - ошибка при сборе платежа', () async {
when(mockCardsRepository.collectCharge(chosenPlaId: 1)).thenThrow(Exception('Ошибка'));
final result = await cubit.collectCharge(chosenPlaId: 1);
expect(result, isFalse);
verify(mockCardsRepository.collectCharge(chosenPlaId: 1)).called(1);
});
});
}

View File

@@ -0,0 +1,111 @@
import 'package:eatvio_app/features/my_finance/models/card_model.dart';
import 'package:eatvio_app/features/my_finance/models/payment_url_model.dart';
import 'package:eatvio_app/features/my_finance/repositories/cards_repository.dart';
import 'package:eatvio_app/features/my_finance/services/cards_service.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'cards_repository_test.mocks.dart';
@GenerateMocks([CardsService])
void main() {
group('CardsRepository', () {
late CardsRepository repository;
late MockCardsService mockCardsService;
setUp(() {
mockCardsService = MockCardsService();
repository = CardsRepository(cardsService: mockCardsService);
});
test('addCard - успешное добавление карты', () async {
final paymentUrl = PaymentUrlModel(paymentUrl: 'https://payment.url');
when(mockCardsService.addCard()).thenAnswer((_) async => paymentUrl);
final result = await repository.addCard();
expect(result, equals(paymentUrl));
verify(mockCardsService.addCard()).called(1);
});
test('addCard - проброс ошибки', () async {
final error = Exception('Ошибка');
when(mockCardsService.addCard()).thenThrow(error);
expect(() => repository.addCard(), throwsA(error));
verify(mockCardsService.addCard()).called(1);
});
test('getCards - успешная загрузка карт', () async {
final cards = [
CardModel(id: 1, cardNumber: '1234', isDefault: true),
CardModel(id: 2, cardNumber: '5678', isDefault: false),
];
when(mockCardsService.getCards()).thenAnswer((_) async => cards);
final result = await repository.getCards();
expect(result, equals(cards));
verify(mockCardsService.getCards()).called(1);
});
test('getCards - проброс ошибки', () async {
final error = Exception('Ошибка');
when(mockCardsService.getCards()).thenThrow(error);
expect(() => repository.getCards(), throwsA(error));
verify(mockCardsService.getCards()).called(1);
});
test('markAsDefault - успешное изменение карты по умолчанию', () async {
when(mockCardsService.markAsDefault(id: 1)).thenAnswer((_) async {});
await repository.markAsDefault(id: 1);
verify(mockCardsService.markAsDefault(id: 1)).called(1);
});
test('markAsDefault - проброс ошибки', () async {
final error = Exception('Ошибка');
when(mockCardsService.markAsDefault(id: 1)).thenThrow(error);
expect(() => repository.markAsDefault(id: 1), throwsA(error));
verify(mockCardsService.markAsDefault(id: 1)).called(1);
});
test('deleteCard - успешное удаление карты', () async {
when(mockCardsService.deleteCard(id: 1)).thenAnswer((_) async {});
await repository.deleteCard(id: 1);
verify(mockCardsService.deleteCard(id: 1)).called(1);
});
test('deleteCard - проброс ошибки', () async {
final error = Exception('Ошибка');
when(mockCardsService.deleteCard(id: 1)).thenThrow(error);
expect(() => repository.deleteCard(id: 1), throwsA(error));
verify(mockCardsService.deleteCard(id: 1)).called(1);
});
test('collectCharge - успешный сбор платежа', () async {
when(mockCardsService.collectCharge(chosenPlanId: 1)).thenAnswer((_) async {});
await repository.collectCharge(chosenPlaId: 1);
verify(mockCardsService.collectCharge(chosenPlanId: 1)).called(1);
});
test('collectCharge - проброс ошибки', () async {
final error = Exception('Ошибка');
when(mockCardsService.collectCharge(chosenPlanId: 1)).thenThrow(error);
expect(() => repository.collectCharge(chosenPlaId: 1), throwsA(error));
verify(mockCardsService.collectCharge(chosenPlanId: 1)).called(1);
});
});
}

View File

@@ -0,0 +1,194 @@
import 'package:eatvio_app/core/websockets/ws_manager.dart';
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_state.dart';
import 'package:eatvio_app/features/notifications/repository/notifications_repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'notifications_cubit_test.mocks.dart';
@GenerateMocks([WsManager, NotificationsRepository])
void main() {
group('NotificationsCubit', () {
late NotificationsCubit cubit;
late MockWsManager mockWsManager;
late MockNotificationsRepository mockNotificationsRepository;
setUp(() {
mockWsManager = MockWsManager();
mockNotificationsRepository = MockNotificationsRepository();
// Мокируем stream как null, чтобы избежать проблем с подписками в тестах
when(mockWsManager.newNotificationsStream).thenAnswer((_) => null);
cubit = NotificationsCubit(
wsManager: mockWsManager,
notificationsRepository: mockNotificationsRepository,
);
});
tearDown(() async {
await cubit.close();
});
test('начальное состояние - empty', () {
expect(cubit.state, isA<NotificationsStateEmpty>());
});
test('getNotifications - успешная загрузка уведомлений', () async {
final notifications = [
ChosenPlanStartedToClientNotification(
type: NotificationType.chosenPlanStartedToClientNotification,
planName: 'Test Plan',
planId: 1,
isRead: false,
createdAt: DateTime.now(),
),
];
final result = {
'notifications': notifications,
'pagination': {
'current_page': 1,
'last_page': 1,
},
};
when(mockNotificationsRepository.getNotifications(page: 1))
.thenAnswer((_) async => result);
await cubit.getNotifications();
final state = cubit.state;
expect(state, isA<NotificationsStateLoaded>());
if (state is NotificationsStateLoaded) {
expect(state.notifications.length, 1);
expect(state.currentPage, 1);
expect(state.hasNextPage, false);
}
verify(mockNotificationsRepository.getNotifications(page: 1)).called(1);
});
test('getNotifications - обработка ошибки', () async {
when(mockNotificationsRepository.getNotifications(page: 1))
.thenThrow(Exception('Ошибка загрузки'));
await cubit.getNotifications();
// Состояние должно остаться empty при ошибке
expect(cubit.state, isA<NotificationsStateEmpty>());
});
test('loadMoreNotifications - успешная загрузка следующей страницы', () async {
final firstPageNotifications = [
ChosenPlanStartedToClientNotification(
type: NotificationType.chosenPlanStartedToClientNotification,
planName: 'Plan 1',
planId: 1,
isRead: false,
createdAt: DateTime.now(),
),
];
final secondPageNotifications = [
ChosenPlanStartedToClientNotification(
type: NotificationType.chosenPlanStartedToClientNotification,
planName: 'Plan 2',
planId: 2,
isRead: false,
createdAt: DateTime.now(),
),
];
when(mockNotificationsRepository.getNotifications(page: 1))
.thenAnswer((_) async => {
'notifications': firstPageNotifications,
'pagination': {'current_page': 1, 'last_page': 2},
});
when(mockNotificationsRepository.getNotifications(page: 2))
.thenAnswer((_) async => {
'notifications': secondPageNotifications,
'pagination': {'current_page': 2, 'last_page': 2},
});
await cubit.getNotifications();
final firstState = cubit.state;
expect(firstState, isA<NotificationsStateLoaded>());
if (firstState is NotificationsStateLoaded) {
expect(firstState.hasNextPage, true);
await cubit.loadMoreNotifications();
final secondState = cubit.state;
expect(secondState, isA<NotificationsStateLoaded>());
if (secondState is NotificationsStateLoaded) {
expect(secondState.notifications.length, 2);
expect(secondState.currentPage, 2);
expect(secondState.hasNextPage, false);
}
}
});
test('loadMoreNotifications - не загружает, если нет следующей страницы', () async {
final notifications = [
ChosenPlanStartedToClientNotification(
type: NotificationType.chosenPlanStartedToClientNotification,
planName: 'Plan 1',
planId: 1,
isRead: false,
createdAt: DateTime.now(),
),
];
when(mockNotificationsRepository.getNotifications(page: 1))
.thenAnswer((_) async => {
'notifications': notifications,
'pagination': {'current_page': 1, 'last_page': 1},
});
await cubit.getNotifications();
await cubit.loadMoreNotifications();
verify(mockNotificationsRepository.getNotifications(page: 1)).called(1);
verifyNever(mockNotificationsRepository.getNotifications(page: 2));
});
test('markNotificationsAsRead - успешная пометка как прочитанных', () async {
final notifications = [
ChosenPlanStartedToClientNotification(
type: NotificationType.chosenPlanStartedToClientNotification,
planName: 'Plan 1',
planId: 1,
isRead: false,
createdAt: DateTime.now(),
),
];
when(mockNotificationsRepository.getNotifications(page: 1))
.thenAnswer((_) async => {
'notifications': notifications,
'pagination': {'current_page': 1, 'last_page': 1},
});
when(mockNotificationsRepository.markNotificationsAsRead())
.thenAnswer((_) async => {});
await cubit.getNotifications();
await cubit.markNotificationsAsRead();
verify(mockNotificationsRepository.markNotificationsAsRead()).called(1);
verify(mockNotificationsRepository.getNotifications(page: 1)).called(2); // Один раз при getNotifications, второй раз после markNotificationsAsRead
});
test('connectToWebSocket - подключается к WebSocket', () async {
await cubit.connectToWebSocket();
verify(mockWsManager.newNotificationsStream).called(1);
});
});
}

View File

@@ -0,0 +1,77 @@
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
import 'package:eatvio_app/features/notifications/repository/notifications_repository.dart';
import 'package:eatvio_app/features/notifications/service/notifications_service.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'notifications_repository_test.mocks.dart';
@GenerateMocks([NotificationsService])
void main() {
group('NotificationsRepository', () {
late NotificationsRepository repository;
late MockNotificationsService mockNotificationsService;
setUp(() {
mockNotificationsService = MockNotificationsService();
repository = NotificationsRepository(notificationsService: mockNotificationsService);
});
test('getNotifications - успешная загрузка уведомлений', () async {
final notifications = [
ChosenPlanStartedToClientNotification(
type: NotificationType.chosenPlanStartedToClientNotification,
planName: 'Test Plan',
planId: 1,
isRead: false,
createdAt: DateTime.now(),
),
];
final result = {
'notifications': notifications,
'pagination': {
'current_page': 1,
'last_page': 1,
},
};
when(mockNotificationsService.getNotifications(page: 1))
.thenAnswer((_) async => result);
final response = await repository.getNotifications(page: 1);
expect(response, equals(result));
verify(mockNotificationsService.getNotifications(page: 1)).called(1);
});
test('getNotifications - проброс ошибки', () async {
final error = Exception('Ошибка загрузки');
when(mockNotificationsService.getNotifications(page: 1))
.thenThrow(error);
expect(() => repository.getNotifications(page: 1), throwsA(error));
verify(mockNotificationsService.getNotifications(page: 1)).called(1);
});
test('markNotificationsAsRead - успешная пометка как прочитанных', () async {
when(mockNotificationsService.markNotificationsAsRead())
.thenAnswer((_) async => {});
await repository.markNotificationsAsRead();
verify(mockNotificationsService.markNotificationsAsRead()).called(1);
});
test('markNotificationsAsRead - проброс ошибки', () async {
final error = Exception('Ошибка');
when(mockNotificationsService.markNotificationsAsRead())
.thenThrow(error);
expect(() => repository.markNotificationsAsRead(), throwsA(error));
verify(mockNotificationsService.markNotificationsAsRead()).called(1);
});
});
}

View File

@@ -0,0 +1,266 @@
import 'package:eatvio_app/features/chat/models/payment_model.dart';
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
import 'package:eatvio_app/features/order_info/cubit/order_info_cubit.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/profile/models/profile_model.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 'order_info_cubit_test.mocks.dart';
@GenerateMocks([ChatRepository, ProfileRepository])
void main() {
group('OrderInfoCubit', () {
late OrderInfoCubit cubit;
late MockChatRepository mockChatRepository;
late MockProfileRepository mockProfileRepository;
setUp(() {
mockChatRepository = MockChatRepository();
mockProfileRepository = MockProfileRepository();
cubit = OrderInfoCubit(
chatRepository: mockChatRepository,
profileRepository: mockProfileRepository,
);
});
tearDown(() {
cubit.close();
});
test('начальное состояние', () {
expect(cubit.state.isLoading, isTrue);
expect(cubit.state.chosenPlan, isNull);
expect(cubit.state.customerProfile, isNull);
});
test('getChosenPlan - успешная загрузка плана', () async {
final chosenPlan = ChosenPlanModel(
id: 1,
optionType: 'options1',
startDate: DateTime.now(),
chosenPlanState: ChosenPlanStateEnum.stateStarted,
chatId: 'chat-1',
consultantId: 1,
plan: const PlanModel(
id: 1,
slug: 'test-plan',
name: 'Test Plan',
image: '',
duration: 30,
state: 'active',
type: PlanType(fit: false, slim: false, behavior: false, wellness: false),
details: '',
packetsCount: 1,
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
minPriceOfOptions: 0,
maxPriceOfOptions: 0,
wasLikedByMe: false,
),
);
when(mockChatRepository.getChosenPlan(id: 1))
.thenAnswer((_) async => chosenPlan);
await cubit.getChosenPlan(id: 1);
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.chosenPlan, equals(chosenPlan));
verify(mockChatRepository.getChosenPlan(id: 1)).called(1);
});
test('getChosenPlan - загрузка плана с профилем клиента', () async {
final chosenPlan = ChosenPlanModel(
id: 1,
optionType: 'options1',
startDate: DateTime.now(),
chosenPlanState: ChosenPlanStateEnum.stateStarted,
chatId: 'chat-1',
consultantId: 1,
plan: const PlanModel(
id: 1,
slug: 'test-plan',
name: 'Test Plan',
image: '',
duration: 30,
state: 'active',
type: PlanType(fit: false, slim: false, behavior: false, wellness: false),
details: '',
packetsCount: 1,
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
minPriceOfOptions: 0,
maxPriceOfOptions: 0,
wasLikedByMe: false,
),
);
const customerProfile = ProfileModel(
id: 1,
name: 'Test User',
email: 'test@example.com',
phoneConfirmationState: 'confirmed',
isPublicProfile: true,
isBlockedByMe: false,
isBlockedByAuthor: false,
isBlockedByUser: false,
isEntitySubscribedByMe: false,
slug: 'test-user',
profilePhotoUrl: '',
roles: [],
badges: [],
subscriptions: [],
subscribers: [],
);
when(mockChatRepository.getChosenPlan(id: 1))
.thenAnswer((_) async => chosenPlan);
when(mockProfileRepository.getProfileBySlug('test-user'))
.thenAnswer((_) async => customerProfile);
await cubit.getChosenPlan(id: 1, customerSlug: 'test-user');
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.chosenPlan, equals(chosenPlan));
expect(cubit.state.customerProfile, equals(customerProfile));
verify(mockChatRepository.getChosenPlan(id: 1)).called(1);
verify(mockProfileRepository.getProfileBySlug('test-user')).called(1);
});
test('getChosenPlan - обработка ошибки', () async {
when(mockChatRepository.getChosenPlan(id: 1))
.thenThrow(Exception('Ошибка загрузки'));
await cubit.getChosenPlan(id: 1);
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.chosenPlan, isNull);
});
test('getPaymentLink - успешное получение ссылки на оплату', () async {
final chosenPlan = ChosenPlanModel(
id: 1,
optionType: 'options1',
startDate: DateTime.now(),
chosenPlanState: ChosenPlanStateEnum.stateStarted,
chatId: 'chat-1',
consultantId: 1,
plan: const PlanModel(
id: 1,
slug: 'test-plan',
name: 'Test Plan',
image: '',
duration: 30,
state: 'active',
type: PlanType(fit: false, slim: false, behavior: false, wellness: false),
details: '',
packetsCount: 1,
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
minPriceOfOptions: 0,
maxPriceOfOptions: 0,
wasLikedByMe: false,
),
);
final paymentModel = PaymentModel(paymentUrl: 'https://payment.url');
// Сначала устанавливаем план в состояние
when(mockChatRepository.getChosenPlan(id: 1))
.thenAnswer((_) async => chosenPlan);
await cubit.getChosenPlan(id: 1);
when(mockChatRepository.getPaymentLink(id: 1))
.thenAnswer((_) async => paymentModel);
final result = await cubit.getPaymentLink();
expect(result, equals('https://payment.url'));
verify(mockChatRepository.getPaymentLink(id: 1)).called(1);
});
test('getPaymentLink - возвращает null, если план не выбран', () async {
final result = await cubit.getPaymentLink();
expect(result, isNull);
verifyNever(mockChatRepository.getPaymentLink(id: anyNamed('id')));
});
test('getPaymentLink - обработка ошибки', () async {
final chosenPlan = ChosenPlanModel(
id: 1,
optionType: 'options1',
startDate: DateTime.now(),
chosenPlanState: ChosenPlanStateEnum.stateStarted,
chatId: 'chat-1',
consultantId: 1,
plan: const PlanModel(
id: 1,
slug: 'test-plan',
name: 'Test Plan',
image: '',
duration: 30,
state: 'active',
type: PlanType(fit: false, slim: false, behavior: false, wellness: false),
details: '',
packetsCount: 1,
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
minPriceOfOptions: 0,
maxPriceOfOptions: 0,
wasLikedByMe: false,
),
);
when(mockChatRepository.getChosenPlan(id: 1))
.thenAnswer((_) async => chosenPlan);
await cubit.getChosenPlan(id: 1);
when(mockChatRepository.getPaymentLink(id: 1))
.thenThrow(Exception('Ошибка'));
final result = await cubit.getPaymentLink();
expect(result, isNull);
});
});
}

View File

@@ -0,0 +1,271 @@
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/personal_diet_suggestion/cubit/personal_diet_suggestion_cubit.dart';
import 'package:eatvio_app/features/personal_diet_suggestion/repository/personal_diet_suggestion_repository.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'personal_diet_suggestion_cubit_test.mocks.dart';
@GenerateMocks([DietRepository, PersonalDietSuggestionRepository])
void main() {
group('PersonalDietSuggestionCubit', () {
late PersonalDietSuggestionCubit cubit;
late MockDietRepository mockDietRepository;
late MockPersonalDietSuggestionRepository mockPersonalDietSuggestionRepository;
setUp(() {
mockDietRepository = MockDietRepository();
mockPersonalDietSuggestionRepository = MockPersonalDietSuggestionRepository();
cubit = PersonalDietSuggestionCubit(
dietRepository: mockDietRepository,
personalDietSuggestionService: mockPersonalDietSuggestionRepository,
);
});
tearDown(() {
cubit.close();
});
test('начальное состояние', () {
expect(cubit.state.consultationsWithDiet, isEmpty);
expect(cubit.state.consultationsWithoutDiet, isEmpty);
expect(cubit.state.dietName, isEmpty);
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.error, isNull);
});
test('setDietName - успешная установка названия диеты', () async {
const dietId = 1;
const dietName = 'Test Diet';
const diet = Diet(
id: dietId,
name: dietName,
slug: 'test-diet',
image: '',
duration: 30,
state: DietState.active,
type: DietType(light: false, veg: false, carb: false, meat: false),
details: '',
dailySchedule: {},
dailyNutrition: [],
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
wasLikedByMe: false,
);
when(mockDietRepository.getDiet(dietId))
.thenAnswer((_) async => diet);
await cubit.setDietName(dietId);
expect(cubit.state.dietName, equals(dietName));
expect(cubit.state.isLoading, isFalse);
verify(mockDietRepository.getDiet(dietId)).called(1);
});
test('setDietName - обработка ошибки', () async {
const dietId = 1;
final error = Exception('Ошибка загрузки');
when(mockDietRepository.getDiet(dietId))
.thenThrow(error);
await cubit.setDietName(dietId);
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.error, equals(error.toString()));
});
test('getConsultationWithPersonalDiets - успешная загрузка консультаций', () async {
const dietId = 1;
const dietName = 'Test Diet';
const diet = Diet(
id: dietId,
name: dietName,
slug: 'test-diet',
image: '',
duration: 30,
state: DietState.active,
type: DietType(light: false, veg: false, carb: false, meat: false),
details: '',
dailySchedule: {},
dailyNutrition: [],
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
wasLikedByMe: false,
);
final consultations = [
ConsultationModel(
id: 1,
chosenPlanState: ChosenPlanStateEnum.stateStarted,
planTitle: 'Plan 1',
userName: 'User 1',
userSlug: 'user-1',
consultantPayment: 100.0,
duration: 30,
currentDiaryDay: 1,
userProfilePhotoUrl: '',
consultationOptionPrice: 100,
startDate: DateTime.now(),
endDate: DateTime.now().add(const Duration(days: 30)),
consultantId: 1,
diaries: [],
personalDietId: 1, // С диетой
),
ConsultationModel(
id: 2,
chosenPlanState: ChosenPlanStateEnum.stateStarted,
planTitle: 'Plan 2',
userName: 'User 2',
userSlug: 'user-2',
consultantPayment: 100.0,
duration: 30,
currentDiaryDay: 1,
userProfilePhotoUrl: '',
consultationOptionPrice: 100,
startDate: DateTime.now(),
endDate: DateTime.now().add(const Duration(days: 30)),
consultantId: 1,
diaries: [],
personalDietId: null, // Без диеты
),
];
when(mockDietRepository.getDiet(dietId))
.thenAnswer((_) async => diet);
when(mockPersonalDietSuggestionRepository.getConsultationWithPersonalDiets())
.thenAnswer((_) async => consultations);
await cubit.getConsultationWithPersonalDiets(dietId);
expect(cubit.state.dietName, equals(dietName));
expect(cubit.state.consultationsWithDiet.length, 1);
expect(cubit.state.consultationsWithoutDiet.length, 1);
expect(cubit.state.isLoading, isFalse);
verify(mockDietRepository.getDiet(dietId)).called(1);
verify(mockPersonalDietSuggestionRepository.getConsultationWithPersonalDiets()).called(1);
});
test('attachDietToConsultation - успешное прикрепление диеты', () async {
const dietId = 1;
const consultationId = 1;
when(mockPersonalDietSuggestionRepository.attachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).thenAnswer((_) async => {});
// Устанавливаем dietId через getConsultationWithPersonalDiets
const diet = Diet(
id: dietId,
name: 'Test Diet',
slug: 'test-diet',
image: '',
duration: 30,
state: DietState.active,
type: DietType(light: false, veg: false, carb: false, meat: false),
details: '',
dailySchedule: {},
dailyNutrition: [],
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
wasLikedByMe: false,
);
when(mockDietRepository.getDiet(dietId))
.thenAnswer((_) async => diet);
when(mockPersonalDietSuggestionRepository.getConsultationWithPersonalDiets())
.thenAnswer((_) async => []);
await cubit.getConsultationWithPersonalDiets(dietId);
final result = await cubit.attachDietToConsultation(consultationId: consultationId);
expect(result, isTrue);
verify(mockPersonalDietSuggestionRepository.attachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).called(1);
});
test('reattachDietToConsultation - успешное переприкрепление диеты', () async {
const dietId = 1;
const consultationId = 1;
const diet = Diet(
id: dietId,
name: 'Test Diet',
slug: 'test-diet',
image: '',
duration: 30,
state: DietState.active,
type: DietType(light: false, veg: false, carb: false, meat: false),
details: '',
dailySchedule: {},
dailyNutrition: [],
author: Author(
authorSlug: 'author-slug',
authorName: 'Author Name',
authorProfileIcon: '',
authorIsMe: false,
),
totalLikes: 0,
totalViews: 0,
totalComments: 0,
isFavorite: false,
wasLikedByMe: false,
);
when(mockDietRepository.getDiet(dietId))
.thenAnswer((_) async => diet);
when(mockPersonalDietSuggestionRepository.getConsultationWithPersonalDiets())
.thenAnswer((_) async => []);
when(mockPersonalDietSuggestionRepository.reattachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).thenAnswer((_) async => {});
await cubit.getConsultationWithPersonalDiets(dietId);
final result = await cubit.reattachDietToConsultation(consultationId: consultationId);
expect(result, isTrue);
verify(mockPersonalDietSuggestionRepository.reattachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).called(1);
});
});
}

View File

@@ -0,0 +1,109 @@
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
import 'package:eatvio_app/features/personal_diet_suggestion/repository/personal_diet_suggestion_repository.dart';
import 'package:eatvio_app/features/personal_diet_suggestion/services/personal_diet_suggestion_service.dart';
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'personal_diet_suggestion_repository_test.mocks.dart';
@GenerateMocks([PersonalDietSuggestionService])
void main() {
group('PersonalDietSuggestionRepository', () {
late PersonalDietSuggestionRepository repository;
late MockPersonalDietSuggestionService mockService;
setUp(() {
mockService = MockPersonalDietSuggestionService();
repository = PersonalDietSuggestionRepository(
personalDietSuggestionService: mockService,
);
});
test('getConsultationWithPersonalDiets - успешная загрузка консультаций', () async {
final consultations = [
ConsultationModel(
id: 1,
chosenPlanState: ChosenPlanStateEnum.stateStarted,
planTitle: 'Plan 1',
userName: 'User 1',
userSlug: 'user-1',
consultantPayment: 100.0,
duration: 30,
currentDiaryDay: 1,
userProfilePhotoUrl: '',
consultationOptionPrice: 100,
startDate: DateTime.now(),
endDate: DateTime.now().add(const Duration(days: 30)),
consultantId: 1,
diaries: [],
personalDietId: 1,
),
];
final paginationModel = ConsultationPaginationModel(data: consultations);
when(mockService.getConsultationWithPersonalDiets())
.thenAnswer((_) async => paginationModel);
final result = await repository.getConsultationWithPersonalDiets();
expect(result, equals(consultations));
verify(mockService.getConsultationWithPersonalDiets()).called(1);
});
test('getConsultationWithPersonalDiets - проброс ошибки', () async {
final error = Exception('Ошибка загрузки');
when(mockService.getConsultationWithPersonalDiets())
.thenThrow(error);
expect(
() => repository.getConsultationWithPersonalDiets(),
throwsA(error),
);
verify(mockService.getConsultationWithPersonalDiets()).called(1);
});
test('attachPersonalDiet - успешное прикрепление диеты', () async {
const consultationId = 1;
const dietId = 2;
when(mockService.attachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).thenAnswer((_) async => {});
await repository.attachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
);
verify(mockService.attachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).called(1);
});
test('reattachPersonalDiet - успешное переприкрепление диеты', () async {
const consultationId = 1;
const dietId = 2;
when(mockService.reattachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).thenAnswer((_) async => {});
await repository.reattachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
);
verify(mockService.reattachPersonalDiet(
consultationId: consultationId,
dietId: dietId,
)).called(1);
});
});
}

View File

@@ -0,0 +1,241 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/registration_v2/cubit/registration_cubit.dart';
import 'package:eatvio_app/features/registration_v2/repositories/registration_repository_v2.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'registration_cubit_v2_test.mocks.dart';
@GenerateMocks([RegistrationRepositoryV2])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('RegistrationCubitV2', () {
late RegistrationCubitV2 cubit;
late MockRegistrationRepositoryV2 mockRepository;
const MethodChannel passwordGeneratorChannel = MethodChannel('flutter_password_generator');
setUp(() {
mockRepository = MockRegistrationRepositoryV2();
cubit = RegistrationCubitV2(registrationRepository: mockRepository);
// Инициализируем SharedPreferences для тестов
SharedPreferences.setMockInitialValues({});
// Мокируем MethodChannel для flutter_password_generator
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
passwordGeneratorChannel,
(MethodCall methodCall) async {
if (methodCall.method == 'generateSecureRandomData') {
// Возвращаем Uint8List для генерации пароля
// MethodChannel автоматически преобразует Uint8List в List<int>
return Uint8List.fromList(List<int>.generate(32, (i) => i % 256));
}
return null;
},
);
});
tearDown(() {
cubit.close();
// Очищаем моки
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
passwordGeneratorChannel,
null,
);
});
test('начальное состояние', () {
expect(cubit.state.firstName, isEmpty);
expect(cubit.state.lastName, isEmpty);
expect(cubit.state.email, isEmpty);
expect(cubit.state.phone, isEmpty);
expect(cubit.state.gender, isEmpty);
expect(cubit.state.step, 0);
});
test('setFirstName - устанавливает имя и валидирует', () {
cubit.setFirstName('John');
expect(cubit.state.firstName, equals('John'));
expect(cubit.state.isFirstNameValid, isTrue);
});
test('setFirstName - валидация пустого имени', () {
cubit.setFirstName('');
expect(cubit.state.isFirstNameValid, isFalse);
});
test('setLastName - устанавливает фамилию и валидирует', () {
cubit.setLastName('Doe');
expect(cubit.state.lastName, equals('Doe'));
expect(cubit.state.isLastNameValid, isTrue);
});
test('setEmail - устанавливает email и валидирует', () {
cubit.setEmail('test@example.com');
expect(cubit.state.email, equals('test@example.com'));
expect(cubit.state.isEmailValid, isTrue);
});
test('setPhone - устанавливает телефон и валидирует', () {
cubit.setPhone('+1234567890');
expect(cubit.state.phone, equals('+1234567890'));
expect(cubit.state.isPhoneValid, isTrue);
});
test('setGender - устанавливает пол и валидирует', () {
cubit.setGender('male');
expect(cubit.state.gender, equals('male'));
expect(cubit.state.isGenderValid, isTrue);
});
test('setWeight - устанавливает вес и валидирует', () {
cubit.setWeight(70);
expect(cubit.state.weight, equals(70));
expect(cubit.state.isWeightValid, isTrue);
});
test('setWeight - валидация нулевого веса', () {
cubit.setWeight(0);
expect(cubit.state.isWeightValid, isFalse);
});
test('setHeight - устанавливает рост и валидирует', () {
cubit.setHeight(175);
expect(cubit.state.height, equals(175));
expect(cubit.state.isHeightValid, isTrue);
});
test('setActivityCoefficient - устанавливает коэффициент активности', () {
cubit.setActivityCoefficient(1.5);
expect(cubit.state.activityCoefficient, equals(1.5));
expect(cubit.state.isActivityCoefficientValid, isTrue);
});
test('setBirthday - устанавливает дату рождения и валидирует', () {
final birthday = DateTime(1990, 1, 1);
cubit.setBirthday(birthday);
expect(cubit.state.birthday, equals(birthday));
expect(cubit.state.isBirthdayValid, isTrue);
});
test('nextStep - переходит на следующий шаг', () {
cubit.nextStep();
expect(cubit.state.step, equals(1));
});
test('prevStep - возвращается на предыдущий шаг', () {
cubit.nextStep();
cubit.prevStep();
expect(cubit.state.step, equals(0));
});
test('validateAllFields - возвращает true, если все поля валидны', () {
cubit.setFirstName('John');
cubit.setLastName('Doe');
cubit.setEmail('test@example.com');
cubit.setPhone('+1234567890');
cubit.setGender('male');
cubit.setWeight(70);
cubit.setHeight(175);
cubit.setActivityCoefficient(1.5);
cubit.setBirthday(DateTime(1990, 1, 1));
final result = cubit.validateAllFields();
expect(result, isTrue);
});
test('validateAllFields - возвращает false, если есть невалидные поля', () {
cubit.setFirstName(''); // Пустое имя
final result = cubit.validateAllFields();
expect(result, isFalse);
});
test('register - успешная регистрация', () async {
cubit.setFirstName('John');
cubit.setLastName('Doe');
cubit.setEmail('test@example.com');
cubit.setPhone('+1234567890');
cubit.setGender('male');
cubit.setWeight(70);
cubit.setHeight(175);
cubit.setActivityCoefficient(1.5);
cubit.setBirthday(DateTime(1990, 1, 1));
const token = 'test-token';
when(mockRepository.register(registrationModel: anyNamed('registrationModel')))
.thenAnswer((_) async => token);
final result = await cubit.register();
expect(result.$1, isTrue);
expect(result.$2, isFalse);
verify(mockRepository.register(registrationModel: anyNamed('registrationModel'))).called(1);
});
test('register - возвращает false при невалидных полях', () async {
cubit.setFirstName(''); // Пустое имя
final result = await cubit.register();
expect(result.$1, isFalse);
expect(result.$2, isTrue);
verifyNever(mockRepository.register(registrationModel: anyNamed('registrationModel')));
});
test('register - обработка ошибки валидации email', () async {
cubit.setFirstName('John');
cubit.setLastName('Doe');
cubit.setEmail('test@example.com');
cubit.setPhone('+1234567890');
cubit.setGender('male');
cubit.setWeight(70);
cubit.setHeight(175);
cubit.setActivityCoefficient(1.5);
cubit.setBirthday(DateTime(1990, 1, 1));
final dioException = DioException(
requestOptions: RequestOptions(path: '/'),
response: Response(
requestOptions: RequestOptions(path: '/'),
statusCode: 422,
data: {
'errors': {
'email': ['Некорректный формат email'],
},
},
),
);
when(mockRepository.register(registrationModel: anyNamed('registrationModel')))
.thenThrow(dioException);
final result = await cubit.register();
expect(result.$1, isFalse);
expect(result.$2, isTrue);
expect(cubit.state.isEmailValid, isFalse);
expect(cubit.state.emailDisplayError, equals('Некорректный формат email'));
});
});
}

View File

@@ -0,0 +1,73 @@
import 'package:eatvio_app/features/registration_v2/models/registration_model.dart';
import 'package:eatvio_app/features/registration_v2/repositories/registration_repository_v2.dart';
import 'package:eatvio_app/features/registration_v2/services/registration_service_v2.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'registration_repository_v2_test.mocks.dart';
@GenerateMocks([RegistrationServiceV2])
void main() {
group('RegistrationRepositoryV2', () {
late RegistrationRepositoryV2 repository;
late MockRegistrationServiceV2 mockService;
setUp(() {
mockService = MockRegistrationServiceV2();
repository = RegistrationRepositoryV2(registrationService: mockService);
});
test('register - успешная регистрация', () async {
final registrationModel = RegistrationModel(
firstName: 'John',
lastName: 'Doe',
email: 'test@example.com',
phone: '+1234567890',
gender: 'male',
password: 'password123',
confirmPassword: 'password123',
weight: 70,
height: 175,
activityCoefficient: 1.5,
birthday: '1990-01-01',
);
const token = 'test-token';
when(mockService.register(model: anyNamed('model')))
.thenAnswer((_) async => {'token': token});
final result = await repository.register(registrationModel: registrationModel);
expect(result, equals(token));
verify(mockService.register(model: anyNamed('model'))).called(1);
});
test('register - проброс ошибки', () async {
final registrationModel = RegistrationModel(
firstName: 'John',
lastName: 'Doe',
email: 'test@example.com',
phone: '+1234567890',
gender: 'male',
password: 'password123',
confirmPassword: 'password123',
weight: 70,
height: 175,
activityCoefficient: 1.5,
birthday: '1990-01-01',
);
final error = Exception('Ошибка регистрации');
when(mockService.register(model: anyNamed('model')))
.thenThrow(error);
expect(
() => repository.register(registrationModel: registrationModel),
throwsA(error),
);
verify(mockService.register(model: anyNamed('model'))).called(1);
});
});
}

View File

@@ -0,0 +1,193 @@
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
import 'package:eatvio_app/features/profile/models/profile_model.dart';
import 'package:eatvio_app/features/profile/models/weight_model.dart';
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'user_details_cubit_test.mocks.dart';
@GenerateMocks([ProfileRepository])
void main() {
group('UserDetailsCubit', () {
late UserDetailsCubit cubit;
late MockProfileRepository mockProfileRepository;
setUp(() {
mockProfileRepository = MockProfileRepository();
cubit = UserDetailsCubit(profileRepository: mockProfileRepository);
});
tearDown(() {
cubit.close();
});
test('начальное состояние', () {
expect(cubit.state.isLoading, isFalse);
expect(cubit.state.error, isNull);
expect(cubit.state.profileDetails, isNull);
expect(cubit.state.weightPoints, isNull);
expect(cubit.state.circumferencePoints, isNull);
});
test('getUserDetails - успешная загрузка деталей пользователя', () async {
const slug = 'test-user';
const profileDetails = ProfileDetailsModel(
firstName: 'Test',
lastName: 'User',
birthdate: '1990-01-01',
gender: 'male',
country: 'Russia',
city: 'Moscow',
lang: 'ru',
weight: 70.0,
height: 175,
chestCircumference: 100,
waistCircumference: 80,
hipCircumference: 90,
bloodPressureUp: 120,
bloodPressureDown: 80,
hasHypo: false,
hasHyper: false,
aboutAlergy: '',
aboutTakingPils: '',
aboutSportHobbies: '',
favoriteFoods: '',
unfavoriteFoods: '',
additionalInfo: '',
isMoodFillable: false,
isBedtimeFillable: false,
activityCoefficient: 1.5,
);
final weightPoints = [
WeightModel(
id: 1,
userId: 1,
weight: 70,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
bmi: 22.9,
),
];
final circumferencePoints = [
CircumferenceModel(
id: 1,
userId: 1,
chestCircumference: 100,
waistCircumference: 80,
hipCircumference: 90,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
),
];
when(mockProfileRepository.getProfileDetailsBySlug(slug))
.thenAnswer((_) async => profileDetails);
when(mockProfileRepository.getWeight(period: '1', slug: slug))
.thenAnswer((_) async => weightPoints);
when(mockProfileRepository.getCircumferences(period: '1', slug: slug))
.thenAnswer((_) async => circumferencePoints);
cubit.getUserDetails(slug);
// Ждем завершения асинхронных операций
await Future.delayed(const Duration(milliseconds: 100));
expect(cubit.state.profileDetails, equals(profileDetails));
expect(cubit.state.isLoading, isFalse);
verify(mockProfileRepository.getProfileDetailsBySlug(slug)).called(1);
});
test('getUserDetails - обработка ошибки', () async {
const slug = 'test-user';
final error = Exception('Ошибка загрузки');
when(mockProfileRepository.getProfileDetailsBySlug(slug))
.thenThrow(error);
cubit.getUserDetails(slug);
// Ждем завершения асинхронных операций
await Future.delayed(const Duration(milliseconds: 100));
expect(cubit.state.error, equals(error.toString()));
expect(cubit.state.isLoading, isFalse);
});
test('getChartData - успешная загрузка данных графика', () async {
const slug = 'test-user';
const period = '1';
final weightPoints = [
WeightModel(
id: 1,
userId: 1,
weight: 70,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
bmi: 22.9,
),
WeightModel(
id: 2,
userId: 1,
weight: 71,
createdAt: DateTime.now().add(const Duration(days: 1)),
updatedAt: DateTime.now().add(const Duration(days: 1)),
bmi: 23.2,
),
];
final circumferencePoints = [
CircumferenceModel(
id: 1,
userId: 1,
chestCircumference: 100,
waistCircumference: 80,
hipCircumference: 90,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
),
];
when(mockProfileRepository.getWeight(period: period, slug: slug))
.thenAnswer((_) async => weightPoints);
when(mockProfileRepository.getCircumferences(period: period, slug: slug))
.thenAnswer((_) async => circumferencePoints);
cubit.getChartData(period: period, slug: slug);
// Ждем завершения асинхронных операций
await Future.delayed(const Duration(milliseconds: 100));
expect(cubit.state.weightPoints, equals(weightPoints));
expect(cubit.state.circumferencePoints, equals(circumferencePoints));
verify(mockProfileRepository.getWeight(period: period, slug: slug)).called(1);
verify(mockProfileRepository.getCircumferences(period: period, slug: slug)).called(1);
});
test('getChartData - обработка ошибки', () async {
const slug = 'test-user';
const period = '1';
final error = Exception('Ошибка загрузки');
when(mockProfileRepository.getWeight(period: period, slug: slug))
.thenThrow(error);
cubit.getChartData(period: period, slug: slug);
// Ждем завершения асинхронных операций
await Future.delayed(const Duration(milliseconds: 100));
expect(cubit.state.error, equals(error.toString()));
expect(cubit.state.isLoading, isFalse);
});
});
}