Skip to content

TF-3563 E2E download attachment and view inline image in EmailView #3568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: patrol-integration-test
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions integration_test/mixin/scenario_utils_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ mixin ScenarioUtilsMixin {
return file.writeAsBytes(bytes);
}

Future<File> generateImageFromBase64({
required String fileName,
required String base64Data,
}) async {
final bytes = base64Decode(base64Data);
final directory = await getTemporaryDirectory();
final file = File('${directory.path}/$fileName');
return file.writeAsBytes(bytes);
}

Future<List<Attachment>> uploadAttachments(
List<String> attachmentPaths
) async {
Expand Down
6 changes: 6 additions & 0 deletions integration_test/resources/image_resources.dart

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions integration_test/robots/composer_robot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_s
import 'package:tmail_ui_user/features/composer/presentation/widgets/subject_composer_widget.dart';
import 'package:tmail_ui_user/features/upload/domain/state/local_image_picker_state.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';

import '../base/core_robot.dart';
import '../extensions/patrol_finder_extension.dart';
Expand Down Expand Up @@ -126,4 +127,19 @@ class ComposerRobot extends CoreRobot {
fileName: file.path.split('/').last,
)));
}

Future<void> addInlineImageFromFile(File file) async {
final controller = getBinding<ComposerController>();

final filePath = file.path;
final fileSize = await file.length();
final fileName = filePath.split('/').last;

final fileInfo = FileInfo(
filePath: filePath,
fileSize: fileSize,
fileName: fileName,
);
controller?.handleSuccessViewState(LocalImagePickerSuccess(fileInfo));
}
}
6 changes: 6 additions & 0 deletions integration_test/robots/email_robot.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_item_widget.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';

Expand Down Expand Up @@ -60,4 +62,8 @@ class EmailRobot extends CoreRobot {
Future<void> tapArchiveMessageOptionInContextMenu() async {
await $(#archiveMessage_action).tap();
}

Future<void> onTapAttachmentItem() async {
await $(AttachmentItemWidget).$(InkWell).tap();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_item_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';

import '../../base/base_test_scenario.dart';
import '../../models/provisioning_email.dart';
import '../../robots/email_robot.dart';
import '../../robots/thread_robot.dart';

class ExportAttachmentScenario extends BaseTestScenario {

const ExportAttachmentScenario(super.$);

@override
Future<void> runTestLogic() async {
const subject = 'export attachment';
const attachmentContent = 'attachment content';
const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL');
final threadRobot = ThreadRobot($);
final emailRobot = EmailRobot($);
final appLocalizations = AppLocalizations();

final attachmentFile = await preparingTxtFile(attachmentContent);
await provisionEmail(
[
ProvisioningEmail(
toEmail: emailUser,
subject: subject,
content: subject,
attachmentPaths: [attachmentFile.path],
),
],
requestReadReceipt: false,
);
await $.pumpAndSettle();

await threadRobot.openEmailWithSubject(subject);
await $.pumpAndSettle();
_expectAttachmentVisible();

await emailRobot.onTapAttachmentItem();
await $.pumpAndSettle();

await $.native.pressBack();
_expectEmailViewVisible();
_expectExportDialogLoadingInvisible(appLocalizations);
}

void _expectAttachmentVisible() {
expect($(AttachmentItemWidget), findsOneWidget);
}

void _expectEmailViewVisible() {
expect($(EmailView).visible, isTrue);
}

void _expectExportDialogLoadingInvisible(AppLocalizations appLocalizations) {
expect($(appLocalizations.preparing_to_export).visible, isFalse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.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_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';

import '../../base/base_test_scenario.dart';
import '../../resources/image_resources.dart';
import '../../robots/composer_robot.dart';
import '../../robots/thread_robot.dart';

class ViewInlineImageScenario extends BaseTestScenario {

const ViewInlineImageScenario(super.$);

@override
Future<void> runTestLogic() async {
const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL');
const emailSubject = 'View inline image in email view';

final threadRobot = ThreadRobot($);
final composerRobot = ComposerRobot($);
final imagePaths = ImagePaths();

await _createEmailWithInlineImage(
threadRobot: threadRobot,
composerRobot: composerRobot,
imagePaths: imagePaths,
emailUser: emailUser,
emailSubject: emailSubject,
);

await threadRobot.openEmailWithSubject(emailSubject);
await $.pumpAndSettle(duration: const Duration(seconds: 3));
await _expectEmailViewWithCidImageVisible();
}

Future<void> _createEmailWithInlineImage({
required ThreadRobot threadRobot,
required ComposerRobot composerRobot,
required ImagePaths imagePaths,
required String emailUser,
required String emailSubject,
}) async {
await threadRobot.openComposer();
await _expectComposerViewVisible();

await composerRobot.grantContactPermission();

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

final imageFile = await generateImageFromBase64(
fileName: 'inline-image.png',
base64Data: ImageResources.base64,
);
await composerRobot.addInlineImageFromFile(imageFile);
await $.pumpAndSettle(duration: const Duration(seconds: 3));

await _expectInlineImageVisible();

await composerRobot.sendEmail(imagePaths);
await $.pumpAndSettle(duration: const Duration(seconds: 3));

await _expectEmailWithInlineImageVisible(emailSubject);
}

Future<void> _expectComposerViewVisible() => expectViewVisible($(ComposerView));

Future<void> _expectInlineImageVisible() async {
final currentHtmlContent = await getBinding<ComposerController>()?.getContentInEditor() ?? '';
expect(
currentHtmlContent.contains('data:image/') &&
currentHtmlContent.contains(';base64') &&
currentHtmlContent.contains('cid:'),
isTrue,
);
}

Future<void> _expectEmailWithInlineImageVisible(String emailSubject) async {
await expectViewVisible(
$(EmailTileBuilder).which<EmailTileBuilder>(
(widget) => widget.presentationEmail.subject == emailSubject),
);
}

Future<void> _expectEmailViewWithCidImageVisible() 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, 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import '../../base/test_base.dart';
import '../../scenarios/email_detailed/export_attachment_scenario.dart';

void main() {
TestBase().runPatrolTest(
description: 'Should auto preview attachment when export attachment successfully',
scenarioBuilder: ($) => ExportAttachmentScenario($),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import '../../base/test_base.dart';
import '../../scenarios/email_detailed/view_inline_image_scenario.dart';

void main() {
TestBase().runPatrolTest(
description: 'Should see inline image when open email with inline image',
scenarioBuilder: ($) => ViewInlineImageScenario($),
);
}
Loading