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

Listen for messages in HomeFeature

parent 978e4ffd
No related branches found
No related tags found
2 merge requests!102Release 1.0.0,!87Messenger example - chat
......@@ -96,6 +96,10 @@ extension AppEnvironment {
messenger: messenger,
dbManager: dbManager,
authHandler: authHandler,
messageListener: .live(
messenger: messenger,
db: dbManager.getDB
),
mainQueue: mainQueue,
bgQueue: bgQueue,
register: {
......
......@@ -15,6 +15,7 @@ public struct HomeState: Equatable {
public init(
failure: String? = nil,
authFailure: String? = nil,
messageListenerFailure: String? = nil,
isNetworkHealthy: Bool? = nil,
networkNodesReport: NodeRegistrationReport? = nil,
isDeletingAccount: Bool = false,
......@@ -25,6 +26,7 @@ public struct HomeState: Equatable {
) {
self.failure = failure
self.authFailure = authFailure
self.messageListenerFailure = messageListenerFailure
self.isNetworkHealthy = isNetworkHealthy
self.isDeletingAccount = isDeletingAccount
self.alert = alert
......@@ -35,6 +37,7 @@ public struct HomeState: Equatable {
public var failure: String?
public var authFailure: String?
public var messageListenerFailure: String?
public var isNetworkHealthy: Bool?
public var networkNodesReport: NodeRegistrationReport?
public var isDeletingAccount: Bool
......@@ -59,6 +62,13 @@ public enum HomeAction: Equatable {
case failureDismissed
}
public enum MessageListener: Equatable {
case start
case stop
case failure(NSError)
case failureDismissed
}
public enum NetworkMonitor: Equatable {
case start
case stop
......@@ -75,6 +85,7 @@ public enum HomeAction: Equatable {
case messenger(Messenger)
case authHandler(AuthHandler)
case messageListener(MessageListener)
case networkMonitor(NetworkMonitor)
case deleteAccount(DeleteAccount)
case didDismissAlert
......@@ -93,6 +104,7 @@ public struct HomeEnvironment {
messenger: Messenger,
dbManager: DBManager,
authHandler: AuthCallbackHandler,
messageListener: MessageListenerHandler,
mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>,
register: @escaping () -> RegisterEnvironment,
......@@ -102,6 +114,7 @@ public struct HomeEnvironment {
self.messenger = messenger
self.dbManager = dbManager
self.authHandler = authHandler
self.messageListener = messageListener
self.mainQueue = mainQueue
self.bgQueue = bgQueue
self.register = register
......@@ -112,6 +125,7 @@ public struct HomeEnvironment {
public var messenger: Messenger
public var dbManager: DBManager
public var authHandler: AuthCallbackHandler
public var messageListener: MessageListenerHandler
public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue>
public var register: () -> RegisterEnvironment
......@@ -124,6 +138,7 @@ extension HomeEnvironment {
messenger: .unimplemented,
dbManager: .unimplemented,
authHandler: .unimplemented,
messageListener: .unimplemented,
mainQueue: .unimplemented,
bgQueue: .unimplemented,
register: { .unimplemented },
......@@ -137,11 +152,13 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
enum NetworkHealthEffectId {}
enum NetworkNodesEffectId {}
enum AuthCallbacksEffectId {}
enum MessageListenerEffectId {}
switch action {
case .messenger(.start):
return .merge(
Effect(value: .authHandler(.start)),
Effect(value: .messageListener(.start)),
Effect(value: .networkMonitor(.stop)),
Effect.result {
do {
......@@ -203,6 +220,29 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
state.authFailure = nil
return .none
case .messageListener(.start):
return Effect.run { subscriber in
let cancellable = env.messageListener(onError: { error in
subscriber.send(.messageListener(.failure(error as NSError)))
})
return AnyCancellable { cancellable.cancel() }
}
.subscribe(on: env.bgQueue)
.receive(on: env.mainQueue)
.eraseToEffect()
.cancellable(id: MessageListenerEffectId.self, cancelInFlight: true)
case .messageListener(.stop):
return .cancel(id: MessageListenerEffectId.self)
case .messageListener(.failure(let error)):
state.messageListenerFailure = error.localizedDescription
return .none
case .messageListener(.failureDismissed):
state.messageListenerFailure = nil
return .none
case .networkMonitor(.start):
return .merge(
Effect.run { subscriber in
......
......@@ -16,6 +16,7 @@ public struct HomeView: View {
struct ViewState: Equatable {
var failure: String?
var authFailure: String?
var messageListenerFailure: String?
var isNetworkHealthy: Bool?
var networkNodesReport: NodeRegistrationReport?
var isDeletingAccount: Bool
......@@ -23,6 +24,7 @@ public struct HomeView: View {
init(state: HomeState) {
failure = state.failure
authFailure = state.authFailure
messageListenerFailure = state.messageListenerFailure
isNetworkHealthy = state.isNetworkHealthy
isDeletingAccount = state.isDeletingAccount
networkNodesReport = state.networkNodesReport
......@@ -59,6 +61,19 @@ public struct HomeView: View {
}
}
if let messageListenerFailure = viewStore.messageListenerFailure {
Section {
Text(messageListenerFailure)
Button {
viewStore.send(.messageListener(.failureDismissed))
} label: {
Text("Dismiss")
}
} header: {
Text("Message Listener Error")
}
}
Section {
HStack {
Text("Health")
......
......@@ -24,6 +24,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { messengerDidStartWithTimeout.append($0) }
store.environment.messenger.isConnected.run = { false }
store.environment.messenger.connect.run = { messengerDidConnect += 1 }
......@@ -38,12 +39,14 @@ final class HomeFeatureTests: XCTestCase {
XCTAssertNoDifference(messengerDidListenForMessages, 1)
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.didStartUnregistered)) {
$0.register = RegisterState()
}
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testMessengerStartRegistered() {
......@@ -61,6 +64,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { messengerDidStartWithTimeout.append($0) }
store.environment.messenger.isConnected.run = { false }
store.environment.messenger.connect.run = { messengerDidConnect += 1 }
......@@ -86,12 +90,14 @@ final class HomeFeatureTests: XCTestCase {
XCTAssertNoDifference(messengerDidLogIn, 1)
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.didStartRegistered))
store.receive(.networkMonitor(.start))
store.send(.networkMonitor(.stop))
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testRegisterFinished() {
......@@ -109,6 +115,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { messengerDidStartWithTimeout.append($0) }
store.environment.messenger.isConnected.run = { true }
store.environment.messenger.isLoggedIn.run = { false }
......@@ -134,12 +141,14 @@ final class HomeFeatureTests: XCTestCase {
XCTAssertNoDifference(messengerDidLogIn, 1)
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.didStartRegistered))
store.receive(.networkMonitor(.start))
store.send(.networkMonitor(.stop))
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testMessengerStartFailure() {
......@@ -155,17 +164,20 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { _ in throw error }
store.send(.messenger(.start))
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testMessengerStartConnectFailure() {
......@@ -181,6 +193,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { _ in }
store.environment.messenger.isConnected.run = { false }
store.environment.messenger.connect.run = { throw error }
......@@ -188,12 +201,14 @@ final class HomeFeatureTests: XCTestCase {
store.send(.messenger(.start))
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testMessengerStartIsRegisteredFailure() {
......@@ -209,6 +224,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { _ in }
store.environment.messenger.isConnected.run = { true }
store.environment.messenger.isLoggedIn.run = { false }
......@@ -217,12 +233,14 @@ final class HomeFeatureTests: XCTestCase {
store.send(.messenger(.start))
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testMessengerStartLogInFailure() {
......@@ -238,6 +256,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.authHandler.run = { _ in Cancellable {} }
store.environment.messageListener.run = { _ in Cancellable {} }
store.environment.messenger.start.run = { _ in }
store.environment.messenger.isConnected.run = { true }
store.environment.messenger.isLoggedIn.run = { false }
......@@ -247,12 +266,14 @@ final class HomeFeatureTests: XCTestCase {
store.send(.messenger(.start))
store.receive(.authHandler(.start))
store.receive(.messageListener(.start))
store.receive(.networkMonitor(.stop))
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
store.send(.authHandler(.stop))
store.send(.messageListener(.stop))
}
func testNetworkMonitorStart() {
......@@ -565,4 +586,45 @@ final class HomeFeatureTests: XCTestCase {
authHandlerOnError.first?(AuthHandlerError(id: 2))
}
func testMessageListener() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
environment: .unimplemented
)
var didRunMessageListener = 0
var didCancelMessageListener = 0
var messageListenerOnError: [MessageListenerHandler.OnError] = []
store.environment.mainQueue = .immediate
store.environment.bgQueue = .immediate
store.environment.messageListener.run = { onError in
didRunMessageListener += 1
messageListenerOnError.append(onError)
return Cancellable { didCancelMessageListener += 1 }
}
store.send(.messageListener(.start))
XCTAssertNoDifference(didRunMessageListener, 1)
struct MessageListenerError: Error { var id: Int }
messageListenerOnError.first?(MessageListenerError(id: 1))
store.receive(.messageListener(.failure(MessageListenerError(id: 1) as NSError))) {
$0.messageListenerFailure = MessageListenerError(id: 1).localizedDescription
}
store.send(.messageListener(.failureDismissed)) {
$0.messageListenerFailure = nil
}
store.send(.messageListener(.stop))
XCTAssertNoDifference(didCancelMessageListener, 1)
messageListenerOnError.first?(MessageListenerError(id: 2))
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment