Files
swift-composable-architectu…/Tests/ComposableArchitectureTests/DebugTests.swift
Stephen Celis 547d19c9dc Add Sharing dependency (#3517)
* wip

* wip

* remove old case study for shared notifications

* wip

* wip

* wip

* wip

* wip

* 1.17 migration guide

* basics migration guide

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
2024-12-03 13:08:02 -06:00

192 lines
4.6 KiB
Swift

#if DEBUG
import Combine
import CustomDump
import XCTest
@testable import ComposableArchitecture
final class DebugTests: BaseTCATestCase {
func testDebugCaseOutput() {
enum Action {
case action1(Bool, label: String)
case action2(Bool, Int, String)
case screenA(ScreenA)
enum ScreenA {
case row(index: Int, action: RowAction)
enum RowAction {
case tapped
case textChanged(query: String)
}
}
}
XCTAssertEqual(
debugCaseOutput(Action.action1(true, label: "Blob")),
"DebugTests.Action.action1(_:, label:)"
)
XCTAssertEqual(
debugCaseOutput(Action.action2(true, 1, "Blob")),
"DebugTests.Action.action2(_:, _:, _:)"
)
XCTAssertEqual(
debugCaseOutput(Action.screenA(.row(index: 1, action: .tapped))),
"DebugTests.Action.screenA(.row(index:, action: .tapped))"
)
XCTAssertEqual(
debugCaseOutput(Action.screenA(.row(index: 1, action: .textChanged(query: "Hi")))),
"DebugTests.Action.screenA(.row(index:, action: .textChanged(query:)))"
)
}
func testBindingAction() {
struct State {
@BindingState var width = 0
}
let action = BindingAction.set(\State.$width, 50)
var dump = ""
customDump(action, to: &dump)
XCTAssertEqual(
dump,
#"""
.set(\State.$width, 50)
"""#
)
}
func testBindingAction_Nested() {
struct Settings: Equatable {
var isEnabled = false
var description = ""
}
struct State {
@BindingState var settings = Settings()
}
let action = BindingAction.set(\State.$settings, Settings(isEnabled: true))
var dump = ""
customDump(action, to: &dump)
XCTAssertEqual(
dump,
#"""
.set(\State.$settings, DebugTests.Settings(…))
"""#
)
}
func testDebugReducer() async throws {
let logs = LockIsolated<String>("")
let printer = _ReducerPrinter<Int, Bool>(
printChange: { action, oldState, newState in
logs.withValue { _ = dump(action, to: &$0) }
}
)
let store = await Store<Int, Bool>(initialState: 0) {
Reduce<Int, Bool>(internal: { state, action in
state += action ? 1 : -1
return .none
})
._printChanges(printer)
}
await store.send(true)
try await Task.sleep(nanoseconds: 300_000_000)
expectNoDifference(
logs.value,
"""
- true
"""
)
}
@MainActor
func testDebugReducer_Order() {
let logs = LockIsolated<String>("")
let printer = _ReducerPrinter<Int, Bool>(
printChange: { action, oldState, newState in
logs.withValue { _ = dump(action, to: &$0) }
}
)
let store = Store<Int, Bool>(initialState: 0) {
Reduce<Int, Bool>(internal: { state, action in
state += action ? 1 : -1
return .run { _ in await Task.yield() }
})
._printChanges(printer)
._printChanges(printer)
._printChanges(printer)
._printChanges(printer)
}
store.send(true)
store.send(false)
store.send(true)
store.send(false)
_ = XCTWaiter.wait(for: [self.expectation(description: "wait")], timeout: 0.3)
expectNoDifference(
logs.value,
"""
- true
- true
- true
- true
- false
- false
- false
- false
- true
- true
- true
- true
- false
- false
- false
- false
"""
)
}
func testDebugReducer_SharedState() async throws {
let logs = LockIsolated<String>("")
let printer = _ReducerPrinter<State, Bool>(
printChange: { action, oldState, newState in
logs.withValue {
$0.append(diff(oldState, newState).map { "\($0)\n" } ?? " (No state changes)\n")
}
}
)
struct State {
@Shared var count: Int
}
let store = await Store<State, Bool>(initialState: State(count: Shared(value: 0))) {
Reduce<State, Bool>(internal: { state, action in
state.$count.withLock { $0 += action ? 1 : -1 }
return .none
})
._printChanges(printer)
}
await store.send(true)
try await Task.sleep(nanoseconds: 300_000_000)
expectNoDifference(
logs.value,
#"""
DebugTests.State(
- _count: #1 0
+ _count: #1 1
)
"""#
)
}
}
#endif