forked from eatvio/eatvio_app
refactor(tests): update model instantiation to use const for improved performance
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
85
test/features/my_finance/models/card_model_test.dart
Normal file
85
test/features/my_finance/models/card_model_test.dart
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
39
test/features/my_finance/models/payment_url_model_test.dart
Normal file
39
test/features/my_finance/models/payment_url_model_test.dart
Normal 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'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
111
test/features/my_finance/repositories/cards_repository_test.dart
Normal file
111
test/features/my_finance/repositories/cards_repository_test.dart
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
266
test/features/order_info/cubit/order_info_cubit_test.dart
Normal file
266
test/features/order_info/cubit/order_info_cubit_test.dart
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user