Skip to content

Commit cd76e31

Browse files
authored
Update demos to use failing environments (#650)
1 parent adb1f25 commit cd76e31

File tree

23 files changed

+369
-387
lines changed

23 files changed

+369
-387
lines changed

Examples/CaseStudies/SwiftUICaseStudies/00-Core.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ let rootReducer = Reducer<RootState, RootAction, RootEnvironment>.combine(
202202
.init(
203203
date: env.date,
204204
environment: .init(fetchNumber: env.fetchNumber),
205-
mainQueue: { env.mainQueue },
205+
mainQueue: env.mainQueue,
206206
uuid: env.uuid
207207
)
208208
}

Examples/CaseStudies/SwiftUICaseStudies/03-Effects-SystemEnvironment.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ let multipleDependenciesReducer = Reducer<
4646
switch action {
4747
case .alertButtonTapped:
4848
return Effect(value: .alertDelayReceived)
49-
.delay(for: 1, scheduler: environment.mainQueue())
49+
.delay(for: 1, scheduler: environment.mainQueue)
5050
.eraseToEffect()
5151

5252
case .alertDelayReceived:
@@ -159,7 +159,7 @@ struct MultipleDependenciesView_Previews: PreviewProvider {
159159
struct SystemEnvironment<Environment> {
160160
var date: () -> Date
161161
var environment: Environment
162-
var mainQueue: () -> AnySchedulerOf<DispatchQueue>
162+
var mainQueue: AnySchedulerOf<DispatchQueue>
163163
var uuid: () -> UUID
164164

165165
subscript<Dependency>(
@@ -177,7 +177,7 @@ struct SystemEnvironment<Environment> {
177177
Self(
178178
date: Date.init,
179179
environment: environment,
180-
mainQueue: { .main },
180+
mainQueue: .main,
181181
uuid: UUID.init
182182
)
183183
}
@@ -196,17 +196,25 @@ struct SystemEnvironment<Environment> {
196196
}
197197

198198
#if DEBUG
199+
import XCTestDynamicOverlay
200+
199201
extension SystemEnvironment {
200-
static func mock(
201-
date: @escaping () -> Date = { fatalError("date dependency is unimplemented.") },
202+
static func failing(
203+
date: @escaping () -> Date = {
204+
XCTFail("date dependency is unimplemented.")
205+
return Date()
206+
},
202207
environment: Environment,
203-
mainQueue: @escaping () -> AnySchedulerOf<DispatchQueue> = { fatalError() },
204-
uuid: @escaping () -> UUID = { fatalError("UUID dependency is unimplemented.") }
208+
mainQueue: AnySchedulerOf<DispatchQueue> = .failing,
209+
uuid: @escaping () -> UUID = {
210+
XCTFail("UUID dependency is unimplemented.")
211+
return UUID()
212+
}
205213
) -> Self {
206214
Self(
207215
date: date,
208216
environment: environment,
209-
mainQueue: { mainQueue().eraseToAnyScheduler() },
217+
mainQueue: mainQueue,
210218
uuid: uuid
211219
)
212220
}

Examples/CaseStudies/SwiftUICaseStudiesTests/02-Effects-WebSocketTests.swift

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ class WebSocketTests: XCTestCase {
99
let socketSubject = PassthroughSubject<WebSocketClient.Action, Never>()
1010
let receiveSubject = PassthroughSubject<WebSocketClient.Message, NSError>()
1111

12+
var webSocket = WebSocketClient.failing
13+
webSocket.open = { _, _, _ in socketSubject.eraseToEffect() }
14+
webSocket.receive = { _ in receiveSubject.eraseToEffect() }
15+
webSocket.send = { _, _ in Effect(value: nil) }
16+
webSocket.sendPing = { _ in .none }
17+
1218
let store = TestStore(
1319
initialState: .init(),
1420
reducer: webSocketReducer,
1521
environment: WebSocketEnvironment(
1622
mainQueue: .immediate,
17-
webSocket: .mock(
18-
open: { _, _, _ in socketSubject.eraseToEffect() },
19-
receive: { _ in receiveSubject.eraseToEffect() },
20-
send: { _, _ in Effect(value: nil) },
21-
sendPing: { _ in .none }
22-
)
23+
webSocket: webSocket
2324
)
2425
)
2526

@@ -57,17 +58,18 @@ class WebSocketTests: XCTestCase {
5758
let socketSubject = PassthroughSubject<WebSocketClient.Action, Never>()
5859
let receiveSubject = PassthroughSubject<WebSocketClient.Message, NSError>()
5960

61+
var webSocket = WebSocketClient.failing
62+
webSocket.open = { _, _, _ in socketSubject.eraseToEffect() }
63+
webSocket.receive = { _ in receiveSubject.eraseToEffect() }
64+
webSocket.send = { _, _ in Effect(value: NSError(domain: "", code: 1)) }
65+
webSocket.sendPing = { _ in .none }
66+
6067
let store = TestStore(
6168
initialState: .init(),
6269
reducer: webSocketReducer,
6370
environment: WebSocketEnvironment(
6471
mainQueue: .immediate,
65-
webSocket: .mock(
66-
open: { _, _, _ in socketSubject.eraseToEffect() },
67-
receive: { _ in receiveSubject.eraseToEffect() },
68-
send: { _, _ in Effect(value: NSError(domain: "", code: 1)) },
69-
sendPing: { _ in .none }
70-
)
72+
webSocket: webSocket
7173
)
7274
)
7375

@@ -101,17 +103,18 @@ class WebSocketTests: XCTestCase {
101103
let socketSubject = PassthroughSubject<WebSocketClient.Action, Never>()
102104
let pingSubject = PassthroughSubject<NSError?, Never>()
103105

106+
var webSocket = WebSocketClient.failing
107+
webSocket.open = { _, _, _ in socketSubject.eraseToEffect() }
108+
webSocket.receive = { _ in .none }
109+
webSocket.sendPing = { _ in pingSubject.eraseToEffect() }
110+
104111
let scheduler = DispatchQueue.test
105112
let store = TestStore(
106113
initialState: .init(),
107114
reducer: webSocketReducer,
108115
environment: WebSocketEnvironment(
109116
mainQueue: scheduler.eraseToAnyScheduler(),
110-
webSocket: .mock(
111-
open: { _, _, _ in socketSubject.eraseToEffect() },
112-
receive: { _ in .none },
113-
sendPing: { _ in pingSubject.eraseToEffect() }
114-
)
117+
webSocket: webSocket
115118
)
116119
)
117120

@@ -138,17 +141,18 @@ class WebSocketTests: XCTestCase {
138141
func testWebSocketConnectError() {
139142
let socketSubject = PassthroughSubject<WebSocketClient.Action, Never>()
140143

144+
var webSocket = WebSocketClient.failing
145+
webSocket.cancel = { _, _, _ in .fireAndForget { socketSubject.send(completion: .finished) } }
146+
webSocket.open = { _, _, _ in socketSubject.eraseToEffect() }
147+
webSocket.receive = { _ in .none }
148+
webSocket.sendPing = { _ in .none }
149+
141150
let store = TestStore(
142151
initialState: .init(),
143152
reducer: webSocketReducer,
144153
environment: WebSocketEnvironment(
145154
mainQueue: .immediate,
146-
webSocket: .mock(
147-
cancel: { _, _, _ in .fireAndForget { socketSubject.send(completion: .finished) } },
148-
open: { _, _, _ in socketSubject.eraseToEffect() },
149-
receive: { _ in .none },
150-
sendPing: { _ in .none }
151-
)
155+
webSocket: webSocket
152156
)
153157
)
154158

@@ -164,25 +168,11 @@ class WebSocketTests: XCTestCase {
164168
}
165169

166170
extension WebSocketClient {
167-
static func mock(
168-
cancel: @escaping (AnyHashable, URLSessionWebSocketTask.CloseCode, Data?) -> Effect<
169-
Never, Never
170-
> = { _, _, _ in fatalError() },
171-
open: @escaping (AnyHashable, URL, [String]) -> Effect<Action, Never> = { _, _, _ in
172-
fatalError()
173-
},
174-
receive: @escaping (AnyHashable) -> Effect<Message, NSError> = { _ in fatalError() },
175-
send: @escaping (AnyHashable, URLSessionWebSocketTask.Message) -> Effect<NSError?, Never> = {
176-
_, _ in fatalError()
177-
},
178-
sendPing: @escaping (AnyHashable) -> Effect<NSError?, Never> = { _ in fatalError() }
179-
) -> Self {
180-
Self(
181-
cancel: cancel,
182-
open: open,
183-
receive: receive,
184-
send: send,
185-
sendPing: sendPing
186-
)
187-
}
171+
static let failing = Self(
172+
cancel: { _, _, _ in .failing("WebSocketClient.cancel") },
173+
open: { _, _, _ in .failing("WebSocketClient.open") },
174+
receive: { _ in .failing("WebSocketClient.receive") },
175+
send: { _, _ in .failing("WebSocketClient.send") },
176+
sendPing: { _ in .failing("WebSocketClient.sendPing") }
177+
)
188178
}

Examples/CaseStudies/SwiftUICaseStudiesTests/04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
1818
let scheduler = DispatchQueue.test
1919

2020
func testDownloadFlow() {
21+
var downloadClient = DownloadClient.failing
22+
downloadClient.download = { _, _ in self.downloadSubject.eraseToEffect() }
23+
2124
let store = TestStore(
2225
initialState: DownloadComponentState(
2326
id: 1,
@@ -26,9 +29,7 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
2629
),
2730
reducer: reducer,
2831
environment: DownloadComponentEnvironment(
29-
downloadClient: .mock(
30-
download: { _, _ in self.downloadSubject.eraseToEffect() }
31-
),
32+
downloadClient: downloadClient,
3233
mainQueue: self.scheduler.eraseToAnyScheduler()
3334
)
3435
)
@@ -52,6 +53,9 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
5253
}
5354

5455
func testDownloadThrottling() {
56+
var downloadClient = DownloadClient.failing
57+
downloadClient.download = { _, _ in self.downloadSubject.eraseToEffect() }
58+
5559
let store = TestStore(
5660
initialState: DownloadComponentState(
5761
id: 1,
@@ -60,9 +64,7 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
6064
),
6165
reducer: reducer,
6266
environment: DownloadComponentEnvironment(
63-
downloadClient: .mock(
64-
download: { _, _ in self.downloadSubject.eraseToEffect() }
65-
),
67+
downloadClient: downloadClient,
6668
mainQueue: self.scheduler.eraseToAnyScheduler()
6769
)
6870
)
@@ -91,6 +93,12 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
9193
}
9294

9395
func testCancelDownloadFlow() {
96+
var downloadClient = DownloadClient.failing
97+
downloadClient.cancel = { _ in
98+
.fireAndForget { self.downloadSubject.send(completion: .finished) }
99+
}
100+
downloadClient.download = { _, _ in self.downloadSubject.eraseToEffect() }
101+
94102
let store = TestStore(
95103
initialState: DownloadComponentState(
96104
id: 1,
@@ -99,10 +107,7 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
99107
),
100108
reducer: reducer,
101109
environment: DownloadComponentEnvironment(
102-
downloadClient: .mock(
103-
cancel: { _ in .fireAndForget { self.downloadSubject.send(completion: .finished) } },
104-
download: { _, _ in self.downloadSubject.eraseToEffect() }
105-
),
110+
downloadClient: downloadClient,
106111
mainQueue: self.scheduler.eraseToAnyScheduler()
107112
)
108113
)
@@ -128,6 +133,12 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
128133
}
129134

130135
func testDownloadFinishesWhileTryingToCancel() {
136+
var downloadClient = DownloadClient.failing
137+
downloadClient.cancel = { _ in
138+
.fireAndForget { self.downloadSubject.send(completion: .finished) }
139+
}
140+
downloadClient.download = { _, _ in self.downloadSubject.eraseToEffect() }
141+
131142
let store = TestStore(
132143
initialState: DownloadComponentState(
133144
id: 1,
@@ -136,10 +147,7 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
136147
),
137148
reducer: reducer,
138149
environment: DownloadComponentEnvironment(
139-
downloadClient: .mock(
140-
cancel: { _ in .fireAndForget { self.downloadSubject.send(completion: .finished) } },
141-
download: { _, _ in self.downloadSubject.eraseToEffect() }
142-
),
150+
downloadClient: downloadClient,
143151
mainQueue: self.scheduler.eraseToAnyScheduler()
144152
)
145153
)
@@ -166,6 +174,12 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
166174
}
167175

168176
func testDeleteDownloadFlow() {
177+
var downloadClient = DownloadClient.failing
178+
downloadClient.cancel = { _ in
179+
.fireAndForget { self.downloadSubject.send(completion: .finished) }
180+
}
181+
downloadClient.download = { _, _ in self.downloadSubject.eraseToEffect() }
182+
169183
let store = TestStore(
170184
initialState: DownloadComponentState(
171185
id: 1,
@@ -174,10 +188,7 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
174188
),
175189
reducer: reducer,
176190
environment: DownloadComponentEnvironment(
177-
downloadClient: .mock(
178-
cancel: { _ in .fireAndForget { self.downloadSubject.send(completion: .finished) } },
179-
download: { _, _ in self.downloadSubject.eraseToEffect() }
180-
),
191+
downloadClient: downloadClient,
181192
mainQueue: self.scheduler.eraseToAnyScheduler()
182193
)
183194
)
@@ -198,13 +209,8 @@ class ReusableComponentsDownloadComponentTests: XCTestCase {
198209
}
199210

200211
extension DownloadClient {
201-
static func mock(
202-
cancel: @escaping (AnyHashable) -> Effect<Never, Never> = { _ in fatalError() },
203-
download: @escaping (AnyHashable, URL) -> Effect<Action, Error> = { _, _ in fatalError() }
204-
) -> Self {
205-
Self(
206-
cancel: cancel,
207-
download: download
208-
)
209-
}
212+
static let failing = Self(
213+
cancel: { _ in .failing("DownloadClient.cancel") },
214+
download: { _, _ in .failing("DownloadClient.download") }
215+
)
210216
}

Examples/Search/Search/WeatherClient.swift

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,10 @@ extension WeatherClient {
6565
// MARK: - Mock API implementations
6666

6767
extension WeatherClient {
68-
static func mock(
69-
searchLocation: @escaping (String) -> Effect<[Location], Failure> = { _ in
70-
fatalError("Unmocked")
71-
},
72-
weather: @escaping (Int) -> Effect<LocationWeather, Failure> = { _ in fatalError("Unmocked") }
73-
) -> Self {
74-
Self(
75-
searchLocation: searchLocation,
76-
weather: weather
77-
)
78-
}
68+
static let failing = Self(
69+
searchLocation: { _ in .failing("WeatherClient.searchLocation") },
70+
weather: { _ in .failing("WeatherClient.weather") }
71+
)
7972
}
8073

8174
// MARK: - Private helpers

0 commit comments

Comments
 (0)