Skip to content

Commit

Permalink
TF-3514 Add integration test for reply email with content contain ima…
Browse files Browse the repository at this point in the history
…ge base64

Signed-off-by: dab246 <[email protected]>
  • Loading branch information
dab246 committed Mar 6, 2025
1 parent 70c5273 commit 474357e
Show file tree
Hide file tree
Showing 11 changed files with 9,339 additions and 5,699 deletions.
9 changes: 9 additions & 0 deletions integration_test/robots/email_robot.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_back_button.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';

import '../base/core_robot.dart';
Expand All @@ -15,4 +16,12 @@ class EmailRobot extends CoreRobot {
await $(AppLocalizations().downloadAll).tap();
await $.pumpAndSettle();
}

Future<void> onTapReplyEmail() async {
await $(#reply_email_button).tap();
}

Future<void> onTapBackButton() async {
await $(find.byType(EmailViewBackButton)).first.tap();
}
}
5 changes: 4 additions & 1 deletion integration_test/robots/search_robot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ class SearchRobot extends CoreRobot {
}

Future<void> openEmailWithSubject(String subject) async {
await $(find.byType(EmailTileBuilder)).first.tap();
await $(find.byType(EmailTileBuilder))
.which<EmailTileBuilder>((view) => view.presentationEmail.subject == subject)
.first
.tap();
await $.pump(const Duration(seconds: 2));
}
}
5 changes: 4 additions & 1 deletion integration_test/robots/thread_robot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class ThreadRobot extends CoreRobot {
}

Future<void> openEmailWithSubject(String subject) async {
await $(find.byType(EmailTileBuilder)).first.tap();
await $(find.byType(EmailTileBuilder))
.which<EmailTileBuilder>((view) => view.presentationEmail.subject == subject)
.first
.tap();
await $.pump(const Duration(seconds: 2));
}

Expand Down
19 changes: 10 additions & 9 deletions integration_test/scenarios/no_disposition_inline_scenario.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart';
Expand All @@ -8,13 +9,12 @@ import '../robots/search_robot.dart';
import '../robots/thread_robot.dart';

