TF-3413 Fix ReplyAll & Reply is buggy
This commit is contained in:
@@ -23,7 +23,6 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
@@ -647,8 +646,6 @@ class ComposerController extends BaseController
|
|||||||
_initEmailAddress(
|
_initEmailAddress(
|
||||||
presentationEmail: arguments.presentationEmail!,
|
presentationEmail: arguments.presentationEmail!,
|
||||||
actionType: arguments.emailActionType,
|
actionType: arguments.emailActionType,
|
||||||
mailboxRole: arguments.presentationEmail!.mailboxContain?.role
|
|
||||||
?? mailboxDashBoardController.selectedMailbox.value?.role,
|
|
||||||
listPost: arguments.listPost,
|
listPost: arguments.listPost,
|
||||||
);
|
);
|
||||||
_initSubjectEmail(
|
_initSubjectEmail(
|
||||||
@@ -802,32 +799,23 @@ class ComposerController extends BaseController
|
|||||||
void _initEmailAddress({
|
void _initEmailAddress({
|
||||||
required PresentationEmail presentationEmail,
|
required PresentationEmail presentationEmail,
|
||||||
required EmailActionType actionType,
|
required EmailActionType actionType,
|
||||||
Role? mailboxRole,
|
|
||||||
String? listPost,
|
String? listPost,
|
||||||
}) {
|
}) {
|
||||||
log('ComposerController::_initEmailAddress:listPost = $listPost');
|
final userName = mailboxDashBoardController.sessionCurrent?.username.value;
|
||||||
|
final isSender = presentationEmail.from
|
||||||
|
.asList()
|
||||||
|
.any((element) => element.emailAddress.isNotEmpty && element.emailAddress == userName);
|
||||||
|
|
||||||
final recipients = presentationEmail.generateRecipientsEmailAddressForComposer(
|
final recipients = presentationEmail.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: actionType,
|
emailActionType: actionType,
|
||||||
mailboxRole: mailboxRole,
|
isSender: isSender,
|
||||||
|
userName: userName,
|
||||||
listPost: listPost,
|
listPost: listPost,
|
||||||
);
|
);
|
||||||
final userName = mailboxDashBoardController.sessionCurrent?.username;
|
|
||||||
if (userName != null) {
|
listToEmailAddress = List.from(recipients.value1);
|
||||||
final isSender = presentationEmail.from.asList().every((element) => element.email == userName.value);
|
listCcEmailAddress = List.from(recipients.value2);
|
||||||
if (isSender) {
|
listBccEmailAddress = List.from(recipients.value3);
|
||||||
listToEmailAddress = List.from(recipients.value1.toSet());
|
|
||||||
listCcEmailAddress = List.from(recipients.value2.toSet());
|
|
||||||
listBccEmailAddress = List.from(recipients.value3.toSet());
|
|
||||||
} else {
|
|
||||||
listToEmailAddress = List.from(recipients.value1.toSet().filterEmailAddress(userName.value));
|
|
||||||
listCcEmailAddress = List.from(recipients.value2.toSet().filterEmailAddress(userName.value));
|
|
||||||
listBccEmailAddress = List.from(recipients.value3.toSet().filterEmailAddress(userName.value));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
listToEmailAddress = List.from(recipients.value1.toSet());
|
|
||||||
listCcEmailAddress = List.from(recipients.value2.toSet());
|
|
||||||
listBccEmailAddress = List.from(recipients.value3.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) {
|
if (listToEmailAddress.isNotEmpty || listCcEmailAddress.isNotEmpty || listBccEmailAddress.isNotEmpty) {
|
||||||
isInitialRecipient.value = true;
|
isInitialRecipient.value = true;
|
||||||
|
|||||||
@@ -1422,6 +1422,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||||
messageId: currentEmailLoaded.value?.emailCurrent?.messageId,
|
messageId: currentEmailLoaded.value?.emailCurrent?.messageId,
|
||||||
references: currentEmailLoaded.value?.emailCurrent?.references,
|
references: currentEmailLoaded.value?.emailCurrent?.references,
|
||||||
|
listPost: currentEmailLoaded.value?.emailCurrent?.listPost,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -1448,6 +1449,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||||
messageId: currentEmailLoaded.value?.emailCurrent?.messageId,
|
messageId: currentEmailLoaded.value?.emailCurrent?.messageId,
|
||||||
references: currentEmailLoaded.value?.emailCurrent?.references,
|
references: currentEmailLoaded.value?.emailCurrent?.references,
|
||||||
|
listPost: currentEmailLoaded.value?.emailCurrent?.listPost,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,49 +1,91 @@
|
|||||||
|
|
||||||
import 'package:core/utils/app_logger.dart';
|
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
|
||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
import 'package:model/extensions/list_email_address_extension.dart';
|
import 'package:model/extensions/list_email_address_extension.dart';
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||||
|
|
||||||
extension PresentationEmailExtension on PresentationEmail {
|
extension PresentationEmailExtension on PresentationEmail {
|
||||||
Tuple3<List<EmailAddress>, List<EmailAddress>, List<EmailAddress>> generateRecipientsEmailAddressForComposer({
|
Tuple3<List<EmailAddress>, List<EmailAddress>, List<EmailAddress>> generateRecipientsEmailAddressForComposer({
|
||||||
required EmailActionType emailActionType,
|
required EmailActionType emailActionType,
|
||||||
Role? mailboxRole,
|
bool isSender = false,
|
||||||
|
String? userName,
|
||||||
String? listPost,
|
String? listPost,
|
||||||
}) {
|
}) {
|
||||||
|
final newFromAddress = from.removeDuplicateEmails();
|
||||||
|
final newToAddress = to.removeDuplicateEmails();
|
||||||
|
final newCcAddress = cc.removeDuplicateEmails();
|
||||||
|
final newBccAddress = bcc.removeDuplicateEmails();
|
||||||
|
final newReplyToAddress = replyTo.removeDuplicateEmails();
|
||||||
|
|
||||||
switch (emailActionType) {
|
switch (emailActionType) {
|
||||||
case EmailActionType.reply:
|
case EmailActionType.reply:
|
||||||
if (mailboxRole == PresentationMailbox.roleSent) {
|
final listReplyAddress = isSender ? newToAddress : newFromAddress;
|
||||||
return Tuple3(to.asList(), [], []);
|
final listReplyAddressWithoutUsername = listReplyAddress.withoutMe(userName);
|
||||||
} else {
|
|
||||||
final replyToAddress = replyTo.asList().isNotEmpty
|
return Tuple3(listReplyAddressWithoutUsername, [], []);
|
||||||
? replyTo.asList()
|
|
||||||
: from.asList();
|
|
||||||
return Tuple3(replyToAddress, [], []);
|
|
||||||
}
|
|
||||||
case EmailActionType.replyToList:
|
case EmailActionType.replyToList:
|
||||||
final listEmailAddress = EmailUtils.parsingListPost(listPost ?? '') ?? [];
|
final recipientRecord = EmailUtils.extractRecipientsFromListPost(listPost ?? '');
|
||||||
log('PresentationEmailExtension::generateRecipientsEmailAddressForComposer:listEmailAddress = $listEmailAddress');
|
|
||||||
return Tuple3(listEmailAddress, [], []);
|
final listToAddressWithoutUsername = recipientRecord.toMailAddresses
|
||||||
|
.toSet()
|
||||||
|
.removeDuplicateEmails()
|
||||||
|
.withoutMe(userName);
|
||||||
|
|
||||||
|
final listCcAddressWithoutUsername = recipientRecord.ccMailAddresses
|
||||||
|
.toSet()
|
||||||
|
.removeDuplicateEmails()
|
||||||
|
.withoutMe(userName);
|
||||||
|
|
||||||
|
final listBccAddressWithoutUsername = recipientRecord.bccMailAddresses
|
||||||
|
.toSet()
|
||||||
|
.removeDuplicateEmails()
|
||||||
|
.withoutMe(userName);
|
||||||
|
|
||||||
|
return Tuple3(
|
||||||
|
listToAddressWithoutUsername,
|
||||||
|
listCcAddressWithoutUsername,
|
||||||
|
listBccAddressWithoutUsername,
|
||||||
|
);
|
||||||
case EmailActionType.replyAll:
|
case EmailActionType.replyAll:
|
||||||
if (mailboxRole == PresentationMailbox.roleSent) {
|
final recipientRecord = EmailUtils.extractRecipientsFromListPost(listPost ?? '');
|
||||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
|
||||||
} else {
|
final listToAddress = recipientRecord.toMailAddresses
|
||||||
final senderReplyToAddress = replyTo.asList().isNotEmpty
|
+ newReplyToAddress
|
||||||
? replyTo.asList()
|
+ newFromAddress
|
||||||
: from.asList();
|
+ newToAddress;
|
||||||
return Tuple3(
|
final listCcAddress = recipientRecord.ccMailAddresses + newCcAddress;
|
||||||
to.asList() + senderReplyToAddress,
|
final listBccAddress = recipientRecord.bccMailAddresses + newBccAddress;
|
||||||
cc.asList(),
|
|
||||||
bcc.asList(),
|
final listToAddressWithoutUsername = listToAddress
|
||||||
);
|
.toSet()
|
||||||
}
|
.removeDuplicateEmails()
|
||||||
|
.withoutMe(userName);
|
||||||
|
final listCcAddressWithoutUsername = listCcAddress
|
||||||
|
.toSet()
|
||||||
|
.removeDuplicateEmails()
|
||||||
|
.withoutMe(userName);
|
||||||
|
final listBccAddressWithoutUsername = listBccAddress
|
||||||
|
.toSet()
|
||||||
|
.removeDuplicateEmails()
|
||||||
|
.withoutMe(userName);
|
||||||
|
|
||||||
|
return Tuple3(
|
||||||
|
listToAddressWithoutUsername,
|
||||||
|
listCcAddressWithoutUsername,
|
||||||
|
listBccAddressWithoutUsername,
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
final listToAddressWithoutUsername = newToAddress.withoutMe(userName);
|
||||||
|
final listCcAddressWithoutUsername = newCcAddress.withoutMe(userName);
|
||||||
|
final listBccAddressWithoutUsername = newBccAddress.withoutMe(userName);
|
||||||
|
|
||||||
|
return Tuple3(
|
||||||
|
listToAddressWithoutUsername,
|
||||||
|
listCcAddressWithoutUsername,
|
||||||
|
listBccAddressWithoutUsername,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,6 +122,7 @@ class ComposerArguments extends RouterArguments {
|
|||||||
Role? mailboxRole,
|
Role? mailboxRole,
|
||||||
MessageIdsHeaderValue? messageId,
|
MessageIdsHeaderValue? messageId,
|
||||||
MessageIdsHeaderValue? references,
|
MessageIdsHeaderValue? references,
|
||||||
|
String? listPost,
|
||||||
}) => ComposerArguments(
|
}) => ComposerArguments(
|
||||||
emailActionType: EmailActionType.reply,
|
emailActionType: EmailActionType.reply,
|
||||||
presentationEmail: presentationEmail,
|
presentationEmail: presentationEmail,
|
||||||
@@ -130,6 +131,7 @@ class ComposerArguments extends RouterArguments {
|
|||||||
mailboxRole: mailboxRole,
|
mailboxRole: mailboxRole,
|
||||||
messageId: messageId,
|
messageId: messageId,
|
||||||
references: references,
|
references: references,
|
||||||
|
listPost: listPost,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory ComposerArguments.replyToListEmail({
|
factory ComposerArguments.replyToListEmail({
|
||||||
@@ -158,6 +160,7 @@ class ComposerArguments extends RouterArguments {
|
|||||||
Role? mailboxRole,
|
Role? mailboxRole,
|
||||||
MessageIdsHeaderValue? messageId,
|
MessageIdsHeaderValue? messageId,
|
||||||
MessageIdsHeaderValue? references,
|
MessageIdsHeaderValue? references,
|
||||||
|
String? listPost,
|
||||||
}) => ComposerArguments(
|
}) => ComposerArguments(
|
||||||
emailActionType: EmailActionType.replyAll,
|
emailActionType: EmailActionType.replyAll,
|
||||||
presentationEmail: presentationEmail,
|
presentationEmail: presentationEmail,
|
||||||
@@ -166,6 +169,7 @@ class ComposerArguments extends RouterArguments {
|
|||||||
mailboxRole: mailboxRole,
|
mailboxRole: mailboxRole,
|
||||||
messageId: messageId,
|
messageId: messageId,
|
||||||
references: references,
|
references: references,
|
||||||
|
listPost: listPost,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory ComposerArguments.forwardEmail({
|
factory ComposerArguments.forwardEmail({
|
||||||
|
|||||||
@@ -86,37 +86,108 @@ class EmailUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<EmailAddress>? parsingListPost(String listPost) {
|
static List<String> extractMailtoLinksFromListPost(String listPost) {
|
||||||
try {
|
try {
|
||||||
if (listPost.isEmpty) {
|
if (listPost.trim().isEmpty) return [];
|
||||||
return null;
|
|
||||||
|
final decodedInput = Uri.decodeComponent(listPost);
|
||||||
|
|
||||||
|
final mailtoRegex = RegExp(r'<(mailto:[^<>]+)>');
|
||||||
|
|
||||||
|
final matches = mailtoRegex.allMatches(decodedInput);
|
||||||
|
|
||||||
|
if (matches.isEmpty) {
|
||||||
|
log('EmailUtils::extractMailtoLinksFromListPost: Not found mailto link');
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
final regExpMailtoLinks = RegExp(r'mailto:([^>,]*)');
|
return matches.map((match) => match.group(1)!).toList();
|
||||||
final allMatchesMailtoLinks = regExpMailtoLinks.allMatches(listPost);
|
|
||||||
final listMailtoLinks = allMatchesMailtoLinks
|
|
||||||
.map((match) => match.group(0))
|
|
||||||
.whereNotNull()
|
|
||||||
.toList();
|
|
||||||
log('EmailUtils::parsingListPost:listMailtoLinks: $listMailtoLinks');
|
|
||||||
|
|
||||||
if (listMailtoLinks.isNotEmpty) {
|
|
||||||
return listMailtoLinks
|
|
||||||
.map((mailto) {
|
|
||||||
final mapMailto = RouteUtils.parseMapMailtoFromUri(mailto);
|
|
||||||
final emailAddress = mapMailto[RouteUtils.paramMailtoAddress];
|
|
||||||
return emailAddress != null
|
|
||||||
? EmailAddress(null, emailAddress)
|
|
||||||
: null;
|
|
||||||
})
|
|
||||||
.whereNotNull()
|
|
||||||
.toList();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('EmailUtils::parsingListPost:Exception = $e');
|
logError('EmailUtils::extractMailtoLinksFromListPost:Exception = $e');
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ({
|
||||||
|
List<EmailAddress> toMailAddresses,
|
||||||
|
List<EmailAddress> ccMailAddresses,
|
||||||
|
List<EmailAddress> bccMailAddresses,
|
||||||
|
}) extractRecipientsFromListMailtoLink(List<String> mailtoLinks) {
|
||||||
|
try {
|
||||||
|
log('EmailUtils::extractRecipientsFromListMailtoLink: mailtoLinks: $mailtoLinks:');
|
||||||
|
if (mailtoLinks.isEmpty) {
|
||||||
|
return (
|
||||||
|
toMailAddresses: [],
|
||||||
|
ccMailAddresses: [],
|
||||||
|
bccMailAddresses: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final toMailAddresses = <EmailAddress>[];
|
||||||
|
final ccMailAddresses = <EmailAddress>[];
|
||||||
|
final bccMailAddresses = <EmailAddress>[];
|
||||||
|
|
||||||
|
for (var mailtoLink in mailtoLinks) {
|
||||||
|
final recipientRecord = extractRecipientsFromMailtoLink(mailtoLink);
|
||||||
|
toMailAddresses.addAll(recipientRecord.toMailAddresses);
|
||||||
|
ccMailAddresses.addAll(recipientRecord.ccMailAddresses);
|
||||||
|
bccMailAddresses.addAll(recipientRecord.bccMailAddresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
toMailAddresses: toMailAddresses,
|
||||||
|
ccMailAddresses: ccMailAddresses,
|
||||||
|
bccMailAddresses: bccMailAddresses
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
logError('EmailUtils::extractRecipientsFromListMailtoLink:Exception = $e');
|
||||||
|
return (
|
||||||
|
toMailAddresses: [],
|
||||||
|
ccMailAddresses: [],
|
||||||
|
bccMailAddresses: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ({
|
||||||
|
List<EmailAddress> toMailAddresses,
|
||||||
|
List<EmailAddress> ccMailAddresses,
|
||||||
|
List<EmailAddress> bccMailAddresses,
|
||||||
|
}) extractRecipientsFromMailtoLink(String mailtoLink) {
|
||||||
|
try {
|
||||||
|
log('EmailUtils::extractRecipientsFromMailtoLink:mailtoLink: $mailtoLink:');
|
||||||
|
if (mailtoLink.isEmpty) {
|
||||||
|
return (
|
||||||
|
toMailAddresses: [],
|
||||||
|
ccMailAddresses: [],
|
||||||
|
bccMailAddresses: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final navigationRouter =
|
||||||
|
RouteUtils.generateNavigationRouterFromMailtoLink(mailtoLink);
|
||||||
|
log('EmailUtils::extractRecipientsFromMailtoLink:navigationRouter = $navigationRouter');
|
||||||
|
return (
|
||||||
|
toMailAddresses: navigationRouter.listEmailAddress ?? [],
|
||||||
|
ccMailAddresses: navigationRouter.cc ?? [],
|
||||||
|
bccMailAddresses: navigationRouter.bcc ?? [],
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
logError('EmailUtils::extractRecipientsFromMailtoLink:Exception = $e');
|
||||||
|
return (
|
||||||
|
toMailAddresses: [],
|
||||||
|
ccMailAddresses: [],
|
||||||
|
bccMailAddresses: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ({
|
||||||
|
List<EmailAddress> toMailAddresses,
|
||||||
|
List<EmailAddress> ccMailAddresses,
|
||||||
|
List<EmailAddress> bccMailAddresses,
|
||||||
|
}) extractRecipientsFromListPost(String listPost) {
|
||||||
|
final mailtoLinks = extractMailtoLinksFromListPost(listPost);
|
||||||
|
return extractRecipientsFromListMailtoLink(mailtoLinks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,27 @@ extension SetEmailAddressExtension on Set<EmailAddress>? {
|
|||||||
Set<EmailAddress> withoutMe(String userName) {
|
Set<EmailAddress> withoutMe(String userName) {
|
||||||
return filterEmailAddress(userName).toSet();
|
return filterEmailAddress(userName).toSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<EmailAddress> removeDuplicateEmails() {
|
||||||
|
final seenEmails = <String>{};
|
||||||
|
return this?.where((emailAddress) {
|
||||||
|
if (emailAddress.emailAddress.isEmpty ||
|
||||||
|
seenEmails.contains(emailAddress.emailAddress)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
seenEmails.add(emailAddress.emailAddress);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}).toList() ?? [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ListEmailAddressExtension on List<EmailAddress> {
|
extension ListEmailAddressExtension on List<EmailAddress> {
|
||||||
Set<String> asSetAddress() => map((emailAddress) => emailAddress.emailAddress).toSet();
|
Set<String> asSetAddress() => map((emailAddress) => emailAddress.emailAddress).toSet();
|
||||||
|
|
||||||
|
List<EmailAddress> withoutMe(String? userName) {
|
||||||
|
if (userName == null) return this;
|
||||||
|
|
||||||
|
return where((emailAddress) => emailAddress.emailAddress != userName).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
|
|
||||||
PresentationEmail toggleSelect() {
|
PresentationEmail toggleSelect() {
|
||||||
return PresentationEmail(
|
return PresentationEmail(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
size: size,
|
size: size,
|
||||||
@@ -78,7 +78,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
|
|
||||||
PresentationEmail toSelectedEmail({required SelectMode selectMode}) {
|
PresentationEmail toSelectedEmail({required SelectMode selectMode}) {
|
||||||
return PresentationEmail(
|
return PresentationEmail(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
size: size,
|
size: size,
|
||||||
@@ -104,7 +104,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
|
|
||||||
Email toEmail() {
|
Email toEmail() {
|
||||||
return Email(
|
return Email(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
size: size,
|
size: size,
|
||||||
@@ -137,7 +137,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
final matchedMailbox = findMailboxContain(mapMailboxes);
|
final matchedMailbox = findMailboxContain(mapMailboxes);
|
||||||
|
|
||||||
return PresentationEmail(
|
return PresentationEmail(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
size: size,
|
size: size,
|
||||||
@@ -176,7 +176,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
|
|
||||||
PresentationEmail withRouteWeb(Uri routeWeb) {
|
PresentationEmail withRouteWeb(Uri routeWeb) {
|
||||||
return PresentationEmail(
|
return PresentationEmail(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
size: size,
|
size: size,
|
||||||
@@ -205,7 +205,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
combinedMap.removeWhere((key, value) => !value);
|
combinedMap.removeWhere((key, value) => !value);
|
||||||
log('PresentationEmailExtension::updateKeywords:combinedMap = $combinedMap');
|
log('PresentationEmailExtension::updateKeywords:combinedMap = $combinedMap');
|
||||||
return PresentationEmail(
|
return PresentationEmail(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: combinedMap,
|
keywords: combinedMap,
|
||||||
size: size,
|
size: size,
|
||||||
@@ -231,7 +231,7 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
|
|
||||||
PresentationEmail syncPresentationEmail({PresentationMailbox? mailboxContain, Uri? routeWeb}) {
|
PresentationEmail syncPresentationEmail({PresentationMailbox? mailboxContain, Uri? routeWeb}) {
|
||||||
return PresentationEmail(
|
return PresentationEmail(
|
||||||
id: this.id,
|
id: id,
|
||||||
blobId: blobId,
|
blobId: blobId,
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
size: size,
|
size: size,
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('EmailUtils::extractMailtoLinksFromListPost::', () {
|
||||||
|
test('should return a list of mailto links when valid mailto links are present', () {
|
||||||
|
const listPost = '<mailto:example1@test.com>, <mailto:example2@test.com>';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, ['mailto:example1@test.com', 'mailto:example2@test.com']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return an empty list when no mailto links are present', () {
|
||||||
|
const listPost = '<example@test.com>, <other@test.com>';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return an empty list for an empty string input', () {
|
||||||
|
const listPost = '';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle inputs with whitespace only', () {
|
||||||
|
const listPost = ' ';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle unexpected exceptions and return an empty list', () {
|
||||||
|
const listPost = '\uD800';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should decode encoded URI input and extract mailto links', () {
|
||||||
|
const listPost = '<mailto:example1%40test.com>, <mailto:example2%40test.com>';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, ['mailto:example1@test.com', 'mailto:example2@test.com']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle mailto links with additional parameters like cc and bcc', () {
|
||||||
|
const listPost = '<mailto:johndoe@fakeemail.com>, <mailto:janedoe@fakeemail.com?cc=jackdoe@fakeemail.com&bcc=jennydoe@fakeemail.com>';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, ['mailto:johndoe@fakeemail.com', 'mailto:janedoe@fakeemail.com?cc=jackdoe@fakeemail.com&bcc=jennydoe@fakeemail.com']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle mailto links with additional parameters like cc, bcc, subject and body', () {
|
||||||
|
const listPost = '<mailto:johndoe@fakeemail.com>, <mailto:janedoe@fakeemail.com?cc=jackdoe@fakeemail.com&bcc=jennydoe@fakeemail.com&subject=TestSubject&body=TestBody>';
|
||||||
|
final result = EmailUtils.extractMailtoLinksFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result, [
|
||||||
|
'mailto:johndoe@fakeemail.com',
|
||||||
|
'mailto:janedoe@fakeemail.com?cc=jackdoe@fakeemail.com&bcc=jennydoe@fakeemail.com&subject=TestSubject&body=TestBody',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('EmailUtils::extractRecipientsFromMailtoLink::', () {
|
||||||
|
test('should return empty lists for empty mailtoLink', () {
|
||||||
|
final result = EmailUtils.extractRecipientsFromMailtoLink('');
|
||||||
|
expect(result.toMailAddresses, isEmpty);
|
||||||
|
expect(result.ccMailAddresses, isEmpty);
|
||||||
|
expect(result.bccMailAddresses, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should extract recipients from valid mailtoLink', () {
|
||||||
|
const mailtoLink = 'mailto:test@example.com?cc=cc@example.com&bcc=bcc@example.com';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromMailtoLink(mailtoLink);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [EmailAddress(null, 'test@example.com')]);
|
||||||
|
expect(result.ccMailAddresses, [EmailAddress(null, 'cc@example.com')]);
|
||||||
|
expect(result.bccMailAddresses, [EmailAddress(null, 'bcc@example.com')]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle malformed mailtoLink gracefully', () {
|
||||||
|
const malformedMailtoLink = 'mailto:test@example.com?invalid=params';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromMailtoLink(malformedMailtoLink);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [EmailAddress(null, 'test@example.com')]);
|
||||||
|
expect(result.ccMailAddresses, isEmpty);
|
||||||
|
expect(result.bccMailAddresses, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle exceptions gracefully', () {
|
||||||
|
const invalidMailtoLink = 'mailto:invalid-link, mailto:%E0%A4%A';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromMailtoLink(invalidMailtoLink);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, isEmpty);
|
||||||
|
expect(result.ccMailAddresses, isEmpty);
|
||||||
|
expect(result.bccMailAddresses, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should decode and extract recipients from encoded mailtoLink', () {
|
||||||
|
const encodedMailtoLink = 'mailto:test%40example.com?cc=cc1%40example.com%2Ccc2%40example.com&bcc=bcc%40example.com';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromMailtoLink(encodedMailtoLink);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [EmailAddress(null, 'test@example.com')]);
|
||||||
|
expect(result.ccMailAddresses, [EmailAddress(null, 'cc1@example.com'), EmailAddress(null, 'cc2@example.com')]);
|
||||||
|
expect(result.bccMailAddresses, [EmailAddress(null, 'bcc@example.com')]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should extract recipients from mailto links with additional parameters like cc, bcc, subject and body', () {
|
||||||
|
const mailtoLink = 'mailto:test@example.com?cc=cc@example.com&bcc=bcc@example.com&subject=TestSubject&body=TestBody';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromMailtoLink(mailtoLink);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [EmailAddress(null, 'test@example.com')]);
|
||||||
|
expect(result.ccMailAddresses, [EmailAddress(null, 'cc@example.com')]);
|
||||||
|
expect(result.bccMailAddresses, [EmailAddress(null, 'bcc@example.com')]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('EmailUtils::extractRecipientsFromListPost::', () {
|
||||||
|
test('should return empty lists for empty listPost', () {
|
||||||
|
final result = EmailUtils.extractRecipientsFromListPost('');
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, isEmpty);
|
||||||
|
expect(result.ccMailAddresses, isEmpty);
|
||||||
|
expect(result.bccMailAddresses, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should extract recipients from a valid listPost', () {
|
||||||
|
const listPost = '<mailto:test@example.com?cc=cc@example.com&bcc=bcc@example.com>, <mailto:another@example.com>';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [
|
||||||
|
EmailAddress(null, 'test@example.com'),
|
||||||
|
EmailAddress(null, 'another@example.com'),
|
||||||
|
]);
|
||||||
|
expect(result.ccMailAddresses, [EmailAddress(null, 'cc@example.com')]);
|
||||||
|
expect(result.bccMailAddresses, [EmailAddress(null, 'bcc@example.com')]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle listPost with no valid mailto links', () {
|
||||||
|
const listPost = 'content without mailto links';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, isEmpty);
|
||||||
|
expect(result.ccMailAddresses, isEmpty);
|
||||||
|
expect(result.bccMailAddresses, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should decode and extract recipients from listPost with encoded mailto links', () {
|
||||||
|
const listPost = '%3Cmailto%3Atest%2540example.com%3Fcc%3Dcc1%2540example.com%252Ccc2%2540example.com%26bcc%3Dbcc%2540example.com%3E%2C%20%3Cmailto%3Aanother%2540example.com%3E';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [
|
||||||
|
EmailAddress(null, 'test@example.com'),
|
||||||
|
EmailAddress(null, 'another@example.com'),
|
||||||
|
]);
|
||||||
|
expect(result.ccMailAddresses, [
|
||||||
|
EmailAddress(null, 'cc1@example.com'),
|
||||||
|
EmailAddress(null, 'cc2@example.com'),
|
||||||
|
]);
|
||||||
|
expect(result.bccMailAddresses, [
|
||||||
|
EmailAddress(null, 'bcc@example.com'),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should extract recipients from list post with additional parameters like cc, bcc, subject and body', () {
|
||||||
|
const listPost = '<mailto:test@example.com?cc=cc@example.com&bcc=bcc@example.com&subject=TestSubject&body=TestBody>';
|
||||||
|
|
||||||
|
final result = EmailUtils.extractRecipientsFromListPost(listPost);
|
||||||
|
|
||||||
|
expect(result.toMailAddresses, [EmailAddress(null, 'test@example.com')]);
|
||||||
|
expect(result.ccMailAddresses, [EmailAddress(null, 'cc@example.com')]);
|
||||||
|
expect(result.bccMailAddresses, [EmailAddress(null, 'bcc@example.com')]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:model/extensions/list_email_address_extension.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('parsing email list post test', () {
|
|
||||||
test('parsingListPost returns null for empty input', () {
|
|
||||||
expect(EmailUtils.parsingListPost(''), isNull);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parsingListPost returns null for input without links', () {
|
|
||||||
expect(EmailUtils.parsingListPost('Some text without links'), isNull);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parsingListPost parses mailto links', () {
|
|
||||||
final listEmailAddress =
|
|
||||||
EmailUtils.parsingListPost('<mailto:user@example.com>');
|
|
||||||
expect(listEmailAddress, isNotNull);
|
|
||||||
expect(listEmailAddress![0].email, contains('user@example.com'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parsingListPost parses both mailto without <>', () {
|
|
||||||
final listEmailAddress =
|
|
||||||
EmailUtils.parsingListPost('mailto:support@example.com');
|
|
||||||
expect(listEmailAddress, isNotNull);
|
|
||||||
expect(listEmailAddress![0].email, contains('support@example.com'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parsingListPost parses more mailto', () {
|
|
||||||
final listEmailAddress = EmailUtils.parsingListPost(
|
|
||||||
'<mailto:support@example.com>, <mailto:support@example2.com>, <mailto:support@example3.com>');
|
|
||||||
expect(listEmailAddress, isNotNull);
|
|
||||||
expect(listEmailAddress!.length, equals(3));
|
|
||||||
expect(
|
|
||||||
listEmailAddress.asSetAddress(),
|
|
||||||
containsAll({
|
|
||||||
'support@example.com',
|
|
||||||
'support@example2.com',
|
|
||||||
'support@example3.com'
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parsingListPost returns null for input with invalid links', () {
|
|
||||||
expect(EmailUtils.parsingListPost('Invalid link: invalid'), isNull);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
|||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
import 'package:model/extensions/email_address_extension.dart';
|
import 'package:model/extensions/email_address_extension.dart';
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart';
|
import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -30,7 +29,8 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.reply,
|
emailActionType: EmailActionType.reply,
|
||||||
mailboxRole: PresentationMailbox.roleSent
|
isSender: true,
|
||||||
|
userName: userAEmailAddress.emailAddress,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
@@ -50,7 +50,8 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.replyAll,
|
emailActionType: EmailActionType.replyAll,
|
||||||
mailboxRole: PresentationMailbox.roleSent
|
isSender: true,
|
||||||
|
userName: userAEmailAddress.emailAddress,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
@@ -61,7 +62,7 @@ void main() {
|
|||||||
|
|
||||||
group('GIVEN user B is the sender, SENDER configured the replyTo email AND send an email to user A and user E, cc to user C, bcc to user D', () {
|
group('GIVEN user B is the sender, SENDER configured the replyTo email AND send an email to user A and user E, cc to user C, bcc to user D', () {
|
||||||
test('THEN user A click reply, generateRecipientsEmailAddressForComposer SHOULD return only replyToEmailAddress email to reply' , () {
|
test('THEN user A click reply, generateRecipientsEmailAddressForComposer SHOULD return only replyToEmailAddress email to reply' , () {
|
||||||
final expectedResult = Tuple3([replyToEmailAddress], <EmailAddress>[], <EmailAddress>[]);
|
final expectedResult = Tuple3([userBEmailAddress], <EmailAddress>[], <EmailAddress>[]);
|
||||||
|
|
||||||
final emailToReply = PresentationEmail(
|
final emailToReply = PresentationEmail(
|
||||||
from: {userBEmailAddress},
|
from: {userBEmailAddress},
|
||||||
@@ -73,7 +74,7 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.reply,
|
emailActionType: EmailActionType.reply,
|
||||||
mailboxRole: PresentationMailbox.roleInbox
|
isSender: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
@@ -94,7 +95,7 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.replyAll,
|
emailActionType: EmailActionType.replyAll,
|
||||||
mailboxRole: PresentationMailbox.roleInbox
|
isSender: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
@@ -116,7 +117,7 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.reply,
|
emailActionType: EmailActionType.reply,
|
||||||
mailboxRole: PresentationMailbox.roleInbox
|
isSender: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
@@ -136,7 +137,7 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.replyAll,
|
emailActionType: EmailActionType.replyAll,
|
||||||
mailboxRole: PresentationMailbox.roleInbox
|
isSender: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
@@ -160,7 +161,7 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReplyToList.generateRecipientsEmailAddressForComposer(
|
final result = emailToReplyToList.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.replyToList,
|
emailActionType: EmailActionType.replyToList,
|
||||||
mailboxRole: PresentationMailbox.roleInbox,
|
isSender: false,
|
||||||
listPost: '<mailto:${replyToListEmailAddress.emailAddress}>',
|
listPost: '<mailto:${replyToListEmailAddress.emailAddress}>',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -183,7 +184,7 @@ void main() {
|
|||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
emailActionType: EmailActionType.forward,
|
emailActionType: EmailActionType.forward,
|
||||||
mailboxRole: PresentationMailbox.roleInbox
|
isSender: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
expect(result.value1, containsAll(expectedResult.value1));
|
||||||
|
|||||||
Reference in New Issue
Block a user