Testing helpers and extensions for SwiftRex and Combine
let (dependencies, scheduler) = self.setup
assert(
initialValue: AppState.initial,
reducer: Reducer.myReducer.lift(action: \.actionReducerScope, state: \.stateReducerScope),
middleware: MyHandler.middleware.inject(dependencies),
steps: {
Send(action: .certainAction(.verySpecific))
SideEffectResult {
scheduler.advance(by: .seconds(5))
}
Send(action: .anotherAction(.withSomeValues(list: [], date: dependencies.now())))
// if you receive an action and don't add this block, the test will fail to remind you
Receive { action -> Bool in
// validates that the received action is what you would expect
// if this function returns false, the test will fail to show you that you've got an unexpected action
if case let .my(.expectedAction(list)) = action {
return list.isEmpty
} else {
return false
}
}
SideEffectResult {
scheduler.advance(by: .seconds(5))
}
Send(action: .anotherAction(.stopSomething)).expectStateToHaveChanged { state in
// if during Send or Receive action, your state is expected to mutate, you must indicate which change is expected to happen here:
state.somePropertyShouldHaveChangedTo = true
// any unexpected state mutation will fail the test, as well as any expected state mutation that doesn't occur, will also fail the test
}
SideEffectResult {
scheduler.advance(by: .seconds(5))
}
// if you receive an action and don't add this block, the test will fail to remind you
Receive { action -> Bool in
// validates that the received action is what you would expect
// if this function returns false, the test will fail to show you that you've got an unexpected action
if case let .my(.expectedAction(list)) = action {
return list.isEmpty
} else {
return false
}
}.expectStateToHaveChanged { state in
// if during Send or Receive action, your state is expected to mutate, you must indicate which change is expected to happen here:
state.somePropertyShouldHaveChangedTo = true
// any unexpected state mutation will fail the test, as well as any expected state mutation that doesn't occur, will also fail the test
}
}
)
Validate Output of Publishers
let operation = assert(
publisher: myPublisher,
eventuallyReceives: "๐", "๐", "๐",
andCompletes: false
)
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
operation.wait(0.0001)
Validate Output and Successful Completion of Publishers
let operation = assert(
publisher: myPublisher,
eventuallyReceives: "๐", "๐", "๐",
andCompletesWith: .isSuccess
)
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherCompletes()
operation.wait(0.0001)
Validate Output and some Failure of Publishers
let operation = assert(
publisher: myPublisher,
eventuallyReceives: "๐", "๐", "๐",
andCompletesWith: .isFailure
)
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherFails(SomeError())
operation.wait(0.0001)
Validate Output and specific Failure of Publishers
let operation = assert(
publisher: myPublisher,
eventuallyReceives: "๐", "๐", "๐",
andCompletesWith: .failedWithError { error in error == SomeError("123") }
)
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherReceives("๐")
somethingHappensAndPublisherFails(SomeError("123"))
operation.wait(0.0001)
Validate No Output but completion of Publishers
let operation = assert(
publisher: myPublisher,
completesWithoutValues: .isSuccess
)
somethingHappensAndPublisherCompletes()
operation.wait(0.0001)