TF-3369 Fix cid image without disposition (#3373)

This commit is contained in:
Dat Dang
2024-12-26 12:39:47 +07:00
committed by Dat H. Pham
parent f0e0869f96
commit 2d976bed18
8 changed files with 5761 additions and 4 deletions
@@ -24,8 +24,11 @@ Brief the logic flows to make it easier to track changes during `attachment` dis
2. Inline attachments: Displayed within the email body
- Display is only allowed when the following conditions are met:
- `cid is not NULL` AND `disposition = 'inline'`
- `cid is not NULL` AND `disposition = 'inline' || disposition = NULL`
## Consequences
- Any changes to attachment display while reading emails should be updated in this ADR.
## References
- [rfc2392](https://datatracker.ietf.org/doc/html/rfc2392)
+11
View File
@@ -19,4 +19,15 @@ class ThreadRobot extends CoreRobot {
Future<void> tapOnSearchField() async {
await $(ThreadView).$(SearchBarView).tap();
}
Future<void> openMailbox(String mailboxName) async {
await $(#mobile_mailbox_menu_button).tap();
await $.scrollUntilVisible(finder: $(mailboxName));
await $(mailboxName).tap();
}
Future<void> openEmailWithSubject(String subject) async {
await $.scrollUntilVisible(finder: $(subject));
await $(subject).tap();
}
}
@@ -0,0 +1,43 @@
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import '../base/base_scenario.dart';
import '../robots/search_robot.dart';
import '../robots/thread_robot.dart';
import 'login_with_basic_auth_scenario.dart';
class NoDispositionInlineScenario extends BaseScenario {
NoDispositionInlineScenario(
super.$, {
required this.loginWithBasicAuthScenario,
});
final LoginWithBasicAuthScenario loginWithBasicAuthScenario;
@override
Future<void> execute() async {
final threadRobot = ThreadRobot($);
final searchRobot = SearchRobot($);
await loginWithBasicAuthScenario.execute();
await threadRobot.openSearchView();
await searchRobot.enterQueryString('Greeting Card');
await $.pumpAndTrySettle();
await threadRobot.openEmailWithSubject('Greeting');
await $.pumpAndTrySettle();
_expectEmailViewWithBase64Image(_base64);
}
void _expectEmailViewWithBase64Image(String base64) {
expect(
$(EmailView)
.$(HtmlContentViewer)
.which<HtmlContentViewer>((view) => view.contentHtml.contains(base64)),
findsOneWidget,
);
}
static const _base64 = '''/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMAEAsMDgwKEA4NDhIREBM''';
}
@@ -0,0 +1,23 @@
import '../../base/test_base.dart';
import '../../scenarios/login_with_basic_auth_scenario.dart';
import '../../scenarios/no_disposition_inline_scenario.dart';
void main() {
TestBase().runPatrolTest(
description: 'Should see base64 inline image when attachment has no disposition but has cid',
test: ($) async {
final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($,
username: const String.fromEnvironment('USERNAME'),
hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'),
email: const String.fromEnvironment('BASIC_AUTH_EMAIL'),
password: const String.fromEnvironment('PASSWORD'),
);
final noDispositionInlineScenario = NoDispositionInlineScenario($,
loginWithBasicAuthScenario: loginWithBasicAuthScenario,
);
await noDispositionInlineScenario.execute();
}
);
}
+2
View File
@@ -39,6 +39,8 @@ class Attachment with EquatableMixin {
bool isDispositionInlined() => disposition == ContentDisposition.inline;
bool isDispositionUndefined() => disposition == null;
bool isApplicationRTFInlined() => type?.mimeType == applicationRTFType && isDispositionInlined();
String getDownloadUrl(String baseDownloadUrl, AccountId accountId) {
@@ -25,7 +25,7 @@ extension ListAttachmentExtension on List<Attachment> {
}
List<Attachment> get listAttachmentsDisplayedInContent =>
where((attachment) => attachment.hasCid() && attachment.isDispositionInlined())
where((attachment) => attachment.hasCid() && (attachment.isDispositionInlined() || attachment.isDispositionUndefined()))
.toList();
Map<String, String> toMapCidImageDownloadUrl({
@@ -2,7 +2,7 @@
# Define users and folders
users=("alice" "bob" "brian" "charlotte" "david" "emma")
bobFolders=("Search Emails" "Forward Emails")
bobFolders=("Search Emails" "Forward Emails" "Disposition")
# Add users
for user in "${users[@]}"; do
@@ -25,4 +25,9 @@ done
# For test forward email
# Import emails into 'Forward Emails' folder for user Bob
echo "Importing 0.eml into 'Forward Emails' folder for user bob"
james-cli ImportEml \#private "bob@example.com" "Forward Emails" "/root/conf/integration_test/eml/forward_email/0.eml"
james-cli ImportEml \#private "bob@example.com" "Forward Emails" "/root/conf/integration_test/eml/forward_email/0.eml"
# For test email with no-disposition inline image
# Import email into 'Disposition' folder for user Bob
echo "Importing no_disposition_inline.eml into 'Disposition' folder for user bob"
james-cli ImportEml \#private "bob@example.com" "Disposition" "/root/conf/integration_test/eml/no_disposition_inline/no_disposition_inline.eml"