forked from eatvio/eatvio_app
feat(tests): added new tests and updated fixtures
This commit is contained in:
@@ -139,70 +139,70 @@ jobs:
|
||||
- name: Native Analyze
|
||||
run: flutter analyze
|
||||
|
||||
# - name: Test
|
||||
# run: flutter test --coverage
|
||||
- name: Test
|
||||
run: flutter test --coverage
|
||||
|
||||
# - name: Test coverage
|
||||
# run: |
|
||||
# echo "📊 Analyzing test coverage..."
|
||||
# echo ""
|
||||
# awk -F: '
|
||||
# /^SF:/ {
|
||||
# file = $0
|
||||
# sub(/^SF:/, "", file)
|
||||
# sub(/^[[:space:]]+/, "", file)
|
||||
# is_generated = 0
|
||||
# if (file ~ /\.(g|freezed|gr|mocks)\.dart$/) {
|
||||
# is_generated = 1
|
||||
# generated_files++
|
||||
# } else if (file ~ /\/(build|\.dart_tool)\//) {
|
||||
# is_generated = 1
|
||||
# generated_files++
|
||||
# } else {
|
||||
# source_files++
|
||||
# }
|
||||
# }
|
||||
# /^LF:/ {
|
||||
# if (!is_generated) {
|
||||
# total += $2
|
||||
# } else {
|
||||
# generated_lines += $2
|
||||
# }
|
||||
# }
|
||||
# /^LH:/ {
|
||||
# if (!is_generated) {
|
||||
# covered += $2
|
||||
# } else {
|
||||
# generated_covered += $2
|
||||
# }
|
||||
# }
|
||||
# END {
|
||||
# print "📁 Files:"
|
||||
# printf " Source files: %d\n", source_files
|
||||
# printf " Generated files: %d (excluded)\n", generated_files
|
||||
# print ""
|
||||
# print "📝 Lines:"
|
||||
# printf " Total lines: %d\n", total
|
||||
# printf " Covered lines: %d\n", covered
|
||||
# printf " Uncovered lines: %d\n", total - covered
|
||||
# print ""
|
||||
# if (total == 0) {
|
||||
# print "⚠️ Coverage: 0%"
|
||||
# exit 1
|
||||
# } else {
|
||||
# percentage = (covered / total) * 100
|
||||
# printf "✅ Coverage: %.2f%%\n", percentage
|
||||
# print ""
|
||||
# if (percentage < 60) {
|
||||
# printf "⚠️ Warning: Coverage is below 60%%\n"
|
||||
# } else if (percentage < 80) {
|
||||
# printf "💛 Good: Coverage is above 60%%\n"
|
||||
# } else {
|
||||
# printf "💚 Excellent: Coverage is above 80%%\n"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# ' coverage/lcov.info
|
||||
- name: Test coverage
|
||||
run: |
|
||||
echo "📊 Analyzing test coverage..."
|
||||
echo ""
|
||||
awk -F: '
|
||||
/^SF:/ {
|
||||
file = $0
|
||||
sub(/^SF:/, "", file)
|
||||
sub(/^[[:space:]]+/, "", file)
|
||||
is_generated = 0
|
||||
if (file ~ /\.(g|freezed|gr|mocks)\.dart$/) {
|
||||
is_generated = 1
|
||||
generated_files++
|
||||
} else if (file ~ /\/(build|\.dart_tool)\//) {
|
||||
is_generated = 1
|
||||
generated_files++
|
||||
} else {
|
||||
source_files++
|
||||
}
|
||||
}
|
||||
/^LF:/ {
|
||||
if (!is_generated) {
|
||||
total += $2
|
||||
} else {
|
||||
generated_lines += $2
|
||||
}
|
||||
}
|
||||
/^LH:/ {
|
||||
if (!is_generated) {
|
||||
covered += $2
|
||||
} else {
|
||||
generated_covered += $2
|
||||
}
|
||||
}
|
||||
END {
|
||||
print "📁 Files:"
|
||||
printf " Source files: %d\n", source_files
|
||||
printf " Generated files: %d (excluded)\n", generated_files
|
||||
print ""
|
||||
print "📝 Lines:"
|
||||
printf " Total lines: %d\n", total
|
||||
printf " Covered lines: %d\n", covered
|
||||
printf " Uncovered lines: %d\n", total - covered
|
||||
print ""
|
||||
if (total == 0) {
|
||||
print "⚠️ Coverage: 0%"
|
||||
exit 1
|
||||
} else {
|
||||
percentage = (covered / total) * 100
|
||||
printf "✅ Coverage: %.2f%%\n", percentage
|
||||
print ""
|
||||
if (percentage < 60) {
|
||||
printf "⚠️ Warning: Coverage is below 60%%\n"
|
||||
} else if (percentage < 80) {
|
||||
printf "💛 Good: Coverage is above 60%%\n"
|
||||
} else {
|
||||
printf "💚 Excellent: Coverage is above 80%%\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
' coverage/lcov.info
|
||||
|
||||
- name: Build apk
|
||||
run: |
|
||||
|
||||
@@ -201,6 +201,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
}
|
||||
|
||||
Future<Diet?> getDietForPreview() async {
|
||||
if (!_isFormValidForDraft()) return null;
|
||||
final authorProfile = await profileRepository.getMyProfile();
|
||||
final imageBytes = (await state.dietData.image?.readAsBytes()) ?? <int>[];
|
||||
String image = base64.encode(imageBytes);
|
||||
@@ -317,6 +318,11 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
return 'validation';
|
||||
}
|
||||
try {
|
||||
final dietState = state.dietData.state;
|
||||
if (dietState == null) {
|
||||
emit(state.copyWith(isDietPublishing: false, dietStateError: 'Статус диеты не выбран'));
|
||||
return 'validation';
|
||||
}
|
||||
File? file;
|
||||
if (state.dietData.imageUrl != null) {
|
||||
file = await downloadImageAsFile(state.dietData.imageUrl!);
|
||||
@@ -325,7 +331,6 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
if (state.dietData.image?.path != null) {
|
||||
image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
|
||||
}
|
||||
final dietState = state.dietData.state!;
|
||||
final dailySchedule = state.dietData.dailySchedule;
|
||||
await createDietRepository.createDiet(
|
||||
name: state.dietData.name ?? '',
|
||||
|
||||
@@ -82,7 +82,12 @@ class CreateDietRepository {
|
||||
return MapEntry(
|
||||
int.parse(key),
|
||||
(value as Map<String, dynamic>).map((key, value) {
|
||||
return MapEntry(int.parse(key), DailySchedule.fromJson(value as Map<String, dynamic>));
|
||||
final portionMap = Map<String, dynamic>.from(value as Map<String, dynamic>);
|
||||
final pnvid = portionMap['product_nutritional_value_id'];
|
||||
if (pnvid is String) {
|
||||
portionMap['product_nutritional_value_id'] = int.tryParse(pnvid);
|
||||
}
|
||||
return MapEntry(int.parse(key), DailySchedule.fromJson(portionMap));
|
||||
}),
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -7,6 +7,8 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_cubit.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_state.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/pages/blog_post_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -159,5 +161,49 @@ void main() {
|
||||
expect(find.byType(BlogPostScreen), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('renders loaded state with blog post model', (tester) async {
|
||||
await mockNetworkImagesFor(() async {
|
||||
final blogPostCubit = MockBlogPostCubit();
|
||||
final feedCubit = MockFeedCubit();
|
||||
final commentsCubit = MockCommentsCubit();
|
||||
final blogPostModel = FeedBlogPostModel(
|
||||
id: 1,
|
||||
title: 'Test Post Title',
|
||||
description: 'Test post description',
|
||||
image: 'https://example.com/image.jpg',
|
||||
state: 'published',
|
||||
author: const Author(authorSlug: 'author-1', authorName: 'Author Name', authorProfileIcon: 'https://example.com/icon.jpg', authorIsMe: false),
|
||||
videoUrl: '',
|
||||
createdAt: DateTime(2024, 1, 15),
|
||||
updatedAt: DateTime(2024, 1, 15),
|
||||
totalLikes: 10,
|
||||
totalViews: 100,
|
||||
totalComments: 5,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
final state = BlogPostState(isLoading: false, blogPostModel: blogPostModel, error: null);
|
||||
|
||||
when(blogPostCubit.state).thenReturn(state);
|
||||
when(blogPostCubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(blogPostCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(feedCubit.viewPost(any)).thenAnswer((_) async => Future<void>.value());
|
||||
when(feedCubit.stream).thenAnswer((_) => const Stream.empty());
|
||||
when(feedCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.state).thenReturn(const CommentsState());
|
||||
when(commentsCubit.stream).thenAnswer((_) => const Stream<CommentsState>.empty());
|
||||
when(commentsCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.getComments(any, any, any)).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
registerMocks(blogPostCubit, commentsCubit);
|
||||
|
||||
await tester.pumpWidget(wrap(blogPostCubit, feedCubit, commentsCubit, const BlogPostScreen(id: 1)));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(BlogPostScreen), findsOneWidget);
|
||||
expect(find.text('Test Post Title'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,5 +67,39 @@ void main() {
|
||||
|
||||
expect(find.byType(CreateDietScreenContent), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders create diet screen with loading state', (tester) async {
|
||||
final cubit = MockCreateDietCubit();
|
||||
final state = CreateDietState.initial().copyWith(isLoading: true);
|
||||
|
||||
when(cubit.state).thenReturn(state);
|
||||
when(cubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(cubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(cubit.setInitialData(any)).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
sl.registerLazySingleton<CreateDietCubit>(() => cubit);
|
||||
|
||||
await tester.pumpWidget(wrap(const CreateDietScreenContent(), cubit));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byType(CreateDietScreenContent), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders create diet screen with diet publishing state', (tester) async {
|
||||
final cubit = MockCreateDietCubit();
|
||||
final state = CreateDietState.initial().copyWith(isDietPublishing: true);
|
||||
|
||||
when(cubit.state).thenReturn(state);
|
||||
when(cubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(cubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(cubit.setInitialData(any)).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
sl.registerLazySingleton<CreateDietCubit>(() => cubit);
|
||||
|
||||
await tester.pumpWidget(wrap(const CreateDietScreenContent(), cubit));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byType(CreateDietScreenContent), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:eatvio_app/features/create_diet/repositories/create_diet_reposit
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
|
||||
import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
@@ -236,6 +237,51 @@ void main() {
|
||||
expect(result, null);
|
||||
});
|
||||
|
||||
test('getDietForPreview returns Diet when form is valid', () async {
|
||||
const profile = ProfileModel(
|
||||
id: 1,
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
phoneConfirmationState: 'confirmed',
|
||||
slug: 'test-user',
|
||||
isPublicProfile: true,
|
||||
isBlockedByMe: false,
|
||||
isBlockedByAuthor: false,
|
||||
isBlockedByUser: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
profilePhotoUrl: 'https://example.com/photo.jpg',
|
||||
roles: [],
|
||||
badges: [],
|
||||
subscriptions: [],
|
||||
subscribers: [],
|
||||
);
|
||||
when(profileRepository.getMyProfile()).thenAnswer((_) async => profile);
|
||||
|
||||
cubit.setName('Test Diet');
|
||||
cubit.setDetails('Test Description');
|
||||
cubit.setDuration(0);
|
||||
cubit.setDietState(DietState.active);
|
||||
const portion = DailySchedule(
|
||||
name: 'Apple',
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
cubit.setImage(null, imageUrl: 'https://example.com/cover.jpg');
|
||||
|
||||
final result = await cubit.getDietForPreview();
|
||||
|
||||
expect(result, isNotNull);
|
||||
expect(result!.name, 'Test Diet');
|
||||
expect(result.details, 'Test Description');
|
||||
expect(result.duration, 7);
|
||||
expect(result.author.authorName, 'Test User');
|
||||
expect(result.author.authorSlug, 'test-user');
|
||||
verify(profileRepository.getMyProfile()).called(1);
|
||||
});
|
||||
|
||||
test('createDiet returns validation error when form is invalid', () async {
|
||||
final result = await cubit.createDiet();
|
||||
expect(result, 'validation');
|
||||
@@ -257,7 +303,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
// Set image with non-existent file to trigger error in compression
|
||||
@@ -280,7 +326,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
final image = XFile('test_image.jpg');
|
||||
@@ -302,7 +348,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
final image = XFile('test_image.jpg');
|
||||
@@ -321,7 +367,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
@@ -336,7 +382,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
@@ -405,7 +451,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
final image = XFile('test_image.jpg');
|
||||
@@ -427,7 +473,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
final image = XFile('test_image.jpg');
|
||||
@@ -448,7 +494,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
final image = XFile('test_image.jpg');
|
||||
@@ -469,7 +515,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
final image = XFile('test_image.jpg');
|
||||
@@ -491,7 +537,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
|
||||
@@ -522,7 +568,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
@@ -546,7 +592,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: DailyNutrition(energy: 52.0, proteins: 0.3, fats: 0.2, carbohydrates: 14.0),
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
);
|
||||
|
||||
cubit.addPortion(dayIndex: 0, mealIndex: 0, portion: portion);
|
||||
|
||||
@@ -63,7 +63,7 @@ void main() {
|
||||
dailyNutrition: [],
|
||||
);
|
||||
|
||||
await tester.pumpWidget(wrap(DietPreviewScreen(diet: testDiet)));
|
||||
await tester.pumpWidget(wrap(DietPreviewScreen(diet: testDiet, isImageInBase64: true)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(DietPreviewScreen), findsOneWidget);
|
||||
@@ -103,7 +103,7 @@ void main() {
|
||||
dailyNutrition: [const DailyNutrition(energy: 2000.0, proteins: 100.0, fats: 50.0, carbohydrates: 200.0)],
|
||||
);
|
||||
|
||||
await tester.pumpWidget(wrap(DietPreviewScreen(diet: testDiet)));
|
||||
await tester.pumpWidget(wrap(DietPreviewScreen(diet: testDiet, isImageInBase64: true)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(DietPreviewScreen), findsOneWidget);
|
||||
@@ -131,7 +131,7 @@ void main() {
|
||||
dailyNutrition: [],
|
||||
);
|
||||
|
||||
await tester.pumpWidget(wrap(DietPreviewScreen(diet: testDiet)));
|
||||
await tester.pumpWidget(wrap(DietPreviewScreen(diet: testDiet, isImageInBase64: true)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Test Diet Name'), findsOneWidget);
|
||||
|
||||
@@ -196,7 +196,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: null,
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -236,7 +236,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: null,
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -299,7 +299,7 @@ void main() {
|
||||
portion: Portion.grams,
|
||||
quantity: 100,
|
||||
dailyNutrition: null,
|
||||
productNutritionalValueId: '1',
|
||||
productNutritionalValueId: 1,
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
@@ -103,7 +103,7 @@ void main() {
|
||||
dietData.first['name'] = 'Another Diet';
|
||||
dietData.first['image'] = 'https://someurl.com/img2.jpg';
|
||||
dietData.first['duration'] = duration;
|
||||
dietData.first['state'] = 'draft';
|
||||
dietData.first['state'] = 'drafted';
|
||||
dietData.first['type'] = {'light': false, 'veg': true, 'carb': false, 'meat': false};
|
||||
dietData.first['description_md'] = '';
|
||||
dietData.first['author'] = {'author_slug': 'author-slug', 'author_name': 'Author Name', 'author_profile_icon': '', 'author_is_me': true, 'is_entity_subscribed_by_me': null, 'author_place_in_rating': null};
|
||||
|
||||
@@ -182,5 +182,34 @@ void main() {
|
||||
|
||||
expect(find.byType(AboutPlanScreen), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders with navigateToComments true', (tester) async {
|
||||
final planCubit = MockAboutPlanCubit();
|
||||
final feedCubit = MockFeedCubit();
|
||||
final commentsCubit = MockCommentsCubit();
|
||||
const state = AboutPlanState(isLoading: false, planModel: testPlan, chosenOptionIndex: 0, error: null);
|
||||
|
||||
when(planCubit.state).thenReturn(state);
|
||||
when(planCubit.stream).thenAnswer((_) => const Stream<AboutPlanState>.empty());
|
||||
when(planCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(feedCubit.viewPlan(any)).thenAnswer((_) async => Future<void>.value());
|
||||
when(feedCubit.stream).thenAnswer((_) => const Stream.empty());
|
||||
when(feedCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.state).thenReturn(const CommentsState());
|
||||
when(commentsCubit.stream).thenAnswer((_) => const Stream<CommentsState>.empty());
|
||||
when(commentsCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.getComments(any, any, any)).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
registerMocks(planCubit, commentsCubit);
|
||||
|
||||
await mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(wrap(planCubit, feedCubit, commentsCubit, const AboutPlanScreen(slug: 'test', navigateToComments: true, index: 1)));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
});
|
||||
|
||||
expect(find.byType(AboutPlanScreen), findsOneWidget);
|
||||
expect(find.text('Test Plan'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -193,5 +193,36 @@ void main() {
|
||||
|
||||
expect(find.byType(AboutRecipeScreen), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders with navigateToComments true', (tester) async {
|
||||
final recipeCubit = MockAboutRecipeCubit();
|
||||
final feedCubit = MockFeedCubit();
|
||||
final commentsCubit = MockCommentsCubit();
|
||||
final state = AboutRecipeState.loaded(recipe: testRecipe);
|
||||
|
||||
when(recipeCubit.state).thenReturn(state);
|
||||
when(recipeCubit.stream).thenAnswer((_) => const Stream<AboutRecipeState>.empty());
|
||||
when(recipeCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(feedCubit.viewRecipe(any)).thenAnswer((_) async => Future<void>.value());
|
||||
when(feedCubit.stream).thenAnswer((_) => const Stream.empty());
|
||||
when(feedCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.state).thenReturn(const CommentsState());
|
||||
when(commentsCubit.stream).thenAnswer((_) => const Stream<CommentsState>.empty());
|
||||
when(commentsCubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.getComments(any, any, any)).thenAnswer((_) async => Future<void>.value());
|
||||
when(commentsCubit.setReplyId(any)).thenReturn(null);
|
||||
|
||||
registerMocks(recipeCubit, commentsCubit);
|
||||
|
||||
await mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(
|
||||
wrap(recipeCubit, feedCubit, commentsCubit, const AboutRecipeScreen(recipeSlug: 'test', index: 2, navigateToComments: true)),
|
||||
);
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 600));
|
||||
});
|
||||
|
||||
expect(find.byType(AboutRecipeScreen), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,11 +3,58 @@
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Авокадо",
|
||||
"portion": "grams",
|
||||
"portion": "gr",
|
||||
"quantity": 100,
|
||||
"product_nutritional_value_id": "501"
|
||||
"product_nutritional_value_id": 501,
|
||||
"nutrition": {
|
||||
"energy": 160.0,
|
||||
"proteins": 2.0,
|
||||
"fats": 14.0,
|
||||
"carbohydrates": 9.0
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"name": "Лосось",
|
||||
"portion": "gr",
|
||||
"quantity": 150,
|
||||
"product_nutritional_value_id": 502,
|
||||
"nutrition": {
|
||||
"energy": 312.0,
|
||||
"proteins": 30.0,
|
||||
"fats": 19.5,
|
||||
"carbohydrates": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"name": "Овсянка",
|
||||
"portion": "gr",
|
||||
"quantity": 150,
|
||||
"product_nutritional_value_id": 503,
|
||||
"nutrition": {
|
||||
"energy": 195.0,
|
||||
"proteins": 6.75,
|
||||
"fats": 3.0,
|
||||
"carbohydrates": 33.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Творог",
|
||||
"portion": "gr",
|
||||
"quantity": 200,
|
||||
"product_nutritional_value_id": 504,
|
||||
"nutrition": {
|
||||
"energy": 226.0,
|
||||
"proteins": 31.0,
|
||||
"fats": 9.0,
|
||||
"carbohydrates": 3.4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
77
test/fixtures/diets/diet_response.json
vendored
77
test/fixtures/diets/diet_response.json
vendored
@@ -12,7 +12,66 @@
|
||||
"meat": false
|
||||
},
|
||||
"description_md": "Test details",
|
||||
"daily_schedule": {},
|
||||
"daily_schedule": {
|
||||
"1": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Овсянка",
|
||||
"portion": "gr",
|
||||
"quantity": 150,
|
||||
"product_nutritional_value_id": 101,
|
||||
"nutrition": {
|
||||
"energy": 195.0,
|
||||
"proteins": 6.75,
|
||||
"fats": 3.0,
|
||||
"carbohydrates": 33.0
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"name": "Бананы",
|
||||
"portion": "gr",
|
||||
"quantity": 120,
|
||||
"product_nutritional_value_id": 102,
|
||||
"nutrition": {
|
||||
"energy": 107.0,
|
||||
"proteins": 1.3,
|
||||
"fats": 0.4,
|
||||
"carbohydrates": 27.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"name": "Куриная грудка",
|
||||
"portion": "gr",
|
||||
"quantity": 200,
|
||||
"product_nutritional_value_id": 201,
|
||||
"nutrition": {
|
||||
"energy": 330.0,
|
||||
"proteins": 62.0,
|
||||
"fats": 7.2,
|
||||
"carbohydrates": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Творог",
|
||||
"portion": "gr",
|
||||
"quantity": 200,
|
||||
"product_nutritional_value_id": 301,
|
||||
"nutrition": {
|
||||
"energy": 226.0,
|
||||
"proteins": 31.0,
|
||||
"fats": 9.0,
|
||||
"carbohydrates": 3.4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"author_slug": "author",
|
||||
"author_name": "Author Name",
|
||||
@@ -26,6 +85,18 @@
|
||||
"total_comments": 5,
|
||||
"was_liked_by_me": false,
|
||||
"is_favorite": false,
|
||||
"daily_nutrition": []
|
||||
"daily_nutrition": [
|
||||
{
|
||||
"energy": 864.0,
|
||||
"proteins": 101.05,
|
||||
"fats": 19.6,
|
||||
"carbohydrates": 63.4
|
||||
},
|
||||
{
|
||||
"energy": 532.0,
|
||||
"proteins": 93.3,
|
||||
"fats": 16.2,
|
||||
"carbohydrates": 30.4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
22
test/fixtures/doubles/create_diet_doubles.dart
vendored
22
test/fixtures/doubles/create_diet_doubles.dart
vendored
@@ -53,11 +53,15 @@ class FixtureCreateDietRepository extends CreateDietRepository {
|
||||
portion = Portion.grams;
|
||||
}
|
||||
|
||||
final pnvid = portionData['product_nutritional_value_id'];
|
||||
final nutritionJson = portionData['nutrition'] as Map<String, dynamic>?;
|
||||
final dailyNutrition = nutritionJson != null ? DailyNutrition.fromJson(nutritionJson) : null;
|
||||
mealMap[portionIndex] = DailySchedule(
|
||||
name: portionData['name'] as String,
|
||||
portion: portion,
|
||||
quantity: portionData['quantity'] as int,
|
||||
productNutritionalValueId: portionData['product_nutritional_value_id'] as String?,
|
||||
quantity: portionData['quantity'] is int ? portionData['quantity'] as int : int.parse(portionData['quantity'].toString()),
|
||||
productNutritionalValueId: pnvid == null ? null : (pnvid is int ? pnvid : int.tryParse(pnvid.toString())),
|
||||
dailyNutrition: dailyNutrition,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,13 +79,13 @@ class FixtureCreateDietRepository extends CreateDietRepository {
|
||||
required String name,
|
||||
required int duration,
|
||||
required DietState state,
|
||||
required String meatType,
|
||||
required String carbType,
|
||||
required String vegType,
|
||||
required String lightType,
|
||||
required String details,
|
||||
required File image,
|
||||
required List<List<List<DailySchedule>>> dailySchedule,
|
||||
required String? meatType,
|
||||
required String? carbType,
|
||||
required String? vegType,
|
||||
required String? lightType,
|
||||
required String? details,
|
||||
required File? image,
|
||||
required List<List<List<DailySchedule>>>? dailySchedule,
|
||||
}) async {
|
||||
createRequests.add(<String, dynamic>{
|
||||
'name': name,
|
||||
|
||||
@@ -14,7 +14,54 @@
|
||||
"meat": true
|
||||
},
|
||||
"description_md": "Keto diet description",
|
||||
"daily_schedule": {},
|
||||
"daily_schedule": {
|
||||
"1": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Яйца вареные",
|
||||
"portion": "pcs",
|
||||
"quantity": 2,
|
||||
"product_nutritional_value_id": 401,
|
||||
"nutrition": {
|
||||
"energy": 155.0,
|
||||
"proteins": 12.6,
|
||||
"fats": 10.6,
|
||||
"carbohydrates": 1.1
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"name": "Авокадо",
|
||||
"portion": "gr",
|
||||
"quantity": 100,
|
||||
"product_nutritional_value_id": 501,
|
||||
"nutrition": {
|
||||
"energy": 160.0,
|
||||
"proteins": 2.0,
|
||||
"fats": 14.0,
|
||||
"carbohydrates": 9.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Лосось",
|
||||
"portion": "gr",
|
||||
"quantity": 150,
|
||||
"product_nutritional_value_id": 502,
|
||||
"nutrition": {
|
||||
"energy": 312.0,
|
||||
"proteins": 30.0,
|
||||
"fats": 19.5,
|
||||
"carbohydrates": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"author_slug": "nutritionist-1",
|
||||
"author_name": "Nutritionist Name",
|
||||
@@ -28,7 +75,20 @@
|
||||
"total_comments": 25,
|
||||
"was_liked_by_me": false,
|
||||
"is_favorite": false,
|
||||
"daily_nutrition": []
|
||||
"daily_nutrition": [
|
||||
{
|
||||
"energy": 627.0,
|
||||
"proteins": 44.6,
|
||||
"fats": 44.1,
|
||||
"carbohydrates": 10.1
|
||||
},
|
||||
{
|
||||
"energy": 312.0,
|
||||
"proteins": 30.0,
|
||||
"fats": 19.5,
|
||||
"carbohydrates": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
@@ -50,4 +110,3 @@
|
||||
"total_max_price": null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
112
test/fixtures/my_diets/my_diets_pagination_response.json
vendored
Normal file
112
test/fixtures/my_diets/my_diets_pagination_response.json
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"slug": "my-keto-diet",
|
||||
"name": "My Keto Diet",
|
||||
"image": "https://example.com/my-keto.jpg",
|
||||
"duration": 14,
|
||||
"state": "drafted",
|
||||
"type": {
|
||||
"light": true,
|
||||
"veg": true,
|
||||
"carb": false,
|
||||
"meat": true
|
||||
},
|
||||
"description_md": "My drafted keto diet for two weeks",
|
||||
"daily_schedule": {
|
||||
"1": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Омлет",
|
||||
"portion": "gr",
|
||||
"quantity": 200,
|
||||
"product_nutritional_value_id": 601,
|
||||
"nutrition": {
|
||||
"energy": 318.0,
|
||||
"proteins": 21.2,
|
||||
"fats": 24.2,
|
||||
"carbohydrates": 2.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"name": "Салат с курицей",
|
||||
"portion": "gr",
|
||||
"quantity": 300,
|
||||
"product_nutritional_value_id": 602,
|
||||
"nutrition": {
|
||||
"energy": 285.0,
|
||||
"proteins": 35.0,
|
||||
"fats": 12.0,
|
||||
"carbohydrates": 8.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "Творог 5%",
|
||||
"portion": "gr",
|
||||
"quantity": 200,
|
||||
"product_nutritional_value_id": 603,
|
||||
"nutrition": {
|
||||
"energy": 226.0,
|
||||
"proteins": 31.0,
|
||||
"fats": 9.0,
|
||||
"carbohydrates": 3.4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"author_slug": "me",
|
||||
"author_name": "My Name",
|
||||
"author_profile_icon": "https://example.com/me.jpg",
|
||||
"author_is_me": true,
|
||||
"is_entity_subscribed_by_me": null,
|
||||
"author_place_in_rating": null
|
||||
},
|
||||
"total_likes": 0,
|
||||
"total_views": 0,
|
||||
"total_comments": 0,
|
||||
"was_liked_by_me": false,
|
||||
"is_favorite": false,
|
||||
"daily_nutrition": [
|
||||
{
|
||||
"energy": 603.0,
|
||||
"proteins": 56.2,
|
||||
"fats": 36.2,
|
||||
"carbohydrates": 10.0
|
||||
},
|
||||
{
|
||||
"energy": 226.0,
|
||||
"proteins": 31.0,
|
||||
"fats": 9.0,
|
||||
"carbohydrates": 3.4
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"first": "http://localhost/api/my-diets?page=1",
|
||||
"last": "http://localhost/api/my-diets?page=1",
|
||||
"prev": null,
|
||||
"next": null
|
||||
},
|
||||
"meta": {
|
||||
"current_page": 1,
|
||||
"from": 1,
|
||||
"last_page": 1,
|
||||
"links": [],
|
||||
"path": "http://localhost/api/my-diets",
|
||||
"per_page": 10,
|
||||
"to": 1,
|
||||
"total": 1,
|
||||
"total_min_price": null,
|
||||
"total_max_price": null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user