diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift index 34d9f80675fd106a479ea9707c193ab810344222..cd5d752e89186c7c417cc5696ccf2e1a1367b57e 100644 --- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift +++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift @@ -4,6 +4,7 @@ import ChatFeature import CheckContactAuthFeature import ConfirmRequestFeature import ContactFeature +import ContactLookupFeature import ContactsFeature import Foundation import HomeFeature @@ -38,7 +39,11 @@ extension AppEnvironment { mainQueue: mainQueue, bgQueue: bgQueue, lookup: { - ContactLookupEnvironment() + ContactLookupEnvironment( + messenger: messenger, + mainQueue: mainQueue, + bgQueue: bgQueue + ) }, sendRequest: { SendRequestEnvironment( diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift index 7fd2fc8e893fa9dd62b0934b2030ada99c2ed94d..82a775dd574227f7e95d09f29cbd1a02cd4fd08a 100644 --- a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift +++ b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift @@ -1,46 +1,81 @@ import ComposableArchitecture import Foundation import XCTestDynamicOverlay +import XXClient +import XXMessengerClient public struct ContactLookupState: Equatable { public init( id: Data, - isLookingUp: Bool = false + isLookingUp: Bool = false, + failure: String? = nil ) { self.id = id self.isLookingUp = isLookingUp + self.failure = failure } public var id: Data public var isLookingUp: Bool + public var failure: String? } public enum ContactLookupAction: Equatable { - case task - case cancelTask case lookupTapped + case didLookup(XXClient.Contact) + case didFail(NSError) } public struct ContactLookupEnvironment { - public init() {} + public init( + messenger: Messenger, + mainQueue: AnySchedulerOf<DispatchQueue>, + bgQueue: AnySchedulerOf<DispatchQueue> + ) { + self.messenger = messenger + self.mainQueue = mainQueue + self.bgQueue = bgQueue + } + + public var messenger: Messenger + public var mainQueue: AnySchedulerOf<DispatchQueue> + public var bgQueue: AnySchedulerOf<DispatchQueue> } #if DEBUG extension ContactLookupEnvironment { - public static let unimplemented = ContactLookupEnvironment() + public static let unimplemented = ContactLookupEnvironment( + messenger: .unimplemented, + mainQueue: .unimplemented, + bgQueue: .unimplemented + ) } #endif public let contactLookupReducer = Reducer<ContactLookupState, ContactLookupAction, ContactLookupEnvironment> { state, action, env in switch action { - case .task: - return .none + case .lookupTapped: + state.isLookingUp = true + return Effect.result { [state] in + do { + let contact = try env.messenger.lookupContact(id: state.id) + return .success(.didLookup(contact)) + } catch { + return .success(.didFail(error as NSError)) + } + } + .subscribe(on: env.bgQueue) + .receive(on: env.mainQueue) + .eraseToEffect() - case .cancelTask: + case .didLookup(_): + state.isLookingUp = false return .none - case .lookupTapped: + case .didFail(let error): + state.failure = error.localizedDescription + state.isLookingUp = false return .none } } diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift index 1d1e02085ac84f849318dcf1b6548c5ee9cc4da4..a8bcd339a287e4ee003a37a673f1cc498b68bc99 100644 --- a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift +++ b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift @@ -45,9 +45,6 @@ public struct ContactLookupView: View { } } .navigationTitle("Lookup") - .task { - await viewStore.send(.task).finish() - } } } } diff --git a/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift b/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift index 70847105030548fc33490bc567bb0cc0e57b2224..34ecabc362be0541b52517d1885bffe5c8a18303 100644 --- a/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift +++ b/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift @@ -1,31 +1,57 @@ import ComposableArchitecture import XCTest +import XXClient @testable import ContactLookupFeature final class ContactLookupFeatureTests: XCTestCase { - func testTask() { + func testLookup() { + let id: Data = "1234".data(using: .utf8)! + var didLookupId: [Data] = [] + let lookedUpContact = Contact.unimplemented("123data".data(using: .utf8)!) + let store = TestStore( - initialState: ContactLookupState( - id: "1234".data(using: .utf8)! - ), + initialState: ContactLookupState(id: id), reducer: contactLookupReducer, environment: .unimplemented ) + store.environment.mainQueue = .immediate + store.environment.bgQueue = .immediate + store.environment.messenger.lookupContact.run = { id in + didLookupId.append(id) + return lookedUpContact + } + + store.send(.lookupTapped) { + $0.isLookingUp = true + } - store.send(.task) + XCTAssertEqual(didLookupId, [id]) - store.send(.cancelTask) + store.receive(.didLookup(lookedUpContact)) { + $0.isLookingUp = false + } } - func testLookup() { + func testLookupFailure() { + let id: Data = "1234".data(using: .utf8)! + let failure = NSError(domain: "test", code: 0) + let store = TestStore( - initialState: ContactLookupState( - id: "1234".data(using: .utf8)! - ), + initialState: ContactLookupState(id: id), reducer: contactLookupReducer, environment: .unimplemented ) + store.environment.mainQueue = .immediate + store.environment.bgQueue = .immediate + store.environment.messenger.lookupContact.run = { _ in throw failure } + + store.send(.lookupTapped) { + $0.isLookingUp = true + } - store.send(.lookupTapped) + store.receive(.didFail(failure)) { + $0.failure = failure.localizedDescription + $0.isLookingUp = false + } } }