From 4340b0aff2a2f0907354b895e680590ca20d72b1 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 29 Dec 2025 15:37:19 +0700 Subject: [PATCH] TF-4141 Add widget test for displaying tag of action required in mobile, web, tablet view --- .../email_tile_builder_ai_action_test.dart | 164 ++++++++++++++++++ test/fixtures/widget_fixtures.dart | 43 ++++- 2 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 test/features/thread/presentation/widgets/email_tile_builder_ai_action_test.dart diff --git a/test/features/thread/presentation/widgets/email_tile_builder_ai_action_test.dart b/test/features/thread/presentation/widgets/email_tile_builder_ai_action_test.dart new file mode 100644 index 000000000..22707dc85 --- /dev/null +++ b/test/features/thread/presentation/widgets/email_tile_builder_ai_action_test.dart @@ -0,0 +1,164 @@ +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:model/email/presentation_email.dart'; +import 'package:model/extensions/keyword_identifier_extension.dart'; +import 'package:model/mailbox/select_mode.dart'; +import 'package:tmail_ui_user/features/base/widget/labels/ai_action_tag_widget.dart'; +import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_web_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +import '../../../../fixtures/widget_fixtures.dart'; + +void main() { + setUpAll(() { + Get.put(ResponsiveUtils()); + Get.put(ImagePaths()); + }); + + group('EmailTileBuilder – AI Action tag display', () { + final emailWithNeedsAction = PresentationEmail( + id: EmailId(Id('email-needs-action')), + subject: 'Email needs-action', + keywords: { + KeyWordIdentifierExtension.needsActionMail: true, + }, + ); + + final emailWithoutNeedsAction = PresentationEmail( + id: EmailId(Id('email-normal')), + subject: 'Email normal', + ); + + group('when AI needs action enabled', () { + testWidgets('shows AI Action tag on mobile', (tester) async { + await WidgetFixtures.pumpResponsiveWidget( + tester, + WidgetFixtures.makeTestableWidget( + child: EmailTileBuilder( + presentationEmail: emailWithNeedsAction, + selectAllMode: SelectMode.INACTIVE, + isShowingEmailContent: false, + isAINeedsActionEnabled: true, + ), + ), + logicalSize: const Size(375, 812), + ); + + expect(find.byType(AiActionTagWidget), findsOneWidget); + + WidgetFixtures.resetResponsive(tester); + }); + + testWidgets('shows AI Action tag on tablet', (tester) async { + await WidgetFixtures.pumpResponsiveWidget( + tester, + WidgetFixtures.makeTestableWidget( + child: EmailTileBuilder( + presentationEmail: emailWithNeedsAction, + selectAllMode: SelectMode.INACTIVE, + isShowingEmailContent: false, + isAINeedsActionEnabled: true, + ), + ), + logicalSize: const Size(1024, 1366), + ); + + expect(find.byType(AiActionTagWidget), findsOneWidget); + + WidgetFixtures.resetResponsive(tester); + }); + + testWidgets('shows AI Action tag on desktop', (tester) async { + await WidgetFixtures.pumpResponsiveWidget( + tester, + WidgetFixtures.makeTestableWidget( + child: EmailTileBuilder( + presentationEmail: emailWithNeedsAction, + selectAllMode: SelectMode.INACTIVE, + isShowingEmailContent: false, + isAINeedsActionEnabled: true, + ), + ), + logicalSize: const Size(1920, 1080), + platform: TargetPlatform.macOS, + ); + + expect(find.byType(AiActionTagWidget), findsOneWidget); + + WidgetFixtures.resetResponsive(tester); + }); + + testWidgets( + 'does not show AI Action tag when email has no needs-action keyword', + (tester) async { + await WidgetFixtures.pumpResponsiveWidget( + tester, + WidgetFixtures.makeTestableWidget( + child: EmailTileBuilder( + presentationEmail: emailWithoutNeedsAction, + selectAllMode: SelectMode.INACTIVE, + isShowingEmailContent: false, + isAINeedsActionEnabled: true, + ), + ), + logicalSize: const Size(375, 812), + ); + + expect(find.byType(AiActionTagWidget), findsNothing); + + WidgetFixtures.resetResponsive(tester); + }, + ); + + testWidgets( + 'shows localized actionRequired text', + (tester) async { + await WidgetFixtures.pumpResponsiveWidget( + tester, + WidgetFixtures.makeTestableWidget( + child: EmailTileBuilder( + presentationEmail: emailWithNeedsAction, + selectAllMode: SelectMode.INACTIVE, + isShowingEmailContent: false, + isAINeedsActionEnabled: true, + ), + ), + logicalSize: const Size(375, 812), + ); + + final context = tester.element(find.byType(EmailTileBuilder)); + final expectedText = AppLocalizations.of(context).actionRequired; + + expect(find.text(expectedText), findsOneWidget); + + WidgetFixtures.resetResponsive(tester); + }, + ); + }); + + group('when AI needs action disabled', () { + testWidgets( + 'does not show AI Action tag', + (tester) async { + await tester.pumpWidget( + WidgetFixtures.makeTestableWidget( + child: EmailTileBuilder( + presentationEmail: emailWithNeedsAction, + selectAllMode: SelectMode.INACTIVE, + isShowingEmailContent: false, + isAINeedsActionEnabled: false, + ), + ), + ); + + expect(find.byType(AiActionTagWidget), findsNothing); + }, + ); + }); + }); +} diff --git a/test/fixtures/widget_fixtures.dart b/test/fixtures/widget_fixtures.dart index d651d4eaa..8fdec8642 100644 --- a/test/fixtures/widget_fixtures.dart +++ b/test/fixtures/widget_fixtures.dart @@ -1,6 +1,7 @@ - +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations_delegate.dart'; import 'package:tmail_ui_user/main/localizations/localization_service.dart'; @@ -19,4 +20,42 @@ class WidgetFixtures { home: Scaffold(body: child), ); } -} \ No newline at end of file + + static Future setupResponsive( + WidgetTester tester, { + required Size logicalSize, + TargetPlatform? platform, + }) async { + if (platform != null) { + debugDefaultTargetPlatformOverride = platform; + } + + final dpi = tester.view.devicePixelRatio; + tester.view.physicalSize = + Size(logicalSize.width * dpi, logicalSize.height * dpi); + + await tester.pump(); + } + + static void resetResponsive(WidgetTester tester) { + debugDefaultTargetPlatformOverride = null; + tester.view.reset(); + } + + static Future pumpResponsiveWidget( + WidgetTester tester, + Widget widget, { + required Size logicalSize, + TargetPlatform? platform, + }) async { + await tester.pumpWidget(widget); + + await WidgetFixtures.setupResponsive( + tester, + logicalSize: logicalSize, + platform: platform, + ); + + await tester.pump(); + } +}