forked from eatvio/eatvio_app
254 lines
8.7 KiB
Dart
254 lines
8.7 KiB
Dart
import 'package:eatvio_app/core/app_config.dart';
|
|
import 'package:eatvio_app/core/app_initializer.dart';
|
|
import 'package:eatvio_app/core/locator_service.dart';
|
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
|
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
import 'package:eatvio_app/features/feed/models/recipes_model.dart' as recipes;
|
|
import 'package:eatvio_app/features/recipe/presentation/widgets/ingredients_widget.dart';
|
|
import 'package:eatvio_app/features/recipe/presentation/widgets/steps_widget.dart';
|
|
import 'package:eatvio_app/generated/l10n.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:flutter_portal/flutter_portal.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
import 'package:network_image_mock/network_image_mock.dart';
|
|
|
|
void main() {
|
|
group('Recipes Widgets Tests', () {
|
|
setUp(() async {
|
|
await sl.reset();
|
|
dotenv.loadFromString(envString: 'DEV_BASE_URL=http://localhost\nBASE_URL=http://localhost');
|
|
sl.registerLazySingleton<AppConfig>(() => AppConfig(buildType: AppBuildType.tests)..setBaseUrl('http://localhost'));
|
|
});
|
|
|
|
Widget createTestWidget(Widget child) {
|
|
return MaterialApp(
|
|
theme: ThemeHelper().themeData(),
|
|
localizationsDelegates: const [
|
|
S.delegate,
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
],
|
|
supportedLocales: const [Locale('ru')],
|
|
home: Portal(
|
|
child: Scaffold(body: SingleChildScrollView(child: child)),
|
|
),
|
|
);
|
|
}
|
|
|
|
group('IngredientsWidget', () {
|
|
testWidgets('should display IngredientsWidget with ingredients', (WidgetTester tester) async {
|
|
// Arrange
|
|
const recipe = recipes.Recipe(
|
|
id: 1,
|
|
image: 'test-image.jpg',
|
|
state: 'active',
|
|
cookingTime: 30,
|
|
activeCookingTime: 15,
|
|
ingredients: [
|
|
recipes.Ingredient(name: 'Flour', unit: 'g', portion: '200', productId: 1),
|
|
recipes.Ingredient(name: 'Sugar', unit: 'g', portion: '100', productId: 2),
|
|
],
|
|
description: 'Test recipe',
|
|
steps: [],
|
|
videoUrl: null,
|
|
createdAt: null,
|
|
updatedAt: null,
|
|
title: 'Test Recipe',
|
|
type: 'main',
|
|
slug: 'test-recipe',
|
|
commentsCount: 0,
|
|
wasLikedByMe: false,
|
|
isFavorite: false,
|
|
calories: 300.0,
|
|
servings: 4,
|
|
likesCount: 0,
|
|
viewsCount: 0,
|
|
tags: [],
|
|
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
|
|
);
|
|
const widget = IngredientsWidget(recipe: recipe);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(widget));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 300));
|
|
|
|
// Assert
|
|
expect(find.byType(IngredientsWidget), findsOneWidget);
|
|
expect(find.byType(ExpansionTile), findsOneWidget);
|
|
// The ingredients text may be formatted with units, so just check the widget structure
|
|
});
|
|
|
|
testWidgets('should display IngredientsWidget with empty ingredients', (WidgetTester tester) async {
|
|
// Arrange
|
|
const recipe = recipes.Recipe(
|
|
id: 1,
|
|
image: 'test-image.jpg',
|
|
state: 'active',
|
|
cookingTime: 30,
|
|
activeCookingTime: 15,
|
|
ingredients: [],
|
|
description: 'Test recipe',
|
|
steps: [],
|
|
videoUrl: null,
|
|
createdAt: null,
|
|
updatedAt: null,
|
|
title: 'Test Recipe',
|
|
type: 'main',
|
|
slug: 'test-recipe',
|
|
commentsCount: 0,
|
|
wasLikedByMe: false,
|
|
isFavorite: false,
|
|
calories: 300.0,
|
|
servings: 4,
|
|
likesCount: 0,
|
|
viewsCount: 0,
|
|
tags: [],
|
|
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
|
|
);
|
|
const widget = IngredientsWidget(recipe: recipe);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(widget));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 100));
|
|
|
|
// Assert
|
|
expect(find.byType(IngredientsWidget), findsOneWidget);
|
|
});
|
|
});
|
|
|
|
group('StepsWidget', () {
|
|
testWidgets('should display StepsWidget with steps', (WidgetTester tester) async {
|
|
await mockNetworkImagesFor(() async {
|
|
// Arrange
|
|
const recipe = recipes.Recipe(
|
|
id: 1,
|
|
image: 'test-image.jpg',
|
|
state: 'active',
|
|
cookingTime: 30,
|
|
activeCookingTime: 15,
|
|
ingredients: [],
|
|
description: 'Test recipe',
|
|
steps: [
|
|
recipes.Step(image: 'step1.jpg', description: 'Step 1 description'),
|
|
recipes.Step(image: 'step2.jpg', description: 'Step 2 description'),
|
|
],
|
|
videoUrl: null,
|
|
createdAt: null,
|
|
updatedAt: null,
|
|
title: 'Test Recipe',
|
|
type: 'main',
|
|
slug: 'test-recipe',
|
|
commentsCount: 0,
|
|
wasLikedByMe: false,
|
|
isFavorite: false,
|
|
calories: 300.0,
|
|
servings: 4,
|
|
likesCount: 0,
|
|
viewsCount: 0,
|
|
tags: [],
|
|
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
|
|
);
|
|
const widget = StepsWidget(recipe: recipe);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(widget));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 100));
|
|
|
|
// Assert
|
|
expect(find.byType(StepsWidget), findsOneWidget);
|
|
expect(find.text('Step 1 description'), findsOneWidget);
|
|
expect(find.text('Step 2 description'), findsOneWidget);
|
|
});
|
|
await tester.pump(const Duration(milliseconds: 600));
|
|
});
|
|
|
|
testWidgets('should display StepsWidget with steps without images', (WidgetTester tester) async {
|
|
// Arrange
|
|
const recipe = recipes.Recipe(
|
|
id: 1,
|
|
image: 'test-image.jpg',
|
|
state: 'active',
|
|
cookingTime: 30,
|
|
activeCookingTime: 15,
|
|
ingredients: [],
|
|
description: 'Test recipe',
|
|
steps: [
|
|
recipes.Step(image: '', description: 'Step 1 description'),
|
|
recipes.Step(image: '', description: 'Step 2 description'),
|
|
],
|
|
videoUrl: null,
|
|
createdAt: null,
|
|
updatedAt: null,
|
|
title: 'Test Recipe',
|
|
type: 'main',
|
|
slug: 'test-recipe',
|
|
commentsCount: 0,
|
|
wasLikedByMe: false,
|
|
isFavorite: false,
|
|
calories: 300.0,
|
|
servings: 4,
|
|
likesCount: 0,
|
|
viewsCount: 0,
|
|
tags: [],
|
|
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
|
|
);
|
|
const widget = StepsWidget(recipe: recipe);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(widget));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 100));
|
|
|
|
// Assert
|
|
expect(find.byType(StepsWidget), findsOneWidget);
|
|
expect(find.text('Step 1 description'), findsOneWidget);
|
|
expect(find.text('Step 2 description'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display StepsWidget with empty steps', (WidgetTester tester) async {
|
|
// Arrange
|
|
const recipe = recipes.Recipe(
|
|
id: 1,
|
|
image: 'test-image.jpg',
|
|
state: 'active',
|
|
cookingTime: 30,
|
|
activeCookingTime: 15,
|
|
ingredients: [],
|
|
description: 'Test recipe',
|
|
steps: [],
|
|
videoUrl: null,
|
|
createdAt: null,
|
|
updatedAt: null,
|
|
title: 'Test Recipe',
|
|
type: 'main',
|
|
slug: 'test-recipe',
|
|
commentsCount: 0,
|
|
wasLikedByMe: false,
|
|
isFavorite: false,
|
|
calories: 300.0,
|
|
servings: 4,
|
|
likesCount: 0,
|
|
viewsCount: 0,
|
|
tags: [],
|
|
author: Author(authorSlug: '', authorName: '', authorProfileIcon: '', authorIsMe: false),
|
|
);
|
|
const widget = StepsWidget(recipe: recipe);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(widget));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 100));
|
|
|
|
// Assert
|
|
expect(find.byType(StepsWidget), findsOneWidget);
|
|
});
|
|
});
|
|
});
|
|
}
|