|
167 | 167 | /// not expect it would cause a test failure.
|
168 | 168 | ///
|
169 | 169 | public final class TestStore<State, LocalState, Action, LocalAction, Environment> {
|
| 170 | + /// The current environment. |
| 171 | + /// |
| 172 | + /// The environment can be modified throughout a test store's lifecycle in order to influence |
| 173 | + /// how it produces effects. |
170 | 174 | public var environment: Environment
|
171 | 175 |
|
| 176 | + /// The current state. |
| 177 | + /// |
| 178 | + /// When read from a trailing closure assertion in ``send`` or ``receive``, it will equal the |
| 179 | + /// `inout` state passed to the closure. |
| 180 | + public private(set) var state: State |
| 181 | + |
172 | 182 | private let file: StaticString
|
173 | 183 | private let fromLocalAction: (LocalAction) -> Action
|
174 | 184 | private var line: UInt
|
175 | 185 | private var inFlightEffects: Set<LongLivingEffect> = []
|
176 | 186 | var receivedActions: [(action: Action, state: State)] = []
|
177 | 187 | private let reducer: Reducer<State, Action, Environment>
|
178 |
| - public private(set) var state: State |
179 | 188 | private var store: Store<State, TestAction>!
|
180 | 189 | private let toLocalState: (State) -> LocalState
|
181 | 190 |
|
|
332 | 341 | }
|
333 | 342 |
|
334 | 343 | extension TestStore where LocalState: Equatable {
|
| 344 | + /// Sends an action to the store and asserts when state changes. |
| 345 | + /// |
| 346 | + /// - Parameters: |
| 347 | + /// - action: An action. |
| 348 | + /// - updateExpectingResult: A closure that asserts state changed by sending the action to the |
| 349 | + /// store. The mutable state sent to this closure must be modified to match the state of the |
| 350 | + /// store after processing the given action. Do not provide a closure if no change is |
| 351 | + /// expected. |
335 | 352 | public func send(
|
336 | 353 | _ action: LocalAction,
|
| 354 | + _ updateExpectingResult: ((inout LocalState) throws -> Void)? = nil, |
337 | 355 | file: StaticString = #file,
|
338 |
| - line: UInt = #line, |
339 |
| - _ update: ((inout LocalState) throws -> Void)? = nil |
| 356 | + line: UInt = #line |
340 | 357 | ) {
|
341 | 358 | if !self.receivedActions.isEmpty {
|
342 | 359 | var actions = ""
|
|
361 | 378 |
|
362 | 379 | try self.expectedStateShouldChange(
|
363 | 380 | expected: &expectedState,
|
364 |
| - update: update, |
| 381 | + modify: updateExpectingResult, |
365 | 382 | file: file,
|
366 | 383 | line: line
|
367 | 384 | )
|
|
381 | 398 |
|
382 | 399 | private func expectedStateShouldChange(
|
383 | 400 | expected: inout LocalState,
|
384 |
| - update: ((inout LocalState) throws -> Void)? = nil, |
| 401 | + modify: ((inout LocalState) throws -> Void)? = nil, |
385 | 402 | file: StaticString,
|
386 | 403 | line: UInt
|
387 | 404 | ) throws {
|
388 |
| - guard let update = update else { return } |
| 405 | + guard let modify = modify else { return } |
389 | 406 | let current = expected
|
390 |
| - try update(&expected) |
| 407 | + try modify(&expected) |
391 | 408 | if expected == current {
|
392 | 409 | XCTFail(
|
393 | 410 | """
|
394 |
| - Expected to modify the expected state, but no change occurred. |
| 411 | + Expected state to change, but no change occurred. |
395 | 412 |
|
396 |
| - Ensure that the state was modified or remove the closure to assert no change. |
| 413 | + The trailing closure made no observable modifications to state. If no change to state is \ |
| 414 | + expected, omit the trailing closure. |
397 | 415 | """,
|
398 | 416 | file: file, line: line
|
399 | 417 | )
|
|
432 | 450 | }
|
433 | 451 |
|
434 | 452 | extension TestStore where LocalState: Equatable, Action: Equatable {
|
| 453 | + /// Asserts an action was received from an effect and asserts when state changes. |
| 454 | + /// |
| 455 | + /// - Parameters: |
| 456 | + /// - expectedAction: An action expected from an effect. |
| 457 | + /// - updateExpectingResult: A closure that asserts state changed by sending the action to the |
| 458 | + /// store. The mutable state sent to this closure must be modified to match the state of the |
| 459 | + /// store after processing the given action. Do not provide a closure if no change is |
| 460 | + /// expected. |
435 | 461 | public func receive(
|
436 | 462 | _ expectedAction: Action,
|
| 463 | + _ updateExpectingResult: ((inout LocalState) throws -> Void)? = nil, |
437 | 464 | file: StaticString = #file,
|
438 |
| - line: UInt = #line, |
439 |
| - _ update: ((inout LocalState) throws -> Void)? = nil |
| 465 | + line: UInt = #line |
440 | 466 | ) {
|
441 | 467 | guard !self.receivedActions.isEmpty else {
|
442 | 468 | XCTFail(
|
|
473 | 499 | do {
|
474 | 500 | try self.expectedStateShouldChange(
|
475 | 501 | expected: &expectedState,
|
476 |
| - update: update, |
| 502 | + modify: updateExpectingResult, |
477 | 503 | file: file,
|
478 | 504 | line: line
|
479 | 505 | )
|
|
0 commit comments