diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactComponent.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactComponent.swift new file mode 100644 index 0000000000000000000000000000000000000000..160c671feac5b1e7bf16a221259364e7549f50c1 --- /dev/null +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactComponent.swift @@ -0,0 +1,273 @@ +import AppCore +import ChatFeature +import CheckContactAuthFeature +import ComposableArchitecture +import ComposablePresentation +import ConfirmRequestFeature +import ContactLookupFeature +import Foundation +import ResetAuthFeature +import SendRequestFeature +import VerifyContactFeature +import XCTestDynamicOverlay +import XXClient +import XXMessengerClient +import XXModels + +public struct ContactComponent: ReducerProtocol { + public struct State: Equatable { + public init( + id: Data, + dbContact: XXModels.Contact? = nil, + xxContact: XXClient.Contact? = nil, + importUsername: Bool = true, + importEmail: Bool = true, + importPhone: Bool = true, + lookup: ContactLookupComponent.State? = nil, + sendRequest: SendRequestComponent.State? = nil, + verifyContact: VerifyContactComponent.State? = nil, + confirmRequest: ConfirmRequestComponent.State? = nil, + checkAuth: CheckContactAuthComponent.State? = nil, + resetAuth: ResetAuthComponent.State? = nil, + chat: ChatComponent.State? = nil + ) { + self.id = id + self.dbContact = dbContact + self.xxContact = xxContact + self.importUsername = importUsername + self.importEmail = importEmail + self.importPhone = importPhone + self.lookup = lookup + self.sendRequest = sendRequest + self.verifyContact = verifyContact + self.confirmRequest = confirmRequest + self.checkAuth = checkAuth + self.resetAuth = resetAuth + self.chat = chat + } + + public var id: Data + public var dbContact: XXModels.Contact? + public var xxContact: XXClient.Contact? + @BindableState public var importUsername: Bool + @BindableState public var importEmail: Bool + @BindableState public var importPhone: Bool + public var lookup: ContactLookupComponent.State? + public var sendRequest: SendRequestComponent.State? + public var verifyContact: VerifyContactComponent.State? + public var confirmRequest: ConfirmRequestComponent.State? + public var checkAuth: CheckContactAuthComponent.State? + public var resetAuth: ResetAuthComponent.State? + public var chat: ChatComponent.State? + } + + public enum Action: Equatable, BindableAction { + case start + case dbContactFetched(XXModels.Contact?) + case importFactsTapped + case lookupTapped + case lookupDismissed + case lookup(ContactLookupComponent.Action) + case sendRequestTapped + case sendRequestDismissed + case sendRequest(SendRequestComponent.Action) + case verifyContactTapped + case verifyContactDismissed + case verifyContact(VerifyContactComponent.Action) + case checkAuthTapped + case checkAuthDismissed + case checkAuth(CheckContactAuthComponent.Action) + case confirmRequestTapped + case confirmRequestDismissed + case confirmRequest(ConfirmRequestComponent.Action) + case resetAuthTapped + case resetAuthDismissed + case resetAuth(ResetAuthComponent.Action) + case chatTapped + case chatDismissed + case chat(ChatComponent.Action) + case binding(BindingAction<State>) + } + + public init() {} + + @Dependency(\.app.messenger) var messenger: Messenger + @Dependency(\.app.dbManager.getDB) var db: DBManagerGetDB + @Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue> + @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue> + + public var body: some ReducerProtocol<State, Action> { + BindingReducer() + Reduce { state, action in + enum DBFetchEffectID {} + + switch action { + case .start: + return try! db().fetchContactsPublisher(.init(id: [state.id])) + .assertNoFailure() + .map(\.first) + .map(Action.dbContactFetched) + .subscribe(on: bgQueue) + .receive(on: mainQueue) + .eraseToEffect() + .cancellable(id: DBFetchEffectID.self, cancelInFlight: true) + + case .dbContactFetched(let contact): + state.dbContact = contact + return .none + + case .importFactsTapped: + guard let xxContact = state.xxContact else { return .none } + return .fireAndForget { [state] in + var dbContact = state.dbContact ?? XXModels.Contact(id: state.id) + dbContact.marshaled = xxContact.data + if state.importUsername { + dbContact.username = try? xxContact.getFact(.username)?.value + } + if state.importEmail { + dbContact.email = try? xxContact.getFact(.email)?.value + } + if state.importPhone { + dbContact.phone = try? xxContact.getFact(.phone)?.value + } + _ = try! db().saveContact(dbContact) + } + .subscribe(on: bgQueue) + .receive(on: mainQueue) + .eraseToEffect() + + case .lookupTapped: + state.lookup = ContactLookupComponent.State(id: state.id) + return .none + + case .lookupDismissed: + state.lookup = nil + return .none + + case .lookup(.didLookup(let xxContact)): + state.xxContact = xxContact + state.lookup = nil + return .none + + case .sendRequestTapped: + if let xxContact = state.xxContact { + state.sendRequest = SendRequestComponent.State(contact: xxContact) + } else if let marshaled = state.dbContact?.marshaled { + state.sendRequest = SendRequestComponent.State(contact: .live(marshaled)) + } + return .none + + case .sendRequestDismissed: + state.sendRequest = nil + return .none + + case .sendRequest(.sendSucceeded): + state.sendRequest = nil + return .none + + case .verifyContactTapped: + if let marshaled = state.dbContact?.marshaled { + state.verifyContact = VerifyContactComponent.State( + contact: .live(marshaled) + ) + } + return .none + + case .verifyContactDismissed: + state.verifyContact = nil + return .none + + case .checkAuthTapped: + if let marshaled = state.dbContact?.marshaled { + state.checkAuth = CheckContactAuthComponent.State( + contact: .live(marshaled) + ) + } + return .none + + case .checkAuthDismissed: + state.checkAuth = nil + return .none + + case .confirmRequestTapped: + if let marshaled = state.dbContact?.marshaled { + state.confirmRequest = ConfirmRequestComponent.State( + contact: .live(marshaled) + ) + } + return .none + + case .confirmRequestDismissed: + state.confirmRequest = nil + return .none + + case .chatTapped: + state.chat = ChatComponent.State(id: .contact(state.id)) + return .none + + case .chatDismissed: + state.chat = nil + return .none + + case .resetAuthTapped: + if let marshaled = state.dbContact?.marshaled { + state.resetAuth = ResetAuthComponent.State( + partner: .live(marshaled) + ) + } + return .none + + case .resetAuthDismissed: + state.resetAuth = nil + return .none + + case .binding(_), .lookup(_), .sendRequest(_), + .verifyContact(_), .confirmRequest(_), + .checkAuth(_), .resetAuth(_), .chat(_): + return .none + } + } + .presenting( + state: .keyPath(\.lookup), + id: .notNil(), + action: /ContactComponent.Action.lookup, + presented: { ContactLookupComponent() } + ) + .presenting( + state: .keyPath(\.sendRequest), + id: .notNil(), + action: /ContactComponent.Action.sendRequest, + presented: { SendRequestComponent() } + ) + .presenting( + state: .keyPath(\.verifyContact), + id: .notNil(), + action: /ContactComponent.Action.verifyContact, + presented: { VerifyContactComponent() } + ) + .presenting( + state: .keyPath(\.confirmRequest), + id: .notNil(), + action: /ContactComponent.Action.confirmRequest, + presented: { ConfirmRequestComponent() } + ) + .presenting( + state: .keyPath(\.checkAuth), + id: .notNil(), + action: /ContactComponent.Action.checkAuth, + presented: { CheckContactAuthComponent() } + ) + .presenting( + state: .keyPath(\.resetAuth), + id: .notNil(), + action: /ContactComponent.Action.resetAuth, + presented: { ResetAuthComponent() } + ) + .presenting( + state: .keyPath(\.chat), + id: .keyPath(\.?.id), + action: /ContactComponent.Action.chat, + presented: { ChatComponent() } + ) + } +} diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift deleted file mode 100644 index be66fc8dfc8f59f7f2e20e1a1899a23da10106f6..0000000000000000000000000000000000000000 --- a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift +++ /dev/null @@ -1,328 +0,0 @@ -import AppCore -import ChatFeature -import CheckContactAuthFeature -import ComposableArchitecture -import ComposablePresentation -import ConfirmRequestFeature -import ContactLookupFeature -import Foundation -import ResetAuthFeature -import SendRequestFeature -import VerifyContactFeature -import XCTestDynamicOverlay -import XXClient -import XXMessengerClient -import XXModels - -public struct ContactState: Equatable { - public init( - id: Data, - dbContact: XXModels.Contact? = nil, - xxContact: XXClient.Contact? = nil, - importUsername: Bool = true, - importEmail: Bool = true, - importPhone: Bool = true, - lookup: ContactLookupState? = nil, - sendRequest: SendRequestState? = nil, - verifyContact: VerifyContactState? = nil, - confirmRequest: ConfirmRequestState? = nil, - checkAuth: CheckContactAuthState? = nil, - resetAuth: ResetAuthState? = nil, - chat: ChatState? = nil - ) { - self.id = id - self.dbContact = dbContact - self.xxContact = xxContact - self.importUsername = importUsername - self.importEmail = importEmail - self.importPhone = importPhone - self.lookup = lookup - self.sendRequest = sendRequest - self.verifyContact = verifyContact - self.confirmRequest = confirmRequest - self.checkAuth = checkAuth - self.resetAuth = resetAuth - self.chat = chat - } - - public var id: Data - public var dbContact: XXModels.Contact? - public var xxContact: XXClient.Contact? - @BindableState public var importUsername: Bool - @BindableState public var importEmail: Bool - @BindableState public var importPhone: Bool - public var lookup: ContactLookupState? - public var sendRequest: SendRequestState? - public var verifyContact: VerifyContactState? - public var confirmRequest: ConfirmRequestState? - public var checkAuth: CheckContactAuthState? - public var resetAuth: ResetAuthState? - public var chat: ChatState? -} - -public enum ContactAction: Equatable, BindableAction { - case start - case dbContactFetched(XXModels.Contact?) - case importFactsTapped - case lookupTapped - case lookupDismissed - case lookup(ContactLookupAction) - case sendRequestTapped - case sendRequestDismissed - case sendRequest(SendRequestAction) - case verifyContactTapped - case verifyContactDismissed - case verifyContact(VerifyContactAction) - case checkAuthTapped - case checkAuthDismissed - case checkAuth(CheckContactAuthAction) - case confirmRequestTapped - case confirmRequestDismissed - case confirmRequest(ConfirmRequestAction) - case resetAuthTapped - case resetAuthDismissed - case resetAuth(ResetAuthAction) - case chatTapped - case chatDismissed - case chat(ChatAction) - case binding(BindingAction<ContactState>) -} - -public struct ContactEnvironment { - public init( - messenger: Messenger, - db: DBManagerGetDB, - mainQueue: AnySchedulerOf<DispatchQueue>, - bgQueue: AnySchedulerOf<DispatchQueue>, - lookup: @escaping () -> ContactLookupEnvironment, - sendRequest: @escaping () -> SendRequestEnvironment, - verifyContact: @escaping () -> VerifyContactEnvironment, - confirmRequest: @escaping () -> ConfirmRequestEnvironment, - checkAuth: @escaping () -> CheckContactAuthEnvironment, - resetAuth: @escaping () -> ResetAuthEnvironment, - chat: @escaping () -> ChatEnvironment - ) { - self.messenger = messenger - self.db = db - self.mainQueue = mainQueue - self.bgQueue = bgQueue - self.lookup = lookup - self.sendRequest = sendRequest - self.verifyContact = verifyContact - self.confirmRequest = confirmRequest - self.checkAuth = checkAuth - self.resetAuth = resetAuth - self.chat = chat - } - - public var messenger: Messenger - public var db: DBManagerGetDB - public var mainQueue: AnySchedulerOf<DispatchQueue> - public var bgQueue: AnySchedulerOf<DispatchQueue> - public var lookup: () -> ContactLookupEnvironment - public var sendRequest: () -> SendRequestEnvironment - public var verifyContact: () -> VerifyContactEnvironment - public var confirmRequest: () -> ConfirmRequestEnvironment - public var checkAuth: () -> CheckContactAuthEnvironment - public var resetAuth: () -> ResetAuthEnvironment - public var chat: () -> ChatEnvironment -} - -#if DEBUG -extension ContactEnvironment { - public static let unimplemented = ContactEnvironment( - messenger: .unimplemented, - db: .unimplemented, - mainQueue: .unimplemented, - bgQueue: .unimplemented, - lookup: { .unimplemented }, - sendRequest: { .unimplemented }, - verifyContact: { .unimplemented }, - confirmRequest: { .unimplemented }, - checkAuth: { .unimplemented }, - resetAuth: { .unimplemented }, - chat: { .unimplemented } - ) -} -#endif - -public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironment> -{ state, action, env in - enum DBFetchEffectID {} - - switch action { - case .start: - return try! env.db().fetchContactsPublisher(.init(id: [state.id])) - .assertNoFailure() - .map(\.first) - .map(ContactAction.dbContactFetched) - .subscribe(on: env.bgQueue) - .receive(on: env.mainQueue) - .eraseToEffect() - .cancellable(id: DBFetchEffectID.self, cancelInFlight: true) - - case .dbContactFetched(let contact): - state.dbContact = contact - return .none - - case .importFactsTapped: - guard let xxContact = state.xxContact else { return .none } - return .fireAndForget { [state] in - var dbContact = state.dbContact ?? XXModels.Contact(id: state.id) - dbContact.marshaled = xxContact.data - if state.importUsername { - dbContact.username = try? xxContact.getFact(.username)?.value - } - if state.importEmail { - dbContact.email = try? xxContact.getFact(.email)?.value - } - if state.importPhone { - dbContact.phone = try? xxContact.getFact(.phone)?.value - } - _ = try! env.db().saveContact(dbContact) - } - .subscribe(on: env.bgQueue) - .receive(on: env.mainQueue) - .eraseToEffect() - - case .lookupTapped: - state.lookup = ContactLookupState(id: state.id) - return .none - - case .lookupDismissed: - state.lookup = nil - return .none - - case .lookup(.didLookup(let xxContact)): - state.xxContact = xxContact - state.lookup = nil - return .none - - case .sendRequestTapped: - if let xxContact = state.xxContact { - state.sendRequest = SendRequestState(contact: xxContact) - } else if let marshaled = state.dbContact?.marshaled { - state.sendRequest = SendRequestState(contact: .live(marshaled)) - } - return .none - - case .sendRequestDismissed: - state.sendRequest = nil - return .none - - case .sendRequest(.sendSucceeded): - state.sendRequest = nil - return .none - - case .verifyContactTapped: - if let marshaled = state.dbContact?.marshaled { - state.verifyContact = VerifyContactState( - contact: .live(marshaled) - ) - } - return .none - - case .verifyContactDismissed: - state.verifyContact = nil - return .none - - case .checkAuthTapped: - if let marshaled = state.dbContact?.marshaled { - state.checkAuth = CheckContactAuthState( - contact: .live(marshaled) - ) - } - return .none - - case .checkAuthDismissed: - state.checkAuth = nil - return .none - - case .confirmRequestTapped: - if let marshaled = state.dbContact?.marshaled { - state.confirmRequest = ConfirmRequestState( - contact: .live(marshaled) - ) - } - return .none - - case .confirmRequestDismissed: - state.confirmRequest = nil - return .none - - case .chatTapped: - state.chat = ChatState(id: .contact(state.id)) - return .none - - case .chatDismissed: - state.chat = nil - return .none - - case .resetAuthTapped: - if let marshaled = state.dbContact?.marshaled { - state.resetAuth = ResetAuthState( - partner: .live(marshaled) - ) - } - return .none - - case .resetAuthDismissed: - state.resetAuth = nil - return .none - - case .binding(_), .lookup(_), .sendRequest(_), - .verifyContact(_), .confirmRequest(_), - .checkAuth(_), .resetAuth(_), .chat(_): - return .none - } -} -.binding() -.presenting( - contactLookupReducer, - state: .keyPath(\.lookup), - id: .notNil(), - action: /ContactAction.lookup, - environment: { $0.lookup() } -) -.presenting( - sendRequestReducer, - state: .keyPath(\.sendRequest), - id: .notNil(), - action: /ContactAction.sendRequest, - environment: { $0.sendRequest() } -) -.presenting( - verifyContactReducer, - state: .keyPath(\.verifyContact), - id: .notNil(), - action: /ContactAction.verifyContact, - environment: { $0.verifyContact() } -) -.presenting( - confirmRequestReducer, - state: .keyPath(\.confirmRequest), - id: .notNil(), - action: /ContactAction.confirmRequest, - environment: { $0.confirmRequest() } -) -.presenting( - checkContactAuthReducer, - state: .keyPath(\.checkAuth), - id: .notNil(), - action: /ContactAction.checkAuth, - environment: { $0.checkAuth() } -) -.presenting( - resetAuthReducer, - state: .keyPath(\.resetAuth), - id: .notNil(), - action: /ContactAction.resetAuth, - environment: { $0.resetAuth() } -) -.presenting( - chatReducer, - state: .keyPath(\.chat), - id: .keyPath(\.?.id), - action: /ContactAction.chat, - environment: { $0.chat() } -) diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift index 7da763e03748536aabb0cc99698c2edd0ee0fba4..1cbf0e91bdf20a090838fd770861a9120825afba 100644 --- a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift @@ -13,11 +13,11 @@ import XXClient import XXModels public struct ContactView: View { - public init(store: Store<ContactState, ContactAction>) { + public init(store: StoreOf<ContactComponent>) { self.store = store } - let store: Store<ContactState, ContactAction> + let store: StoreOf<ContactComponent> struct ViewState: Equatable { var dbContact: XXModels.Contact? @@ -35,7 +35,7 @@ public struct ContactView: View { var canCheckAuthorization: Bool var canResetAuthorization: Bool - init(state: ContactState) { + init(state: ContactComponent.State) { dbContact = state.dbContact xxContactIsSet = state.xxContact != nil xxContactUsername = try? state.xxContact?.getFact(.username)?.value @@ -217,7 +217,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.lookup, - action: ContactAction.lookup + action: ContactComponent.Action.lookup ), mapState: replayNonNil(), onDeactivate: { viewStore.send(.lookupDismissed) }, @@ -226,7 +226,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.sendRequest, - action: ContactAction.sendRequest + action: ContactComponent.Action.sendRequest ), mapState: replayNonNil(), onDeactivate: { viewStore.send(.sendRequestDismissed) }, @@ -235,7 +235,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.verifyContact, - action: ContactAction.verifyContact + action: ContactComponent.Action.verifyContact ), onDeactivate: { viewStore.send(.verifyContactDismissed) }, destination: VerifyContactView.init(store:) @@ -243,7 +243,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.confirmRequest, - action: ContactAction.confirmRequest + action: ContactComponent.Action.confirmRequest ), onDeactivate: { viewStore.send(.confirmRequestDismissed) }, destination: ConfirmRequestView.init(store:) @@ -251,7 +251,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.checkAuth, - action: ContactAction.checkAuth + action: ContactComponent.Action.checkAuth ), onDeactivate: { viewStore.send(.checkAuthDismissed) }, destination: CheckContactAuthView.init(store:) @@ -259,7 +259,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.resetAuth, - action: ContactAction.resetAuth + action: ContactComponent.Action.resetAuth ), onDeactivate: { viewStore.send(.resetAuthDismissed) }, destination: ResetAuthView.init(store:) @@ -267,7 +267,7 @@ public struct ContactView: View { .background(NavigationLinkWithStore( store.scope( state: \.chat, - action: ContactAction.chat + action: ContactComponent.Action.chat ), onDeactivate: { viewStore.send(.chatDismissed) }, destination: ChatView.init(store:) @@ -280,11 +280,10 @@ public struct ContactView: View { public struct ContactView_Previews: PreviewProvider { public static var previews: some View { ContactView(store: Store( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)! ), - reducer: .empty, - environment: () + reducer: EmptyReducer() )) } } diff --git a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactComponentTests.swift similarity index 70% rename from Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift rename to Examples/xx-messenger/Tests/ContactFeatureTests/ContactComponentTests.swift index eba41b7ab57d1dddfc0827747760a9bce224bdab..04caf49dbcb5205ee5dd081398983c72a6694011 100644 --- a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift +++ b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactComponentTests.swift @@ -16,19 +16,18 @@ import XXModels final class ContactFeatureTests: XCTestCase { func testStart() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)! ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) var dbDidFetchContacts: [XXModels.Contact.Query] = [] let dbContactsPublisher = PassthroughSubject<[XXModels.Contact], Error>() - store.environment.mainQueue = .immediate - store.environment.bgQueue = .immediate - store.environment.db.run = { + store.dependencies.app.mainQueue = .immediate + store.dependencies.app.bgQueue = .immediate + store.dependencies.app.dbManager.getDB.run = { var db: Database = .unimplemented db.fetchContactsPublisher.run = { query in dbDidFetchContacts.append(query) @@ -68,20 +67,19 @@ final class ContactFeatureTests: XCTestCase { } let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, dbContact: dbContact, xxContact: xxContact ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) var dbDidSaveContact: [XXModels.Contact] = [] - store.environment.mainQueue = .immediate - store.environment.bgQueue = .immediate - store.environment.db.run = { + store.dependencies.app.mainQueue = .immediate + store.dependencies.app.bgQueue = .immediate + store.dependencies.app.dbManager.getDB.run = { var db: Database = .unimplemented db.saveContact.run = { contact in dbDidSaveContact.append(contact) @@ -104,27 +102,25 @@ final class ContactFeatureTests: XCTestCase { func testLookupTapped() { let contactId = "contact-id".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: contactId ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.lookupTapped) { - $0.lookup = ContactLookupState(id: contactId) + $0.lookup = ContactLookupComponent.State(id: contactId) } } func testLookupDismissed() { let contactId = "contact-id".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: contactId, - lookup: ContactLookupState(id: contactId) + lookup: ContactLookupComponent.State(id: contactId) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.lookupDismissed) { @@ -136,12 +132,11 @@ final class ContactFeatureTests: XCTestCase { let contactId = "contact-id".data(using: .utf8)! let contact = Contact.unimplemented("contact-data".data(using: .utf8)!) let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: contactId, - lookup: ContactLookupState(id: contactId) + lookup: ContactLookupComponent.State(id: contactId) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.lookup(.didLookup(contact))) { @@ -155,16 +150,15 @@ final class ContactFeatureTests: XCTestCase { dbContact.marshaled = "contact-data".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: dbContact.id, dbContact: dbContact ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.sendRequestTapped) { - $0.sendRequest = SendRequestState(contact: .live(dbContact.marshaled!)) + $0.sendRequest = SendRequestComponent.State(contact: .live(dbContact.marshaled!)) } } @@ -172,29 +166,27 @@ final class ContactFeatureTests: XCTestCase { let xxContact = XXClient.Contact.unimplemented("contact-id".data(using: .utf8)!) let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, xxContact: xxContact ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.sendRequestTapped) { - $0.sendRequest = SendRequestState(contact: xxContact) + $0.sendRequest = SendRequestComponent.State(contact: xxContact) } } func testSendRequestDismissed() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, - sendRequest: SendRequestState( + sendRequest: SendRequestComponent.State( contact: .unimplemented("contact-id".data(using: .utf8)!) ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.sendRequestDismissed) { @@ -204,14 +196,13 @@ final class ContactFeatureTests: XCTestCase { func testSendRequestSucceeded() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, - sendRequest: SendRequestState( + sendRequest: SendRequestComponent.State( contact: .unimplemented("contact-id".data(using: .utf8)!) ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.sendRequest(.sendSucceeded)) { @@ -222,19 +213,18 @@ final class ContactFeatureTests: XCTestCase { func testVerifyContactTapped() { let contactData = "contact-data".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: Data(), dbContact: XXModels.Contact( id: Data(), marshaled: contactData ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.verifyContactTapped) { - $0.verifyContact = VerifyContactState( + $0.verifyContact = VerifyContactComponent.State( contact: .unimplemented(contactData) ) } @@ -242,14 +232,13 @@ final class ContactFeatureTests: XCTestCase { func testVerifyContactDismissed() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, - verifyContact: VerifyContactState( + verifyContact: VerifyContactComponent.State( contact: .unimplemented("contact-data".data(using: .utf8)!) ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.verifyContactDismissed) { @@ -260,19 +249,18 @@ final class ContactFeatureTests: XCTestCase { func testCheckAuthTapped() { let contactData = "contact-data".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: Data(), dbContact: XXModels.Contact( id: Data(), marshaled: contactData ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.checkAuthTapped) { - $0.checkAuth = CheckContactAuthState( + $0.checkAuth = CheckContactAuthComponent.State( contact: .unimplemented(contactData) ) } @@ -280,14 +268,13 @@ final class ContactFeatureTests: XCTestCase { func testCheckAuthDismissed() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, - checkAuth: CheckContactAuthState( + checkAuth: CheckContactAuthComponent.State( contact: .unimplemented("contact-data".data(using: .utf8)!) ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.checkAuthDismissed) { @@ -298,19 +285,18 @@ final class ContactFeatureTests: XCTestCase { func testResetAuthTapped() { let contactData = "contact-data".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: Data(), dbContact: XXModels.Contact( id: Data(), marshaled: contactData ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.resetAuthTapped) { - $0.resetAuth = ResetAuthState( + $0.resetAuth = ResetAuthComponent.State( partner: .unimplemented(contactData) ) } @@ -318,14 +304,13 @@ final class ContactFeatureTests: XCTestCase { func testResetAuthDismissed() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: Data(), - resetAuth: ResetAuthState( + resetAuth: ResetAuthComponent.State( partner: .unimplemented(Data()) ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.resetAuthDismissed) { @@ -336,19 +321,18 @@ final class ContactFeatureTests: XCTestCase { func testConfirmRequestTapped() { let contactData = "contact-data".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: Data(), dbContact: XXModels.Contact( id: Data(), marshaled: contactData ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.confirmRequestTapped) { - $0.confirmRequest = ConfirmRequestState( + $0.confirmRequest = ConfirmRequestComponent.State( contact: .unimplemented(contactData) ) } @@ -356,14 +340,13 @@ final class ContactFeatureTests: XCTestCase { func testConfirmRequestDismissed() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, - confirmRequest: ConfirmRequestState( + confirmRequest: ConfirmRequestComponent.State( contact: .unimplemented("contact-data".data(using: .utf8)!) ) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.confirmRequestDismissed) { @@ -374,26 +357,24 @@ final class ContactFeatureTests: XCTestCase { func testChatTapped() { let contactId = "contact-id".data(using: .utf8)! let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: contactId ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.chatTapped) { - $0.chat = ChatState(id: .contact(contactId)) + $0.chat = ChatComponent.State(id: .contact(contactId)) } } func testChatDismissed() { let store = TestStore( - initialState: ContactState( + initialState: ContactComponent.State( id: "contact-id".data(using: .utf8)!, - chat: ChatState(id: .contact("contact-id".data(using: .utf8)!)) + chat: ChatComponent.State(id: .contact("contact-id".data(using: .utf8)!)) ), - reducer: contactReducer, - environment: .unimplemented + reducer: ContactComponent() ) store.send(.chatDismissed) {