From b344062068c0710bd445b8c6ac212fd35c5fdaec Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 25 Oct 2024 15:47:15 +0700 Subject: [PATCH] TF-3226 Parsing minInputLength from Autocomplete capability in session --- .../model/autocomplete_capability.dart | 31 +++++ contact/lib/contact_module.dart | 3 +- lib/features/base/base_controller.dart | 9 ++ .../domain/extensions/session_extensions.dart | 18 +++ lib/main/utils/app_config.dart | 2 +- test/features/base/base_controller_test.dart | 127 ++++++++++++++++++ .../session/session_extensions_test.dart | 105 +++++++++++++++ 7 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 contact/lib/contact/model/autocomplete_capability.dart create mode 100644 test/features/session/session_extensions_test.dart diff --git a/contact/lib/contact/model/autocomplete_capability.dart b/contact/lib/contact/model/autocomplete_capability.dart new file mode 100644 index 0000000000..b5a099d8b0 --- /dev/null +++ b/contact/lib/contact/model/autocomplete_capability.dart @@ -0,0 +1,31 @@ +import 'package:jmap_dart_client/http/converter/unsigned_int_nullable_converter.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_properties.dart'; +import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'autocomplete_capability.g.dart'; + +@JsonSerializable( + explicitToJson: true, + includeIfNull: false, + converters: [ + UnsignedIntNullableConverter() + ] +) +class AutocompleteCapability extends CapabilityProperties { + final UnsignedInt? minInputLength; + + AutocompleteCapability({this.minInputLength}); + + factory AutocompleteCapability.fromJson(Map json) + => _$AutocompleteCapabilityFromJson(json); + + Map toJson() => _$AutocompleteCapabilityToJson(this); + + static AutocompleteCapability deserialize(Map json) { + return AutocompleteCapability.fromJson(json); + } + + @override + List get props => [minInputLength]; +} \ No newline at end of file diff --git a/contact/lib/contact_module.dart b/contact/lib/contact_module.dart index 7b49234bba..6858970d70 100644 --- a/contact/lib/contact_module.dart +++ b/contact/lib/contact_module.dart @@ -11,4 +11,5 @@ export 'data/datasource_impl/tmail_contact_datasource_impl.dart'; export 'contact/autocomplete/autocomplete_tmail_contact_method.dart'; export 'contact/autocomplete/autocomplete_tmail_contact_response.dart'; -export 'contact/model/capability_contact.dart'; \ No newline at end of file +export 'contact/model/capability_contact.dart'; +export 'contact/model/autocomplete_capability.dart'; \ No newline at end of file diff --git a/lib/features/base/base_controller.dart b/lib/features/base/base_controller.dart index 852b63873c..1c8f904e8a 100644 --- a/lib/features/base/base_controller.dart +++ b/lib/features/base/base_controller.dart @@ -32,6 +32,7 @@ import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_mixin.da import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/email/presentation/bindings/mdn_interactor_bindings.dart'; +import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart'; @@ -516,4 +517,12 @@ abstract class BaseController extends GetxController authorizationInterceptors.clear(); await cachingManager.closeHive(); } + + int getMinInputLengthAutocomplete({ + required Session session, + required AccountId accountId, + }) { + final minInputLength = session.getMinInputLengthAutocomplete(accountId); + return minInputLength?.value.toInt() ?? AppConfig.defaultMinInputLengthAutocomplete; + } } diff --git a/lib/features/home/domain/extensions/session_extensions.dart b/lib/features/home/domain/extensions/session_extensions.dart index 5afafc577d..cb01440fb0 100644 --- a/lib/features/home/domain/extensions/session_extensions.dart +++ b/lib/features/home/domain/extensions/session_extensions.dart @@ -1,12 +1,16 @@ import 'dart:convert'; +import 'package:contact/contact/model/autocomplete_capability.dart'; +import 'package:contact/contact/model/capability_contact.dart'; import 'package:core/presentation/extensions/uri_extension.dart'; import 'package:core/utils/app_logger.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/http/converter/state_converter.dart'; import 'package:jmap_dart_client/http/converter/user_name_converter.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/home/data/model/session_hive_obj.dart'; import 'package:tmail_ui_user/features/home/domain/converter/session_account_converter.dart'; @@ -61,4 +65,18 @@ extension SessionExtensions on Session { return ''; } } + + UnsignedInt? getMinInputLengthAutocomplete(AccountId accountId) { + try { + final autocompleteCapability = getCapabilityProperties( + accountId, + tmailContactCapabilityIdentifier); + final minInputLength = autocompleteCapability?.minInputLength; + log('SessionExtensions::getMinInputLengthAutocomplete:minInputLength = $minInputLength'); + return minInputLength; + } catch (e) { + logError('SessionExtensions::getMinInputLengthAutocomplete():[Exception] $e'); + return null; + } + } } \ No newline at end of file diff --git a/lib/main/utils/app_config.dart b/lib/main/utils/app_config.dart index ceb41963ad..34ed89452e 100644 --- a/lib/main/utils/app_config.dart +++ b/lib/main/utils/app_config.dart @@ -7,7 +7,7 @@ import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.d import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class AppConfig { - static const int limitCharToStartSearch = 3; + static const int defaultMinInputLengthAutocomplete = 3; static const int warningAttachmentFileSizeInMegabytes = 10; static const String appDashboardConfigurationPath = "configurations/app_dashboard.json"; diff --git a/test/features/base/base_controller_test.dart b/test/features/base/base_controller_test.dart index 8380fae76c..43449553ff 100644 --- a/test/features/base/base_controller_test.dart +++ b/test/features/base/base_controller_test.dart @@ -1,3 +1,5 @@ +import 'package:contact/contact/model/autocomplete_capability.dart'; +import 'package:contact/contact/model/capability_contact.dart'; import 'package:core/data/network/config/dynamic_url_interceptors.dart'; import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/state/failure.dart'; @@ -6,6 +8,12 @@ import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/utils/application_manager.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/core/account/account.dart'; +import 'package:jmap_dart_client/jmap/core/capability/empty_capability.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:mockito/annotations.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; @@ -16,9 +24,11 @@ import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_ import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; +import 'package:tmail_ui_user/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; +import '../../fixtures/account_fixtures.dart'; import 'base_controller_test.mocks.dart'; class MockBaseController extends BaseController { @@ -201,4 +211,121 @@ void main() { expect(mockBaseController.isUrgentExceptionEnable, false); }); }); + + group('BaseController::getMinInputLengthAutocomplete::test', () { + late MockBaseController mockBaseController; + + setUp(() { + mockBaseController = MockBaseController(); + }); + + test('SHOULD return session min input length WHEN AutocompleteCapability available', () { + // Arrange + const expectedMinInputLength = 5; + final session = Session( + { + tmailContactCapabilityIdentifier: AutocompleteCapability( + minInputLength: UnsignedInt(expectedMinInputLength) + ) + }, + { + AccountFixtures.aliceAccountId: Account( + AccountName('Alice'), + true, + false, + { + tmailContactCapabilityIdentifier: AutocompleteCapability( + minInputLength: UnsignedInt(expectedMinInputLength) + ) + }, + ) + }, + {}, + UserName(''), + Uri(), + Uri(), + Uri(), + Uri(), + State('')); + + // Act + final result = mockBaseController.getMinInputLengthAutocomplete( + session: session, + accountId: AccountFixtures.aliceAccountId, + ); + + // Assert + expect(result, expectedMinInputLength); + }); + + test('SHOULD return session min input length WHEN AutocompleteCapability available, but no minInputLength', () { + // Arrange + const expectedMinInputLength = AppConfig.defaultMinInputLengthAutocomplete; + final session = Session( + { + tmailContactCapabilityIdentifier: AutocompleteCapability() + }, + { + AccountFixtures.aliceAccountId: Account( + AccountName('Alice'), + true, + false, + { + tmailContactCapabilityIdentifier: AutocompleteCapability() + }, + ) + }, + {}, + UserName(''), + Uri(), + Uri(), + Uri(), + Uri(), + State(''), + ); + + // Act + final result = mockBaseController.getMinInputLengthAutocomplete( + session: session, + accountId: AccountFixtures.aliceAccountId, + ); + + // Assert + expect(result, expectedMinInputLength); + }); + + test('SHOULD return default min input length WHEN AutocompleteCapability is not available', () { + // Arrange + final session = Session( + { + tmailContactCapabilityIdentifier: EmptyCapability() + }, + { + AccountFixtures.aliceAccountId: Account( + AccountName('Alice'), + true, + false, + { + tmailContactCapabilityIdentifier: EmptyCapability() + }, + ) + }, + {}, + UserName(''), + Uri(), + Uri(), + Uri(), + Uri(), + State('')); + + // Act + final result = mockBaseController.getMinInputLengthAutocomplete( + session: session, + accountId: AccountFixtures.aliceAccountId, + ); + + // Assert + expect(result, AppConfig.defaultMinInputLengthAutocomplete); + }); + }); } diff --git a/test/features/session/session_extensions_test.dart b/test/features/session/session_extensions_test.dart new file mode 100644 index 0000000000..221914a42c --- /dev/null +++ b/test/features/session/session_extensions_test.dart @@ -0,0 +1,105 @@ +import 'package:contact/contact_module.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/core/account/account.dart'; +import 'package:jmap_dart_client/jmap/core/capability/empty_capability.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; + +import '../../fixtures/account_fixtures.dart'; + +void main() { + group('getMinInputLengthAutocomplete::test', () { + test('SHOULD return minInputLength WHEN AutocompleteCapability is available', () { + // Arrange + final autocompleteCapability = AutocompleteCapability(minInputLength: UnsignedInt(3)); + final session = Session( + { + tmailContactCapabilityIdentifier: autocompleteCapability + }, + { + AccountFixtures.aliceAccountId: Account( + AccountName('Alice'), + true, + false, + { + tmailContactCapabilityIdentifier: autocompleteCapability + }, + ) + }, + {}, + UserName(''), + Uri(), + Uri(), + Uri(), + Uri(), + State('')); + + // Act + final result = session.getMinInputLengthAutocomplete(AccountFixtures.aliceAccountId); + + // Assert + expect(result, autocompleteCapability.minInputLength); + }); + + test('SHOULD return null WHEN AutocompleteCapability is not available', () { + // Arrange + final session = Session( + { + tmailContactCapabilityIdentifier: EmptyCapability() + }, + { + AccountFixtures.aliceAccountId: Account( + AccountName('Alice'), + true, + false, + { + tmailContactCapabilityIdentifier: EmptyCapability() + }, + ) + }, + {}, + UserName(''), + Uri(), + Uri(), + Uri(), + Uri(), + State('')); + + // Act + final result = session.getMinInputLengthAutocomplete(AccountFixtures.aliceAccountId); + + // Assert + expect(result, isNull); + }); + + test('SHOULD return null WHEN autocomplete capability is not supported', () { + // Arrange + final session = Session( + {}, + { + AccountFixtures.aliceAccountId: Account( + AccountName('Alice'), + true, + false, + {}, + ) + }, + {}, + UserName(''), + Uri(), + Uri(), + Uri(), + Uri(), + State('')); + + // Act + final result = session.getMinInputLengthAutocomplete(AccountFixtures.aliceAccountId); + + // Assert + expect(result, isNull); + }); + }); +}