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

Observe identity in MyIdentityFeature

parent b16ba0e8
No related branches found
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.
Finish editing this message first!
Please register or to comment