Skip to content
Snippets Groups Projects
Commit 551df629 authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Migrate ConfirmRequestFeature to ReducerProtocol

parent 60da16a6
No related branches found
No related tags found
2 merge requests!126Migrate example app to ComposableArchitecture's ReducerProtocol,!102Release 1.0.0
This commit is part of merge request !102. Comments created here will be created in the context of that merge request.
import AppCore
import ComposableArchitecture
import Foundation
import XCTestDynamicOverlay
import XXClient
import XXMessengerClient
import XXModels
public struct ConfirmRequestComponent: ReducerProtocol {
public struct State: Equatable {
public enum Result: Equatable {
case success
case failure(String)
}
public init(
contact: XXClient.Contact,
isConfirming: Bool = false,
result: Result? = nil
) {
self.contact = contact
self.isConfirming = isConfirming
self.result = result
}
public var contact: XXClient.Contact
public var isConfirming: Bool
public var result: Result?
}
public enum Action: Equatable {
case confirmTapped
case didConfirm(State.Result)
}
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 func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
switch action {
case .confirmTapped:
state.isConfirming = true
state.result = nil
return Effect.result { [state] in
func updateStatus(_ status: XXModels.Contact.AuthStatus) throws {
try db().bulkUpdateContacts.callAsFunction(
.init(id: [try state.contact.getId()]),
.init(authStatus: status)
)
}
do {
try updateStatus(.confirming)
let e2e = try messenger.e2e.tryGet()
_ = try e2e.confirmReceivedRequest(partner: state.contact)
try updateStatus(.friend)
return .success(.didConfirm(.success))
} catch {
try? updateStatus(.confirmationFailed)
return .success(.didConfirm(.failure(error.localizedDescription)))
}
}
.subscribe(on: bgQueue)
.receive(on: mainQueue)
.eraseToEffect()
case .didConfirm(let result):
state.isConfirming = false
state.result = result
return .none
}
}
}
import AppCore
import ComposableArchitecture
import Foundation
import XCTestDynamicOverlay
import XXClient
import XXMessengerClient
import XXModels
public struct ConfirmRequestState: Equatable {
public enum Result: Equatable {
case success
case failure(String)
}
public init(
contact: XXClient.Contact,
isConfirming: Bool = false,
result: Result? = nil
) {
self.contact = contact
self.isConfirming = isConfirming
self.result = result
}
public var contact: XXClient.Contact
public var isConfirming: Bool
public var result: Result?
}
public enum ConfirmRequestAction: Equatable {
case confirmTapped
case didConfirm(ConfirmRequestState.Result)
}
public struct ConfirmRequestEnvironment {
public init(
messenger: Messenger,
db: DBManagerGetDB,
mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>
) {
self.messenger = messenger
self.db = db
self.mainQueue = mainQueue
self.bgQueue = bgQueue
}
public var messenger: Messenger
public var db: DBManagerGetDB
public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue>
}
#if DEBUG
extension ConfirmRequestEnvironment {
public static let unimplemented = ConfirmRequestEnvironment(
messenger: .unimplemented,
db: .unimplemented,
mainQueue: .unimplemented,
bgQueue: .unimplemented
)
}
#endif
public let confirmRequestReducer = Reducer<ConfirmRequestState, ConfirmRequestAction, ConfirmRequestEnvironment>
{ state, action, env in
switch action {
case .confirmTapped:
state.isConfirming = true
state.result = nil
return Effect.result { [state] in
func updateStatus(_ status: XXModels.Contact.AuthStatus) throws {
try env.db().bulkUpdateContacts.callAsFunction(
.init(id: [try state.contact.getId()]),
.init(authStatus: status)
)
}
do {
try updateStatus(.confirming)
let e2e = try env.messenger.e2e.tryGet()
_ = try e2e.confirmReceivedRequest(partner: state.contact)
try updateStatus(.friend)
return .success(.didConfirm(.success))
} catch {
try? updateStatus(.confirmationFailed)
return .success(.didConfirm(.failure(error.localizedDescription)))
}
}
.subscribe(on: env.bgQueue)
.receive(on: env.mainQueue)
.eraseToEffect()
case .didConfirm(let result):
state.isConfirming = false
state.result = result
return .none
}
}
...@@ -2,20 +2,20 @@ import ComposableArchitecture ...@@ -2,20 +2,20 @@ import ComposableArchitecture
import SwiftUI import SwiftUI
public struct ConfirmRequestView: View { public struct ConfirmRequestView: View {
public init(store: Store<ConfirmRequestState, ConfirmRequestAction>) { public init(store: StoreOf<ConfirmRequestComponent>) {
self.store = store self.store = store
} }
let store: Store<ConfirmRequestState, ConfirmRequestAction> let store: StoreOf<ConfirmRequestComponent>
struct ViewState: Equatable { struct ViewState: Equatable {
var username: String? var username: String?
var email: String? var email: String?
var phone: String? var phone: String?
var isConfirming: Bool var isConfirming: Bool
var result: ConfirmRequestState.Result? var result: ConfirmRequestComponent.State.Result?
init(state: ConfirmRequestState) { init(state: ConfirmRequestComponent.State) {
username = try? state.contact.getFact(.username)?.value username = try? state.contact.getFact(.username)?.value
email = try? state.contact.getFact(.email)?.value email = try? state.contact.getFact(.email)?.value
phone = try? state.contact.getFact(.phone)?.value phone = try? state.contact.getFact(.phone)?.value
...@@ -84,11 +84,10 @@ public struct ConfirmRequestView: View { ...@@ -84,11 +84,10 @@ public struct ConfirmRequestView: View {
public struct ConfirmRequestView_Previews: PreviewProvider { public struct ConfirmRequestView_Previews: PreviewProvider {
public static var previews: some View { public static var previews: some View {
ConfirmRequestView(store: Store( ConfirmRequestView(store: Store(
initialState: ConfirmRequestState( initialState: ConfirmRequestComponent.State(
contact: .unimplemented("contact-data".data(using: .utf8)!) contact: .unimplemented("contact-data".data(using: .utf8)!)
), ),
reducer: .empty, reducer: EmptyReducer()
environment: ()
)) ))
} }
} }
......
...@@ -5,27 +5,26 @@ import XXClient ...@@ -5,27 +5,26 @@ import XXClient
import XXModels import XXModels
@testable import ConfirmRequestFeature @testable import ConfirmRequestFeature
final class ConfirmRequestFeatureTests: XCTestCase { final class ConfirmRequestComponentTests: XCTestCase {
func testConfirm() { func testConfirm() {
var contact = XXClient.Contact.unimplemented("contact-data".data(using: .utf8)!) var contact = XXClient.Contact.unimplemented("contact-data".data(using: .utf8)!)
let contactId = "contact-id".data(using: .utf8)! let contactId = "contact-id".data(using: .utf8)!
contact.getIdFromContact.run = { _ in contactId } contact.getIdFromContact.run = { _ in contactId }
let store = TestStore( let store = TestStore(
initialState: ConfirmRequestState( initialState: ConfirmRequestComponent.State(
contact: contact contact: contact
), ),
reducer: confirmRequestReducer, reducer: ConfirmRequestComponent()
environment: .unimplemented
) )
var didConfirmRequestFromContact: [XXClient.Contact] = [] var didConfirmRequestFromContact: [XXClient.Contact] = []
var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = [] var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = []
var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = [] var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = []
store.environment.mainQueue = .immediate store.dependencies.app.mainQueue = .immediate
store.environment.bgQueue = .immediate store.dependencies.app.bgQueue = .immediate
store.environment.messenger.e2e.get = { store.dependencies.app.messenger.e2e.get = {
var e2e: E2E = .unimplemented var e2e: E2E = .unimplemented
e2e.confirmReceivedRequest.run = { contact in e2e.confirmReceivedRequest.run = { contact in
didConfirmRequestFromContact.append(contact) didConfirmRequestFromContact.append(contact)
...@@ -33,7 +32,7 @@ final class ConfirmRequestFeatureTests: XCTestCase { ...@@ -33,7 +32,7 @@ final class ConfirmRequestFeatureTests: XCTestCase {
} }
return e2e return e2e
} }
store.environment.db.run = { store.dependencies.app.dbManager.getDB.run = {
var db: Database = .unimplemented var db: Database = .unimplemented
db.bulkUpdateContacts.run = { query, assignments in db.bulkUpdateContacts.run = { query, assignments in
didBulkUpdateContactsWithQuery.append(query) didBulkUpdateContactsWithQuery.append(query)
...@@ -70,11 +69,10 @@ final class ConfirmRequestFeatureTests: XCTestCase { ...@@ -70,11 +69,10 @@ final class ConfirmRequestFeatureTests: XCTestCase {
contact.getIdFromContact.run = { _ in contactId } contact.getIdFromContact.run = { _ in contactId }
let store = TestStore( let store = TestStore(
initialState: ConfirmRequestState( initialState: ConfirmRequestComponent.State(
contact: contact contact: contact
), ),
reducer: confirmRequestReducer, reducer: ConfirmRequestComponent()
environment: .unimplemented
) )
struct Failure: Error {} struct Failure: Error {}
...@@ -83,14 +81,14 @@ final class ConfirmRequestFeatureTests: XCTestCase { ...@@ -83,14 +81,14 @@ final class ConfirmRequestFeatureTests: XCTestCase {
var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = [] var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = []
var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = [] var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = []
store.environment.mainQueue = .immediate store.dependencies.app.mainQueue = .immediate
store.environment.bgQueue = .immediate store.dependencies.app.bgQueue = .immediate
store.environment.messenger.e2e.get = { store.dependencies.app.messenger.e2e.get = {
var e2e: E2E = .unimplemented var e2e: E2E = .unimplemented
e2e.confirmReceivedRequest.run = { _ in throw error } e2e.confirmReceivedRequest.run = { _ in throw error }
return e2e return e2e
} }
store.environment.db.run = { store.dependencies.app.dbManager.getDB.run = {
var db: Database = .unimplemented var db: Database = .unimplemented
db.bulkUpdateContacts.run = { query, assignments in db.bulkUpdateContacts.run = { query, assignments in
didBulkUpdateContactsWithQuery.append(query) didBulkUpdateContactsWithQuery.append(query)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment