[bugfix] TF-2316 Can not delete folder when its children are hidden (#2519)

This commit is contained in:
Bùi Trung Hiếu
2026-04-06 13:18:34 +07:00
committed by GitHub
parent 7cf61ac2f0
commit ea7b9fed33
7 changed files with 785 additions and 371 deletions
@@ -0,0 +1,277 @@
import 'package:dartz/dartz.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:jmap_dart_client/jmap/core/error/error_type.dart';
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart';
import '../../../../fixtures/account_fixtures.dart';
import '../../../../fixtures/mailbox_fixtures.dart';
import '../../../../fixtures/session_fixtures.dart';
import 'delete_multiple_mailbox_interactor_test.mocks.dart';
@GenerateMocks([MailboxRepository])
void _stubGetMailboxState(MailboxRepository repo, jmap.State state) {
when(
repo.getMailboxState(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenAnswer((_) => Future.value(state));
}
void _stubGetAllMailboxWithHiddenMailboxes(MailboxRepository repo, jmap.State state) {
when(
repo.getAllMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenAnswer((_) => Stream.fromIterable({
JmapMailboxResponse(
mailboxes: [
MailboxFixtures.inboxMailbox,
MailboxFixtures.sentMailbox,
MailboxFixtures.selectedFolderToDelete,
MailboxFixtures.selectedFolderToDelete_1,
MailboxFixtures.selectedFolderToDelete_2,
],
state: state,
),
JmapMailboxResponse(
mailboxes: [
MailboxFixtures.inboxMailbox,
MailboxFixtures.sentMailbox,
MailboxFixtures.selectedFolderToDelete,
MailboxFixtures.selectedFolderToDelete_1,
MailboxFixtures.selectedFolderToDelete_2,
MailboxFixtures.selectedFolderToDelete_3,
MailboxFixtures.selectedFolderToDelete_4,
MailboxFixtures.selectedFolderToDelete_5,
MailboxFixtures.selectedFolderToDelete_6,
MailboxFixtures.selectedFolderToDelete_7,
MailboxFixtures.selectedFolderToDelete_8,
MailboxFixtures.selectedFolderToDelete_9,
MailboxFixtures.selectedFolderToDelete_10,
],
state: state,
),
}));
}
void _stubGetAllMailboxWithSubscribedFolders(MailboxRepository repo, jmap.State state) {
when(
repo.getAllMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenAnswer((_) => Stream.value(JmapMailboxResponse(
mailboxes: [MailboxFixtures.subscribedFolder, MailboxFixtures.subscribedChild],
state: state,
)));
}
void _stubDeleteMailboxSuccess(MailboxRepository repo, List<MailboxId> ids) {
when(
repo.deleteMultipleMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, ids),
).thenAnswer((_) => Future.value({}));
}
void _stubDeleteMailboxFailure(
MailboxRepository repo,
List<MailboxId> ids,
Map<Id, SetError> errors,
) {
when(
repo.deleteMultipleMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, ids),
).thenAnswer((_) => Future.value(errors));
}
Stream<dynamic> _executeDelete(
DeleteMultipleMailboxInteractor interactor,
List<MailboxId> ids,
) => interactor.execute(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId, ids);
Matcher _emitsLoadingThen(dynamic result) => emitsInOrder([
Right(LoadingDeleteMultipleMailboxAll()),
result,
]);
void main() {
late MailboxRepository mailboxRepository;
late DeleteMultipleMailboxInteractor deleteMultipleMailboxInteractor;
group('[DeleteMultipleMailboxInteractor]', () {
setUp(() {
mailboxRepository = MockMailboxRepository();
deleteMultipleMailboxInteractor = DeleteMultipleMailboxInteractor(mailboxRepository);
});
group('with hidden mailbox responses', () {
final state = jmap.State('s1');
setUp(() {
_stubGetMailboxState(mailboxRepository, state);
_stubGetAllMailboxWithHiddenMailboxes(mailboxRepository, state);
// second batch defaults to success; override per-test when needed
_stubDeleteMailboxSuccess(mailboxRepository, MailboxFixtures.listDescendantMailboxForSelectedFolder2);
});
test('Should execute to delete selected mailbox an all its children included hidden mailbox', () {
_stubDeleteMailboxSuccess(mailboxRepository, MailboxFixtures.listDescendantMailboxForSelectedFolder);
expect(
_executeDelete(deleteMultipleMailboxInteractor, MailboxFixtures.listMailboxIdsToDelete),
_emitsLoadingThen(Right(DeleteMultipleMailboxAllSuccess(
MailboxFixtures.listMailboxIdToDelete,
currentMailboxState: state,
))),
);
});
test('Should execute and yield DeleteMultipleMailboxAllFailure when delete selected mailbox all fail', () {
_stubDeleteMailboxFailure(
mailboxRepository,
MailboxFixtures.listDescendantMailboxForSelectedFolder,
{Id('folderToDelete'): SetError(ErrorType('error'))},
);
_stubDeleteMailboxFailure(
mailboxRepository,
MailboxFixtures.listDescendantMailboxForSelectedFolder2,
{Id('folderToDelete_8'): SetError(ErrorType('error'))},
);
expect(
_executeDelete(deleteMultipleMailboxInteractor, MailboxFixtures.listMailboxIdsToDelete),
_emitsLoadingThen(Left(DeleteMultipleMailboxAllFailure())),
);
});
test('Should execute and yield DeleteMultipleMailboxHasSomeSuccess when delete selected mailbox has some fail', () {
_stubDeleteMailboxFailure(
mailboxRepository,
MailboxFixtures.listDescendantMailboxForSelectedFolder,
{Id('folderToDelete'): SetError(ErrorType('error'))},
);
expect(
_executeDelete(deleteMultipleMailboxInteractor, MailboxFixtures.listMailboxIdsToDelete),
_emitsLoadingThen(Right(DeleteMultipleMailboxHasSomeSuccess(
MailboxFixtures.listMailboxIdToDelete,
currentMailboxState: state,
))),
);
});
});
test('Should yield AllSuccess with empty lists when selectedMailboxIds is empty', () {
final state = jmap.State('s1');
_stubGetMailboxState(mailboxRepository, state);
when(
mailboxRepository.getAllMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenAnswer((_) => Stream.value(JmapMailboxResponse(
mailboxes: [MailboxFixtures.inboxMailbox, MailboxFixtures.sentMailbox],
state: state,
)));
expect(
_executeDelete(deleteMultipleMailboxInteractor, []),
_emitsLoadingThen(Right(DeleteMultipleMailboxAllSuccess(
[],
currentMailboxState: state,
))),
);
});
test('Should execute and yield DeleteMultipleMailboxFailure when getAllMailbox fail', () {
final state = jmap.State('s1');
_stubGetMailboxState(mailboxRepository, state);
when(
mailboxRepository.getAllMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenThrow('error');
expect(
_executeDelete(deleteMultipleMailboxInteractor, MailboxFixtures.listMailboxIdsToDelete),
_emitsLoadingThen(Left(DeleteMultipleMailboxFailure('error'))),
);
});
test('Should delete selected mailbox alone when it is absent from allMailboxes (no children found)', () {
final state = jmap.State('s1');
final ghostMailboxId = MailboxId(Id('ghostMailbox'));
_stubGetMailboxState(mailboxRepository, state);
when(
mailboxRepository.getAllMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenAnswer((_) => Stream.value(JmapMailboxResponse(
mailboxes: [MailboxFixtures.inboxMailbox, MailboxFixtures.sentMailbox],
state: state,
)));
_stubDeleteMailboxSuccess(mailboxRepository, [ghostMailboxId]);
expect(
_executeDelete(deleteMultipleMailboxInteractor, [ghostMailboxId]),
_emitsLoadingThen(Right(DeleteMultipleMailboxAllSuccess(
[ghostMailboxId],
currentMailboxState: state,
))),
);
});
group('with subscribed folders', () {
final state = jmap.State('s1');
setUp(() {
_stubGetMailboxState(mailboxRepository, state);
_stubGetAllMailboxWithSubscribedFolders(mailboxRepository, state);
_stubDeleteMailboxSuccess(mailboxRepository, MailboxFixtures.expectedDeleteListSubscribedOnly);
});
test('Should delete subscribed child before parent when no hidden subfolders exist', () {
expect(
_executeDelete(deleteMultipleMailboxInteractor, MailboxFixtures.listMailboxIdsForSubscribedOnly),
_emitsLoadingThen(Right(DeleteMultipleMailboxAllSuccess(
MailboxFixtures.expectedDeleteListSubscribedOnly,
currentMailboxState: state,
))),
);
});
test('Should skip already-processed descendant when it also appears in selectedMailboxIds', () {
// subscribedChild is a descendant of subscribedFolder — it must be skipped
// as a root and subsumed into the parent's batch instead.
expect(
_executeDelete(deleteMultipleMailboxInteractor, [
MailboxFixtures.subscribedFolder.id!,
MailboxFixtures.subscribedChild.id!,
]),
_emitsLoadingThen(Right(DeleteMultipleMailboxAllSuccess(
MailboxFixtures.expectedDeleteListSubscribedOnly,
currentMailboxState: state,
))),
);
});
});
test('Should delete 3-level unsubscribed nesting in deepest-first order', () {
final state = jmap.State('s1');
_stubGetMailboxState(mailboxRepository, state);
when(
mailboxRepository.getAllMailbox(SessionFixtures.aliceSession, AccountFixtures.aliceAccountId),
).thenAnswer((_) => Stream.value(JmapMailboxResponse(
mailboxes: [
MailboxFixtures.parentFolder,
MailboxFixtures.hiddenLevel1,
MailboxFixtures.hiddenLevel2,
MailboxFixtures.hiddenLevel3,
],
state: state,
)));
_stubDeleteMailboxSuccess(mailboxRepository, MailboxFixtures.expectedDeleteListThreeLevelNesting);
expect(
_executeDelete(deleteMultipleMailboxInteractor, [MailboxFixtures.parentFolder.id!]),
_emitsLoadingThen(Right(DeleteMultipleMailboxAllSuccess(
MailboxFixtures.expectedDeleteListThreeLevelNesting,
currentMailboxState: state,
))),
);
});
});
}
@@ -1,282 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart';
void main() {
group('generate mapping delete multiple mailbox test', () {
final expectedMapOfTwoMailboxId = {
MailboxId(Id("A")): [
MailboxId(Id('A_1_1')),
MailboxId(Id('A_1')),
MailboxId(Id('A_2_1')),
MailboxId(Id('A_2')),
MailboxId(Id('A'))
],
MailboxId(Id("B_1")): [MailboxId(Id('B_1'))],
};
final expectedListMailboxId = [
MailboxId(Id('A_1_1')),
MailboxId(Id('A_1')),
MailboxId(Id('A_2_1')),
MailboxId(Id('A_2')),
MailboxId(Id('A')),
MailboxId(Id('B_1')),
];
final expectedMapOfOneMailboxId = {
MailboxId(Id("A")): [
MailboxId(Id('A_1_1')),
MailboxId(Id('A_1')),
MailboxId(Id('A_2_1')),
MailboxId(Id('A_2')),
MailboxId(Id('A'))
]
};
final expectedMapOfThreeMailboxId = {
MailboxId(Id("A")): [
MailboxId(Id('A_1_1')),
MailboxId(Id('A_1')),
MailboxId(Id('A_2_1')),
MailboxId(Id('A_2')),
MailboxId(Id('A'))
],
MailboxId(Id("B_1")): [MailboxId(Id('B_1'))],
MailboxId(Id("C_1")): [MailboxId(Id('C_1'))],
};
test('_generateMapDescendantIdsAndMailboxIdList should return map with 2 items when mailboxes belong to 2 different tree', () async {
final defaultMailboxTree = MailboxTree(MailboxNode(PresentationMailbox(MailboxId(Id('root')))));
final folderMailboxTree = MailboxTree(
MailboxNode(
PresentationMailbox(MailboxId(Id('root'))),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A_2')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_2_1')), parentId: MailboxId(Id('A_2'))))
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('A_1')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_1_1')), parentId: MailboxId(Id('A_1'))))
]
),
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('B')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('B_2')), parentId: MailboxId(Id('B'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('B_2_1')), parentId: MailboxId(Id('B_2'))))
]
),
MailboxNode(PresentationMailbox(MailboxId(Id('B_1')), parentId: MailboxId(Id('B')))),
]
)
]
)
);
final selectedMailboxList = [
PresentationMailbox(MailboxId(Id("A")), parentId: null),
PresentationMailbox(MailboxId(Id('A_1')), parentId: MailboxId(Id('A'))),
PresentationMailbox(MailboxId(Id('A_2_1')), parentId: MailboxId(Id('A_2'))),
PresentationMailbox(MailboxId(Id("B_1")), parentId: MailboxId(Id('B')))
];
final tupleResult = MailboxUtils.generateMapDescendantIdsAndMailboxIdList(
selectedMailboxList,
defaultMailboxTree,
folderMailboxTree);
expect(tupleResult.value1, equals(expectedMapOfTwoMailboxId));
});
test('_generateMapDescendantIdsAndMailboxIdList should return list with 5 item when mailboxes belong to 2 different tree', () async {
final defaultMailboxTree = MailboxTree(MailboxNode(PresentationMailbox(MailboxId(Id('root')))));
final folderMailboxTree = MailboxTree(
MailboxNode(
PresentationMailbox(MailboxId(Id('root'))),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A_2')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_2_1')), parentId: MailboxId(Id('A_2'))))
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('A_1')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_1_1')), parentId: MailboxId(Id('A_1'))))
]
),
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('B')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('B_2')), parentId: MailboxId(Id('B'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('B_2_1')), parentId: MailboxId(Id('B_2'))))
]
),
MailboxNode(PresentationMailbox(MailboxId(Id('B_1')), parentId: MailboxId(Id('B')))),
]
)
]
)
);
final selectedMailboxList = [
PresentationMailbox(MailboxId(Id("A")), parentId: null),
PresentationMailbox(MailboxId(Id('A_1')), parentId: MailboxId(Id('A'))),
PresentationMailbox(MailboxId(Id('A_2_1')), parentId: MailboxId(Id('A_2'))),
PresentationMailbox(MailboxId(Id("B_1")), parentId: MailboxId(Id('B')))
];
final tupleResult = MailboxUtils.generateMapDescendantIdsAndMailboxIdList(
selectedMailboxList,
defaultMailboxTree,
folderMailboxTree);
expect(tupleResult.value2, equals(expectedListMailboxId));
});
test('_generateMapDescendantIdsAndMailboxIdList should return map with 1 items when mailboxes belong to 2 different tree', () async {
final defaultMailboxTree = MailboxTree(MailboxNode(PresentationMailbox(MailboxId(Id('root')))));
final folderMailboxTree = MailboxTree(
MailboxNode(
PresentationMailbox(MailboxId(Id('root'))),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A_2')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_2_1')), parentId: MailboxId(Id('A_2'))))
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('A_1')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_1_1')), parentId: MailboxId(Id('A_1'))))
]
),
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('B')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('B_2')), parentId: MailboxId(Id('B'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('B_2_1')), parentId: MailboxId(Id('B_2'))))
]
),
MailboxNode(PresentationMailbox(MailboxId(Id('B_1')), parentId: MailboxId(Id('B')))),
]
)
]
)
);
final selectedMailboxList = [
PresentationMailbox(MailboxId(Id("A")), parentId: null),
];
final tupleResult = MailboxUtils.generateMapDescendantIdsAndMailboxIdList(
selectedMailboxList,
defaultMailboxTree,
folderMailboxTree);
expect(tupleResult.value1, equals(expectedMapOfOneMailboxId));
});
test('_generateMapDescendantIdsAndMailboxIdList should return map with 3 items when mailboxes belong to 2 different tree', () async {
final defaultMailboxTree = MailboxTree(MailboxNode(PresentationMailbox(MailboxId(Id('root')))));
final folderMailboxTree = MailboxTree(
MailboxNode(
PresentationMailbox(MailboxId(Id('root'))),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('A_2')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_2_1')), parentId: MailboxId(Id('A_2'))))
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('A_1')), parentId: MailboxId(Id('A'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('A_1_1')), parentId: MailboxId(Id('A_1'))))
]
),
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('B')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('B_2')), parentId: MailboxId(Id('B'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('B_2_1')), parentId: MailboxId(Id('B_2'))))
]
),
MailboxNode(PresentationMailbox(MailboxId(Id('B_1')), parentId: MailboxId(Id('B')))),
]
),
MailboxNode(
PresentationMailbox(MailboxId(Id('C')), parentId: null),
childrenItems: [
MailboxNode(
PresentationMailbox(MailboxId(Id('C_2')), parentId: MailboxId(Id('C'))),
childrenItems: [
MailboxNode(PresentationMailbox(MailboxId(Id('C_2_1')), parentId: MailboxId(Id('C_2'))))
]
),
MailboxNode(PresentationMailbox(MailboxId(Id('C_1')), parentId: MailboxId(Id('C')))),
]
)
]
)
);
final selectedMailboxList = [
PresentationMailbox(MailboxId(Id("A")), parentId: null),
PresentationMailbox(MailboxId(Id("B_1")), parentId: MailboxId(Id('B'))),
PresentationMailbox(MailboxId(Id("C_1")), parentId: MailboxId(Id('C')))
];
final tupleResult = MailboxUtils.generateMapDescendantIdsAndMailboxIdList(
selectedMailboxList,
defaultMailboxTree,
folderMailboxTree);
expect(tupleResult.value1, equals(expectedMapOfThreeMailboxId));
});
});
}
+403
View File
@@ -107,4 +107,407 @@ class MailboxFixtures {
PresentationMailbox.actionRequiredFolder;
static final currentState = State('2c9f1b12-b35a-43e6-9af2-0106fb53a943');
static final selectedFolderToDelete = Mailbox(
id: MailboxId(Id('folderToDelete')),
name: MailboxName('folderToDelete'),
parentId: null,
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(true)
);
static final selectedFolderToDelete_1 = Mailbox(
id: MailboxId(Id('folderToDelete_1')),
name: MailboxName('folderToDelete_1'),
parentId: MailboxId(Id("folderToDelete")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_2 = Mailbox(
id: MailboxId(Id('folderToDelete_2')),
name: MailboxName('folderToDelete_2'),
parentId: MailboxId(Id("folderToDelete_1")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_3 = Mailbox(
id: MailboxId(Id('folderToDelete_3')),
name: MailboxName('folderToDelete_3'),
parentId: MailboxId(Id("folderToDelete")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(true)
);
static final selectedFolderToDelete_4 = Mailbox(
id: MailboxId(Id('folderToDelete_4')),
name: MailboxName('folderToDelete_4'),
parentId: MailboxId(Id("folderToDelete_3")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_5 = Mailbox(
id: MailboxId(Id('folderToDelete_5')),
name: MailboxName('folderToDelete_5'),
parentId: MailboxId(Id("folderToDelete_3")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_6 = Mailbox(
id: MailboxId(Id('folderToDelete_6')),
name: MailboxName('folderToDelete_6'),
parentId: MailboxId(Id("folderToDelete_5")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_7 = Mailbox(
id: MailboxId(Id('folderToDelete_7')),
name: MailboxName('folderToDelete_7'),
parentId: MailboxId(Id("folderToDelete_6")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_8 = Mailbox(
id: MailboxId(Id('folderToDelete_8')),
name: MailboxName('folderToDelete_8'),
parentId: null,
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(true)
);
static final selectedFolderToDelete_9 = Mailbox(
id: MailboxId(Id('folderToDelete_9')),
name: MailboxName('folderToDelete_9'),
parentId: MailboxId(Id("folderToDelete_8")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final selectedFolderToDelete_10 = Mailbox(
id: MailboxId(Id('folderToDelete_10')),
name: MailboxName('folderToDelete_10'),
parentId: MailboxId(Id("folderToDelete_8")),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(123)),
unreadEmails: UnreadEmails(UnsignedInt(12)),
totalThreads: TotalThreads(UnsignedInt(123)),
unreadThreads: UnreadThreads(UnsignedInt(12)),
myRights: MailboxRights(
true,
true,
true,
true,
true,
true,
true,
true,
true
),
isSubscribed: IsSubscribed(false)
);
static final listMailboxIdToDelete = [
MailboxId(Id('folderToDelete_7')),
MailboxId(Id('folderToDelete_6')),
MailboxId(Id('folderToDelete_5')),
MailboxId(Id('folderToDelete_4')),
MailboxId(Id('folderToDelete_3')),
MailboxId(Id('folderToDelete_2')),
MailboxId(Id('folderToDelete_1')),
MailboxId(Id('folderToDelete')),
MailboxId(Id('folderToDelete_10')),
MailboxId(Id('folderToDelete_9')),
MailboxId(Id('folderToDelete_8'))
];
static final listDescendantMailboxForSelectedFolder = <MailboxId>[
MailboxId(Id('folderToDelete_7')),
MailboxId(Id('folderToDelete_6')),
MailboxId(Id('folderToDelete_5')),
MailboxId(Id('folderToDelete_4')),
MailboxId(Id('folderToDelete_3')),
MailboxId(Id('folderToDelete_2')),
MailboxId(Id('folderToDelete_1')),
MailboxId(Id('folderToDelete')),
];
static final listDescendantMailboxForSelectedFolder2 = <MailboxId>[
MailboxId(Id('folderToDelete_10')),
MailboxId(Id('folderToDelete_9')),
MailboxId(Id('folderToDelete_8'))
];
static final listMailboxIdsToDelete = <MailboxId>[
selectedFolderToDelete.id!,
selectedFolderToDelete_8.id!,
];
// Fixtures for "no hidden children" scenario — all mailboxes are subscribed.
static final subscribedFolder = Mailbox(
id: MailboxId(Id('subscribedFolder')),
name: MailboxName('subscribedFolder'),
parentId: null,
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(0)),
unreadEmails: UnreadEmails(UnsignedInt(0)),
totalThreads: TotalThreads(UnsignedInt(0)),
unreadThreads: UnreadThreads(UnsignedInt(0)),
myRights: MailboxRights(true, true, true, true, true, true, true, true, true),
isSubscribed: IsSubscribed(true),
);
static final subscribedChild = Mailbox(
id: MailboxId(Id('subscribedChild')),
name: MailboxName('subscribedChild'),
parentId: MailboxId(Id('subscribedFolder')),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(0)),
unreadEmails: UnreadEmails(UnsignedInt(0)),
totalThreads: TotalThreads(UnsignedInt(0)),
unreadThreads: UnreadThreads(UnsignedInt(0)),
myRights: MailboxRights(true, true, true, true, true, true, true, true, true),
isSubscribed: IsSubscribed(true),
);
static final listMailboxIdsForSubscribedOnly = <MailboxId>[
MailboxId(Id('subscribedFolder')),
];
static final expectedDeleteListSubscribedOnly = <MailboxId>[
MailboxId(Id('subscribedChild')),
MailboxId(Id('subscribedFolder')),
];
// Fixtures for "3-level unsubscribed nesting" scenario.
// Tree: parentFolder (subscribed) → level1 (unsubscribed) → level2 (unsubscribed) → level3 (unsubscribed)
static final parentFolder = Mailbox(
id: MailboxId(Id('parentFolder')),
name: MailboxName('parentFolder'),
parentId: null,
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(0)),
unreadEmails: UnreadEmails(UnsignedInt(0)),
totalThreads: TotalThreads(UnsignedInt(0)),
unreadThreads: UnreadThreads(UnsignedInt(0)),
myRights: MailboxRights(true, true, true, true, true, true, true, true, true),
isSubscribed: IsSubscribed(true),
);
static final hiddenLevel1 = Mailbox(
id: MailboxId(Id('hiddenLevel1')),
name: MailboxName('hiddenLevel1'),
parentId: MailboxId(Id('parentFolder')),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(0)),
unreadEmails: UnreadEmails(UnsignedInt(0)),
totalThreads: TotalThreads(UnsignedInt(0)),
unreadThreads: UnreadThreads(UnsignedInt(0)),
myRights: MailboxRights(true, true, true, true, true, true, true, true, true),
isSubscribed: IsSubscribed(false),
);
static final hiddenLevel2 = Mailbox(
id: MailboxId(Id('hiddenLevel2')),
name: MailboxName('hiddenLevel2'),
parentId: MailboxId(Id('hiddenLevel1')),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(0)),
unreadEmails: UnreadEmails(UnsignedInt(0)),
totalThreads: TotalThreads(UnsignedInt(0)),
unreadThreads: UnreadThreads(UnsignedInt(0)),
myRights: MailboxRights(true, true, true, true, true, true, true, true, true),
isSubscribed: IsSubscribed(false),
);
static final hiddenLevel3 = Mailbox(
id: MailboxId(Id('hiddenLevel3')),
name: MailboxName('hiddenLevel3'),
parentId: MailboxId(Id('hiddenLevel2')),
role: null,
sortOrder: SortOrder(sortValue: 1000),
totalEmails: TotalEmails(UnsignedInt(0)),
unreadEmails: UnreadEmails(UnsignedInt(0)),
totalThreads: TotalThreads(UnsignedInt(0)),
unreadThreads: UnreadThreads(UnsignedInt(0)),
myRights: MailboxRights(true, true, true, true, true, true, true, true, true),
isSubscribed: IsSubscribed(false),
);
static final expectedDeleteListThreeLevelNesting = <MailboxId>[
MailboxId(Id('hiddenLevel3')),
MailboxId(Id('hiddenLevel2')),
MailboxId(Id('hiddenLevel1')),
MailboxId(Id('parentFolder')),
];
}