Skip to content

Commit 8259610

Browse files
author
Oguz Yuksel
committed
add unit tests
1 parent a1a9886 commit 8259610

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

Tests/ComposableArchitectureTests/Reducers/PresentationReducerTests.swift

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,6 +2657,41 @@ final class PresentationReducerTests: BaseTCATestCase {
26572657
// XCTAssertNil(store.alert)
26582658
// }
26592659
#endif
2660+
2661+
@MainActor
2662+
func testPresentation_dismissWorksAfterParentEnumTransition() async {
2663+
let scheduler = DispatchQueue.test
2664+
let store = TestStore(initialState: EnumTransitionParent.State.online(.init())) {
2665+
EnumTransitionParent()
2666+
} withDependencies: {
2667+
$0.mainQueue = scheduler.eraseToAnyScheduler()
2668+
}
2669+
2670+
// Present modal in .online state
2671+
await store.send(.online(.presentModal)) {
2672+
$0.online?.modal = .init()
2673+
}
2674+
2675+
// Start timer that will dismiss
2676+
await store.send(.online(.modal(.presented(.startTimer))))
2677+
2678+
// Transition to .offline (timer cancelled, modal stays presented)
2679+
await store.send(.setOnline(false)) {
2680+
$0 = .offline($0.online ?? .init())
2681+
}
2682+
2683+
// Transition back to .online (modal still presented, timer restarts)
2684+
await store.send(.setOnline(true)) {
2685+
$0 = .online($0.offline ?? .init())
2686+
}
2687+
await store.send(.online(.modal(.presented(.startTimer))))
2688+
2689+
// Timer completes and dismiss should work
2690+
await scheduler.advance(by: .milliseconds(100))
2691+
await store.receive(\.online.modal.dismiss) {
2692+
$0.online?.modal = nil
2693+
}
2694+
}
26602695
}
26612696

26622697
@Reducer
@@ -2687,3 +2722,112 @@ private struct NestedDismissFeature {
26872722
}
26882723
}
26892724
}
2725+
2726+
@Reducer
2727+
private struct EnumTransitionModal {
2728+
struct State: Equatable {}
2729+
enum Action {
2730+
case startTimer
2731+
}
2732+
@Dependency(\.dismiss) var dismiss
2733+
@Dependency(\.mainQueue) var mainQueue
2734+
2735+
var body: some Reducer<State, Action> {
2736+
Reduce { state, action in
2737+
switch action {
2738+
case .startTimer:
2739+
return .run { _ in
2740+
try await mainQueue.sleep(for: .milliseconds(100))
2741+
await dismiss()
2742+
}
2743+
}
2744+
}
2745+
}
2746+
}
2747+
2748+
@Reducer
2749+
private struct EnumTransitionChild {
2750+
struct State: Equatable {
2751+
@PresentationState var modal: EnumTransitionModal.State?
2752+
}
2753+
enum Action {
2754+
case presentModal
2755+
case modal(PresentationAction<EnumTransitionModal.Action>)
2756+
}
2757+
var body: some Reducer<State, Action> {
2758+
Reduce { state, action in
2759+
switch action {
2760+
case .presentModal:
2761+
state.modal = .init()
2762+
return .none
2763+
case .modal:
2764+
return .none
2765+
}
2766+
}
2767+
.ifLet(\.$modal, action: \.modal) {
2768+
EnumTransitionModal()
2769+
}
2770+
}
2771+
}
2772+
2773+
@Reducer
2774+
private struct EnumTransitionParent {
2775+
@ObservableState
2776+
enum State: Equatable {
2777+
case online(EnumTransitionChild.State)
2778+
case offline(EnumTransitionChild.State)
2779+
2780+
var online: EnumTransitionChild.State? {
2781+
get {
2782+
guard case let .online(state) = self else { return nil }
2783+
return state
2784+
}
2785+
set {
2786+
guard let newValue else { return }
2787+
self = .online(newValue)
2788+
}
2789+
}
2790+
2791+
var offline: EnumTransitionChild.State? {
2792+
get {
2793+
guard case let .offline(state) = self else { return nil }
2794+
return state
2795+
}
2796+
set {
2797+
guard let newValue else { return }
2798+
self = .offline(newValue)
2799+
}
2800+
}
2801+
}
2802+
2803+
enum Action {
2804+
case setOnline(Bool)
2805+
case online(EnumTransitionChild.Action)
2806+
case offline(EnumTransitionChild.Action)
2807+
}
2808+
2809+
var body: some Reducer<State, Action> {
2810+
Reduce { state, action in
2811+
switch action {
2812+
case .setOnline(true):
2813+
if case let .offline(offlineState) = state {
2814+
state = .online(offlineState)
2815+
}
2816+
return .none
2817+
case .setOnline(false):
2818+
if case let .online(onlineState) = state {
2819+
state = .offline(onlineState)
2820+
}
2821+
return .none
2822+
default:
2823+
return .none
2824+
}
2825+
}
2826+
.ifCaseLet(\.online, action: \.online) {
2827+
EnumTransitionChild()
2828+
}
2829+
.ifCaseLet(\.offline, action: \.offline) {
2830+
EmptyReducer()
2831+
}
2832+
}
2833+
}

0 commit comments

Comments
 (0)