From 16929860f48226e8f8b470080f1cc2ba6d8b4046 Mon Sep 17 00:00:00 2001 From: Hessam Mahdiabadi <67460597+iamHEssam@users.noreply.github.com> Date: Sun, 5 Nov 2023 21:50:59 +0330 Subject: [PATCH 1/2] Add Update of Favorite Status If Exist in Database --- Data/Sources/Data/Local/Local.swift | 1 + Data/Sources/Data/Local/LocalImpl.swift | 46 +++++++++++++++++++ .../PersonBankAccountRepositoryImpl.swift | 4 +- .../DataTests/LocalTests/LocalTests.swift | 41 ++++++++++++++++- .../RepositoriesTests/Mock/MockLocal.swift | 15 ++++++ .../PersonBankAccountRepositoryTests.swift | 40 ++++++++++++++++ .../PersonBankAccountRepository.swift | 2 +- .../PersonBankAccountUseCaseImpl.swift | 2 +- 8 files changed, 146 insertions(+), 5 deletions(-) diff --git a/Data/Sources/Data/Local/Local.swift b/Data/Sources/Data/Local/Local.swift index 646c59a..5ae0531 100644 --- a/Data/Sources/Data/Local/Local.swift +++ b/Data/Sources/Data/Local/Local.swift @@ -13,4 +13,5 @@ public protocol Local { func fetchFavoritePersonAccounts() async throws -> [PersonBankAccount] func savePersonAccountToFavorites(_ personBankAccount: PersonBankAccount) async throws -> PersonBankAccount func removePersonAccountFromFavorites(_ personBankAccount: PersonBankAccount) async throws -> PersonBankAccount + func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount } diff --git a/Data/Sources/Data/Local/LocalImpl.swift b/Data/Sources/Data/Local/LocalImpl.swift index 87a8df3..8c3bdd7 100644 --- a/Data/Sources/Data/Local/LocalImpl.swift +++ b/Data/Sources/Data/Local/LocalImpl.swift @@ -151,4 +151,50 @@ public class LocalImpl: Local { } } } + + public func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount { + return await withCheckedContinuation { [weak self] continuation in + guard let self else { + continuation.resume(returning: personBankAccount) + return + } + + self.database.backgroundContext.performAndWait { [weak self] in + guard let self else { + continuation.resume(returning: personBankAccount) + return + } + + do { + let fetchRequest: + NSFetchRequest = PersonBankAccountEntity.fetchRequest() + let sort = PersonBankAccountEntity.sortDescriptor + fetchRequest.sortDescriptors = [sort] + fetchRequest.fetchLimit = 1 + + let namePredicate = NSPredicate(format: "person.name == %@", + personBankAccount.person?.name ?? "") + let cardNumberPredicate = NSPredicate(format: "card.cardNumber == %@", + personBankAccount.card?.cardNumber ?? "") + let predicate = NSCompoundPredicate(type: .and, + subpredicates: [namePredicate, cardNumberPredicate]) + fetchRequest.predicate = predicate + + try Task.checkCancellation() + let accounts = try self.database.backgroundContext.fetch(fetchRequest) + guard let entity = accounts.first else { + continuation.resume(returning: personBankAccount) + return + } + + var newPersonBankAccount = personBankAccount + newPersonBankAccount.update(favoriteStatus: entity.isFavorite) + continuation.resume(returning: newPersonBankAccount) + + } catch { + continuation.resume(returning: personBankAccount) + } + } + } + } } diff --git a/Data/Sources/Data/Repositories/PersonBankAccountRepositoryImpl.swift b/Data/Sources/Data/Repositories/PersonBankAccountRepositoryImpl.swift index 460a23f..542cb43 100644 --- a/Data/Sources/Data/Repositories/PersonBankAccountRepositoryImpl.swift +++ b/Data/Sources/Data/Repositories/PersonBankAccountRepositoryImpl.swift @@ -40,7 +40,7 @@ public class PersonBankAccountRepositoryImpl: PersonBankAccountRepository { try await local.removePersonAccountFromFavorites(personBankAccount) } - public func updatefavoriteStatusForPersonAccount(_ personBankAccount: Domain.PersonBankAccount) async -> Domain.PersonBankAccount { - fatalError() + public func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount { + await local.updatefavoriteStatusBasedOnFavorites(personBankAccount) } } diff --git a/Data/Tests/DataTests/LocalTests/LocalTests.swift b/Data/Tests/DataTests/LocalTests/LocalTests.swift index 8a9982d..a16a06d 100644 --- a/Data/Tests/DataTests/LocalTests/LocalTests.swift +++ b/Data/Tests/DataTests/LocalTests/LocalTests.swift @@ -70,7 +70,7 @@ final class LocalTests: XCTestCase { // when do { - let _ = try await local.savePersonAccountToFavorites(createBankAccount()) + let _ = try await local.savePersonAccountToFavorites(createBankAccount()) let accounts = try await local.fetchFavoritePersonAccounts() XCTAssertEqual(accounts.count, 1) @@ -80,4 +80,43 @@ final class LocalTests: XCTestCase { XCTAssertNil(error) } } + + func testSuccessUpdateFavoriteStatus() async { + + // given + local = LocalImpl(database: MockDatabase()) + + // when + do { + let _ = try await local.savePersonAccountToFavorites(createBankAccount()) + let account = await local.updatefavoriteStatusBasedOnFavorites(createBankAccount()) + + XCTAssertEqual(account.isFavorite, true) + + } catch { + // then + XCTAssertNil(error) + } + } + + func testDoesNotUpdateFavoriteStatus() async { + + // given + local = LocalImpl(database: MockDatabase()) + + // when + do { + let _ = try await local.savePersonAccountToFavorites(createBankAccount()) + var newAccountDoesNotExsit = createBankAccount() + newAccountDoesNotExsit.person?.name = "new person" + newAccountDoesNotExsit.card?.cardNumber = "453" + let account = await local.updatefavoriteStatusBasedOnFavorites(newAccountDoesNotExsit) + + XCTAssertEqual(account.isFavorite, false) + + } catch { + // then + XCTAssertNil(error) + } + } } diff --git a/Data/Tests/DataTests/RepositoriesTests/Mock/MockLocal.swift b/Data/Tests/DataTests/RepositoriesTests/Mock/MockLocal.swift index 600e595..afd3043 100644 --- a/Data/Tests/DataTests/RepositoriesTests/Mock/MockLocal.swift +++ b/Data/Tests/DataTests/RepositoriesTests/Mock/MockLocal.swift @@ -38,6 +38,12 @@ class MockLocal: Local { newAccount.update(favoriteStatus: false) return newAccount } + + func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount { + var newAccount = personBankAccount + newAccount.update(favoriteStatus: true) + return newAccount + } } class MockSucceesRemoveLocal: MockLocal { @@ -64,3 +70,12 @@ class MockFailFetchFavoriteAccountLocal: MockLocal { throw LocalError.cannotFetchFavorites } } + +class MockDoesNotExistInFavoriteLocal: MockLocal { + + override func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount { + var newAccount = personBankAccount + newAccount.update(favoriteStatus: false) + return newAccount + } +} diff --git a/Data/Tests/DataTests/RepositoriesTests/PersonBankAccountRepositoryTests.swift b/Data/Tests/DataTests/RepositoriesTests/PersonBankAccountRepositoryTests.swift index a596e2e..5763e75 100644 --- a/Data/Tests/DataTests/RepositoriesTests/PersonBankAccountRepositoryTests.swift +++ b/Data/Tests/DataTests/RepositoriesTests/PersonBankAccountRepositoryTests.swift @@ -144,4 +144,44 @@ final class PersonBankAccountRepositoryTests: XCTestCase { XCTAssertEqual(error as? LocalError, .cannotFetchFavorites) } } + + func testSuccessUpdateFavoriteStatus() async { + + // given + let local = MockLocal() + repository = PersonBankAccountRepositoryImpl(api: MockApi(), + local: local) + + // when + do { + let _ = try await repository.savePersonAccountToFavorites(local.createAccount()) + let account = await repository.updatefavoriteStatusBasedOnFavorites(local.createAccount()) + + XCTAssertEqual(account.isFavorite, true) + + } catch { + // then + XCTAssertNil(error) + } + } + + func testDoesNotUpdateFavoriteStatus() async { + + // given + let local = MockDoesNotExistInFavoriteLocal() + repository = PersonBankAccountRepositoryImpl(api: MockApi(), + local: local) + + // when + do { + let _ = try await repository.savePersonAccountToFavorites(local.createAccount()) + let account = await repository.updatefavoriteStatusBasedOnFavorites(local.createAccount()) + + XCTAssertEqual(account.isFavorite, false) + + } catch { + // then + XCTAssertNil(error) + } + } } diff --git a/Domain/Sources/Domain/Repositories/PersonBankAccountRepository.swift b/Domain/Sources/Domain/Repositories/PersonBankAccountRepository.swift index 44b9f89..74de235 100644 --- a/Domain/Sources/Domain/Repositories/PersonBankAccountRepository.swift +++ b/Domain/Sources/Domain/Repositories/PersonBankAccountRepository.swift @@ -13,5 +13,5 @@ public protocol PersonBankAccountRepository { func fetchFavoritePersonAccounts() async throws -> [PersonBankAccount] func savePersonAccountToFavorites(_ personBankAccount: PersonBankAccount) async throws -> PersonBankAccount func removePersonAccountFromFavorites(_ personBankAccount: PersonBankAccount) async throws -> PersonBankAccount - func updatefavoriteStatusForPersonAccount(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount + func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount } diff --git a/Domain/Sources/Domain/UseCases/PersonBankAccountUseCaseImpl.swift b/Domain/Sources/Domain/UseCases/PersonBankAccountUseCaseImpl.swift index 7cbf183..261fefe 100644 --- a/Domain/Sources/Domain/UseCases/PersonBankAccountUseCaseImpl.swift +++ b/Domain/Sources/Domain/UseCases/PersonBankAccountUseCaseImpl.swift @@ -84,7 +84,7 @@ public class PersonBankAccountUseCaseImpl: PersonBankAccountUseCase { func createUpdateFavoriteStatusTask(atIndex index: Int) { taskGroup.addTask { var updatedAccount = await self.repository - .updatefavoriteStatusForPersonAccount(accounts[index]) + .updatefavoriteStatusBasedOnFavorites(accounts[index]) updatedAccount.update(indexAtList: index) return updatedAccount } From 653f3a446ebceb0806e3bc93c823f77d1dc26be3 Mon Sep 17 00:00:00 2001 From: Hessam Mahdiabadi <67460597+iamHEssam@users.noreply.github.com> Date: Sun, 5 Nov 2023 22:01:02 +0330 Subject: [PATCH 2/2] fixes compiler error in mock test. implemented updatefavoriteStatusBasedOnFavorites function --- Domain/Tests/DomainTests/UseCasesTests/MockRepository.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Domain/Tests/DomainTests/UseCasesTests/MockRepository.swift b/Domain/Tests/DomainTests/UseCasesTests/MockRepository.swift index 77c6cc5..c812693 100644 --- a/Domain/Tests/DomainTests/UseCasesTests/MockRepository.swift +++ b/Domain/Tests/DomainTests/UseCasesTests/MockRepository.swift @@ -9,7 +9,7 @@ import Foundation @testable import Domain class MockPersonBankAccountRepository: PersonBankAccountRepository { - + func createMockPersonAccount() -> PersonBankAccount { let person = Person(name: "hessam", email: "h.mahdi", avatar: nil) let card = Card(cardNumber: "123", cardType: "master") @@ -38,6 +38,10 @@ class MockPersonBankAccountRepository: PersonBankAccountRepository { func updatefavoriteStatusForPersonAccount(_ personBankAccount: Domain.PersonBankAccount) async -> Domain.PersonBankAccount { return personBankAccount } + + func updatefavoriteStatusBasedOnFavorites(_ personBankAccount: Domain.PersonBankAccount) async -> Domain.PersonBankAccount { + return personBankAccount + } } class MockSuccessEmptyFetchAccountRepository: MockPersonBankAccountRepository {