// // RootTests.swift // secantTests // // Created by Lukáš Korba on 12.04.2022. // import XCTest import ComposableArchitecture import ZcashLightClientKit import FileManager import DatabaseFiles import ZcashSDKEnvironment import WalletStorage import Root @testable import secant_testnet @MainActor class RootTests: XCTestCase { func testWalletInitializationState_Uninitialized() throws { let walletState = RootReducer.walletInitializationState( databaseFiles: .noOp, walletStorage: .noOp, zcashNetwork: ZcashNetworkBuilder.network(for: .testnet) ) XCTAssertEqual(walletState, .uninitialized) } func testWalletInitializationState_FilesPresentKeysMissing() throws { let wfmMock = FileManagerClient( url: { _, _, _, _ in .emptyURL }, fileExists: { _ in return true }, removeItem: { _ in } ) let walletState = RootReducer.walletInitializationState( databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)), walletStorage: .noOp, zcashNetwork: ZcashNetworkBuilder.network(for: .testnet) ) XCTAssertEqual(walletState, .keysMissing) } func testWalletInitializationState_FilesMissingKeysMissing() throws { let wfmMock = FileManagerClient( url: { _, _, _, _ in .emptyURL }, fileExists: { _ in return false }, removeItem: { _ in } ) let walletState = RootReducer.walletInitializationState( databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)), walletStorage: .noOp, zcashNetwork: ZcashNetworkBuilder.network(for: .testnet) ) XCTAssertEqual(walletState, .uninitialized) } func testWalletInitializationState_FilesMissing() throws { let wfmMock = FileManagerClient( url: { _, _, _, _ in .emptyURL }, fileExists: { _ in return false }, removeItem: { _ in } ) var walletStorage = WalletStorageClient.noOp walletStorage.areKeysPresent = { true } let walletState = RootReducer.walletInitializationState( databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)), walletStorage: walletStorage, zcashNetwork: ZcashNetworkBuilder.network(for: .testnet) ) XCTAssertEqual(walletState, .filesMissing) } func testWalletInitializationState_Initialized() throws { let wfmMock = FileManagerClient( url: { _, _, _, _ in .emptyURL }, fileExists: { _ in return true }, removeItem: { _ in } ) var walletStorage = WalletStorageClient.noOp walletStorage.areKeysPresent = { true } let walletState = RootReducer.walletInitializationState( databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)), walletStorage: walletStorage, zcashNetwork: ZcashNetworkBuilder.network(for: .testnet) ) XCTAssertEqual(walletState, .initialized) } @MainActor func testRespondToWalletInitializationState_Uninitialized() async throws { let store = TestStore( initialState: .initial ) { RootReducer() } store.dependencies.mainQueue = .immediate store.dependencies.crashReporter = .noOp store.dependencies.walletStorage = .noOp store.dependencies.databaseFiles = .noOp await store.send(.initialization(.respondToWalletInitializationState(.uninitialized))) await store.receive(.destination(.updateDestination(.onboarding))) { state in state.destinationState.destination = .onboarding state.appInitializationState = .uninitialized } await store.finish() } func testRespondToWalletInitializationState_KeysMissing() async throws { let store = TestStore( initialState: .initial ) { RootReducer() } store.dependencies.mainQueue = .immediate store.dependencies.crashReporter = .noOp store.dependencies.walletStorage = .noOp store.dependencies.databaseFiles = .noOp await store.send(.initialization(.respondToWalletInitializationState(.keysMissing))) { state in state.appInitializationState = .keysMissing state.alert = AlertState.tmpMigrationToBeDeveloped() } await store.finish() } func testRespondToWalletInitializationState_FilesMissing() async throws { let walletStorageError: Error = "export failed" let zcashError = ZcashError.unknown(walletStorageError) let store = TestStore( initialState: .initial ) { RootReducer() } store.dependencies.walletStorage = .noOp store.dependencies.walletStorage.exportWallet = { throw zcashError } store.dependencies.restoreWalletStorage = .noOp await store.send(.initialization(.respondToWalletInitializationState(.filesMissing))) { state in state.appInitializationState = .filesMissing state.isRestoringWallet = true } await store.receive(.initialization(.initializeSDK(.restoreWallet))) await store.receive(.initialization(.initializationFailed(zcashError))) { state in state.appInitializationState = .failed state.alert = AlertState.initializationFailed(zcashError) } await store.receive(.initialization(.checkBackupPhraseValidation)) { state in // failed is expected because environment is throwing errors state.appInitializationState = .failed state.alert = AlertState.cantLoadSeedPhrase() } await store.finish() } func testRespondToWalletInitializationState_Initialized() async throws { let walletStorageError: Error = "export failed" let zcashError = ZcashError.unknown(walletStorageError) let store = TestStore( initialState: .initial ) { RootReducer() } store.dependencies.walletStorage = .noOp store.dependencies.walletStorage.exportWallet = { throw walletStorageError } await store.send(.initialization(.respondToWalletInitializationState(.initialized))) await store.receive(.initialization(.initializeSDK(.existingWallet))) await store.receive(.initialization(.checkBackupPhraseValidation)) { state in // failed is expected because environment is throwing errors state.appInitializationState = .failed state.alert = AlertState.cantLoadSeedPhrase() } await store.receive(.initialization(.initializationFailed(zcashError))) { state in state.alert = AlertState.initializationFailed(zcashError) } await store.finish() } func testInitializationSuccessfullyDone() async throws { let store = TestStore( initialState: .initial ) { RootReducer() } store.dependencies.mainQueue = .immediate store.dependencies.sdkSynchronizer = .noOp // swiftlint:disable line_length let uAddress = try UnifiedAddress( encoding: "utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyzwtgnuc76h", network: .testnet ) await store.send(.initialization(.initializationSuccessfullyDone(uAddress))) { state in state.tabsState.addressDetailsState.uAddress = uAddress } await store.receive(.initialization(.registerForSynchronizersUpdate)) await store.finish() } }