From 885a38606839726bcc01c367c7a0e429460d8a49 Mon Sep 17 00:00:00 2001 From: Dat PHAM HOANG Date: Fri, 21 Jun 2024 23:23:22 +0700 Subject: [PATCH] Fix duplicated selected AccountCache --- .../data/local/account_cache_manager.dart | 2 +- .../local/account_cache_manager_test.dart | 234 ++++++++++++++++++ .../local/memory_account_cache_client.dart | 109 ++++++++ 3 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 test/features/login/data/local/account_cache_manager_test.dart create mode 100644 test/features/login/data/local/memory_account_cache_client.dart diff --git a/lib/features/login/data/local/account_cache_manager.dart b/lib/features/login/data/local/account_cache_manager.dart index 3d3d6a43e..d7c483902 100644 --- a/lib/features/login/data/local/account_cache_manager.dart +++ b/lib/features/login/data/local/account_cache_manager.dart @@ -35,8 +35,8 @@ class AccountCacheManager { .removeDuplicated() .whereNot((account) => account.accountId == newAccountCache.accountId) .toList(); + await _accountCacheClient.clearAllData(); if (newAllAccounts.isNotEmpty) { - await _accountCacheClient.clearAllData(); await _accountCacheClient.updateMultipleItem(newAllAccounts.toMap()); } } diff --git a/test/features/login/data/local/account_cache_manager_test.dart b/test/features/login/data/local/account_cache_manager_test.dart new file mode 100644 index 000000000..dd4647c24 --- /dev/null +++ b/test/features/login/data/local/account_cache_manager_test.dart @@ -0,0 +1,234 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/caching/clients/account_cache_client.dart'; +import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; +import 'package:tmail_ui_user/features/login/data/model/account_cache.dart'; + +import 'memory_account_cache_client.dart'; + +void main() { + late AccountCacheManager accountCacheManager; + late AccountCacheClient accountCacheClient; + + group('setCurrentAccount for the same accountId', () { + setUp(() { + accountCacheClient = MemoryAccountCacheClient(); + accountCacheManager = AccountCacheManager(accountCacheClient); + }); + + test('WHEN cache have no account \n' + 'AND another account is selected \n' + 'THEN cache will have only new account', () async { + // arrange + final personalAccount3 = PersonalAccount( + '834191067', + AuthenticationType.oidc, + isSelected: true, + accountId: AccountId(Id( + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246')), + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: UserName('username@domain.com'), + ); + + // act + await accountCacheManager.setCurrentAccount(personalAccount3); + + // assert + final allAccounts = await accountCacheClient.getAll(); + expect(allAccounts.length, 1); + final result = await accountCacheManager.getCurrentAccount(); + expect(result, personalAccount3); + }); + + test('WHEN cache have one selected account \n' + 'AND another account which have same accountId is selected \n' + 'THEN cache will have only new account', () async { + // arrange + final account1 = AccountCache( + '253956617', + 'oidc', + isSelected: true, + accountId: + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246', + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: 'username@domain.com', + ); + + final personalAccount3 = PersonalAccount( + '834191067', + AuthenticationType.oidc, + isSelected: true, + accountId: AccountId(Id( + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246')), + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: UserName('username@domain.com'), + ); + + accountCacheClient.insertMultipleItem({ + account1.id: account1, + }); + + // act + await accountCacheManager.setCurrentAccount(personalAccount3); + + // assert + final allAccounts = await accountCacheClient.getAll(); + expect(allAccounts.length, 1); + final result = await accountCacheManager.getCurrentAccount(); + expect(result, personalAccount3); + }); + + test('WHEN cache have two selected account \n' + 'AND another account which have the same accountId is selected \n' + 'THEN cache will have only new account', () async { + // arrange + final account1 = AccountCache( + '253956617', + 'oidc', + isSelected: true, + accountId: + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246', + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: 'username@domain.com', + ); + final account2 = AccountCache( + '60734964', + 'oidc', + isSelected: true, + accountId: + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246', + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: 'username@domain.com', + ); + final personalAccount3 = PersonalAccount( + '834191067', + AuthenticationType.oidc, + isSelected: true, + accountId: AccountId(Id( + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246')), + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: UserName('username@domain.com'), + ); + + accountCacheClient.insertMultipleItem({ + account1.id: account1, + account2.id: account2, + }); + + // act + await accountCacheManager.setCurrentAccount(personalAccount3); + + // assert + final allAccounts = await accountCacheClient.getAll(); + expect(allAccounts.length, 1); + final result = await accountCacheManager.getCurrentAccount(); + expect(result, personalAccount3); + }); + }); + + group('setCurrentAccount for different accountId', () { + setUp(() { + accountCacheClient = MemoryAccountCacheClient(); + accountCacheManager = AccountCacheManager(accountCacheClient); + }); + + test('WHEN cache have one selected account \n' + 'AND another account is selected \n' + 'THEN cache will update with new selection', () async { + // arrange + final account1 = AccountCache( + '253956617', + 'oidc', + isSelected: true, + accountId: + '5c2e278644f9517aaf25e8246ae08b34da40b48f30ec0b94db05675894262fbc', + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: 'name@domain.com', + ); + + final personalAccount3 = PersonalAccount( + '834191067', + AuthenticationType.oidc, + isSelected: true, + accountId: AccountId(Id( + 'ae08b34da40b48f30ec0b94db05675894262fbc5c2e278644f9517aaf25e8246')), + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: UserName('username@domain.com'), + ); + + accountCacheClient.insertItem(account1.id, account1); + + // act + await accountCacheManager.setCurrentAccount(personalAccount3); + + // assert + final allAccounts = await accountCacheClient.getAll(); + expect(allAccounts.length, 2); + + final oldSelected = await accountCacheClient.getItem(account1.id); + expect(oldSelected!.isSelected, false); + + final newSelected = await accountCacheManager.getCurrentAccount(); + expect(newSelected, personalAccount3); + expect(newSelected.isSelected, true); + }); + + test('WHEN cache have two selected account \n' + 'AND another account is selected \n' + 'THEN cache will update with new selected account', () async { + // arrange + final account1 = AccountCache( + '253956617', + 'oidc', + isSelected: true, + accountId: + 'f30ec0b94db05675894262fbc5c2e27ae08b34da40b488644f9517aaf25e8246', + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: 'usernameA@domain.com', + ); + final account2 = AccountCache( + '60734964', + 'oidc', + isSelected: true, + accountId: + '4db05675894262fbc5c2e27ae08b34da40b48f30ec0b98644f9517aaf25e8246', + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: 'usernameB@domain.com', + ); + final personalAccount3 = PersonalAccount( + '834191067', + AuthenticationType.oidc, + isSelected: true, + accountId: AccountId(Id( + '5675894262fbc5c2e278644f9517aaf25e8246ae08b34da40b48f30ec0b94db0')), + apiUrl: 'https://jmap.domain.com/oidc/jmap', + userName: UserName('usernameC@domain.com'), + ); + + accountCacheClient.insertMultipleItem({ + account1.id: account1, + account2.id: account2, + }); + + // act + await accountCacheManager.setCurrentAccount(personalAccount3); + + // assert + final allAccounts = await accountCacheClient.getAll(); + expect(allAccounts.length, 3); + + final oldOne = await accountCacheClient.getItem(account1.id); + expect(oldOne!.isSelected, false); + + final oldTwo = await accountCacheClient.getItem(account2.id); + expect(oldTwo!.isSelected, false); + + final newSelected = await accountCacheManager.getCurrentAccount(); + expect(newSelected, personalAccount3); + expect(newSelected.isSelected, true); + }); + }); +} diff --git a/test/features/login/data/local/memory_account_cache_client.dart b/test/features/login/data/local/memory_account_cache_client.dart new file mode 100644 index 000000000..e4349a76e --- /dev/null +++ b/test/features/login/data/local/memory_account_cache_client.dart @@ -0,0 +1,109 @@ +import 'package:hive/hive.dart'; +import 'package:tmail_ui_user/features/caching/clients/account_cache_client.dart'; +import 'package:tmail_ui_user/features/login/data/model/account_cache.dart'; + +class MemoryAccountCacheClient implements AccountCacheClient { + final Map _cache = {}; + + @override + Future clearAllData() { + _cache.clear(); + return Future.value(); + } + + @override + Future clearAllDataContainKey(String nestedKey) { + _cache.removeWhere((key, value) => key == nestedKey); + return Future.value(); + } + + @override + Future closeBox() { + return Future.value(); + } + + @override + Future deleteBox() { + return Future.value(); + } + + @override + Future deleteItem(String key) { + _cache.remove(key); + return Future.value(); + } + + @override + Future deleteMultipleItem(List listKey) { + _cache.removeWhere((key, value) => listKey.contains(key)); + return Future.value(); + } + + @override + bool get encryption => false; + + @override + Future> getAll() { + return Future.value(_cache.values.toList()); + } + + @override + Future getItem(String key, {bool needToReopen = false}) { + return Future.value(_cache[key]); + } + + @override + Future> getListByNestedKey(String nestedKey) { + return Future.value( + _cache.values.where((account) => account.id == nestedKey).toList()); + } + + @override + Future> getValuesByListKey(List listKeys) { + return Future.value(_cache.values + .where((account) => listKeys.contains(account.id)) + .toList()); + } + + @override + Future insertItem(String key, AccountCache newObject) { + _cache[key] = newObject; + return Future.value(); + } + + @override + Future insertMultipleItem(Map mapObject) { + _cache.addAll(mapObject); + return Future.value(); + } + + @override + Future isExistItem(String key) { + return Future.value(_cache.containsKey(key)); + } + + @override + Future> openBox() { + throw UnimplementedError(); + } + + @override + Future> openBoxEncryption() { + throw UnimplementedError(); + } + + @override + String get tableName => 'AccountCache'; + + @override + Future updateItem(String key, AccountCache newObject) { + _cache[key] = newObject; + return Future.value(); + } + + @override + Future updateMultipleItem(Map mapObject) { + _cache.addAll(mapObject); + return Future.value(); + } +}