diff --git a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift index f2625b91e6a4042624ad68141515ab34ace7c90c..4204a5ed81d4c1291e1522755af0ccac5ff3a833 100644 --- a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift +++ b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift @@ -1,4 +1,5 @@ import AppCore +import Combine import ComposableArchitecture import Foundation import XCTestDynamicOverlay @@ -40,7 +41,8 @@ public enum SendRequestAction: Equatable, BindableAction { case sendSucceeded case sendFailed(String) case binding(BindingAction<SendRequestState>) - case myContactFetched(XXClient.Contact?) + case myContactFetched(XXClient.Contact) + case myContactFetchFailed(NSError) } public struct SendRequestEnvironment { @@ -75,25 +77,32 @@ extension SendRequestEnvironment { public let sendRequestReducer = Reducer<SendRequestState, SendRequestAction, SendRequestEnvironment> { state, action, env in - enum DBFetchEffectID {} - switch action { case .start: - return Effect - .catching { try env.messenger.e2e.tryGet().getContact().getId() } - .tryMap { try env.db().fetchContactsPublisher(.init(id: [$0])) } - .flatMap { $0 } - .assertNoFailure() - .map(\.first) - .map { $0?.marshaled.map { XXClient.Contact.live($0) } } - .map(SendRequestAction.myContactFetched) - .subscribe(on: env.bgQueue) - .receive(on: env.mainQueue) - .eraseToEffect() - .cancellable(id: DBFetchEffectID.self, cancelInFlight: true) + return Effect.run { subscriber in + do { + var contact = try env.messenger.e2e.tryGet().getContact() + let facts = try env.messenger.ud.tryGet().getFacts() + try contact.setFacts(facts) + subscriber.send(.myContactFetched(contact)) + } catch { + subscriber.send(.myContactFetchFailed(error as NSError)) + } + subscriber.send(completion: .finished) + return AnyCancellable {} + } + .receive(on: env.mainQueue) + .subscribe(on: env.bgQueue) + .eraseToEffect() case .myContactFetched(let contact): state.myContact = contact + state.failure = nil + return .none + + case .myContactFetchFailed(let failure): + state.myContact = nil + state.failure = failure.localizedDescription return .none case .sendTapped: diff --git a/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift b/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift index 9b15f6cd39884e45f7214875ba586cbb0e2b7712..7681289691ce4268430d9242f6c41b638c41e185 100644 --- a/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift +++ b/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift @@ -8,6 +8,22 @@ import XXModels final class SendRequestFeatureTests: XCTestCase { func testStart() { + var didSetFactsOnE2EContact: [[Fact]] = [] + let e2eContactData = "e2e-contact-data".data(using: .utf8)! + let e2eContactDataWithFacts = "e2e-contact-data-with-facts".data(using: .utf8)! + let e2eContact: XXClient.Contact = { + var contact = XXClient.Contact.unimplemented(e2eContactData) + contact.setFactsOnContact.run = { data, facts in + didSetFactsOnE2EContact.append(facts) + return e2eContactDataWithFacts + } + return contact + }() + let udFacts = [ + Fact(type: .username, value: "ud-username"), + Fact(type: .email, value: "ud-email"), + Fact(type: .phone, value: "ud-phone"), + ] let store = TestStore( initialState: SendRequestState( contact: .unimplemented("contact-data".data(using: .utf8)!) @@ -15,47 +31,56 @@ final class SendRequestFeatureTests: XCTestCase { reducer: sendRequestReducer, environment: .unimplemented ) - - var dbDidFetchContacts: [XXModels.Contact.Query] = [] - let dbContactsPublisher = PassthroughSubject<[XXModels.Contact], Error>() - store.environment.mainQueue = .immediate store.environment.bgQueue = .immediate store.environment.messenger.e2e.get = { var e2e: E2E = .unimplemented - e2e.getContact.run = { - var contact: XXClient.Contact = .unimplemented("my-contact-data".data(using: .utf8)!) - contact.getIdFromContact.run = { _ in "my-contact-id".data(using: .utf8)! } - return contact - } + e2e.getContact.run = { e2eContact } return e2e } - store.environment.db.run = { - var db: Database = .unimplemented - db.fetchContactsPublisher.run = { query in - dbDidFetchContacts.append(query) - return dbContactsPublisher.eraseToAnyPublisher() - } - return db + store.environment.messenger.ud.get = { + var ud: UserDiscovery = .unimplemented + ud.getFacts.run = { udFacts } + return ud } store.send(.start) - XCTAssertNoDifference(dbDidFetchContacts, [.init(id: ["my-contact-id".data(using: .utf8)!])]) + store.receive(.myContactFetched(.unimplemented(e2eContactDataWithFacts))) { + $0.myContact = .unimplemented(e2eContactDataWithFacts) + } + } - dbContactsPublisher.send([]) + func testMyContactFailure() { + struct Failure: Error {} + let failure = Failure() - store.receive(.myContactFetched(nil)) + let store = TestStore( + initialState: SendRequestState( + contact: .unimplemented("contact-data".data(using: .utf8)!) + ), + reducer: sendRequestReducer, + environment: .unimplemented + ) + store.environment.mainQueue = .immediate + store.environment.bgQueue = .immediate + store.environment.messenger.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getContact.run = { .unimplemented(Data()) } + return e2e + } + store.environment.messenger.ud.get = { + var ud: UserDiscovery = .unimplemented + ud.getFacts.run = { throw failure } + return ud + } - var myDbContact = XXModels.Contact(id: "my-contact-id".data(using: .utf8)!) - myDbContact.marshaled = "my-contact-data".data(using: .utf8)! - dbContactsPublisher.send([myDbContact]) + store.send(.start) - store.receive(.myContactFetched(.live("my-contact-data".data(using: .utf8)!))) { - $0.myContact = .live("my-contact-data".data(using: .utf8)!) + store.receive(.myContactFetchFailed(failure as NSError)) { + $0.myContact = nil + $0.failure = failure.localizedDescription } - - dbContactsPublisher.send(completion: .finished) } func testSendRequest() {