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/diets/presentation/widgets/author_card.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/type_badges.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/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('Diets Widgets Tests', () { setUp(() async { await sl.reset(); dotenv.loadFromString(envString: 'DEV_BASE_URL=http://localhost\nBASE_URL=http://localhost'); sl.registerLazySingleton(() => 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('InfoBouble', () { testWidgets('should display InfoBouble with children', (WidgetTester tester) async { // Arrange const widget = InfoBouble(children: [Text('Test Text')]); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); // Assert expect(find.byType(InfoBouble), findsOneWidget); expect(find.text('Test Text'), findsOneWidget); }); testWidgets('should display InfoBouble with multiple children', (WidgetTester tester) async { // Arrange const widget = InfoBouble(children: [Text('First'), Text('Second')]); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); // Assert expect(find.byType(InfoBouble), findsOneWidget); expect(find.text('First'), findsOneWidget); expect(find.text('Second'), findsOneWidget); }); testWidgets('should display InfoBouble with custom radius', (WidgetTester tester) async { // Arrange const widget = InfoBouble(radius: 20, children: [Text('Test')]); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); // Assert expect(find.byType(InfoBouble), findsOneWidget); expect(find.text('Test'), findsOneWidget); }); }); group('ExpandableText', () { testWidgets('should display ExpandableText with short text', (WidgetTester tester) async { // Arrange const widget = ExpandableText(text: 'Short text', maxLines: 5); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(ExpandableText), findsOneWidget); expect(find.text('Short text'), findsOneWidget); }); testWidgets('should display ExpandableText with long text', (WidgetTester tester) async { // Arrange const longText = 'This is a very long text that should be truncated and show an expand button when it exceeds the maximum number of lines specified in the widget. This text should be long enough to trigger the expand functionality.'; const widget = ExpandableText(text: longText, maxLines: 3); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 200)); // Assert expect(find.byType(ExpandableText), findsOneWidget); }); testWidgets('should toggle expansion when expand button is tapped', (WidgetTester tester) async { // Arrange const longText = 'This is a very long text that should be truncated and show an expand button when it exceeds the maximum number of lines specified in the widget. This text should be long enough to trigger the expand functionality.'; const widget = ExpandableText(text: longText, maxLines: 3); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 200)); // Try to find and tap expand button if it exists final expandButtons = find.text('Развернуть'); if (expandButtons.evaluate().isNotEmpty) { await tester.tap(expandButtons); await tester.pump(); await tester.pump(const Duration(milliseconds: 200)); } // Assert expect(find.byType(ExpandableText), findsOneWidget); }); }); group('AuthorCard', () { testWidgets('should display AuthorCard with author information', (WidgetTester tester) async { await mockNetworkImagesFor(() async { // Arrange const author = Author(authorSlug: 'test-author', authorName: 'Test Author', authorProfileIcon: 'https://example.com/icon.jpg', authorIsMe: false); const widget = AuthorCard(author: author, title: 'Автор'); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(AuthorCard), findsOneWidget); expect(find.text('Test Author'), findsOneWidget); expect(find.text('Автор'), findsOneWidget); }); await tester.pump(const Duration(milliseconds: 600)); }); testWidgets('should display AuthorCard with rating when available', (WidgetTester tester) async { await mockNetworkImagesFor(() async { // Arrange const author = Author( authorSlug: 'test-author', authorName: 'Test Author', authorProfileIcon: 'https://example.com/icon.jpg', authorIsMe: false, authorPlaceInRating: 5, ); const widget = AuthorCard(author: author, title: 'Автор'); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(AuthorCard), findsOneWidget); expect(find.text('Test Author'), findsOneWidget); }); await tester.pump(const Duration(milliseconds: 600)); }); }); group('TypeBadges', () { testWidgets('should display TypeBadges with diet type', (WidgetTester tester) async { // Arrange const dietType = DietType(light: true, veg: false, carb: false, meat: false); const widget = TypeBadges(type: dietType, disableDescriptionOfTypes: false); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(TypeBadges), findsOneWidget); }); testWidgets('should display TypeBadges with plan type', (WidgetTester tester) async { // Arrange const planType = PlanType(fit: true, slim: false, behavior: false, wellness: false); const widget = TypeBadges(planType: planType, disableDescriptionOfTypes: false); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(TypeBadges), findsOneWidget); }); testWidgets('should display TypeBadges with multiple types', (WidgetTester tester) async { // Arrange const dietType = DietType(light: true, veg: true, carb: false, meat: false); const widget = TypeBadges(type: dietType, disableDescriptionOfTypes: false); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(TypeBadges), findsOneWidget); }); testWidgets('should not show overlay when disableDescriptionOfTypes is true', (WidgetTester tester) async { // Arrange const dietType = DietType(light: true, veg: false, carb: false, meat: false); const widget = TypeBadges(type: dietType, disableDescriptionOfTypes: true); // Act await tester.pumpWidget(createTestWidget(widget)); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // Assert expect(find.byType(TypeBadges), findsOneWidget); }); }); }); }