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

Implement resetting authenticated channel

parent 3b520853
No related branches found
No related tags found
2 merge requests!115Messenger example - reset authenticated channel,!102Release 1.0.0
......@@ -316,8 +316,10 @@ let package = Package(
.target(
name: "ResetAuthFeature",
dependencies: [
.target(name: "AppCore"),
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
.product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
],
swiftSettings: swiftSettings
),
......
......@@ -79,7 +79,11 @@ extension AppEnvironment {
)
},
resetAuth: {
ResetAuthEnvironment()
ResetAuthEnvironment(
messenger: messenger,
mainQueue: mainQueue,
bgQueue: bgQueue
)
},
chat: {
ChatEnvironment(
......
import ComposableArchitecture
import Foundation
import XCTestDynamicOverlay
import XXClient
import XXMessengerClient
public struct ResetAuthState: Equatable {
public init(
partner: Contact
partner: Contact,
isResetting: Bool = false,
failure: String? = nil,
didReset: Bool = false
) {
self.partner = partner
self.isResetting = isResetting
self.failure = failure
self.didReset = didReset
}
var partner: Contact
public var partner: Contact
public var isResetting: Bool
public var failure: String?
public var didReset: Bool
}
public enum ResetAuthAction: Equatable {}
public enum ResetAuthAction: Equatable {
case resetTapped
case didReset
case didFail(String)
}
public struct ResetAuthEnvironment {
public init() {}
public init(
messenger: Messenger,
mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>
) {
self.messenger = messenger
self.mainQueue = mainQueue
self.bgQueue = bgQueue
}
public var messenger: Messenger
public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue>
}
#if DEBUG
extension ResetAuthEnvironment {
public static let unimplemented = ResetAuthEnvironment()
public static let unimplemented = ResetAuthEnvironment(
messenger: .unimplemented,
mainQueue: .unimplemented,
bgQueue: .unimplemented
)
}
#endif
public let resetAuthReducer = Reducer<ResetAuthState, ResetAuthAction, ResetAuthEnvironment>.empty
public let resetAuthReducer = Reducer<ResetAuthState, ResetAuthAction, ResetAuthEnvironment>
{ state, action, env in
switch action {
case .resetTapped:
state.isResetting = true
state.didReset = false
state.failure = nil
return Effect.result { [state] in
do {
let e2e = try env.messenger.e2e.tryGet()
_ = try e2e.resetAuthenticatedChannel(partner: state.partner)
return .success(.didReset)
} catch {
return .success(.didFail(error.localizedDescription))
}
}
.subscribe(on: env.bgQueue)
.receive(on: env.mainQueue)
.eraseToEffect()
case .didReset:
state.isResetting = false
state.didReset = true
state.failure = nil
return .none
case .didFail(let failure):
state.isResetting = false
state.didReset = false
state.failure = failure
return .none
}
}
import AppCore
import ComposableArchitecture
import SwiftUI
......@@ -9,13 +10,53 @@ public struct ResetAuthView: View {
let store: Store<ResetAuthState, ResetAuthAction>
struct ViewState: Equatable {
init(state: ResetAuthState) {}
init(state: ResetAuthState) {
contactID = try? state.partner.getId()
isResetting = state.isResetting
failure = state.failure
didReset = state.didReset
}
var contactID: Data?
var isResetting: Bool
var failure: String?
var didReset: Bool
}
public var body: some View {
WithViewStore(store, observe: ViewState.init) { viewStore in
Form {
Text("Unimplemented")
Section {
Text(viewStore.contactID?.hexString() ?? "")
.font(.footnote.monospaced())
.textSelection(.enabled)
} header: {
Label("ID", systemImage: "number")
}
Button {
viewStore.send(.resetTapped)
} label: {
HStack {
Text("Reset authenticated channel")
Spacer()
if viewStore.isResetting {
ProgressView()
} else if viewStore.didReset {
Image(systemName: "checkmark")
.foregroundColor(.green)
}
}
}
.disabled(viewStore.isResetting)
if let failure = viewStore.failure {
Section {
Text(failure)
} header: {
Text("Error")
}
}
}
.navigationTitle("Reset auth")
}
......
import ComposableArchitecture
import CustomDump
import XCTest
import XXClient
@testable import ResetAuthFeature
final class ResetAuthFeatureTests: XCTestCase {
func testExample() {
XCTAssert(true)
func testReset() {
let partnerData = "contact-data".data(using: .utf8)!
let partner = Contact.unimplemented(partnerData)
var didResetAuthChannel: [Contact] = []
let store = TestStore(
initialState: ResetAuthState(
partner: partner
),
reducer: resetAuthReducer,
environment: .unimplemented
)
store.environment.mainQueue = .immediate
store.environment.bgQueue = .immediate
store.environment.messenger.e2e.get = {
var e2e: E2E = .unimplemented
e2e.resetAuthenticatedChannel.run = { contact in
didResetAuthChannel.append(contact)
return 0
}
return e2e
}
store.send(.resetTapped) {
$0.isResetting = true
}
XCTAssertNoDifference(didResetAuthChannel, [partner])
store.receive(.didReset) {
$0.isResetting = false
$0.didReset = true
}
}
func testResetFailure() {
struct Failure: Error {}
let failure = Failure()
let store = TestStore(
initialState: ResetAuthState(
partner: .unimplemented(Data())
),
reducer: resetAuthReducer,
environment: .unimplemented
)
store.environment.mainQueue = .immediate
store.environment.bgQueue = .immediate
store.environment.messenger.e2e.get = {
var e2e: E2E = .unimplemented
e2e.resetAuthenticatedChannel.run = { _ in throw failure }
return e2e
}
store.send(.resetTapped) {
$0.isResetting = true
}
store.receive(.didFail(failure.localizedDescription)) {
$0.isResetting = false
$0.failure = failure.localizedDescription
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment