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

Observe identity in MyIdentityFeature

parent b16ba0e8
Branches
No related tags found
1 merge request!14[Example App] Make identity & contact
......@@ -144,6 +144,10 @@ let package = Package(
name: "ComposableArchitecture",
package: "swift-composable-architecture"
),
.product(
name: "ElixxirDAppsSDK",
package: "elixxir-dapps-sdk-swift"
),
],
swiftSettings: swiftSettings
),
......
......@@ -23,6 +23,7 @@ struct App: SwiftUI.App {
extension AppEnvironment {
static func live() -> AppEnvironment {
let clientSubject = CurrentValueSubject<Client?, Never>(nil)
let identitySubject = CurrentValueSubject<Identity?, Never>(nil)
let mainScheduler = DispatchQueue.main.eraseToAnyScheduler()
let bgScheduler = DispatchQueue(
label: "xx.network.dApps.ExampleApp.bg",
......@@ -48,7 +49,12 @@ extension AppEnvironment {
mainScheduler: mainScheduler,
makeId: UUID.init,
error: ErrorEnvironment(),
myIdentity: MyIdentityEnvironment()
myIdentity: MyIdentityEnvironment(
getClient: { clientSubject.value },
observeIdentity: { identitySubject.eraseToAnyPublisher() },
bgScheduler: bgScheduler,
mainScheduler: mainScheduler
)
)
)
}
......
import Combine
import ComposableArchitecture
import ElixxirDAppsSDK
public struct MyIdentityState: Equatable {
public init(
......@@ -8,18 +10,67 @@ public struct MyIdentityState: Equatable {
}
public var id: UUID
public var identity: Identity?
}
public enum MyIdentityAction: Equatable {}
public enum MyIdentityAction: Equatable {
case viewDidLoad
case observeMyIdentity
case didUpdateMyIdentity(Identity?)
}
public struct MyIdentityEnvironment {
public init() {}
public init(
getClient: @escaping () -> Client?,
observeIdentity: @escaping () -> AnyPublisher<Identity?, Never>,
bgScheduler: AnySchedulerOf<DispatchQueue>,
mainScheduler: AnySchedulerOf<DispatchQueue>
) {
self.getClient = getClient
self.observeIdentity = observeIdentity
self.bgScheduler = bgScheduler
self.mainScheduler = mainScheduler
}
public var getClient: () -> Client?
public var observeIdentity: () -> AnyPublisher<Identity?, Never>
public var bgScheduler: AnySchedulerOf<DispatchQueue>
public var mainScheduler: AnySchedulerOf<DispatchQueue>
}
public let myIdentityReducer = Reducer<MyIdentityState, MyIdentityAction, MyIdentityEnvironment>.empty
public let myIdentityReducer = Reducer<MyIdentityState, MyIdentityAction, MyIdentityEnvironment>
{ state, action, env in
switch action {
case .viewDidLoad:
return .merge([
.init(value: .observeMyIdentity),
])
case .observeMyIdentity:
struct EffectId: Hashable {
let id: UUID
}
return env.observeIdentity()
.removeDuplicates()
.map(MyIdentityAction.didUpdateMyIdentity)
.subscribe(on: env.bgScheduler)
.receive(on: env.mainScheduler)
.eraseToEffect()
.cancellable(id: EffectId(id: state.id), cancelInFlight: true)
case .didUpdateMyIdentity(let identity):
state.identity = identity
return .none
}
}
#if DEBUG
extension MyIdentityEnvironment {
public static let failing = MyIdentityEnvironment()
public static let failing = MyIdentityEnvironment(
getClient: { fatalError() },
observeIdentity: { fatalError() },
bgScheduler: .failing,
mainScheduler: .failing
)
}
#endif
......@@ -15,6 +15,9 @@ public struct MyIdentityView: View {
public var body: some View {
WithViewStore(store.scope(state: ViewState.init)) { viewStore in
Text("MyIdentityView")
.task {
viewStore.send(.viewDidLoad)
}
}
}
}
......
import Combine
import ComposableArchitecture
import ElixxirDAppsSDK
import XCTest
@testable import MyIdentityFeature
final class MyIdentityFeatureTests: XCTestCase {
func testExample() {
XCTAssert(true)
func testViewDidLoad() {
let myIdentitySubject = PassthroughSubject<Identity?, Never>()
let bgScheduler = DispatchQueue.test
let mainScheduler = DispatchQueue.test
var env = MyIdentityEnvironment.failing
env.observeIdentity = { myIdentitySubject.eraseToAnyPublisher() }
env.bgScheduler = bgScheduler.eraseToAnyScheduler()
env.mainScheduler = mainScheduler.eraseToAnyScheduler()
let store = TestStore(
initialState: MyIdentityState(id: UUID()),
reducer: myIdentityReducer,
environment: env
)
store.send(.viewDidLoad)
store.receive(.observeMyIdentity)
bgScheduler.advance()
let identity = Identity.stub()
myIdentitySubject.send(identity)
mainScheduler.advance()
store.receive(.didUpdateMyIdentity(identity)) {
$0.identity = identity
}
myIdentitySubject.send(nil)
mainScheduler.advance()
store.receive(.didUpdateMyIdentity(nil)) {
$0.identity = nil
}
myIdentitySubject.send(completion: .finished)
mainScheduler.advance()
}
}
private extension Identity {
static func stub() -> Identity {
Identity(
id: "\(Int.random(in: 100...999))".data(using: .utf8)!,
rsaPrivatePem: "\(Int.random(in: 100...999))".data(using: .utf8)!,
salt: "\(Int.random(in: 100...999))".data(using: .utf8)!,
dhKeyPrivate: "\(Int.random(in: 100...999))".data(using: .utf8)!
)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment