Files
swift-tca-extras/Tests/swift-composable-subscriberTests/swift_composable_subscriberTests.swift

145 lines
3.0 KiB
Swift

import ComposableArchitecture
import XCTest
@testable import ComposableSubscriber
@DependencyClient
struct NumberClient {
var numberStreamWithoutArg: @Sendable () async -> AsyncStream<Int> = { .never }
var numberStreamWithArg: @Sendable (Int) async -> AsyncStream<Int> = { _ in .never }
}
extension NumberClient: TestDependencyKey {
static var live: NumberClient {
NumberClient(
numberStreamWithoutArg: {
AsyncStream { continuation in
continuation.yield(1)
continuation.finish()
}
},
numberStreamWithArg: { number in
AsyncStream { continuation in
continuation.yield(number)
continuation.finish()
}
}
)
}
static let testValue = Self()
}
extension DependencyValues {
var numberClient: NumberClient {
get { self[NumberClient.self] }
set { self[NumberClient.self] = newValue }
}
}
struct NumberState: Equatable {
var number: Int
var currentNumber: Int?
}
@CasePathable
enum NumberAction {
case receive(Int)
case task
}
@Reducer
struct ReducerWithArg {
typealias State = NumberState
typealias Action = NumberAction
@Dependency(\.numberClient) var numberClient
var body: some Reducer<State, Action> {
Reduce<State, Action> { state, action in
switch action {
case let .receive(number):
state.currentNumber = number
return .none
case .task:
return .none
}
}
.subscribe(
using: \.number,
to: numberClient.numberStreamWithArg,
on: \.task,
with: \.receive
)
}
}
@Reducer
struct ReducerWithTransform {
typealias State = NumberState
typealias Action = NumberAction
@Dependency(\.numberClient) var numberClient
var body: some Reducer<State, Action> {
Reduce<State, Action> { state, action in
switch action {
case let .receive(number):
state.currentNumber = number
return .none
case .task:
return .none
}
}
.subscribe(
using: \.number,
to: numberClient.numberStreamWithArg,
on: \.task,
with: \.receive
) {
$0 * 2
}
}
}
@MainActor
final class swift_composable_subscriberTests: XCTestCase {
func testSubscribeWithArg() async throws {
let store = TestStore(
initialState: ReducerWithArg.State(number: 19),
reducer: ReducerWithArg.init
) {
$0.numberClient = .live
}
let task = await store.send(.task)
await store.receive(\.receive) {
$0.currentNumber = 19
}
await task.cancel()
await store.finish()
}
func testSubscribeWithArgAndTransform() async throws {
let store = TestStore(
initialState: ReducerWithTransform.State(number: 10),
reducer: ReducerWithTransform.init
) {
$0.numberClient = .live
}
let task = await store.send(.task)
await store.receive(\.receive) {
$0.currentNumber = 20
}
await task.cancel()
await store.finish()
}
}