diff --git a/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift b/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift index 4b175e86..560c3619 100644 --- a/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift +++ b/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift @@ -25,6 +25,8 @@ public enum ModuleDependency { } public static let Core: TargetDependency = .project(target: "Core", path: .relativeToRoot("Projects/Core")) + + public static let Testing: TargetDependency = .project(target: "Testing", path: .relativeToRoot("Projects/Testing")) } // External dependencies diff --git a/project/Projects/App/Sources/DIAssembly/DataAssembly.swift b/project/Projects/App/Sources/DIAssembly/DataAssembly.swift index fe727782..31714a6e 100644 --- a/project/Projects/App/Sources/DIAssembly/DataAssembly.swift +++ b/project/Projects/App/Sources/DIAssembly/DataAssembly.swift @@ -30,6 +30,31 @@ public struct DataAssembly: Assembly { container.register(LocalStorageService.self) { _ in return DefaultLocalStorageService() } + container.register((any ApplyService).self) { _ in + DefaultApplyService() + } + container.register((any AuthService).self) { _ in + DefaultAuthService() + } + container.register((any CrawlingPostService).self) { _ in + DefaultCrawlingPostService() + } + container.register((any ExternalRequestService).self) { _ in + DefaultExternalRequestService() + } + container.register((any NotificationsService).self) { _ in + DefaultNotificationsService() + } + container.register((any NotificationTokenTransferService).self) { _ in + DefaultNotificationTokenTransferService() + } + container.register((any RecruitmentPostService).self) { _ in + DefaultRecruitmentPostService() + } + container.register((any UserInformationService).self) { _ in + DefaultUserInformationService() + } + // MARK: 캐싱 레포지토리 container.register(CacheRepository.self) { _ in @@ -38,11 +63,8 @@ public struct DataAssembly: Assembly { .inObjectScope(.container) // MARK: 로컬에 저장된 유저정보 레포지토리 - container.register(UserInfoLocalRepository.self) { resolver in - let localStorageService = resolver.resolve(LocalStorageService.self)! - return DefaultUserInfoLocalRepository( - localStorageService: localStorageService - ) + container.register(UserInfoLocalRepository.self) { _ in + DefaultUserInfoLocalRepository() } // MARK: 회원가입 입력 검증 레포지토리 diff --git a/project/Projects/App/Sources/DIAssembly/DomainAssembly.swift b/project/Projects/App/Sources/DIAssembly/DomainAssembly.swift index 0115cb24..d5958689 100644 --- a/project/Projects/App/Sources/DIAssembly/DomainAssembly.swift +++ b/project/Projects/App/Sources/DIAssembly/DomainAssembly.swift @@ -18,58 +18,36 @@ public struct DomainAssembly: Assembly { // MARK: UseCase container.register(NotificationTokenUseCase.self) { _ in - return DefaultNotificationTokenUseCase() + DefaultNotificationTokenUseCase() } .inObjectScope(.container) - container.register(AuthInputValidationUseCase.self) { resolver in - let repository = resolver.resolve(AuthInputValidationRepository.self)! - - return DefaultAuthInputValidationUseCase(repository: repository) + container.register(AuthInputValidationUseCase.self) { _ in + DefaultAuthInputValidationUseCase() } container.register(AuthUseCase.self) { _ in - return DefaultAuthUseCase() + DefaultAuthUseCase() } - container.register(CenterProfileUseCase.self) { resolver in - let userProfileRepository = resolver.resolve(UserProfileRepository.self)! - let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)! - return DefaultCenterProfileUseCase( - userProfileRepository: userProfileRepository, - userInfoLocalRepository: userInfoLocalRepository - ) + container.register(CenterProfileUseCase.self) { _ in + DefaultCenterProfileUseCase() } - container.register(RecruitmentPostUseCase.self) { resolver in - let repository = resolver.resolve(RecruitmentPostRepository.self)! - - return DefaultRecruitmentPostUseCase( - repository: repository - ) + container.register(RecruitmentPostUseCase.self) { _ in + DefaultRecruitmentPostUseCase() } - container.register(WorkerProfileUseCase.self) { resolver in - let userProfileRepository = resolver.resolve(UserProfileRepository.self)! - let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)! - return DefaultWorkerProfileUseCase( - userProfileRepository: userProfileRepository, - userInfoLocalRepository: userInfoLocalRepository - ) + container.register(WorkerProfileUseCase.self) { _ in + DefaultWorkerProfileUseCase() } container.register(SettingScreenUseCase.self) { _ in - return DefaultSettingUseCase() + DefaultSettingUseCase() } - container.register(CenterCertificateUseCase.self) { resolver in - let authRepository = resolver.resolve(AuthRepository.self)! - let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)! - - return DefaultCenterCertificateUseCase( - authRepository: authRepository, - userInfoLocalRepository: userInfoLocalRepository - ) + container.register(CenterCertificateUseCase.self) { _ in + DefaultCenterCertificateUseCase() } } } diff --git a/project/Projects/Data/DataSource/Service/ApplyService.swift b/project/Projects/Data/DataSource/Service/ApplyService.swift index c6bd3222..e028063c 100644 --- a/project/Projects/Data/DataSource/Service/ApplyService.swift +++ b/project/Projects/Data/DataSource/Service/ApplyService.swift @@ -7,7 +7,6 @@ import Foundation -public class ApplyService: BaseNetworkService { - - public override init() { } -} +public protocol ApplyService: NetworkService where TagetAPI == ApplyAPI { } + +public class DefaultApplyService: BaseNetworkService, ApplyService { } diff --git a/project/Projects/Data/DataSource/Service/BaseNetworkService.swift b/project/Projects/Data/DataSource/Service/BaseNetworkService.swift index bdd6d2c7..a82031d6 100644 --- a/project/Projects/Data/DataSource/Service/BaseNetworkService.swift +++ b/project/Projects/Data/DataSource/Service/BaseNetworkService.swift @@ -15,11 +15,24 @@ import Alamofire import Moya import RxMoya -public class BaseNetworkService { +public protocol NetworkService { + associatedtype TagetAPI: BaseAPI + + func request(api: TagetAPI, with: RequestType) -> Single + + func requestDecodable(api: TagetAPI, with: RequestType) -> Single +} + +public enum RequestType { + case plain + case withToken +} + +public class BaseNetworkService: NetworkService { @Injected var keyValueStore: KeyValueStore - init() { } + public init() { } private lazy var providerWithToken: MoyaProvider = { @@ -177,11 +190,6 @@ public class BaseNetworkService { // MARK: DataRequest public extension BaseNetworkService { - enum RequestType { - case plain - case withToken - } - private func _request(api: TagetAPI, provider: MoyaProvider) -> Single { provider.rx @@ -249,43 +257,6 @@ public extension BaseNetworkService { request(api: api, with: with) .map(T.self) } - -// // MARK: Request with Progress -// struct ProgressResponse { -// -// let progress: Double -// let data: T? -// } -// -// func requestDecodableWithProgress(api: TagetAPI) -> Single> { -// -// Single>.create { single in -// -// self.provider.rx -// .requestWithProgress(api) -// .subscribe(onNext: { response in -// -// if let result = response.response { -// -// do { -// -// let decoded = try result.map(T.self) -// -// let item = ProgressResponse( -// progress: response.progress, -// data: decoded -// ) -// -// single(.success(item)) -// -// } catch { -// -// single(.failure(error)) -// } -// } -// }) -// } -// } } // MARK: HTTPResponseException+Extension diff --git a/project/Projects/Data/DataSource/Service/CenterRegisterService.swift b/project/Projects/Data/DataSource/Service/CenterRegisterService.swift index c60f69ba..4926be53 100644 --- a/project/Projects/Data/DataSource/Service/CenterRegisterService.swift +++ b/project/Projects/Data/DataSource/Service/CenterRegisterService.swift @@ -7,7 +7,6 @@ import Foundation -public class AuthService: BaseNetworkService { - - public override init() { } -} +public protocol AuthService: NetworkService where TagetAPI == AuthAPI { } + +public class DefaultAuthService: BaseNetworkService, AuthService { } diff --git a/project/Projects/Data/DataSource/Service/CrawlingPostService.swift b/project/Projects/Data/DataSource/Service/CrawlingPostService.swift index f5965c42..af01edb0 100644 --- a/project/Projects/Data/DataSource/Service/CrawlingPostService.swift +++ b/project/Projects/Data/DataSource/Service/CrawlingPostService.swift @@ -7,7 +7,7 @@ import Foundation -public class CrawlingPostService: BaseNetworkService { - - public override init() { } -} + +public protocol CrawlingPostService: NetworkService where TagetAPI == CrawlingPostAPI { } + +public class DefaultCrawlingPostService: BaseNetworkService, CrawlingPostService { } diff --git a/project/Projects/Data/DataSource/Service/ExternalRequestService.swift b/project/Projects/Data/DataSource/Service/ExternalRequestService.swift index 24d67bb1..70e9d247 100644 --- a/project/Projects/Data/DataSource/Service/ExternalRequestService.swift +++ b/project/Projects/Data/DataSource/Service/ExternalRequestService.swift @@ -7,7 +7,7 @@ import Foundation -public class ExternalRequestService: BaseNetworkService { - - public override init() { } -} + +public protocol ExternalRequestService: NetworkService where TagetAPI == ExtenalUrlAPI { } + +public class DefaultExternalRequestService: BaseNetworkService, ExternalRequestService { } diff --git a/project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift b/project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift index 1b03f091..7c521e0d 100644 --- a/project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift +++ b/project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift @@ -7,7 +7,7 @@ import Foundation -public class NotificationTokenTransferService: BaseNetworkService { - - public override init() { } -} + +public protocol NotificationTokenTransferService: NetworkService where TagetAPI == NotificationTokenAPI { } + +public class DefaultNotificationTokenTransferService: BaseNetworkService, NotificationTokenTransferService { } diff --git a/project/Projects/Data/DataSource/Service/NotificationsService.swift b/project/Projects/Data/DataSource/Service/NotificationsService.swift index 1a493d88..7e290073 100644 --- a/project/Projects/Data/DataSource/Service/NotificationsService.swift +++ b/project/Projects/Data/DataSource/Service/NotificationsService.swift @@ -7,7 +7,6 @@ import Foundation -public class NotificationsService: BaseNetworkService { - - public override init() { } -} +public protocol NotificationsService: NetworkService where TagetAPI == NotificationsAPI { } + +public class DefaultNotificationsService: BaseNetworkService, NotificationsService { } diff --git a/project/Projects/Data/DataSource/Service/RecruitmentPostService.swift b/project/Projects/Data/DataSource/Service/RecruitmentPostService.swift index 7fe16e2f..9ef3f437 100644 --- a/project/Projects/Data/DataSource/Service/RecruitmentPostService.swift +++ b/project/Projects/Data/DataSource/Service/RecruitmentPostService.swift @@ -7,7 +7,7 @@ import Foundation -public class RecruitmentPostService: BaseNetworkService { - - public override init() { } -} + +public protocol RecruitmentPostService: NetworkService where TagetAPI == RcruitmentPostAPI { } + +public class DefaultRecruitmentPostService: BaseNetworkService, RecruitmentPostService { } diff --git a/project/Projects/Data/DataSource/Service/UserInformationService.swift b/project/Projects/Data/DataSource/Service/UserInformationService.swift index cf1ff819..710ebc5b 100644 --- a/project/Projects/Data/DataSource/Service/UserInformationService.swift +++ b/project/Projects/Data/DataSource/Service/UserInformationService.swift @@ -7,7 +7,6 @@ import Foundation -public class UserInformationService: BaseNetworkService { - - public override init() { } -} +public protocol UserInformationService: NetworkService where TagetAPI == UserInformationAPI { } + +public class DefaultUserInformationService: BaseNetworkService, UserInformationService { } diff --git a/project/Projects/Data/DataSource/Util/KeyValueStore/KeyChainList.swift b/project/Projects/Data/DataSource/Util/KeyValueStore/KeyChainList.swift index bec8cdbf..84c0df95 100644 --- a/project/Projects/Data/DataSource/Util/KeyValueStore/KeyChainList.swift +++ b/project/Projects/Data/DataSource/Util/KeyValueStore/KeyChainList.swift @@ -37,8 +37,8 @@ public class KeyChainList: KeyValueStore { try keyChain.removeAll() // UserDefaults의 경우 수동으로 정보를 삭제합니다. - UserDefaults.standard.removeObject(forKey: Key.Auth.kaccessToken) - UserDefaults.standard.removeObject(forKey: Key.Auth.krefreshToken) + UserDefaults.standard.removeObject(forKey: KeyValueStoreKey.kaccessToken) + UserDefaults.standard.removeObject(forKey: KeyValueStoreKey.krefreshToken) } public func get(key: String) -> String? { diff --git a/project/Projects/Data/DataSource/Util/KeyValueStore/KeyValueStore.swift b/project/Projects/Data/DataSource/Util/KeyValueStore/KeyValueStore.swift index bd11eef2..4f9863f0 100644 --- a/project/Projects/Data/DataSource/Util/KeyValueStore/KeyValueStore.swift +++ b/project/Projects/Data/DataSource/Util/KeyValueStore/KeyValueStore.swift @@ -14,18 +14,16 @@ public protocol KeyValueStore { func removeAll() throws } -enum Key { - enum Auth { - static let kaccessToken = "idle_accessToken" - static let krefreshToken = "idle_refreshToken" - } +public enum KeyValueStoreKey { + public static let kaccessToken = "idle_accessToken" + public static let krefreshToken = "idle_refreshToken" } public extension KeyValueStore { func getAuthToken() -> (accessToken: String, refreshToken: String)? { - guard let accessToken = get(key: Key.Auth.kaccessToken), let refreshToken = get(key: Key.Auth.krefreshToken) else { + guard let accessToken = get(key: KeyValueStoreKey.kaccessToken), let refreshToken = get(key: KeyValueStoreKey.krefreshToken) else { return nil } @@ -34,7 +32,7 @@ public extension KeyValueStore { func saveAuthToken(accessToken: String, refreshToken: String) throws { - try save(key: Key.Auth.kaccessToken, value: accessToken) - try save(key: Key.Auth.krefreshToken, value: refreshToken) + try save(key: KeyValueStoreKey.kaccessToken, value: accessToken) + try save(key: KeyValueStoreKey.krefreshToken, value: refreshToken) } } diff --git a/project/Projects/Data/DataTests/APITesting/TestAssembly.swift b/project/Projects/Data/DataTests/APITesting/TestAssembly.swift deleted file mode 100644 index 711d41aa..00000000 --- a/project/Projects/Data/DataTests/APITesting/TestAssembly.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// TestAssembly.swift -// DataTests -// -// Created by choijunios on 10/15/24. -// - -import Foundation -import DataSource - - -import Swinject - -class TestAssembly: Assembly { - - func assemble(container: Swinject.Container) { - container.register(KeyValueStore.self) { _ in - TestKeyValueStore() - } - } -} diff --git a/project/Projects/Data/DataTests/APITesting/TokenTesting.swift b/project/Projects/Data/DataTests/APITesting/TokenTesting.swift deleted file mode 100644 index 695f5d0c..00000000 --- a/project/Projects/Data/DataTests/APITesting/TokenTesting.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// TokenTesting.swift -// ConcreteRepository -// -// Created by choijunios on 6/28/24. -// - -import Foundation -import RxSwift -@testable import DataSource - -// TestKeyValueStore -public class TestKeyValueStore: KeyValueStore { - - public init(testStore: [String : String] = [:]) { - self.testStore = [ - Key.Auth.kaccessToken: "access_token", - Key.Auth.krefreshToken: "refresh_token", - ].merging(testStore, uniquingKeysWith: { $1 }) - } - - var testStore: [String: String] = [:] - - public func save(key: String, value: String) throws { - - testStore[key] = value - } - - public func get(key: String) -> String? { - - return testStore[key] - } - - public func delete(key: String) throws { - - testStore.removeValue(forKey: key) - } - - public func removeAll() throws { - - testStore.removeAll() - } -} diff --git a/project/Projects/Data/DataTests/ImageCachingTest.swift b/project/Projects/Data/DataTests/ImageCachingTest.swift index c59dbf05..9e45a523 100644 --- a/project/Projects/Data/DataTests/ImageCachingTest.swift +++ b/project/Projects/Data/DataTests/ImageCachingTest.swift @@ -7,20 +7,20 @@ import Foundation import XCTest +import Core +import Domain + @testable import Repository -@testable import Domain +@testable import Testing import RxSwift class ImageCachingTest: XCTestCase { - var cacheRepository: DefaultCacheRepository! - var disposeBag: DisposeBag! + var disposeBag: DisposeBag = .init() - override func setUp() { - super.setUp() - self.cacheRepository = .init(maxFileCount: 5, removeFileCountForOveflow: 1) - self.disposeBag = .init() + static override func setUp() { + DependencyInjector.shared.assemble(MockAssemblies) } func test_diskcache_oveflows_50images() { @@ -35,6 +35,8 @@ class ImageCachingTest: XCTestCase { return; + let cacheRepository = DefaultCacheRepository(maxFileCount: 5, removeFileCountForOveflow: 1) + // 디스크 캐싱 내역 삭제 cacheRepository.clearImageCacheDirectory() diff --git a/project/Projects/Data/DataTests/InputValidationTest.swift b/project/Projects/Data/DataTests/InputValidationTest.swift deleted file mode 100644 index 3bea8e6f..00000000 --- a/project/Projects/Data/DataTests/InputValidationTest.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// InputValidationTest.swift -// DataTests -// -// Created by choijunios on 9/30/24. -// - -import XCTest -import Foundation -//@testable import Repository -//@testable import Domain - - -import RxSwift - - -/// 사용자의 입력을 판단하는 UseCase를 테스트 합니다. -final class InputValidationTests: XCTestCase { -// -// let usecase = DefaultAuthInputValidationUseCase( -// repository: DefaultAuthInputValidationRepository() -// ) -// -// func testPhoneNumberRegex() { -// -// let result1 = usecase.checkPhoneNumberIsValid( -// phoneNumber: "01012341234" -// ) -// print(result1) -// XCTAssertTrue(result1, "✅ 올바른 번호 성공") -// -// let result2 = usecase.checkPhoneNumberIsValid( -// phoneNumber: "0101234123213" -// ) -// -// XCTAssertFalse(result2, "✅ 올바른 번호 실패") -// -// let result3 = usecase.checkPhoneNumberIsValid( -// phoneNumber: "안녕하세요" -// ) -// -// XCTAssertFalse(result3, "✅ 올바른 번호 실패") -// } -// -// // MARK: Id & Password -// -// func testValidId() { -// // 유효한 아이디 테스트 -// XCTAssertTrue(usecase.checkIdIsValid(id: "User123")) -// XCTAssertTrue(usecase.checkIdIsValid(id: "user12")) -// XCTAssertTrue(usecase.checkIdIsValid(id: "123456")) -// XCTAssertTrue(usecase.checkIdIsValid(id: "abcdef")) -// XCTAssertTrue(usecase.checkIdIsValid(id: "ABCDEF")) -// } -// -// func testInvalidId() { -// // 유효하지 않은 아이디 테스트 -// XCTAssertFalse(usecase.checkIdIsValid(id: "Us3!")) // 너무 짧음 -// XCTAssertFalse(usecase.checkIdIsValid(id: "user@123")) // 특수 문자 포함 -// XCTAssertFalse(usecase.checkIdIsValid(id: "123456789012345678901")) // 너무 길음 -// XCTAssertFalse(usecase.checkIdIsValid(id: "user name")) // 공백 포함 -// } -// -// func testValidPassword() { -// // 유효한 비밀번호 테스트 -// XCTAssertTrue(usecase.checkPasswordIsValid(password: "Password1")) -// XCTAssertTrue(usecase.checkPasswordIsValid(password: "pass1234")) -// XCTAssertTrue(usecase.checkPasswordIsValid(password: "1234Abcd!")) -// XCTAssertTrue(usecase.checkPasswordIsValid(password: "Valid123")) -// XCTAssertTrue(usecase.checkPasswordIsValid(password: "StrongPass1!")) -// } -// -// func testInvalidPassword() { -// // 유효하지 않은 비밀번호 테스트 -// XCTAssertFalse(usecase.checkPasswordIsValid(password: "short1")) // 너무 짧음 -// XCTAssertFalse(usecase.checkPasswordIsValid(password: "alllowercase")) // 숫자 없음 -// XCTAssertFalse(usecase.checkPasswordIsValid(password: "ALLUPPERCASE")) // 숫자 없음 -// XCTAssertFalse(usecase.checkPasswordIsValid(password: "12345678")) // 영문자 없음 -// XCTAssertFalse(usecase.checkPasswordIsValid(password: "123456789012345678901")) // 너무 길음 -// } -} diff --git a/project/Projects/Data/DataTests/NotificationRepositoryMockTest.swift b/project/Projects/Data/DataTests/NotificationRepositoryMockTest.swift deleted file mode 100644 index e4df0e10..00000000 --- a/project/Projects/Data/DataTests/NotificationRepositoryMockTest.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// NotificationRepositoryMockTest.swift -// DataTests -// -// Created by choijunios on 10/15/24. -// - -import XCTest -import Repository -import DataSource -import Core - - -import RxSwift -import Swinject - -final class NotificationRepositoryMockTest: XCTestCase { - - let disposeBag = DisposeBag() - - static override func setUp() { - - DependencyInjector.shared.assemble([ - TestAssembly() - ]) - } - - func testNotificationList() throws { - - let expectation = expectation(description: "DefaultNotificationsRepositoryTest") - - let repository = DefaultNotificationsRepository() - - let readResult = repository - .readNotification(id: "-1") - .asObservable() - .share() - let readSuccess = readResult.compactMap { $0.value } - let readFailure = readResult.compactMap { $0.error } - - let unreadNotificationCountResult = repository - .unreadNotificationCount() - .asObservable() - .share() - let unreadNotificationCountSuccess = unreadNotificationCountResult.compactMap { $0.value } - let unreadNotificationCountFailure = unreadNotificationCountResult.compactMap { $0.error } - - let notifcationListResult = repository - .notifcationList() - .asObservable() - .share() - let notifcationListSuccess = notifcationListResult.compactMap { $0.value } - let notifcationListFailure = notifcationListResult.compactMap { $0.error } - - Observable.combineLatest( - readSuccess.asObservable(), - unreadNotificationCountSuccess.asObservable(), - notifcationListSuccess.asObservable() - ) - .subscribe { (_, count, notifications) in - - print("수: \(count)") - print(notifications) - - expectation.fulfill() - } - .disposed(by: disposeBag) - - Observable.merge( - readFailure.asObservable(), - unreadNotificationCountFailure.asObservable(), - notifcationListFailure.asObservable() - ) - .subscribe(onNext: { (domainError) in - - XCTFail(domainError.message) - }) - .disposed(by: disposeBag) - - wait(for: [expectation], timeout: 20) - } -} diff --git a/project/Projects/Data/DataTests/SaveUserInfoDataTests.swift b/project/Projects/Data/DataTests/SaveUserInfoDataTests.swift index 4aa1fc21..36b56b8e 100644 --- a/project/Projects/Data/DataTests/SaveUserInfoDataTests.swift +++ b/project/Projects/Data/DataTests/SaveUserInfoDataTests.swift @@ -7,17 +7,23 @@ import Foundation import XCTest +import Core + + @testable import Repository @testable import DataSource +@testable import Testing class SaveUserInfoDataTests: XCTestCase { - let repository = DefaultUserInfoLocalRepository( - localStorageService: DefaultLocalStorageService() - ) + static override func setUp() { + DependencyInjector.shared.assemble(MockAssemblies) + } func testUserTypeCRUD() { + let repository = DefaultUserInfoLocalRepository() + var userType = repository.getUserType() XCTAssertNil(userType) @@ -44,6 +50,7 @@ class SaveUserInfoDataTests: XCTestCase { func testUserInfoCRUD() { // MARK: Center + let repository = DefaultUserInfoLocalRepository() var centerInfo = repository.getCurrentCenterData() diff --git a/project/Projects/Data/Project.swift b/project/Projects/Data/Project.swift index 9c05f8a9..6ce92599 100644 --- a/project/Projects/Data/Project.swift +++ b/project/Projects/Data/Project.swift @@ -74,6 +74,7 @@ let project = Project( sources: ["DataTests/**"], dependencies: [ D.Data.Repository, + D.Testing, ], settings: .settings( configurations: IdleConfiguration.dataConfigurations diff --git a/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift index 1f68a9e6..ed1177c6 100644 --- a/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift +++ b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift @@ -15,7 +15,7 @@ import RxSwift public class DefaultAuthInputValidationRepository: AuthInputValidationRepository { - let networkService = AuthService() + @Injected var networkService: any AuthService public init() { } diff --git a/project/Projects/Data/Repository/DefaultAuthRepository.swift b/project/Projects/Data/Repository/DefaultAuthRepository.swift index 395d75b4..a970f722 100644 --- a/project/Projects/Data/Repository/DefaultAuthRepository.swift +++ b/project/Projects/Data/Repository/DefaultAuthRepository.swift @@ -16,8 +16,7 @@ import RxSwift public class DefaultAuthRepository: AuthRepository { @Injected var keyValueStore: KeyValueStore - - let networkService = AuthService() + @Injected var authService: any AuthService public init() { } } @@ -43,14 +42,14 @@ public extension DefaultAuthRepository { let data = (try? JSONEncoder().encode(dto)) ?? Data() - let dataTask = networkService.request(api: .registerCenterAccount(data: data), with: .plain) + let dataTask = authService.request(api: .registerCenterAccount(data: data), with: .plain) .mapToVoid() return convertToDomain(task: dataTask) } func requestCenterLogin(id: String, password: String) -> Single> { - let dataTask = networkService.requestDecodable(api: .centerLogin(id: id, password: password), with: .plain) + let dataTask = authService.requestDecodable(api: .centerLogin(id: id, password: password), with: .plain) .flatMap { [unowned self] in saveTokenToStore(token: $0) } @@ -59,7 +58,7 @@ public extension DefaultAuthRepository { } func signoutCenterAccount() -> Single> { - let dataTask = networkService + let dataTask = authService .request(api: .signoutCenterAccount, with: .withToken) .mapToVoid() @@ -70,7 +69,7 @@ public extension DefaultAuthRepository { let reasonString = reasons.joined(separator: "|") - let dataTask = networkService + let dataTask = authService .request( api: .deregisterCenterAccount( reason: reasonString, @@ -84,7 +83,7 @@ public extension DefaultAuthRepository { } func getCenterJoinStatus() -> Single> { - let dataTask = networkService + let dataTask = authService .request(api: .centerJoinStatus, with: .withToken) .map(CenterJoinStatusInfoVO.self) @@ -92,7 +91,7 @@ public extension DefaultAuthRepository { } func requestCenterJoin() -> Single> { - let dataTask = networkService + let dataTask = authService .request(api: .requestCenterJoin, with: .withToken) .mapToVoid() @@ -100,7 +99,7 @@ public extension DefaultAuthRepository { } func setNewPassword(phoneNumber: String, password: String) -> Single> { - let dataTask = networkService + let dataTask = authService .request(api: .makeNewPassword(phoneNumber: phoneNumber, newPassword: password), with: .plain) .mapToVoid() @@ -124,21 +123,21 @@ public extension DefaultAuthRepository { let data = (try? JSONEncoder().encode(dto)) ?? Data() - let dataTask = networkService.requestDecodable(api: .registerWorkerAccount(data: data), with: .plain) + let dataTask = authService.requestDecodable(api: .registerWorkerAccount(data: data), with: .plain) .flatMap { [unowned self] in saveTokenToStore(token: $0) } return convertToDomain(task: dataTask) } func requestWorkerLogin(phoneNumber: String, authNumber: String) -> Single> { - let dataTask = networkService.requestDecodable(api: .workerLogin(phoneNumber: phoneNumber, verificationNumber: authNumber), with: .plain) + let dataTask = authService.requestDecodable(api: .workerLogin(phoneNumber: phoneNumber, verificationNumber: authNumber), with: .plain) .flatMap { [unowned self] in saveTokenToStore(token: $0) } return convertToDomain(task: dataTask) } func signoutWorkerAccount() -> Single> { - let dataTask = networkService + let dataTask = authService .request(api: .signoutWorkerAccount, with: .withToken) .mapToVoid() @@ -147,7 +146,7 @@ public extension DefaultAuthRepository { func deregisterWorkerAccount(reasons: [String]) -> Single> { let reasonString = reasons.joined(separator: "|") - let dataTask = networkService + let dataTask = authService .request( api: .deregisterWorkerAccount(reason: reasonString), with: .withToken diff --git a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift index 0815df2b..0bfd672d 100644 --- a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift +++ b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift @@ -8,13 +8,14 @@ import Foundation import Domain import DataSource +import Core import RxSwift public class DefaultNotificationTokenTransferRepository: NotificationTokenTransferRepository { - let transferService: NotificationTokenTransferService = .init() + @Injected var transferService: any NotificationTokenTransferService public init() { } diff --git a/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift b/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift index 8234e524..7ad11190 100644 --- a/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift +++ b/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift @@ -8,6 +8,7 @@ import Foundation import Domain import DataSource +import Core import Moya @@ -15,9 +16,9 @@ import RxSwift public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { - private var recruitmentPostService: RecruitmentPostService = .init() - private var crawlingPostService: CrawlingPostService = .init() - private var applyService: ApplyService = .init() + @Injected var recruitmentPostService: any RecruitmentPostService + @Injected var crawlingPostService: any CrawlingPostService + @Injected var applyService: any ApplyService public init() { } diff --git a/project/Projects/Data/Repository/DefaultUserInfoLocalRepository.swift b/project/Projects/Data/Repository/DefaultUserInfoLocalRepository.swift index b5ac4a8a..1519bfa9 100644 --- a/project/Projects/Data/Repository/DefaultUserInfoLocalRepository.swift +++ b/project/Projects/Data/Repository/DefaultUserInfoLocalRepository.swift @@ -8,6 +8,7 @@ import Foundation import DataSource import Domain +import Core import RxSwift @@ -29,16 +30,12 @@ public class DefaultUserInfoLocalRepository: UserInfoLocalRepository { typealias K = UserInfoStorageKey - let localStorageService: LocalStorageService + @Injected var localStorageService: LocalStorageService let jsonDecoder = JSONDecoder() let encoder = JSONEncoder() - public init( - localStorageService: LocalStorageService - ) { - self.localStorageService = localStorageService - } + public init() { } public func getUserType() -> UserType? { let rawValue: String? = localStorageService.fetchData(key: K.userType.rawValue) diff --git a/project/Projects/Data/Repository/DefaultUserProfileRepository.swift b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift index a76d1dec..85d6a79d 100644 --- a/project/Projects/Data/Repository/DefaultUserProfileRepository.swift +++ b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift @@ -8,14 +8,15 @@ import Foundation import Domain import DataSource +import Core import RxSwift public class DefaultUserProfileRepository: UserProfileRepository { - let userInformationService: UserInformationService = .init() - let externalRequestService: ExternalRequestService = .init() + @Injected var userInformationService: any UserInformationService + @Injected var externalRequestService: any ExternalRequestService public init() { } diff --git a/project/Projects/Data/Repository/NotificationsRepository.swift b/project/Projects/Data/Repository/NotificationsRepository.swift index ecdbd2d3..cdd9f9ea 100644 --- a/project/Projects/Data/Repository/NotificationsRepository.swift +++ b/project/Projects/Data/Repository/NotificationsRepository.swift @@ -13,19 +13,19 @@ import Core public class DefaultNotificationsRepository: NotificationsRepository { - let service: NotificationsService = .init() + @Injected var notificationsService: any NotificationsService public init() { } public func readNotification(id: String) -> Sult { - let dataTask = service + let dataTask = notificationsService .request(api: .readNotification(id: id), with: .withToken) .mapToVoid() return convertToDomain(task: dataTask) } public func unreadNotificationCount() -> Sult { - let dataTask = service.request(api: .notReadNotificationsCount, with: .withToken) + let dataTask = notificationsService.request(api: .notReadNotificationsCount, with: .withToken) .map { response -> Int in let jsonObject = try JSONSerialization.jsonObject(with: response.data) as! [String: Any] let count = jsonObject["unreadNotificationCount"] as! Int @@ -35,7 +35,7 @@ public class DefaultNotificationsRepository: NotificationsRepository { } public func notifcationList() -> Sult<[NotificationVO], DomainError> { - let dataTask = service.request(api: .allNotifications, with: .withToken) + let dataTask = notificationsService.request(api: .allNotifications, with: .withToken) .map { response in let data = response.data let decoded = try JSONDecoder().decode([NotificationItemDTO].self, from: data) diff --git a/project/Projects/Domain/DomainTests/RegisterValidationTests.swift b/project/Projects/Domain/DomainTests/RegisterValidationTests.swift new file mode 100644 index 00000000..f6842ff9 --- /dev/null +++ b/project/Projects/Domain/DomainTests/RegisterValidationTests.swift @@ -0,0 +1,92 @@ +// +// RegisterValidationTests.swift +// DomainTests +// +// Created by choijunios on 10/16/24. +// + +import Foundation +import XCTest +import Core + +@testable import Domain +@testable import Testing + +final class RegisterValidationTests: XCTestCase { + + static override func setUp() { + DependencyInjector.shared.assemble(MockAssemblies) + } + + func testPhoneNumberRegex() { + + let usecase = DefaultAuthInputValidationUseCase() + + let result1 = usecase.checkPhoneNumberIsValid( + phoneNumber: "01012341234" + ) + print(result1) + XCTAssertTrue(result1, "✅ 올바른 번호 성공") + + let result2 = usecase.checkPhoneNumberIsValid( + phoneNumber: "0101234123213" + ) + + XCTAssertFalse(result2, "✅ 올바른 번호 실패") + + let result3 = usecase.checkPhoneNumberIsValid( + phoneNumber: "안녕하세요" + ) + + XCTAssertFalse(result3, "✅ 올바른 번호 실패") + } + + // MARK: Id & Password + + func testValidId() { + + let usecase = DefaultAuthInputValidationUseCase() + + // 유효한 아이디 테스트 + XCTAssertTrue(usecase.checkIdIsValid(id: "User123")) + XCTAssertTrue(usecase.checkIdIsValid(id: "user12")) + XCTAssertTrue(usecase.checkIdIsValid(id: "123456")) + XCTAssertTrue(usecase.checkIdIsValid(id: "abcdef")) + XCTAssertTrue(usecase.checkIdIsValid(id: "ABCDEF")) + } + + func testInvalidId() { + + let usecase = DefaultAuthInputValidationUseCase() + + // 유효하지 않은 아이디 테스트 + XCTAssertFalse(usecase.checkIdIsValid(id: "Us3!")) // 너무 짧음 + XCTAssertFalse(usecase.checkIdIsValid(id: "user@123")) // 특수 문자 포함 + XCTAssertFalse(usecase.checkIdIsValid(id: "123456789012345678901")) // 너무 길음 + XCTAssertFalse(usecase.checkIdIsValid(id: "user name")) // 공백 포함 + } + + func testValidPassword() { + + let usecase = DefaultAuthInputValidationUseCase() + + // 유효한 비밀번호 테스트 + XCTAssertTrue(usecase.checkPasswordIsValid(password: "Password1")) + XCTAssertTrue(usecase.checkPasswordIsValid(password: "pass1234")) + XCTAssertTrue(usecase.checkPasswordIsValid(password: "1234Abcd!")) + XCTAssertTrue(usecase.checkPasswordIsValid(password: "Valid123")) + XCTAssertTrue(usecase.checkPasswordIsValid(password: "StrongPass1!")) + } + + func testInvalidPassword() { + + let usecase = DefaultAuthInputValidationUseCase() + + // 유효하지 않은 비밀번호 테스트 + XCTAssertFalse(usecase.checkPasswordIsValid(password: "short1")) // 너무 짧음 + XCTAssertFalse(usecase.checkPasswordIsValid(password: "alllowercase")) // 숫자 없음 + XCTAssertFalse(usecase.checkPasswordIsValid(password: "ALLUPPERCASE")) // 숫자 없음 + XCTAssertFalse(usecase.checkPasswordIsValid(password: "12345678")) // 영문자 없음 + XCTAssertFalse(usecase.checkPasswordIsValid(password: "123456789012345678901")) // 너무 길음 + } +} diff --git a/project/Projects/Domain/DomainTests/Testing/Empty.swift b/project/Projects/Domain/DomainTests/Testing/Empty.swift deleted file mode 100644 index 8b137891..00000000 --- a/project/Projects/Domain/DomainTests/Testing/Empty.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/project/Projects/Domain/Project.swift b/project/Projects/Domain/Project.swift index 54b93933..256d9e93 100644 --- a/project/Projects/Domain/Project.swift +++ b/project/Projects/Domain/Project.swift @@ -47,6 +47,7 @@ let project = Project( // for test D.Domain, + D.Testing, ], settings: .settings( configurations: IdleConfiguration.domainConfigurations diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift index 5f047c93..90033d75 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift @@ -6,17 +6,16 @@ // import Foundation +import Core import RxSwift public class DefaultAuthInputValidationUseCase: AuthInputValidationUseCase { - let repository: AuthInputValidationRepository + @Injected var repository: AuthInputValidationRepository - public init(repository: AuthInputValidationRepository) { - self.repository = repository - } + public init() { } // MARK: 이름 인증 public func checkNameIsValid(name: String) -> Bool { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift index b6853563..ae780a5b 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift @@ -6,19 +6,17 @@ // import Foundation +import Core import RxSwift public class DefaultCenterCertificateUseCase: CenterCertificateUseCase { - let authRepository: AuthRepository - let userInfoLocalRepository: UserInfoLocalRepository + @Injected var authRepository: AuthRepository + @Injected var userInfoLocalRepository: UserInfoLocalRepository - public init(authRepository: AuthRepository, userInfoLocalRepository: UserInfoLocalRepository) { - self.authRepository = authRepository - self.userInfoLocalRepository = userInfoLocalRepository - } + public init() { } public func requestCenterCertificate() -> RxSwift.Single> { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift index 371f79c0..da9a44ea 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift @@ -6,17 +6,15 @@ // import Foundation - +import Core import RxSwift public class DefaultRecruitmentPostUseCase: RecruitmentPostUseCase { - let repository: RecruitmentPostRepository + @Injected var repository: RecruitmentPostRepository - public init(repository: RecruitmentPostRepository) { - self.repository = repository - } + public init() { } public func registerRecruitmentPost(inputs: RegisterRecruitmentPostBundle) -> Single> { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift index 280a40fe..70ef4948 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift @@ -6,19 +6,17 @@ // import Foundation +import Core import RxSwift public class DefaultCenterProfileUseCase: CenterProfileUseCase { - let userProfileRepository: UserProfileRepository - let userInfoLocalRepository: UserInfoLocalRepository + @Injected var userProfileRepository: UserProfileRepository + @Injected var userInfoLocalRepository: UserInfoLocalRepository - public init(userProfileRepository: UserProfileRepository, userInfoLocalRepository: UserInfoLocalRepository) { - self.userProfileRepository = userProfileRepository - self.userInfoLocalRepository = userInfoLocalRepository - } + public init() { } public func getProfile(mode: ProfileMode) -> Single> { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift index eb607214..d50e597e 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift @@ -6,19 +6,17 @@ // import Foundation +import Core import RxSwift public class DefaultWorkerProfileUseCase: WorkerProfileUseCase { - let userProfileRepository: UserProfileRepository - let userInfoLocalRepository: UserInfoLocalRepository + @Injected var userProfileRepository: UserProfileRepository + @Injected var userInfoLocalRepository: UserInfoLocalRepository - public init(userProfileRepository: UserProfileRepository, userInfoLocalRepository: UserInfoLocalRepository) { - self.userProfileRepository = userProfileRepository - self.userInfoLocalRepository = userInfoLocalRepository - } + public init() { } public func getProfile(mode: ProfileMode) -> Single> { diff --git a/project/Projects/Testing/Project.swift b/project/Projects/Testing/Project.swift new file mode 100644 index 00000000..a3640155 --- /dev/null +++ b/project/Projects/Testing/Project.swift @@ -0,0 +1,38 @@ +// +// Project.swift +// ProjectDescriptionHelpers +// +// Created by 최준영 on 10/16/24. +// + +import ProjectDescription +import ProjectDescriptionHelpers +import ConfigurationPlugin +import DependencyPlugin + +let project = Project( + name: "Testing", + settings: .settings( + configurations: IdleConfiguration.emptyConfigurations + ), + targets: [ + + .target( + name: "Testing", + destinations: DeploymentSettings.platforms, + product: .framework, + bundleId: "$(PRODUCT_BUNDLE_IDENTIFIER)", + deploymentTargets: DeploymentSettings.deployment_version, + sources: ["Sources/**"], + dependencies: [ + D.Domain, + D.Data.DataSource, + D.Data.Repository, + ], + settings: .settings( + base: ["ENABLE_TESTABILITY": "YES"], + configurations: IdleConfiguration.dataConfigurations + ) + ), + ] +) diff --git a/project/Projects/Testing/Sources/Data/MockAuthInputValidationRepository.swift b/project/Projects/Testing/Sources/Data/MockAuthInputValidationRepository.swift new file mode 100644 index 00000000..cbca7f7a --- /dev/null +++ b/project/Projects/Testing/Sources/Data/MockAuthInputValidationRepository.swift @@ -0,0 +1,31 @@ +// +// MockAuthInputValidationRepository.swift +// Testing +// +// Created by choijunios on 10/16/24. +// + +import Foundation +import Domain + + +import RxSwift + +class MockAuthInputValidationRepository: AuthInputValidationRepository { + + func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> { + .just(.success("")) + } + + func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> { + .just(.success("")) + } + + func requestBusinessNumberAuthentication(businessNumber: String) -> Single> { + .just(.success(.mock)) + } + + func requestCheckingIdDuplication(id: String) -> Single> { + .just(.success(())) + } +} diff --git a/project/Projects/Testing/Sources/Data/MockLocalStorageService.swift b/project/Projects/Testing/Sources/Data/MockLocalStorageService.swift new file mode 100644 index 00000000..7832f5e6 --- /dev/null +++ b/project/Projects/Testing/Sources/Data/MockLocalStorageService.swift @@ -0,0 +1,26 @@ +// +// MockLocalStorageService.swift +// Testing +// +// Created by choijunios on 10/16/24. +// + +import Foundation +import DataSource + +class MockLocalStorageService: LocalStorageService { + + var source: [String: Any] = [:] + + func fetchData(key: String) -> Value? { + source[key] as? Value + } + + func saveData(key: String, value: Value) { + source[key] = value + } + + func remove(key: String) { + source.removeValue(forKey: key) + } +} diff --git a/project/Projects/Testing/Sources/Data/TestKeyValueStore.swift b/project/Projects/Testing/Sources/Data/TestKeyValueStore.swift new file mode 100644 index 00000000..47a2fadc --- /dev/null +++ b/project/Projects/Testing/Sources/Data/TestKeyValueStore.swift @@ -0,0 +1,41 @@ +// +// TestKeyValueStore.swift +// Testing +// +// Created by choijunios on 10/16/24. +// + +import Foundation +import DataSource + +class TestKeyValueStore: KeyValueStore { + + init(testStore: [String : String] = [:]) { + self.testStore = [ + KeyValueStoreKey.kaccessToken: "access_token", + KeyValueStoreKey.krefreshToken: "refresh_token", + ].merging(testStore, uniquingKeysWith: { $1 }) + } + + var testStore: [String: String] = [:] + + func save(key: String, value: String) throws { + + testStore[key] = value + } + + func get(key: String) -> String? { + + return testStore[key] + } + + func delete(key: String) throws { + + testStore.removeValue(forKey: key) + } + + func removeAll() throws { + + testStore.removeAll() + } +} diff --git a/project/Projects/Testing/Sources/Domain/Mock_Domain.swift b/project/Projects/Testing/Sources/Domain/Mock_Domain.swift new file mode 100644 index 00000000..55620108 --- /dev/null +++ b/project/Projects/Testing/Sources/Domain/Mock_Domain.swift @@ -0,0 +1,8 @@ +// +// Mock_Domain.swift +// Testing +// +// Created by choijunios on 10/16/24. +// + +import Foundation diff --git a/project/Projects/Testing/Sources/MockAssemblies.swift b/project/Projects/Testing/Sources/MockAssemblies.swift new file mode 100644 index 00000000..11d1ef78 --- /dev/null +++ b/project/Projects/Testing/Sources/MockAssemblies.swift @@ -0,0 +1,44 @@ +// +// MockAssemblies.swift +// Testing +// +// Created by choijunios on 10/16/24. +// + +import Foundation +import Domain +import DataSource + + +import Swinject + +let MockAssemblies: [Assembly] = [ + MockDataAssembly(), + MockDomainAssembly(), +] + +// MARK: Domain Assembly +struct MockDomainAssembly: Assembly { + + func assemble(container: Container) { + + } +} + +// MARK: Data Assembly +struct MockDataAssembly: Assembly { + + func assemble(container: Container) { + container.register(AuthInputValidationRepository.self) { _ in + MockAuthInputValidationRepository() + } + + container.register(KeyValueStore.self) { _ in + TestKeyValueStore() + } + + container.register(LocalStorageService.self) { _ in + MockLocalStorageService() + } + } +} diff --git a/project/graph.png b/project/graph.png index 53be928f..1b154dfc 100644 Binary files a/project/graph.png and b/project/graph.png differ