diff --git a/Example/example-app/Package.swift b/Example/example-app/Package.swift index 72fd8b73e72ed93e7d71bcba0f0e74d6040f933a..f42e98664a31a186935121b44070f26108abafac 100644 --- a/Example/example-app/Package.swift +++ b/Example/example-app/Package.swift @@ -140,10 +140,15 @@ let package = Package( .target( name: "MyIdentityFeature", dependencies: [ + .target(name: "ErrorFeature"), .product( name: "ComposableArchitecture", package: "swift-composable-architecture" ), + .product( + name: "ComposablePresentation", + package: "swift-composable-presentation" + ), .product( name: "ElixxirDAppsSDK", package: "elixxir-dapps-sdk-swift" diff --git a/Example/example-app/Sources/AppFeature/App.swift b/Example/example-app/Sources/AppFeature/App.swift index 7a4d3ca966a64bc750fc0de05ccd75061fc77bd2..a8b27266dfdafbbd0f1a3fd49525545c1edec130 100644 --- a/Example/example-app/Sources/AppFeature/App.swift +++ b/Example/example-app/Sources/AppFeature/App.swift @@ -54,7 +54,8 @@ extension AppEnvironment { observeIdentity: { identitySubject.eraseToAnyPublisher() }, updateIdentity: { identitySubject.value = $0 }, bgScheduler: bgScheduler, - mainScheduler: mainScheduler + mainScheduler: mainScheduler, + error: ErrorEnvironment() ) ) ) diff --git a/Example/example-app/Sources/MyIdentityFeature/MyIdentityFeature.swift b/Example/example-app/Sources/MyIdentityFeature/MyIdentityFeature.swift index bb58876e62d4eb61044f0f47b5c8bd3315d9da00..0b7bb5b7e04ab47e45b595ebbee1719ffb75ec1c 100644 --- a/Example/example-app/Sources/MyIdentityFeature/MyIdentityFeature.swift +++ b/Example/example-app/Sources/MyIdentityFeature/MyIdentityFeature.swift @@ -1,16 +1,21 @@ import Combine import ComposableArchitecture +import ComposablePresentation import ElixxirDAppsSDK +import ErrorFeature public struct MyIdentityState: Equatable { public init( - id: UUID + id: UUID, + error: ErrorState? = nil ) { self.id = id + self.error = error } public var id: UUID public var identity: Identity? + public var error: ErrorState? } public enum MyIdentityAction: Equatable { @@ -19,6 +24,8 @@ public enum MyIdentityAction: Equatable { case didUpdateMyIdentity(Identity?) case makeIdentity case didFailMakingIdentity(NSError) + case didDismissError + case error(ErrorAction) } public struct MyIdentityEnvironment { @@ -27,13 +34,15 @@ public struct MyIdentityEnvironment { observeIdentity: @escaping () -> AnyPublisher<Identity?, Never>, updateIdentity: @escaping (Identity?) -> Void, bgScheduler: AnySchedulerOf<DispatchQueue>, - mainScheduler: AnySchedulerOf<DispatchQueue> + mainScheduler: AnySchedulerOf<DispatchQueue>, + error: ErrorEnvironment ) { self.getClient = getClient self.observeIdentity = observeIdentity self.updateIdentity = updateIdentity self.bgScheduler = bgScheduler self.mainScheduler = mainScheduler + self.error = error } public var getClient: () -> Client? @@ -41,6 +50,7 @@ public struct MyIdentityEnvironment { public var updateIdentity: (Identity?) -> Void public var bgScheduler: AnySchedulerOf<DispatchQueue> public var mainScheduler: AnySchedulerOf<DispatchQueue> + public var error: ErrorEnvironment } public let myIdentityReducer = Reducer<MyIdentityState, MyIdentityAction, MyIdentityEnvironment> @@ -81,10 +91,22 @@ public let myIdentityReducer = Reducer<MyIdentityState, MyIdentityAction, MyIden .receive(on: env.mainScheduler) .eraseToEffect() + case .didDismissError: + state.error = nil + return .none + case .didFailMakingIdentity(let error): + state.error = ErrorState(error: error) return .none } } +.presenting( + errorReducer, + state: .keyPath(\.error), + id: .keyPath(\.?.error), + action: /MyIdentityAction.error, + environment: \.error +) #if DEBUG extension MyIdentityEnvironment { @@ -93,7 +115,8 @@ extension MyIdentityEnvironment { observeIdentity: { fatalError() }, updateIdentity: { _ in fatalError() }, bgScheduler: .failing, - mainScheduler: .failing + mainScheduler: .failing, + error: .failing ) } #endif diff --git a/Example/example-app/Tests/MyIdentityFeatureTests/MyIdentityFeatureTests.swift b/Example/example-app/Tests/MyIdentityFeatureTests/MyIdentityFeatureTests.swift index 325c16318e2c42b565e0c1a7587ffdc63ce1579b..64bb06d235a5e9f97918577e1d152c939626b71b 100644 --- a/Example/example-app/Tests/MyIdentityFeatureTests/MyIdentityFeatureTests.swift +++ b/Example/example-app/Tests/MyIdentityFeatureTests/MyIdentityFeatureTests.swift @@ -2,6 +2,7 @@ import Combine import ComposableArchitecture import CustomDump import ElixxirDAppsSDK +import ErrorFeature import XCTest @testable import MyIdentityFeature @@ -75,6 +76,40 @@ final class MyIdentityFeatureTests: XCTestCase { mainScheduler.advance() } + + func testMakeIdentityFailure() { + let error = NSError(domain: "test", code: 1234) + let bgScheduler = DispatchQueue.test + let mainScheduler = DispatchQueue.test + + var env = MyIdentityEnvironment.failing + env.getClient = { + var client = Client.failing + client.makeIdentity.make = { throw error } + return client + } + env.bgScheduler = bgScheduler.eraseToAnyScheduler() + env.mainScheduler = mainScheduler.eraseToAnyScheduler() + + let store = TestStore( + initialState: MyIdentityState(id: UUID()), + reducer: myIdentityReducer, + environment: env + ) + + store.send(.makeIdentity) + + bgScheduler.advance() + mainScheduler.advance() + + store.receive(.didFailMakingIdentity(error)) { + $0.error = ErrorState(error: error) + } + + store.send(.didDismissError) { + $0.error = nil + } + } } private extension Identity {