mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-20 09:11:33 +01:00
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Silence test warnings * wip * wip * wip * update a bunch of docs * wip * wip * fix * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Kill integration tests for now * wip * wip * wip * wip * updating docs for @Reducer macro * replaced more Reducer protocols with @Reducer * Fixed some broken docc references * wip * Some @Reducer docs * more docs * convert some old styles to new style * wip * wip * wip * wip * wip * wip * wip * bump * update tutorials to use body * update tutorials to use DML on destination state enum * Add diagnostic * wip * updated a few more tests * wip * wip * Add another gotcha * wip * wip * wip * fixes * wip * wip * wip * wip * wip * fix * wip * remove for now * wip * wip * updated some docs * migration guides * more migration guide * fix ci * fix * soft deprecate all apis using AnyCasePath * wip * Fix * fix tests * swift-format 509 compatibility * wip * wip * Update Sources/ComposableArchitecture/Macros.swift Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com> * wip * wip * update optional state case study * remove initializer * Don't use @State for BasicsView integration demo * fix tests * remove reduce diagnostics for now * diagnose error not warning * Update Sources/ComposableArchitecture/Macros.swift Co-authored-by: Jesse Tipton <jesse@jessetipton.com> * wip * move integration tests to cron * Revert "move integration tests to cron" This reverts commitf9bdf2f04b. * disable flakey tests on CI * wip * wip * Revert "Revert "move integration tests to cron"" This reverts commit66aafa7327. * fix * wip * fix --------- Co-authored-by: Brandon Williams <mbrandonw@hey.com> Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com> Co-authored-by: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Co-authored-by: Jesse Tipton <jesse@jessetipton.com>
161 lines
4.2 KiB
Swift
161 lines
4.2 KiB
Swift
import Combine
|
|
import CombineSchedulers
|
|
import ComposableArchitecture
|
|
import XCTest
|
|
|
|
@MainActor
|
|
final class ComposableArchitectureTests: BaseTCATestCase {
|
|
var cancellables: Set<AnyCancellable> = []
|
|
|
|
func testScheduling() async {
|
|
struct Counter: Reducer {
|
|
typealias State = Int
|
|
enum Action: Equatable {
|
|
case incrAndSquareLater
|
|
case incrNow
|
|
case squareNow
|
|
}
|
|
@Dependency(\.mainQueue) var mainQueue
|
|
var body: some Reducer<State, Action> {
|
|
Reduce { state, action in
|
|
switch action {
|
|
case .incrAndSquareLater:
|
|
return .run { send in
|
|
await withThrowingTaskGroup(of: Void.self) { group in
|
|
group.addTask {
|
|
try await self.mainQueue.sleep(for: .seconds(2))
|
|
await send(.incrNow)
|
|
}
|
|
group.addTask {
|
|
try await self.mainQueue.sleep(for: .seconds(1))
|
|
await send(.squareNow)
|
|
}
|
|
group.addTask {
|
|
try await self.mainQueue.sleep(for: .seconds(2))
|
|
await send(.squareNow)
|
|
}
|
|
}
|
|
}
|
|
case .incrNow:
|
|
state += 1
|
|
return .none
|
|
case .squareNow:
|
|
state *= state
|
|
return .none
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let mainQueue = DispatchQueue.test
|
|
|
|
let store = TestStore(initialState: 2) {
|
|
Counter()
|
|
} withDependencies: {
|
|
$0.mainQueue = mainQueue.eraseToAnyScheduler()
|
|
}
|
|
|
|
await store.send(.incrAndSquareLater)
|
|
await mainQueue.advance(by: 1)
|
|
await store.receive(.squareNow) { $0 = 4 }
|
|
await mainQueue.advance(by: 1)
|
|
await store.receive(.incrNow) { $0 = 5 }
|
|
await store.receive(.squareNow) { $0 = 25 }
|
|
|
|
await store.send(.incrAndSquareLater)
|
|
await mainQueue.advance(by: 2)
|
|
await store.receive(.squareNow) { $0 = 625 }
|
|
await store.receive(.incrNow) { $0 = 626 }
|
|
await store.receive(.squareNow) { $0 = 391876 }
|
|
}
|
|
|
|
func testSimultaneousWorkOrdering() {
|
|
let mainQueue = DispatchQueue.test
|
|
|
|
var values: [Int] = []
|
|
mainQueue.schedule(after: mainQueue.now, interval: 1) { values.append(1) }
|
|
.store(in: &self.cancellables)
|
|
mainQueue.schedule(after: mainQueue.now, interval: 2) { values.append(42) }
|
|
.store(in: &self.cancellables)
|
|
|
|
XCTAssertEqual(values, [])
|
|
mainQueue.advance()
|
|
XCTAssertEqual(values, [1, 42])
|
|
mainQueue.advance(by: 2)
|
|
XCTAssertEqual(values, [1, 42, 1, 1, 42])
|
|
}
|
|
|
|
func testLongLivingEffects() async {
|
|
enum Action { case end, incr, start }
|
|
|
|
let effect = AsyncStream.makeStream(of: Void.self)
|
|
|
|
let store = TestStore(initialState: 0) {
|
|
Reduce<Int, Action> { state, action in
|
|
switch action {
|
|
case .end:
|
|
return .run { _ in
|
|
effect.continuation.finish()
|
|
}
|
|
case .incr:
|
|
state += 1
|
|
return .none
|
|
case .start:
|
|
return .run { send in
|
|
for await _ in effect.stream {
|
|
await send(.incr)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
await store.send(.start)
|
|
await store.send(.incr) { $0 = 1 }
|
|
effect.continuation.yield()
|
|
await store.receive(.incr) { $0 = 2 }
|
|
await store.send(.end)
|
|
}
|
|
|
|
func testCancellation() async {
|
|
let mainQueue = DispatchQueue.test
|
|
|
|
enum Action: Equatable {
|
|
case cancel
|
|
case incr
|
|
case response(Int)
|
|
}
|
|
|
|
let store = TestStore(initialState: 0) {
|
|
Reduce<Int, Action> { state, action in
|
|
enum CancelID { case sleep }
|
|
|
|
switch action {
|
|
case .cancel:
|
|
return .cancel(id: CancelID.sleep)
|
|
|
|
case .incr:
|
|
state += 1
|
|
return .run { [state] send in
|
|
try await mainQueue.sleep(for: .seconds(1))
|
|
await send(.response(state * state))
|
|
}
|
|
.cancellable(id: CancelID.sleep)
|
|
|
|
case let .response(value):
|
|
state = value
|
|
return .none
|
|
}
|
|
}
|
|
}
|
|
|
|
await store.send(.incr) { $0 = 1 }
|
|
await mainQueue.advance(by: .seconds(1))
|
|
await store.receive(.response(1))
|
|
|
|
await store.send(.incr) { $0 = 2 }
|
|
await store.send(.cancel)
|
|
await store.finish()
|
|
}
|
|
}
|