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

Refactor

parent 6445bc63
No related branches found
No related tags found
2 merge requests!102Release 1.0.0,!63Messenger example - network status
......@@ -68,7 +68,7 @@ extension AppEnvironment {
let appReducer = Reducer<AppState, AppAction, AppEnvironment>
{ state, action, env in
switch action {
case .start, .welcome(.finished), .restore(.finished), .home(.didDeleteAccount):
case .start, .welcome(.finished), .restore(.finished), .home(.deleteAccount(.success)):
state.screen = .loading
return .run { subscriber in
do {
......
......@@ -6,7 +6,7 @@ extension AlertState {
title: TextState("Delete Account"),
message: TextState("This will permanently delete your account and can't be undone."),
buttons: [
.destructive(TextState("Delete"), action: .send(.deleteAccountConfirmed)),
.destructive(TextState("Delete"), action: .send(.deleteAccount(.confirmed))),
.cancel(TextState("Cancel"))
]
)
......
......@@ -20,18 +20,31 @@ public struct HomeState: Equatable {
self.isDeletingAccount = isDeletingAccount
}
@BindableState public var failure: String?
@BindableState public var register: RegisterState?
@BindableState public var alert: AlertState<HomeAction>?
@BindableState public var isDeletingAccount: Bool
public var failure: String?
public var register: RegisterState?
public var alert: AlertState<HomeAction>?
public var isDeletingAccount: Bool
}
public enum HomeAction: Equatable, BindableAction {
public enum HomeAction: Equatable {
public enum Messenger: Equatable {
case start
case deleteAccountButtonTapped
case deleteAccountConfirmed
case didDeleteAccount
case binding(BindingAction<HomeState>)
case didStartRegistered
case didStartUnregistered
case failure(NSError)
}
public enum DeleteAccount: Equatable {
case buttonTapped
case confirmed
case success
case failure(NSError)
}
case messenger(Messenger)
case deleteAccount(DeleteAccount)
case didDismissAlert
case didDismissRegister
case register(RegisterAction)
}
......@@ -70,8 +83,8 @@ extension HomeEnvironment {
public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
{ state, action, env in
switch action {
case .start:
return .run { subscriber in
case .messenger(.start):
return .result {
do {
try env.messenger.start()
......@@ -81,29 +94,38 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
if env.messenger.isLoggedIn() == false {
if try env.messenger.isRegistered() == false {
subscriber.send(.set(\.$register, RegisterState()))
subscriber.send(completion: .finished)
return AnyCancellable {}
return .success(.messenger(.didStartUnregistered))
}
try env.messenger.logIn()
}
return .success(.messenger(.didStartRegistered))
} catch {
subscriber.send(.set(\.$failure, error.localizedDescription))
return .success(.messenger(.failure(error as NSError)))
}
subscriber.send(completion: .finished)
return AnyCancellable {}
}
.subscribe(on: env.bgQueue)
.receive(on: env.mainQueue)
.eraseToEffect()
case .deleteAccountButtonTapped:
case .messenger(.didStartUnregistered):
state.register = RegisterState()
return .none
case .messenger(.didStartRegistered):
return .none
case .messenger(.failure(let error)):
state.failure = error.localizedDescription
return .none
case .deleteAccount(.buttonTapped):
state.alert = .confirmAccountDeletion()
return .none
case .deleteAccountConfirmed:
case .deleteAccount(.confirmed):
state.isDeletingAccount = true
return .run { subscriber in
return .result {
do {
let contactId = try env.messenger.e2e.tryGet().getContact().getId()
let contact = try env.db().fetchContacts(.init(id: [contactId])).first
......@@ -113,31 +135,40 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
}
try env.messenger.destroy()
try env.db().drop()
subscriber.send(.didDeleteAccount)
return .success(.deleteAccount(.success))
} catch {
subscriber.send(.set(\.$isDeletingAccount, false))
subscriber.send(.set(\.$alert, .accountDeletionFailed(error)))
return .success(.deleteAccount(.failure(error as NSError)))
}
subscriber.send(completion: .finished)
return AnyCancellable {}
}
.subscribe(on: env.bgQueue)
.receive(on: env.mainQueue)
.eraseToEffect()
case .didDeleteAccount:
case .deleteAccount(.success):
state.isDeletingAccount = false
return .none
case .deleteAccount(.failure(let error)):
state.isDeletingAccount = false
state.alert = .accountDeletionFailed(error)
return .none
case .didDismissAlert:
state.alert = nil
return .none
case .didDismissRegister:
state.register = nil
return .none
case .register(.finished):
state.register = nil
return Effect(value: .start)
return Effect(value: .messenger(.start))
case .binding(_), .register(_):
case .register(_):
return .none
}
}
.binding()
.presenting(
registerReducer,
state: .keyPath(\.register),
......
......@@ -28,7 +28,7 @@ public struct HomeView: View {
Section {
Text(failure)
Button {
viewStore.send(.start)
viewStore.send(.messenger(.start))
} label: {
Text("Retry")
}
......@@ -39,7 +39,7 @@ public struct HomeView: View {
Section {
Button(role: .destructive) {
viewStore.send(.deleteAccountButtonTapped)
viewStore.send(.deleteAccount(.buttonTapped))
} label: {
HStack {
Text("Delete Account")
......@@ -57,18 +57,18 @@ public struct HomeView: View {
.navigationTitle("Home")
.alert(
store.scope(state: \.alert),
dismiss: HomeAction.set(\.$alert, nil)
dismiss: HomeAction.didDismissAlert
)
}
.navigationViewStyle(.stack)
.task { viewStore.send(.start) }
.task { viewStore.send(.messenger(.start)) }
.fullScreenCover(
store.scope(
state: \.register,
action: HomeAction.register
),
onDismiss: {
viewStore.send(.set(\.$register, nil))
viewStore.send(.didDismissRegister)
},
content: RegisterView.init(store:)
)
......
......@@ -159,7 +159,7 @@ final class AppFeatureTests: XCTestCase {
store.environment.messenger.isLoaded.run = { false }
store.environment.messenger.isCreated.run = { false }
store.send(.home(.didDeleteAccount)) {
store.send(.home(.deleteAccount(.success))) {
$0.screen = .loading
}
......
......@@ -7,7 +7,7 @@ import XXModels
@testable import HomeFeature
final class HomeFeatureTests: XCTestCase {
func testStartUnregistered() {
func testMessengerStartUnregistered() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
......@@ -27,7 +27,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.messenger.isLoggedIn.run = { false }
store.environment.messenger.isRegistered.run = { false }
store.send(.start)
store.send(.messenger(.start))
bgQueue.advance()
......@@ -36,12 +36,12 @@ final class HomeFeatureTests: XCTestCase {
mainQueue.advance()
store.receive(.set(\.$register, RegisterState())) {
store.receive(.messenger(.didStartUnregistered)) {
$0.register = RegisterState()
}
}
func testStartRegistered() {
func testMessengerStartRegistered() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
......@@ -63,7 +63,7 @@ final class HomeFeatureTests: XCTestCase {
store.environment.messenger.isRegistered.run = { true }
store.environment.messenger.logIn.run = { messengerDidLogIn += 1 }
store.send(.start)
store.send(.messenger(.start))
bgQueue.advance()
......@@ -72,6 +72,8 @@ final class HomeFeatureTests: XCTestCase {
XCTAssertNoDifference(messengerDidLogIn, 1)
mainQueue.advance()
store.receive(.messenger(.didStartRegistered))
}
func testRegisterFinished() {
......@@ -100,7 +102,7 @@ final class HomeFeatureTests: XCTestCase {
$0.register = nil
}
store.receive(.start)
store.receive(.messenger(.start))
bgQueue.advance()
......@@ -108,9 +110,11 @@ final class HomeFeatureTests: XCTestCase {
XCTAssertNoDifference(messengerDidLogIn, 1)
mainQueue.advance()
store.receive(.messenger(.didStartRegistered))
}
func testStartMessengerStartFailure() {
func testMessengerStartFailure() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
......@@ -124,14 +128,14 @@ final class HomeFeatureTests: XCTestCase {
store.environment.mainQueue = .immediate
store.environment.messenger.start.run = { _ in throw error }
store.send(.start)
store.send(.messenger(.start))
store.receive(.set(\.$failure, error.localizedDescription)) {
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
}
func testStartMessengerConnectFailure() {
func testMessengerStartConnectFailure() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
......@@ -147,14 +151,14 @@ final class HomeFeatureTests: XCTestCase {
store.environment.messenger.isConnected.run = { false }
store.environment.messenger.connect.run = { throw error }
store.send(.start)
store.send(.messenger(.start))
store.receive(.set(\.$failure, error.localizedDescription)) {
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
}
func testStartMessengerIsRegisteredFailure() {
func testMessengerStartIsRegisteredFailure() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
......@@ -171,14 +175,14 @@ final class HomeFeatureTests: XCTestCase {
store.environment.messenger.isLoggedIn.run = { false }
store.environment.messenger.isRegistered.run = { throw error }
store.send(.start)
store.send(.messenger(.start))
store.receive(.set(\.$failure, error.localizedDescription)) {
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
}
func testStartMessengerLogInFailure() {
func testMessengerStartLogInFailure() {
let store = TestStore(
initialState: HomeState(),
reducer: homeReducer,
......@@ -196,9 +200,9 @@ final class HomeFeatureTests: XCTestCase {
store.environment.messenger.isRegistered.run = { true }
store.environment.messenger.logIn.run = { throw error }
store.send(.start)
store.send(.messenger(.start))
store.receive(.set(\.$failure, error.localizedDescription)) {
store.receive(.messenger(.failure(error as NSError))) {
$0.failure = error.localizedDescription
}
}
......@@ -254,15 +258,15 @@ final class HomeFeatureTests: XCTestCase {
messengerDidDestroy += 1
}
store.send(.deleteAccountButtonTapped) {
store.send(.deleteAccount(.buttonTapped)) {
$0.alert = .confirmAccountDeletion()
}
store.send(.set(\.$alert, nil)) {
store.send(.didDismissAlert) {
$0.alert = nil
}
store.send(.deleteAccountConfirmed) {
store.send(.deleteAccount(.confirmed)) {
$0.isDeletingAccount = true
}
......@@ -271,7 +275,7 @@ final class HomeFeatureTests: XCTestCase {
XCTAssertNoDifference(messengerDidDestroy, 1)
XCTAssertNoDifference(dbDidDrop, 1)
store.receive(.didDeleteAccount) {
store.receive(.deleteAccount(.success)) {
$0.isDeletingAccount = false
}
}
......@@ -298,16 +302,41 @@ final class HomeFeatureTests: XCTestCase {
return e2e
}
store.send(.deleteAccountConfirmed) {
store.send(.deleteAccount(.confirmed)) {
$0.isDeletingAccount = true
}
store.receive(.set(\.$isDeletingAccount, false)) {
store.receive(.deleteAccount(.failure(error as NSError))) {
$0.isDeletingAccount = false
$0.alert = .accountDeletionFailed(error)
}
}
store.receive(.set(\.$alert, .accountDeletionFailed(error))) {
$0.alert = .accountDeletionFailed(error)
func testDidDismissAlert() {
let store = TestStore(
initialState: HomeState(
alert: AlertState(title: TextState(""))
),
reducer: homeReducer,
environment: .unimplemented
)
store.send(.didDismissAlert) {
$0.alert = nil
}
}
func testDidDismissRegister() {
let store = TestStore(
initialState: HomeState(
register: RegisterState()
),
reducer: homeReducer,
environment: .unimplemented
)
store.send(.didDismissRegister) {
$0.register = nil
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment