forked from eatvio/eatvio_app
feat(dependencies): add rxdart package and improve string extension methods for better handling of empty strings and gender parsing
This commit is contained in:
54
test/features/plans/models/chosen_plan_model_test.dart
Normal file
54
test/features/plans/models/chosen_plan_model_test.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
||||
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('ChosenPlanModel', () {
|
||||
test('создает ChosenPlanModel с правильными значениями', () {
|
||||
const plan = PlanModel(
|
||||
id: 1,
|
||||
slug: 'test-plan',
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test details',
|
||||
packetsCount: 3,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
isFavorite: false,
|
||||
minPriceOfOptions: 1000,
|
||||
maxPriceOfOptions: 2000,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
|
||||
final chosenPlan = ChosenPlanModel(
|
||||
id: 1,
|
||||
optionType: 'options1',
|
||||
startDate: DateTime(2024, 1, 1),
|
||||
chosenPlanState: ChosenPlanStateEnum.stateInited,
|
||||
chatId: 'chat-1',
|
||||
consultantId: 1,
|
||||
plan: plan,
|
||||
);
|
||||
|
||||
expect(chosenPlan.id, 1);
|
||||
expect(chosenPlan.optionType, 'options1');
|
||||
expect(chosenPlan.chosenPlanState, ChosenPlanStateEnum.stateInited);
|
||||
expect(chosenPlan.plan.id, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_cubit.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_state.dart';
|
||||
import 'package:eatvio_app/features/plans/repositories/plan_repository.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'about_plan_cubit_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([MockSpec<PlanRepository>()])
|
||||
void main() {
|
||||
group('AboutPlanCubit', () {
|
||||
AboutPlanCubit? aboutPlanCubit;
|
||||
late MockPlanRepository mockPlanRepository;
|
||||
|
||||
setUp(() {
|
||||
mockPlanRepository = MockPlanRepository();
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
if (aboutPlanCubit != null && !aboutPlanCubit!.isClosed) {
|
||||
await aboutPlanCubit!.close();
|
||||
aboutPlanCubit = null;
|
||||
}
|
||||
});
|
||||
|
||||
test('начальное состояние - initial', () {
|
||||
aboutPlanCubit = AboutPlanCubit(planRepository: mockPlanRepository);
|
||||
|
||||
expect(aboutPlanCubit!.state, isA<AboutPlanState>());
|
||||
expect(aboutPlanCubit!.state.isLoading, isFalse);
|
||||
expect(aboutPlanCubit!.state.planModel, isNull);
|
||||
});
|
||||
|
||||
test('getPlan - успешная загрузка плана', () async {
|
||||
aboutPlanCubit = AboutPlanCubit(planRepository: mockPlanRepository);
|
||||
|
||||
const testPlan = PlanModel(
|
||||
id: 1,
|
||||
slug: 'test-plan',
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test description',
|
||||
packetsCount: 3,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
wasLikedByMe: false,
|
||||
isFavorite: false,
|
||||
);
|
||||
|
||||
when(mockPlanRepository.getPlan('test-plan'))
|
||||
.thenAnswer((_) async => testPlan);
|
||||
|
||||
await aboutPlanCubit!.getPlan('test-plan');
|
||||
|
||||
expect(aboutPlanCubit!.state.planModel, isNotNull);
|
||||
expect(aboutPlanCubit!.state.planModel!.id, 1);
|
||||
expect(aboutPlanCubit!.state.error, isNull);
|
||||
});
|
||||
|
||||
test('getPlanWithLoading - устанавливает loading состояние', () async {
|
||||
aboutPlanCubit = AboutPlanCubit(planRepository: mockPlanRepository);
|
||||
|
||||
const testPlan = PlanModel(
|
||||
id: 1,
|
||||
slug: 'test-plan',
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test description',
|
||||
packetsCount: 3,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
wasLikedByMe: false,
|
||||
isFavorite: false,
|
||||
);
|
||||
|
||||
when(mockPlanRepository.getPlan('test-plan'))
|
||||
.thenAnswer((_) async => testPlan);
|
||||
|
||||
await aboutPlanCubit!.getPlanWithLoading('test-plan');
|
||||
|
||||
expect(aboutPlanCubit!.state.planModel, isNotNull);
|
||||
expect(aboutPlanCubit!.state.isLoading, isFalse);
|
||||
});
|
||||
|
||||
test('choseOption - изменяет выбранную опцию', () {
|
||||
aboutPlanCubit = AboutPlanCubit(planRepository: mockPlanRepository);
|
||||
|
||||
aboutPlanCubit!.choseOption(2);
|
||||
|
||||
expect(aboutPlanCubit!.state.chosenOptionIndex, 2);
|
||||
});
|
||||
|
||||
test('likePlan - лайк плана', () async {
|
||||
aboutPlanCubit = AboutPlanCubit(planRepository: mockPlanRepository);
|
||||
|
||||
const testPlan = PlanModel(
|
||||
id: 1,
|
||||
slug: 'test-plan',
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test description',
|
||||
packetsCount: 3,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
wasLikedByMe: false,
|
||||
isFavorite: false,
|
||||
);
|
||||
|
||||
when(mockPlanRepository.getPlan('test-plan'))
|
||||
.thenAnswer((_) async => testPlan);
|
||||
when(mockPlanRepository.likePlan('test-plan'))
|
||||
.thenAnswer((_) async => {});
|
||||
|
||||
await aboutPlanCubit!.getPlan('test-plan');
|
||||
await aboutPlanCubit!.likePlan(index: null, slug: 'test-plan');
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 1200));
|
||||
expect(aboutPlanCubit!.state.planModel!.wasLikedByMe, isTrue);
|
||||
expect(aboutPlanCubit!.state.planModel!.totalLikes, 11);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('AboutPlanState', () {
|
||||
test('initial создает начальное состояние', () {
|
||||
final state = AboutPlanState.initial();
|
||||
|
||||
expect(state.isLoading, isFalse);
|
||||
expect(state.error, isNull);
|
||||
expect(state.planModel, isNull);
|
||||
expect(state.chosenOptionIndex, 0);
|
||||
});
|
||||
|
||||
test('создает AboutPlanState с планом', () {
|
||||
const plan = PlanModel(
|
||||
id: 1,
|
||||
slug: 'test-plan',
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test details',
|
||||
packetsCount: 3,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
isFavorite: false,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
|
||||
const state = AboutPlanState(
|
||||
isLoading: false,
|
||||
error: null,
|
||||
planModel: plan,
|
||||
chosenOptionIndex: 1,
|
||||
);
|
||||
|
||||
expect(state.planModel, plan);
|
||||
expect(state.chosenOptionIndex, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
176
test/features/plans/repositories/plan_repository_test.dart
Normal file
176
test/features/plans/repositories/plan_repository_test.dart
Normal file
@@ -0,0 +1,176 @@
|
||||
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/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
||||
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
|
||||
import 'package:eatvio_app/features/plans/repositories/plan_repository.dart';
|
||||
import 'package:eatvio_app/features/plans/services/plan_service.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'plan_repository_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([MockSpec<PlanService>()])
|
||||
void main() {
|
||||
group('PlanRepository', () {
|
||||
late PlanRepository repository;
|
||||
late MockPlanService mockService;
|
||||
|
||||
setUp(() {
|
||||
mockService = MockPlanService();
|
||||
repository = PlanRepository(planService: mockService);
|
||||
});
|
||||
|
||||
test('getPlan - успешное получение плана', () async {
|
||||
const slug = 'test-plan';
|
||||
const expectedPlan = PlanModel(
|
||||
id: 1,
|
||||
slug: slug,
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test details',
|
||||
packetsCount: 3,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
isFavorite: false,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
|
||||
when(mockService.getPlan(slug))
|
||||
.thenAnswer((_) async => expectedPlan);
|
||||
|
||||
final result = await repository.getPlan(slug);
|
||||
|
||||
expect(result, equals(expectedPlan));
|
||||
expect(result.id, 1);
|
||||
verify(mockService.getPlan(slug)).called(1);
|
||||
});
|
||||
|
||||
test('likePlan - успешный лайк', () async {
|
||||
const slug = 'test-plan';
|
||||
|
||||
when(mockService.likePlan(slug: slug))
|
||||
.thenAnswer((_) async => Future.value());
|
||||
|
||||
await repository.likePlan(slug);
|
||||
|
||||
verify(mockService.likePlan(slug: slug)).called(1);
|
||||
});
|
||||
|
||||
test('addToFavorite - успешное добавление в избранное', () async {
|
||||
const slug = 'test-plan';
|
||||
|
||||
when(mockService.addToFavorite(slug: slug))
|
||||
.thenAnswer((_) async => Future.value());
|
||||
|
||||
await repository.addToFavorite(slug);
|
||||
|
||||
verify(mockService.addToFavorite(slug: slug)).called(1);
|
||||
});
|
||||
|
||||
test('removeFromFavorite - успешное удаление из избранного', () async {
|
||||
const slug = 'test-plan';
|
||||
|
||||
when(mockService.removeFromFavorite(slug: slug))
|
||||
.thenAnswer((_) async => Future.value());
|
||||
|
||||
await repository.removeFromFavorite(slug);
|
||||
|
||||
verify(mockService.removeFromFavorite(slug: slug)).called(1);
|
||||
});
|
||||
|
||||
test('chosePlan - успешный выбор плана', () async {
|
||||
const slug = 'test-plan';
|
||||
final option = {'option_type': 'options1'};
|
||||
final expectedChosenPlan = ChosenPlanModel(
|
||||
id: 1,
|
||||
optionType: 'options1',
|
||||
startDate: DateTime(2024, 1, 1),
|
||||
chosenPlanState: ChosenPlanStateEnum.stateInited,
|
||||
chatId: 'chat-1',
|
||||
consultantId: 1,
|
||||
plan: const PlanModel(
|
||||
id: 1,
|
||||
slug: slug,
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test details',
|
||||
packetsCount: 3,
|
||||
author: Author(
|
||||
authorSlug: 'author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
isFavorite: false,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
wasLikedByMe: false,
|
||||
),
|
||||
);
|
||||
|
||||
when(mockService.chosePlan(slug: slug, option: option))
|
||||
.thenAnswer((_) async => expectedChosenPlan);
|
||||
|
||||
final result = await repository.chosePlan(slug, option);
|
||||
|
||||
expect(result, equals(expectedChosenPlan));
|
||||
verify(mockService.chosePlan(slug: slug, option: option)).called(1);
|
||||
});
|
||||
|
||||
test('emitLikesStateToFeed - отправляет состояние лайков', () async {
|
||||
const state = LikesState(
|
||||
wasLikedByMe: true,
|
||||
totalLikes: 10,
|
||||
index: 0,
|
||||
);
|
||||
|
||||
expectLater(repository.planLikeState, emits(state));
|
||||
repository.emitLikesStateToFeed(state);
|
||||
});
|
||||
|
||||
test('emitFavoriteStateToFeed - отправляет состояние избранного', () async {
|
||||
const state = FavoriteState(
|
||||
isFavorite: true,
|
||||
index: 0,
|
||||
);
|
||||
|
||||
expectLater(repository.planFavoriteState, emits(state));
|
||||
repository.emitFavoriteStateToFeed(state);
|
||||
});
|
||||
|
||||
test('emitCommentsStateToFeed - отправляет состояние комментариев', () async {
|
||||
const state = CommentsState(
|
||||
index: 0,
|
||||
totalComments: 5,
|
||||
);
|
||||
|
||||
expectLater(repository.planCommentsState, emits(state));
|
||||
repository.emitCommentsStateToFeed(state);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
67
test/features/plans/repositories/plans_repository_test.dart
Normal file
67
test/features/plans/repositories/plans_repository_test.dart
Normal file
@@ -0,0 +1,67 @@
|
||||
import 'package:eatvio_app/core/models/pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/repositories/plans_repository.dart';
|
||||
import 'package:eatvio_app/features/plans/services/plans_service.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'plans_repository_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([MockSpec<PlansService>()])
|
||||
void main() {
|
||||
group('PlansRepository', () {
|
||||
late PlansRepository repository;
|
||||
late MockPlansService mockService;
|
||||
|
||||
setUp(() {
|
||||
mockService = MockPlansService();
|
||||
repository = PlansRepository(plansService: mockService);
|
||||
});
|
||||
|
||||
test('getPlansBySlug - успешное получение планов', () async {
|
||||
const slug = 'test-author';
|
||||
const plan = PlanModel(
|
||||
id: 1,
|
||||
slug: 'test-plan',
|
||||
name: 'Test Plan',
|
||||
image: 'https://example.com/image.jpg',
|
||||
duration: 7,
|
||||
state: 'active',
|
||||
type: PlanType(fit: true, slim: false, behavior: false, wellness: false),
|
||||
details: 'Test details',
|
||||
packetsCount: 3,
|
||||
author: Author(
|
||||
authorSlug: 'test-author',
|
||||
authorName: 'Author Name',
|
||||
authorProfileIcon: 'https://example.com/icon.jpg',
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: null,
|
||||
authorPlaceInRating: null,
|
||||
),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
isFavorite: false,
|
||||
minPriceOfOptions: 1000.0,
|
||||
maxPriceOfOptions: 2000.0,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
|
||||
const pagination = PlanPaginationModel(
|
||||
data: [plan],
|
||||
links: Links(first: 'https://example.com?page=1', last: 'https://example.com?page=1', prev: null, next: null),
|
||||
meta: Meta(currentPage: 1, from: 1, lastPage: 1, links: [], perPage: 10, to: 1, total: 1),
|
||||
);
|
||||
|
||||
when(mockService.getPlansBySlug(author: slug)).thenAnswer((_) async => pagination);
|
||||
|
||||
final result = await repository.getPlansBySlug(slug);
|
||||
|
||||
expect(result.length, 1);
|
||||
expect(result.first.slug, 'test-plan');
|
||||
verify(mockService.getPlansBySlug(author: slug)).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user