Skip to content

Commit 4aef169

Browse files
dab246hoangdat
authored andcommitted
TF-3514 Add integration test for reply email with content contain image base64
Signed-off-by: dab246 <[email protected]>
1 parent 423a6d6 commit 4aef169

11 files changed

+9339
-5699
lines changed

integration_test/robots/email_robot.dart

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_back_button.dart';
23
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
34

45
import '../base/core_robot.dart';
@@ -15,4 +16,12 @@ class EmailRobot extends CoreRobot {
1516
await $(AppLocalizations().downloadAll).tap();
1617
await $.pumpAndSettle();
1718
}
19+
20+
Future<void> onTapReplyEmail() async {
21+
await $(#reply_email_button).tap();
22+
}
23+
24+
Future<void> onTapBackButton() async {
25+
await $(find.byType(EmailViewBackButton)).first.tap();
26+
}
1827
}

integration_test/robots/search_robot.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ class SearchRobot extends CoreRobot {
7575
}
7676

7777
Future<void> openEmailWithSubject(String subject) async {
78-
await $(find.byType(EmailTileBuilder)).first.tap();
78+
await $(find.byType(EmailTileBuilder))
79+
.which<EmailTileBuilder>((view) => view.presentationEmail.subject == subject)
80+
.first
81+
.tap();
7982
await $.pump(const Duration(seconds: 2));
8083
}
8184
}

integration_test/robots/thread_robot.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ class ThreadRobot extends CoreRobot {
2323
}
2424

2525
Future<void> openEmailWithSubject(String subject) async {
26-
await $(find.byType(EmailTileBuilder)).first.tap();
26+
await $(find.byType(EmailTileBuilder))
27+
.which<EmailTileBuilder>((view) => view.presentationEmail.subject == subject)
28+
.first
29+
.tap();
2730
await $.pump(const Duration(seconds: 2));
2831
}
2932

integration_test/scenarios/no_disposition_inline_scenario.dart

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
2+
import 'package:flutter/material.dart';
23
import 'package:flutter_test/flutter_test.dart';
34
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
45
import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart';
@@ -8,13 +9,12 @@ import '../robots/search_robot.dart';
89
import '../robots/thread_robot.dart';
910