class NoDispositionInlineScenario extends BaseTestScenario {
static const _firstPartOfBase64DataString = 'data:image/jpeg;base64';
static const emailSubject = 'Greeting Card';

const NoDispositionInlineScenario(super.$);

@override
Future<void> runTestLogic() async {
const emailSubject = 'Greeting Card';

final threadRobot = ThreadRobot($);
final searchRobot = SearchRobot($);

Expand All @@ -27,7 +27,7 @@ class NoDispositionInlineScenario extends BaseTestScenario {

await searchRobot.openEmailWithSubject(emailSubject);
await _expectEmailViewVisible();
await _expectHtmlContentViewerVisible();
await _ensureHtmlContentViewerVisible();
await _expectEmailViewWithBase64Image();
}

Expand All @@ -43,16 +43,17 @@ class NoDispositionInlineScenario extends BaseTestScenario {
await expectViewVisible($(EmailView));
}

Future<void> _expectHtmlContentViewerVisible() async {
await expectViewVisible($(HtmlContentViewer));
Future<void> _ensureHtmlContentViewerVisible() async {
await $(HtmlContentViewer).scrollTo(scrollDirection: AxisDirection.down);
}

Future<void> _expectEmailViewWithBase64Image() async {
expect(
$(EmailView)
.$(HtmlContentViewer)
$(HtmlContentViewer)
.which<HtmlContentViewer>((view) {
return view.contentHtml.contains(_firstPartOfBase64DataString);
final contentHtml = view.contentHtml;

return contentHtml.contains('data:image/') && contentHtml.contains(';base64');
}),
findsOneWidget,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:model/email/prefix_email_address.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';

import '../base/base_test_scenario.dart';
import '../robots/composer_robot.dart';
import '../robots/email_robot.dart';
import '../robots/search_robot.dart';
import '../robots/thread_robot.dart';

class ReplyEmailWithContentContainImageBase64DataScenario extends BaseTestScenario {
const ReplyEmailWithContentContainImageBase64DataScenario(super.$);

@override
Future<void> runTestLogic() async {
const emailSubject = 'Mail with base64';
const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL');

final threadRobot = ThreadRobot($);
final searchRobot = SearchRobot($);
final emailRobot = EmailRobot($);
final composerRobot = ComposerRobot($);
final imagePaths = ImagePaths();
final appLocalizations = AppLocalizations();

await threadRobot.openSearchView();
await _expectSearchViewVisible();

await searchRobot.enterQueryString(emailSubject);
await searchRobot.tapOnShowAllResultsText();
await _expectSearchResultEmailListVisible();

await searchRobot.openEmailWithSubject(emailSubject);
await _expectEmailViewVisible();
await _expectReplyEmailButtonVisible();

await emailRobot.onTapReplyEmail();
await _expectComposerViewVisible();

await composerRobot.grantContactPermission();

await composerRobot.addRecipientIntoField(
prefixEmailAddress: PrefixEmailAddress.to,
email: emailUser,
);

await composerRobot.sendEmail(imagePaths);
await _expectSendEmailSuccessToast(appLocalizations);
await Future.delayed(const Duration(seconds: 3));

await emailRobot.onTapBackButton();
await $.pumpAndSettle(duration: const Duration(seconds: 3));
await _expectEmailCidWithSubject(emailSubject);

await threadRobot.openEmailWithSubject(
'${appLocalizations.prefix_reply_email} $emailSubject'
);
await _expectEmailViewVisible();
await Future.delayed(const Duration(seconds: 3));
await _ensureHtmlContentViewerVisible();
await _expectEmailViewWithCidImage();
}

Future<void> _expectSearchViewVisible() async {
await expectViewVisible($(SearchEmailView));
}

Future<void> _expectSearchResultEmailListVisible() async {
await expectViewVisible($(#search_email_list_notification_listener));
}

Future<void> _expectEmailViewVisible() async {
await expectViewVisible($(EmailView));
}

Future<void> _expectReplyEmailButtonVisible() async {
await expectViewVisible($(#reply_email_button));
}

Future<void> _expectComposerViewVisible() async {
await expectViewVisible($(ComposerView));
}

Future<void> _expectSendEmailSuccessToast(AppLocalizations appLocalizations) async {
await expectViewVisible(
$(find.text(appLocalizations.message_has_been_sent_successfully)),
);
}

Future<void> _expectEmailCidWithSubject(String subject) => expectViewVisible(
$(EmailTileBuilder)
.which<EmailTileBuilder>(
(widget) => widget.presentationEmail.subject?.contains(subject) == true
),
);

Future<void> _ensureHtmlContentViewerVisible() async {
await $(HtmlContentViewer).scrollTo(scrollDirection: AxisDirection.down);
}

Future<void> _expectEmailViewWithCidImage() async {
HtmlContentViewer? htmlContentViewer;

await $(HtmlContentViewer)
.which<HtmlContentViewer>((view) {
htmlContentViewer = view;
return true;
})
.first
.tap();

final contentHtml = htmlContentViewer!.contentHtml;
final cidCount = RegExp(r'cid').allMatches(contentHtml).length;
expect(cidCount, 2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import '../../base/test_base.dart';
import '../../scenarios/reply_email_with_content_contain_image_base64_data_scenario.dart';

void main() {
TestBase().runPatrolTest(
description: 'Should see inline image with cid when reply email with content contain image base64 data',
scenarioBuilder: ($) => ReplyEmailWithContentContainImageBase64DataScenario($),
);
}
12 changes: 0 additions & 12 deletions lib/main/bindings/network/network_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter_appauth/flutter_appauth.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/email/data/network/mdn_api.dart';
import 'package:tmail_ui_user/features/home/data/network/session_api.dart';
Expand All @@ -37,7 +36,6 @@ import 'package:tmail_ui_user/features/push_notification/data/network/web_socket
import 'package:tmail_ui_user/features/quotas/data/network/quotas_api.dart';
import 'package:tmail_ui_user/features/server_settings/data/network/server_settings_api.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
import 'package:tmail_ui_user/main/exceptions/send_email_exception_thrower.dart';
import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
Expand Down Expand Up @@ -129,11 +127,6 @@ class NetworkBindings extends Bindings {
Get.put(ServerSettingsAPI(Get.find<HttpClient>()));
Get.put(WebSocketApi(Get.find<DioClient>()));
Get.put(LinagoraEcosystemApi(Get.find<DioClient>()));
Get.put(FileUploader(
Get.find<DioClient>(),
Get.find<Executor>(),
Get.find<FileUtils>(),
));
}

void _bindingConnection() {
Expand All @@ -148,11 +141,6 @@ class NetworkBindings extends Bindings {
void _bindingTransformer() {
Get.put(const HtmlEscape());
Get.put(HtmlTransform(Get.find<DioClient>(), Get.find<HtmlEscape>()));
Get.put(HtmlAnalyzer(
Get.find<HtmlTransform>(),
Get.find<FileUploader>(),
Get.find<Uuid>(),
));
}

void _bindingServices() {
Expand Down
25 changes: 21 additions & 4 deletions lib/main/bindings/network/network_isolate_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
import 'package:flutter_appauth/flutter_appauth.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart';
import 'package:tmail_ui_user/features/login/data/local/authentication_info_cache_manager.dart';
Expand All @@ -19,6 +20,7 @@ import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_work
import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_manager.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart';
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart';
import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
import 'package:uuid/uuid.dart';
Expand All @@ -33,6 +35,7 @@ class NetworkIsolateBindings extends Bindings {
_bindingInterceptors();
_bindingApi();
_bindingIsolateWorker();
_bindingTransformer();
}

void _bindingDio() {
Expand Down Expand Up @@ -84,18 +87,24 @@ class NetworkIsolateBindings extends Bindings {
Get.find<DioClient>(tag: BindingTag.isolateTag),
Get.find<Uuid>()
), tag: BindingTag.isolateTag);

}

void _bindingIsolateWorker() {
Get.put(ThreadIsolateWorker(
Get.find<ThreadAPI>(tag: BindingTag.isolateTag),
Get.find<EmailAPI>(tag: BindingTag.isolateTag),
Get.find<ThreadAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
Get.find<EmailAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
Get.find<Executor>(),
));
Get.put(MailboxIsolateWorker(
Get.find<ThreadAPI>(tag: BindingTag.isolateTag),
Get.find<EmailAPI>(tag: BindingTag.isolateTag),
Get.find<ThreadAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
Get.find<EmailAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
Get.find<Executor>(),
));
Get.put(FileUploader(
Get.find<DioClient>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
Get.find<Executor>(),
Get.find<FileUtils>(),
));
}

Expand All @@ -113,4 +122,12 @@ class NetworkIsolateBindings extends Bindings {
Get.find<MailboxCacheManager>(),
), tag: BindingTag.isolateTag);
}

void _bindingTransformer() {
Get.put(HtmlAnalyzer(
Get.find<HtmlTransform>(),
Get.find<FileUploader>(),
Get.find<Uuid>(),
));
}
}
Loading

0 comments on commit 474357e

Please sign in to comment.