TF-3941 Thread Detail Thread level mark read/star, archive and spam

This commit is contained in:
DatDang
2025-08-05 14:15:03 +07:00
committed by Dat H. Pham
parent f44118af48
commit b7cd3f7179
35 changed files with 902 additions and 552 deletions
@@ -4,6 +4,7 @@ import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/presentation_email.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/model/email_in_thread_detail_info.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/utils/thread_detail_presentation_utils.dart';
void main() {
@@ -492,5 +493,248 @@ void main() {
expect(result, isEmpty);
});
});
group('refreshThreadDetailInfo', () {
final sentMailboxId = MailboxId(Id('sent'));
const ownEmailAddress = 'user@example';
test(
'should return empty list when all inputs are empty',
() {
// arrange
final original = <EmailInThreadDetailInfo>[];
final created = <PresentationEmail>[];
final updated = <PresentationEmail>[];
final destroyed = <EmailId>[];
// act
final result = ThreadDetailPresentationUtils.refreshThreadDetailInfo(
original: original,
created: created,
updated: updated,
destroyed: destroyed,
sentMailboxId: sentMailboxId,
ownEmailAddress: ownEmailAddress,
);
// assert
expect(result, isEmpty);
},
);
test(
'should return original list when no changes are made',
() {
// arrange
final id = Id('email-1');
final emailId = EmailId(id);
final original = [
EmailInThreadDetailInfo(
emailId: emailId,
keywords: {},
mailboxIds: {},
isValidToDisplay: true,
),
];
final created = <PresentationEmail>[];
final updated = <PresentationEmail>[];
final destroyed = <EmailId>[];
// act
final result = ThreadDetailPresentationUtils.refreshThreadDetailInfo(
original: original,
created: created,
updated: updated,
destroyed: destroyed,
sentMailboxId: sentMailboxId,
ownEmailAddress: ownEmailAddress,
);
// assert
expect(result, equals(original));
},
);
test(
'should return created emails when no original emails are present',
() {
// arrange
final id = Id('email-1');
final emailId = EmailId(id);
final created = [
PresentationEmail(
id: emailId,
keywords: {},
mailboxIds: {},
),
];
final original = <EmailInThreadDetailInfo>[];
final updated = <PresentationEmail>[];
final destroyed = <EmailId>[];
// act
final result = ThreadDetailPresentationUtils.refreshThreadDetailInfo(
original: original,
created: created,
updated: updated,
destroyed: destroyed,
sentMailboxId: sentMailboxId,
ownEmailAddress: ownEmailAddress,
);
// assert
expect(result, hasLength(1));
expect(result.first.emailId, equals(emailId));
expect(result.first.keywords, equals({}));
expect(result.first.mailboxIds, equals({}));
},
);
test(
'should return updated emails when emails are updated',
() {
// arrange
final id = Id('email-1');
final emailId = EmailId(id);
final original = [
EmailInThreadDetailInfo(
emailId: emailId,
keywords: {},
mailboxIds: {},
isValidToDisplay: true,
),
];
final updated = [
PresentationEmail(
id: emailId,
keywords: {KeyWordIdentifier('test'): true},
mailboxIds: {},
),
];
final created = <PresentationEmail>[];
final destroyed = <EmailId>[];
// act
final result = ThreadDetailPresentationUtils.refreshThreadDetailInfo(
original: original,
created: created,
updated: updated,
destroyed: destroyed,
sentMailboxId: sentMailboxId,
ownEmailAddress: ownEmailAddress,
);
// assert
expect(result, hasLength(1));
expect(result.first.emailId, equals(emailId));
expect(result.first.keywords, equals({KeyWordIdentifier('test'): true}));
expect(result.first.mailboxIds, equals({}));
},
);
test(
'should remove destroyed emails from the result',
() {
// arrange
final id1 = Id('email-1');
final emailId1 = EmailId(id1);
final id2 = Id('email-2');
final emailId2 = EmailId(id2);
final original = [
EmailInThreadDetailInfo(
emailId: emailId1,
keywords: {},
mailboxIds: {},
isValidToDisplay: true,
),
EmailInThreadDetailInfo(
emailId: emailId2,
keywords: {},
mailboxIds: {},
isValidToDisplay: true,
),
];
final created = <PresentationEmail>[];
final updated = <PresentationEmail>[];
final destroyed = [emailId1];
// act
final result = ThreadDetailPresentationUtils.refreshThreadDetailInfo(
original: original,
created: created,
updated: updated,
destroyed: destroyed,
sentMailboxId: sentMailboxId,
ownEmailAddress: ownEmailAddress,
);
// assert
expect(result, hasLength(1));
expect(result.first.emailId, equals(emailId2));
expect(result.first.keywords, equals({}));
expect(result.first.mailboxIds, equals({}));
},
);
test(
'should apply all changes when multiple changes are present',
() {
// arrange
final id1 = Id('email-1');
final emailId1 = EmailId(id1);
final id2 = Id('email-2');
final emailId2 = EmailId(id2);
final id3 = Id('email-3');
final emailId3 = EmailId(id3);
final original = [
EmailInThreadDetailInfo(
emailId: emailId1,
keywords: {},
mailboxIds: {},
isValidToDisplay: true,
),
EmailInThreadDetailInfo(
emailId: emailId2,
keywords: {},
mailboxIds: {},
isValidToDisplay: true,
),
];
final created = [
PresentationEmail(
id: emailId3,
keywords: {KeyWordIdentifier('test'): true},
mailboxIds: {},
),
];
final updated = [
PresentationEmail(
id: emailId1,
keywords: {KeyWordIdentifier('updated'): true},
mailboxIds: {},
),
];
final destroyed = [emailId2];
// act
final result = ThreadDetailPresentationUtils.refreshThreadDetailInfo(
original: original,
created: created,
updated: updated,
destroyed: destroyed,
sentMailboxId: sentMailboxId,
ownEmailAddress: ownEmailAddress,
);
// assert
expect(result, hasLength(2));
expect(result.first.emailId, equals(emailId1));
expect(result.first.keywords, equals({KeyWordIdentifier('updated'): true}));
expect(result.first.mailboxIds, equals({}));
expect(result.last.emailId, equals(emailId3));
expect(result.last.keywords, equals({KeyWordIdentifier('test'): true}));
expect(result.last.mailboxIds, equals({}));
},
);
});
});
}