1011
class NoDispositionInlineScenario extends BaseTestScenario {
11-
static const _firstPartOfBase64DataString = 'data:image/jpeg;base64';
12-
static const emailSubject = 'Greeting Card';
13-
1412
const NoDispositionInlineScenario(super.$);
1513

1614
@override
1715
Future<void> runTestLogic() async {
16+
const emailSubject = 'Greeting Card';
17+
1818
final threadRobot = ThreadRobot($);
1919
final searchRobot = SearchRobot($);
2020

@@ -27,7 +27,7 @@ class NoDispositionInlineScenario extends BaseTestScenario {
2727

2828
await searchRobot.openEmailWithSubject(emailSubject);
2929
await _expectEmailViewVisible();
30-
await _expectHtmlContentViewerVisible();
30+
await _ensureHtmlContentViewerVisible();
3131
await _expectEmailViewWithBase64Image();
3232
}
3333

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

46-
Future<void> _expectHtmlContentViewerVisible() async {
47-
await expectViewVisible($(HtmlContentViewer));
46+
Future<void> _ensureHtmlContentViewerVisible() async {
47+
await $(HtmlContentViewer).scrollTo(scrollDirection: AxisDirection.down);
4848
}
4949

5050
Future<void> _expectEmailViewWithBase64Image() async {
5151
expect(
52-
$(EmailView)
53-
.$(HtmlContentViewer)
52+
$(HtmlContentViewer)
5453
.which<HtmlContentViewer>((view) {
55-
return view.contentHtml.contains(_firstPartOfBase64DataString);
54+
final contentHtml = view.contentHtml;
55+
56+
return contentHtml.contains('data:image/') && contentHtml.contains(';base64');
5657
}),
5758
findsOneWidget,
5859
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import 'package:core/presentation/resources/image_paths.dart';
2+
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_test/flutter_test.dart';
5+
import 'package:model/email/prefix_email_address.dart';
6+
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
7+
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
8+
import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart';
9+
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
10+
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
11+
12+
import '../base/base_test_scenario.dart';
13+
import '../robots/composer_robot.dart';
14+
import '../robots/email_robot.dart';
15+
import '../robots/search_robot.dart';
16+
import '../robots/thread_robot.dart';
17+
18+
class ReplyEmailWithContentContainImageBase64DataScenario extends BaseTestScenario {
19+
const ReplyEmailWithContentContainImageBase64DataScenario(super.$);
20+
21+
@override
22+
Future<void> runTestLogic() async {
23+
const emailSubject = 'Mail with base64';
24+
const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL');
25+
26+
final threadRobot = ThreadRobot($);
27+
final searchRobot = SearchRobot($);
28+
final emailRobot = EmailRobot($);
29+
final composerRobot = ComposerRobot($);
30+
final imagePaths = ImagePaths();
31+
final appLocalizations = AppLocalizations();
32+
33+
await threadRobot.openSearchView();
34+
await _expectSearchViewVisible();
35+
36+
await searchRobot.enterQueryString(emailSubject);
37+
await searchRobot.tapOnShowAllResultsText();
38+
await _expectSearchResultEmailListVisible();
39+
40+
await searchRobot.openEmailWithSubject(emailSubject);
41+
await _expectEmailViewVisible();
42+
await _expectReplyEmailButtonVisible();
43+
44+
await emailRobot.onTapReplyEmail();
45+
await _expectComposerViewVisible();
46+
47+
await composerRobot.grantContactPermission();
48+
49+
await composerRobot.addRecipientIntoField(
50+
prefixEmailAddress: PrefixEmailAddress.to,
51+
email: emailUser,
52+
);
53+
54+
await composerRobot.sendEmail(imagePaths);
55+
await _expectSendEmailSuccessToast(appLocalizations);
56+
await Future.delayed(const Duration(seconds: 3));
57+
58+
await emailRobot.onTapBackButton();
59+
await $.pumpAndSettle(duration: const Duration(seconds: 3));
60+
await _expectEmailCidWithSubject(emailSubject);
61+
62+
await threadRobot.openEmailWithSubject(
63+
'${appLocalizations.prefix_reply_email} $emailSubject'
64+
);
65+
await _expectEmailViewVisible();
66+
await Future.delayed(const Duration(seconds: 3));
67+
await _ensureHtmlContentViewerVisible();
68+
await _expectEmailViewWithCidImage();
69+
}
70+
71+
Future<void> _expectSearchViewVisible() async {
72+
await expectViewVisible($(SearchEmailView));
73+
}
74+
75+
Future<void> _expectSearchResultEmailListVisible() async {
76+
await expectViewVisible($(#search_email_list_notification_listener));
77+
}
78+
79+
Future<void> _expectEmailViewVisible() async {
80+
await expectViewVisible($(EmailView));
81+
}
82+
83+
Future<void> _expectReplyEmailButtonVisible() async {
84+
await expectViewVisible($(#reply_email_button));
85+
}
86+
87+
Future<void> _expectComposerViewVisible() async {
88+
await expectViewVisible($(ComposerView));
89+
}
90+
91+
Future<void> _expectSendEmailSuccessToast(AppLocalizations appLocalizations) async {
92+
await expectViewVisible(
93+
$(find.text(appLocalizations.message_has_been_sent_successfully)),
94+
);
95+
}
96+
97+
Future<void> _expectEmailCidWithSubject(String subject) => expectViewVisible(
98+
$(EmailTileBuilder)
99+
.which<EmailTileBuilder>(
100+
(widget) => widget.presentationEmail.subject?.contains(subject) == true
101+
),
102+
);
103+
104+
Future<void> _ensureHtmlContentViewerVisible() async {
105+
await $(HtmlContentViewer).scrollTo(scrollDirection: AxisDirection.down);
106+
}
107+
108+
Future<void> _expectEmailViewWithCidImage() async {
109+
HtmlContentViewer? htmlContentViewer;
110+
111+
await $(HtmlContentViewer)
112+
.which<HtmlContentViewer>((view) {
113+
htmlContentViewer = view;
114+
return true;
115+
})
116+
.first
117+
.tap();
118+
119+
final contentHtml = htmlContentViewer!.contentHtml;
120+
final cidCount = RegExp(r'cid').allMatches(contentHtml).length;
121+
expect(cidCount, 2);
122+
}
123+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import '../../base/test_base.dart';
2+
import '../../scenarios/reply_email_with_content_contain_image_base64_data_scenario.dart';
3+
4+
void main() {
5+
TestBase().runPatrolTest(
6+
description: 'Should see inline image with cid when reply email with content contain image base64 data',
7+
scenarioBuilder: ($) => ReplyEmailWithContentContainImageBase64DataScenario($),
8+
);
9+
}

lib/main/bindings/network/network_bindings.dart

-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:flutter/foundation.dart';
1010
import 'package:flutter_appauth/flutter_appauth.dart';
1111
import 'package:get/get.dart';
1212
import 'package:jmap_dart_client/http/http_client.dart';
13-
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
1413
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
1514
import 'package:tmail_ui_user/features/email/data/network/mdn_api.dart';
1615
import 'package:tmail_ui_user/features/home/data/network/session_api.dart';
@@ -37,7 +36,6 @@ import 'package:tmail_ui_user/features/push_notification/data/network/web_socket
3736
import 'package:tmail_ui_user/features/quotas/data/network/quotas_api.dart';
3837
import 'package:tmail_ui_user/features/server_settings/data/network/server_settings_api.dart';
3938
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
40-
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
4139
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
4240
import 'package:tmail_ui_user/main/exceptions/send_email_exception_thrower.dart';
4341
import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
@@ -129,11 +127,6 @@ class NetworkBindings extends Bindings {
129127
Get.put(ServerSettingsAPI(Get.find<HttpClient>()));
130128
Get.put(WebSocketApi(Get.find<DioClient>()));
131129
Get.put(LinagoraEcosystemApi(Get.find<DioClient>()));
132-
Get.put(FileUploader(
133-
Get.find<DioClient>(),
134-
Get.find<Executor>(),
135-
Get.find<FileUtils>(),
136-
));
137130
}
138131

139132
void _bindingConnection() {
@@ -148,11 +141,6 @@ class NetworkBindings extends Bindings {
148141
void _bindingTransformer() {
149142
Get.put(const HtmlEscape());
150143
Get.put(HtmlTransform(Get.find<DioClient>(), Get.find<HtmlEscape>()));
151-
Get.put(HtmlAnalyzer(
152-
Get.find<HtmlTransform>(),
153-
Get.find<FileUploader>(),
154-
Get.find<Uuid>(),
155-
));
156144
}
157145

158146
void _bindingServices() {

lib/main/bindings/network/network_isolate_binding.dart

+21-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
44
import 'package:flutter_appauth/flutter_appauth.dart';
55
import 'package:get/get.dart';
66
import 'package:jmap_dart_client/http/http_client.dart';
7+
import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
78
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
89
import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart';
910
import 'package:tmail_ui_user/features/login/data/local/authentication_info_cache_manager.dart';
@@ -19,6 +20,7 @@ import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_work
1920
import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_manager.dart';
2021
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
2122
import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart';
23+
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
2224
import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart';
2325
import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
2426
import 'package:uuid/uuid.dart';
@@ -33,6 +35,7 @@ class NetworkIsolateBindings extends Bindings {
3335
_bindingInterceptors();
3436
_bindingApi();
3537
_bindingIsolateWorker();
38+
_bindingTransformer();
3639
}
3740

3841
void _bindingDio() {
@@ -84,18 +87,24 @@ class NetworkIsolateBindings extends Bindings {
8487
Get.find<DioClient>(tag: BindingTag.isolateTag),
8588
Get.find<Uuid>()
8689
), tag: BindingTag.isolateTag);
90+
8791
}
8892

8993
void _bindingIsolateWorker() {
9094
Get.put(ThreadIsolateWorker(
91-
Get.find<ThreadAPI>(tag: BindingTag.isolateTag),
92-
Get.find<EmailAPI>(tag: BindingTag.isolateTag),
95+
Get.find<ThreadAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
96+
Get.find<EmailAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
9397
Get.find<Executor>(),
9498
));
9599
Get.put(MailboxIsolateWorker(
96-
Get.find<ThreadAPI>(tag: BindingTag.isolateTag),
97-
Get.find<EmailAPI>(tag: BindingTag.isolateTag),
100+
Get.find<ThreadAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
101+
Get.find<EmailAPI>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
102+
Get.find<Executor>(),
103+
));
104+
Get.put(FileUploader(
105+
Get.find<DioClient>(tag: PlatformInfo.isMobile ? BindingTag.isolateTag : null),
98106
Get.find<Executor>(),
107+
Get.find<FileUtils>(),
99108
));
100109
}
101110

@@ -113,4 +122,12 @@ class NetworkIsolateBindings extends Bindings {
113122
Get.find<MailboxCacheManager>(),
114123
), tag: BindingTag.isolateTag);
115124
}
125+
126+
void _bindingTransformer() {
127+
Get.put(HtmlAnalyzer(
128+
Get.find<HtmlTransform>(),
129+
Get.find<FileUploader>(),
130+
Get.find<Uuid>(),
131+
));
132+
}
116133
}

0 commit comments

Comments
 (0)