feat: Adds overloads for invoking stream's that require an argument from the current reducer's state.

This commit is contained in:
2024-02-24 14:51:35 -05:00
parent 7ee77bd6b7
commit 632e3eb9fc
4 changed files with 677 additions and 20 deletions

View File

@@ -1,12 +1,144 @@
import ComposableArchitecture
import XCTest
@testable import swift_composable_subscriber
@testable import ComposableSubscriber
final class swift_composable_subscriberTests: XCTestCase {
func testExample() throws {
// XCTest Documentation
// https://developer.apple.com/documentation/xctest
// Defining Test Cases and Test Methods
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
}
@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()
}
}