TF-4282 Fix sort of web search suggestion (#4289)
This commit is contained in:
@@ -141,7 +141,7 @@ mixin MailAPIMixin on HandleSetErrorMixin {
|
|||||||
|
|
||||||
if (limit != null) queryEmailMethod.addLimit(limit);
|
if (limit != null) queryEmailMethod.addLimit(limit);
|
||||||
|
|
||||||
if (position != null) queryEmailMethod.addPosition(position);
|
if (position != null && position > 0) queryEmailMethod.addPosition(position);
|
||||||
|
|
||||||
if (sort != null) queryEmailMethod.addSorts(sort);
|
if (sort != null) queryEmailMethod.addSorts(sort);
|
||||||
|
|
||||||
|
|||||||
+1
@@ -138,6 +138,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions
|
|||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/labels/handle_logic_label_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/notify_thread_detail_setting_updated.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/notify_thread_detail_setting_updated.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/quick_search_emails_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/reopen_composer_cache_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/set_error_extension.dart';
|
||||||
|
|||||||
@@ -5,26 +5,15 @@ import 'package:dartz/dartz.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||||
import 'package:labels/model/label.dart';
|
import 'package:labels/model/label.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
|
||||||
import 'package:model/extensions/email_filter_condition_extension.dart';
|
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/base/mixin/date_range_picker_mixin.dart';
|
import 'package:tmail_ui_user/features/base/mixin/date_range_picker_mixin.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_recent_search_latest_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_recent_search_latest_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/quick_search_email_state.dart';
|
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart';
|
||||||
@@ -38,7 +27,7 @@ import 'package:tmail_ui_user/features/thread/presentation/model/search_state.da
|
|||||||
import 'package:tmail_ui_user/features/thread/presentation/model/search_status.dart';
|
import 'package:tmail_ui_user/features/thread/presentation/model/search_status.dart';
|
||||||
|
|
||||||
class SearchController extends BaseController with DateRangePickerMixin {
|
class SearchController extends BaseController with DateRangePickerMixin {
|
||||||
final QuickSearchEmailInteractor _quickSearchEmailInteractor;
|
final QuickSearchEmailInteractor quickSearchEmailInteractor;
|
||||||
final SaveRecentSearchInteractor _saveRecentSearchInteractor;
|
final SaveRecentSearchInteractor _saveRecentSearchInteractor;
|
||||||
final GetAllRecentSearchLatestInteractor _getAllRecentSearchLatestInteractor;
|
final GetAllRecentSearchLatestInteractor _getAllRecentSearchLatestInteractor;
|
||||||
|
|
||||||
@@ -58,7 +47,7 @@ class SearchController extends BaseController with DateRangePickerMixin {
|
|||||||
String currentSearchText = '';
|
String currentSearchText = '';
|
||||||
|
|
||||||
SearchController(
|
SearchController(
|
||||||
this._quickSearchEmailInteractor,
|
this.quickSearchEmailInteractor,
|
||||||
this._saveRecentSearchInteractor,
|
this._saveRecentSearchInteractor,
|
||||||
this._getAllRecentSearchLatestInteractor,
|
this._getAllRecentSearchLatestInteractor,
|
||||||
);
|
);
|
||||||
@@ -108,59 +97,6 @@ class SearchController extends BaseController with DateRangePickerMixin {
|
|||||||
listFilterOnSuggestionForm.remove(searchFilter);
|
listFilterOnSuggestionForm.remove(searchFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<PresentationEmail>> quickSearchEmails({
|
|
||||||
required Session session,
|
|
||||||
required AccountId accountId,
|
|
||||||
required String ownEmailAddress,
|
|
||||||
required String query,
|
|
||||||
}) async {
|
|
||||||
currentSearchText = query;
|
|
||||||
return await _quickSearchEmailInteractor.execute(
|
|
||||||
session,
|
|
||||||
accountId,
|
|
||||||
limit: UnsignedInt(5),
|
|
||||||
sort: <Comparator>{}..add(
|
|
||||||
EmailComparator(EmailComparatorProperty.receivedAt)
|
|
||||||
..setIsAscending(false)),
|
|
||||||
filter: _mappingToFilterOnSuggestionForm(
|
|
||||||
currentUserEmail: ownEmailAddress,
|
|
||||||
query: query,
|
|
||||||
),
|
|
||||||
properties: EmailUtils.getPropertiesForEmailGetMethod(session, accountId),
|
|
||||||
).then((result) => result.fold(
|
|
||||||
(failure) => <PresentationEmail>[],
|
|
||||||
(success) => success is QuickSearchEmailSuccess
|
|
||||||
? success.emailList
|
|
||||||
: <PresentationEmail>[]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Filter? _mappingToFilterOnSuggestionForm({required String query, required String currentUserEmail}) {
|
|
||||||
log('SearchController::_mappingToFilterOnSuggestionForm():query: $query');
|
|
||||||
final filterCondition = EmailFilterCondition(
|
|
||||||
text: query.isNotEmpty == true ? query : null,
|
|
||||||
after: listFilterOnSuggestionForm.contains(QuickSearchFilter.last7Days)
|
|
||||||
? EmailReceiveTimeType.last7Days.toOldestUTCDate()
|
|
||||||
: null,
|
|
||||||
before: listFilterOnSuggestionForm.contains(QuickSearchFilter.last7Days)
|
|
||||||
? EmailReceiveTimeType.last7Days.toLatestUTCDate()
|
|
||||||
: null,
|
|
||||||
hasAttachment: listFilterOnSuggestionForm.contains(QuickSearchFilter.hasAttachment)
|
|
||||||
? true
|
|
||||||
: null,
|
|
||||||
from: listFilterOnSuggestionForm.contains(QuickSearchFilter.fromMe) && currentUserEmail.isNotEmpty
|
|
||||||
? currentUserEmail
|
|
||||||
: null,
|
|
||||||
hasKeyword: listFilterOnSuggestionForm.contains(QuickSearchFilter.starred)
|
|
||||||
? KeyWordIdentifier.emailFlagged.value
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
return filterCondition.hasCondition
|
|
||||||
? filterCondition
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyFilterSuggestionToSearchFilter(String currentUserEmail) {
|
void applyFilterSuggestionToSearchFilter(String currentUserEmail) {
|
||||||
final receiveTime = listFilterOnSuggestionForm.contains(QuickSearchFilter.last7Days)
|
final receiveTime = listFilterOnSuggestionForm.contains(QuickSearchFilter.last7Days)
|
||||||
? EmailReceiveTimeType.last7Days
|
? EmailReceiveTimeType.last7Days
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||||
|
import 'package:model/email/presentation_email.dart';
|
||||||
|
import 'package:model/extensions/email_filter_condition_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/quick_search_email_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart';
|
||||||
|
|
||||||
|
extension QuickSearchEmailsExtension on SearchController {
|
||||||
|
Future<List<PresentationEmail>> quickSearchEmails({
|
||||||
|
required Session session,
|
||||||
|
required AccountId accountId,
|
||||||
|
required String ownEmailAddress,
|
||||||
|
required String query,
|
||||||
|
}) async {
|
||||||
|
currentSearchText = query;
|
||||||
|
return await quickSearchEmailInteractor.execute(
|
||||||
|
session,
|
||||||
|
accountId,
|
||||||
|
limit: UnsignedInt(5),
|
||||||
|
sort: searchEmailFilter.value.sortOrderType
|
||||||
|
.getSortOrder()
|
||||||
|
.toNullable(),
|
||||||
|
filter: _mappingToFilterOnSuggestionForm(
|
||||||
|
currentUserEmail: ownEmailAddress,
|
||||||
|
query: query,
|
||||||
|
),
|
||||||
|
properties: EmailUtils.getPropertiesForEmailGetMethod(session, accountId),
|
||||||
|
).then((result) => result.fold(
|
||||||
|
(failure) => <PresentationEmail>[],
|
||||||
|
(success) => success is QuickSearchEmailSuccess
|
||||||
|
? success.emailList
|
||||||
|
: <PresentationEmail>[]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter? _mappingToFilterOnSuggestionForm({required String query, required String currentUserEmail}) {
|
||||||
|
log('SearchController::_mappingToFilterOnSuggestionForm():query: $query');
|
||||||
|
final filterCondition = EmailFilterCondition(
|
||||||
|
text: query.isNotEmpty == true ? query : null,
|
||||||
|
after: listFilterOnSuggestionForm.contains(QuickSearchFilter.last7Days)
|
||||||
|
? EmailReceiveTimeType.last7Days.toOldestUTCDate()
|
||||||
|
: null,
|
||||||
|
before: listFilterOnSuggestionForm.contains(QuickSearchFilter.last7Days)
|
||||||
|
? EmailReceiveTimeType.last7Days.toLatestUTCDate()
|
||||||
|
: null,
|
||||||
|
hasAttachment: listFilterOnSuggestionForm.contains(QuickSearchFilter.hasAttachment)
|
||||||
|
? true
|
||||||
|
: null,
|
||||||
|
from: listFilterOnSuggestionForm.contains(QuickSearchFilter.fromMe) && currentUserEmail.isNotEmpty
|
||||||
|
? currentUserEmail
|
||||||
|
: null,
|
||||||
|
hasKeyword: listFilterOnSuggestionForm.contains(QuickSearchFilter.starred)
|
||||||
|
? KeyWordIdentifier.emailFlagged.value
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
return filterCondition.hasCondition
|
||||||
|
? filterCondition
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -81,7 +81,7 @@ class ThreadAPI with HandleSetErrorMixin, MailAPIMixin {
|
|||||||
|
|
||||||
if (limit != null) queryEmailMethod.addLimit(limit);
|
if (limit != null) queryEmailMethod.addLimit(limit);
|
||||||
|
|
||||||
if (position != null) queryEmailMethod.addPosition(position);
|
if (position != null && position > 0) queryEmailMethod.addPosition(position);
|
||||||
|
|
||||||
if (sort != null) queryEmailMethod.addSorts(sort);
|
if (sort != null) queryEmailMethod.addSorts(sort);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,253 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:http_mock_adapter/http_mock_adapter.dart';
|
||||||
|
import 'package:jmap_dart_client/http/http_client.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/method/response/set_response.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/state.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
|
||||||
|
import 'package:model/error_type_handler/set_method_error_handler_mixin.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/mixin/mail_api_mixin.dart';
|
||||||
|
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
|
||||||
|
|
||||||
|
import '../../../fixtures/account_fixtures.dart';
|
||||||
|
import '../../../fixtures/session_fixtures.dart';
|
||||||
|
|
||||||
|
class TestMailApiMixin with HandleSetErrorMixin, MailAPIMixin {
|
||||||
|
@override
|
||||||
|
void handleSetErrors({
|
||||||
|
SetMethodErrors? notDestroyedError,
|
||||||
|
SetMethodErrors? notUpdatedError,
|
||||||
|
SetMethodErrors? notCreatedError,
|
||||||
|
Set<SetMethodErrorHandler>? notDestroyedHandlers,
|
||||||
|
Set<SetMethodErrorHandler>? notUpdatedHandlers,
|
||||||
|
Set<SetMethodErrorHandler>? notCreatedHandlers,
|
||||||
|
SetMethodErrorHandler? unCatchErrorHandler,
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<Id, SetError> handleSetResponse(List<SetResponse?> listSetResponse) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
parseErrorForSetResponse(SetResponse? response, Id requestId) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final baseOption = BaseOptions(method: 'POST');
|
||||||
|
final dio = Dio(baseOption)..options.baseUrl = 'http://domain.com/jmap';
|
||||||
|
late DioAdapter dioAdapter;
|
||||||
|
late HttpClient httpClient;
|
||||||
|
late TestMailApiMixin testMailApiMixin;
|
||||||
|
|
||||||
|
final sessionState = State('some-session-state');
|
||||||
|
final state = State('some-state');
|
||||||
|
final filter = EmailFilterCondition(text: 'some-text');
|
||||||
|
final queryState = State('some-query-state');
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
dioAdapter = DioAdapter(dio: dio);
|
||||||
|
httpClient = HttpClient(dio);
|
||||||
|
testMailApiMixin = TestMailApiMixin();
|
||||||
|
});
|
||||||
|
|
||||||
|
group('mail api mixin test:', () {
|
||||||
|
group('fetchAllEmail:', () {
|
||||||
|
Map<String, dynamic> generateRequest({
|
||||||
|
required Filter filter,
|
||||||
|
int? position,
|
||||||
|
}) =>
|
||||||
|
{
|
||||||
|
"using": [
|
||||||
|
"urn:ietf:params:jmap:core",
|
||||||
|
"urn:ietf:params:jmap:mail",
|
||||||
|
"urn:apache:james:params:jmap:mail:shares",
|
||||||
|
],
|
||||||
|
"methodCalls": [
|
||||||
|
[
|
||||||
|
"Email/query",
|
||||||
|
{
|
||||||
|
"accountId": AccountFixtures.aliceAccountId.id.value,
|
||||||
|
if (position != null) "position": position,
|
||||||
|
"filter": filter.toJson(),
|
||||||
|
},
|
||||||
|
"c0"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Email/get",
|
||||||
|
{
|
||||||
|
"accountId": AccountFixtures.aliceAccountId.id.value,
|
||||||
|
"#ids": {
|
||||||
|
"resultOf": "c0",
|
||||||
|
"name": "Email/query",
|
||||||
|
"path": "/ids/*"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"c1"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<String, dynamic> generateResponse({
|
||||||
|
required List<Email> foundEmails,
|
||||||
|
required List<EmailId> notFoundEmailIds,
|
||||||
|
}) =>
|
||||||
|
{
|
||||||
|
"sessionState": sessionState.value,
|
||||||
|
"methodResponses": [
|
||||||
|
[
|
||||||
|
"Email/query",
|
||||||
|
{
|
||||||
|
"accountId": AccountFixtures.aliceAccountId.id.value,
|
||||||
|
"ids": foundEmails.map((email) => email.id?.id.value).toList()
|
||||||
|
..addAll(
|
||||||
|
notFoundEmailIds.map((emailId) => emailId.id.value)),
|
||||||
|
"queryState": queryState.value,
|
||||||
|
"canCalculateChanges": true,
|
||||||
|
"position": 0,
|
||||||
|
},
|
||||||
|
"c0"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Email/get",
|
||||||
|
{
|
||||||
|
"accountId": AccountFixtures.aliceAccountId.id.value,
|
||||||
|
"state": state.value,
|
||||||
|
"list": foundEmails.map((email) => email.toJson()).toList(),
|
||||||
|
"notFound": notFoundEmailIds
|
||||||
|
.map((emailId) => emailId.id.value)
|
||||||
|
.toList(),
|
||||||
|
},
|
||||||
|
"c1"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should not add position to request '
|
||||||
|
'when position is null',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final email = Email(
|
||||||
|
id: EmailId(Id('someEmailId')),
|
||||||
|
);
|
||||||
|
dioAdapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
generateResponse(
|
||||||
|
foundEmails: [email],
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
data: generateRequest(filter: filter),
|
||||||
|
);
|
||||||
|
|
||||||
|
// act
|
||||||
|
final result = await testMailApiMixin.fetchAllEmail(
|
||||||
|
session: SessionFixtures.aliceSession,
|
||||||
|
accountId: AccountFixtures.aliceAccountId,
|
||||||
|
httpClient: httpClient,
|
||||||
|
filter: filter,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(
|
||||||
|
result,
|
||||||
|
equals(
|
||||||
|
EmailsResponse(
|
||||||
|
emailList: [email],
|
||||||
|
state: state,
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should not add position to request '
|
||||||
|
'when position is 0',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final email = Email(
|
||||||
|
id: EmailId(Id('someEmailId')),
|
||||||
|
);
|
||||||
|
dioAdapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
403,
|
||||||
|
generateResponse(
|
||||||
|
foundEmails: [email],
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
data: generateRequest(filter: filter, position: 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// act & assert
|
||||||
|
expect(
|
||||||
|
() => testMailApiMixin.fetchAllEmail(
|
||||||
|
session: SessionFixtures.aliceSession,
|
||||||
|
accountId: AccountFixtures.aliceAccountId,
|
||||||
|
httpClient: httpClient,
|
||||||
|
filter: filter,
|
||||||
|
position: 0,
|
||||||
|
),
|
||||||
|
throwsA(isA<DioException>()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should add position to request '
|
||||||
|
'when position > 0',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final email = Email(
|
||||||
|
id: EmailId(Id('someEmailId')),
|
||||||
|
);
|
||||||
|
dioAdapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
generateResponse(
|
||||||
|
foundEmails: [email],
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
data: generateRequest(filter: filter, position: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// act
|
||||||
|
final result = await testMailApiMixin.fetchAllEmail(
|
||||||
|
session: SessionFixtures.aliceSession,
|
||||||
|
accountId: AccountFixtures.aliceAccountId,
|
||||||
|
httpClient: httpClient,
|
||||||
|
filter: filter,
|
||||||
|
position: 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(
|
||||||
|
result,
|
||||||
|
equals(
|
||||||
|
EmailsResponse(
|
||||||
|
emailList: [email],
|
||||||
|
state: state,
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:get/state_manager.dart';
|
||||||
|
import 'package:mockito/annotations.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/quick_search_email_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/quick_search_emails_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_sort_order_type.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/quick_search_filter.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart';
|
||||||
|
|
||||||
|
import '../../../../fixtures/account_fixtures.dart';
|
||||||
|
import '../../../../fixtures/session_fixtures.dart';
|
||||||
|
import 'quick_search_emails_extension_test.mocks.dart';
|
||||||
|
|
||||||
|
@GenerateNiceMocks([
|
||||||
|
MockSpec<SearchController>(),
|
||||||
|
MockSpec<QuickSearchEmailInteractor>(),
|
||||||
|
])
|
||||||
|
void main() {
|
||||||
|
final session = SessionFixtures.aliceSession;
|
||||||
|
final accountId = AccountFixtures.aliceAccountId;
|
||||||
|
const ownEmailAddress = 'alice@linagora.com';
|
||||||
|
const query = 'test';
|
||||||
|
|
||||||
|
EmailSortOrderType? sortOrderType;
|
||||||
|
|
||||||
|
late MockSearchController searchController;
|
||||||
|
late MockQuickSearchEmailInteractor quickSearchEmailInteractor;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
quickSearchEmailInteractor = MockQuickSearchEmailInteractor();
|
||||||
|
searchController = MockSearchController();
|
||||||
|
when(searchController.quickSearchEmailInteractor)
|
||||||
|
.thenReturn(quickSearchEmailInteractor);
|
||||||
|
when(searchController.listFilterOnSuggestionForm)
|
||||||
|
.thenReturn(<QuickSearchFilter>[].obs);
|
||||||
|
when(
|
||||||
|
quickSearchEmailInteractor.execute(
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
limit: anyNamed('limit'),
|
||||||
|
sort: anyNamed('sort'),
|
||||||
|
filter: anyNamed('filter'),
|
||||||
|
properties: anyNamed('properties'),
|
||||||
|
),
|
||||||
|
).thenAnswer((_) => Future.value(Right(QuickSearchEmailSuccess([]))));
|
||||||
|
});
|
||||||
|
|
||||||
|
group('quickSearchEmails', () {
|
||||||
|
test(
|
||||||
|
'should invoke quickSearchEmailInteractor.execute() with SearchController\'s sort '
|
||||||
|
'when sortOrderType is null',
|
||||||
|
() async {
|
||||||
|
sortOrderType = null;
|
||||||
|
when(searchController.searchEmailFilter)
|
||||||
|
.thenReturn(SearchEmailFilter(sortOrderType: sortOrderType).obs);
|
||||||
|
await searchController.quickSearchEmails(
|
||||||
|
session: session,
|
||||||
|
accountId: accountId,
|
||||||
|
ownEmailAddress: ownEmailAddress,
|
||||||
|
query: query,
|
||||||
|
);
|
||||||
|
verify(quickSearchEmailInteractor.execute(
|
||||||
|
session,
|
||||||
|
accountId,
|
||||||
|
limit: anyNamed('limit'),
|
||||||
|
sort: sortOrderType?.getSortOrder().toNullable(),
|
||||||
|
filter: anyNamed('filter'),
|
||||||
|
properties: anyNamed('properties'),
|
||||||
|
)).called(1);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should invoke quickSearchEmailInteractor.execute() with SearchController\'s sort '
|
||||||
|
'when sortOrderType is not null',
|
||||||
|
() async {
|
||||||
|
sortOrderType = EmailSortOrderType.oldest;
|
||||||
|
when(searchController.searchEmailFilter)
|
||||||
|
.thenReturn(SearchEmailFilter(sortOrderType: sortOrderType).obs);
|
||||||
|
await searchController.quickSearchEmails(
|
||||||
|
session: session,
|
||||||
|
accountId: accountId,
|
||||||
|
ownEmailAddress: ownEmailAddress,
|
||||||
|
query: query,
|
||||||
|
);
|
||||||
|
verify(quickSearchEmailInteractor.execute(
|
||||||
|
session,
|
||||||
|
accountId,
|
||||||
|
limit: anyNamed('limit'),
|
||||||
|
sort: sortOrderType?.getSortOrder().toNullable(),
|
||||||
|
filter: anyNamed('filter'),
|
||||||
|
properties: anyNamed('properties'),
|
||||||
|
)).called(1);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -57,9 +57,9 @@ void main() {
|
|||||||
final dioAdapterHeaders = <String, dynamic>{
|
final dioAdapterHeaders = <String, dynamic>{
|
||||||
'accept': 'application/json;jmapVersion=rfc-8621',
|
'accept': 'application/json;jmapVersion=rfc-8621',
|
||||||
};
|
};
|
||||||
final dioAdapter = DioAdapter(dio: dio);
|
late DioAdapter dioAdapter;
|
||||||
final httpClient = HttpClient(dio);
|
late HttpClient httpClient;
|
||||||
final threadApi = ThreadAPI(httpClient);
|
late ThreadAPI threadApi;
|
||||||
|
|
||||||
final sessionState = State('some-session-state');
|
final sessionState = State('some-session-state');
|
||||||
final state = State('some-state');
|
final state = State('some-state');
|
||||||
@@ -68,9 +68,15 @@ void main() {
|
|||||||
final filter = EmailFilterCondition(text: 'some-text');
|
final filter = EmailFilterCondition(text: 'some-text');
|
||||||
final queryState = State('some-query-state');
|
final queryState = State('some-query-state');
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
dioAdapter = DioAdapter(dio: dio);
|
||||||
|
httpClient = HttpClient(dio);
|
||||||
|
threadApi = ThreadAPI(httpClient);
|
||||||
|
});
|
||||||
|
|
||||||
group('thread api test:', () {
|
group('thread api test:', () {
|
||||||
group('searchEmails:', () {
|
group('searchEmails:', () {
|
||||||
Map<String, dynamic> generateRequest({required Filter filter}) => {
|
Map<String, dynamic> generateRequest({required Filter filter, int? position}) => {
|
||||||
"using": [
|
"using": [
|
||||||
"urn:ietf:params:jmap:core",
|
"urn:ietf:params:jmap:core",
|
||||||
"urn:ietf:params:jmap:mail",
|
"urn:ietf:params:jmap:mail",
|
||||||
@@ -81,6 +87,7 @@ void main() {
|
|||||||
"Email/query",
|
"Email/query",
|
||||||
{
|
{
|
||||||
"accountId": AccountFixtures.aliceAccountId.id.value,
|
"accountId": AccountFixtures.aliceAccountId.id.value,
|
||||||
|
if (position != null) "position": position,
|
||||||
"filter": filter.toJson(),
|
"filter": filter.toJson(),
|
||||||
},
|
},
|
||||||
"c0"
|
"c0"
|
||||||
@@ -267,6 +274,128 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should not add position to request '
|
||||||
|
'when position is null',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final searchEmail = SearchEmail(
|
||||||
|
id: EmailId(Id('someEmailId')),
|
||||||
|
searchSnippetSubject: 'searchSnippetSubject',
|
||||||
|
searchSnippetPreview: 'searchSnippetPreview',
|
||||||
|
);
|
||||||
|
dioAdapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
generateResponse(
|
||||||
|
foundSearchEmails: [searchEmail],
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
searchSnippetError: UnknownMethodResponse(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
data: generateRequest(filter: filter),
|
||||||
|
);
|
||||||
|
|
||||||
|
// act
|
||||||
|
final result = await threadApi.searchEmails(
|
||||||
|
SessionFixtures.aliceSession,
|
||||||
|
AccountFixtures.aliceAccountId,
|
||||||
|
filter: filter,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(
|
||||||
|
result,
|
||||||
|
equals(
|
||||||
|
SearchEmailsResponse(
|
||||||
|
searchSnippets: null,
|
||||||
|
emailList: [Email(id: searchEmail.id)],
|
||||||
|
state: state
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should not add position to request '
|
||||||
|
'when position is 0',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final searchEmail = SearchEmail(
|
||||||
|
id: EmailId(Id('someEmailId')),
|
||||||
|
searchSnippetSubject: 'searchSnippetSubject',
|
||||||
|
searchSnippetPreview: 'searchSnippetPreview',
|
||||||
|
);
|
||||||
|
dioAdapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
403,
|
||||||
|
generateResponse(
|
||||||
|
foundSearchEmails: [searchEmail],
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
searchSnippetError: UnknownMethodResponse(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
data: generateRequest(filter: filter, position: 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// act & assert
|
||||||
|
expect(
|
||||||
|
() => threadApi.searchEmails(
|
||||||
|
SessionFixtures.aliceSession,
|
||||||
|
AccountFixtures.aliceAccountId,
|
||||||
|
filter: filter,
|
||||||
|
position: 0,
|
||||||
|
),
|
||||||
|
throwsA(isA<DioException>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should add position to request '
|
||||||
|
'when position > 0',
|
||||||
|
() async {
|
||||||
|
// arrange
|
||||||
|
final searchEmail = SearchEmail(
|
||||||
|
id: EmailId(Id('someEmailId')),
|
||||||
|
searchSnippetSubject: 'searchSnippetSubject',
|
||||||
|
searchSnippetPreview: 'searchSnippetPreview',
|
||||||
|
);
|
||||||
|
dioAdapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
generateResponse(
|
||||||
|
foundSearchEmails: [searchEmail],
|
||||||
|
notFoundEmailIds: [],
|
||||||
|
searchSnippetError: UnknownMethodResponse(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
data: generateRequest(filter: filter, position: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// act
|
||||||
|
final result = await threadApi.searchEmails(
|
||||||
|
SessionFixtures.aliceSession,
|
||||||
|
AccountFixtures.aliceAccountId,
|
||||||
|
filter: filter,
|
||||||
|
position: 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(
|
||||||
|
result,
|
||||||
|
equals(
|
||||||
|
SearchEmailsResponse(
|
||||||
|
searchSnippets: null,
|
||||||
|
emailList: [Email(id: searchEmail.id)],
|
||||||
|
state: state
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('sortEmails::test', () {
|
group('sortEmails::test', () {
|
||||||
|
|||||||
Reference in New Issue
Block a user