Hey Luke, this solution works great. I think I've made a few improvements:
Passing in parameters for #line, #function, and #file improves the test output in Xcode and helps organize the snapshots
Calling update(&state) first ensures that the state change is applied before the snapshot is taken.
Calling assertSnapshot in a DispatchQueue.main.async block seems to speed up the tests by an order of magnitude (100-300ms down to 10-20ms). I think this is because instead of blocking at each step, the snapshots are deferred until the next iteration of the run loop and executed as a batch.
Hi @remlostime! Is there anything you're specifically asking for an update of? There seem to be some suggested solutions to the problem earlier in the thread, though they may need to be updated for the TestStore's latest API.
@stephencelis Thanks for the reply. I double checked the comments, and find the solution is a little bit out of date. I refactored it to fit the latest TCA and fix some bugs.
extension TestStore where Action: Equatable, LocalState: Equatable {
func receive<V: View>(
_ action: Action,
view: @escaping (Store<LocalState, LocalAction>) -> V,
update: @escaping(inout LocalState) -> Void
) {
receive(action, { state in
update(&state)
let store = Store<LocalState, LocalAction>.init(initialState: state, reducer: .empty, environment: ())
let view = view(store)
assertSnapshot(matching: view, as: .image(layout: .device(config: .iPhone8Plus)))
})
}
func send<V: View>(
_ action: LocalAction,
view: @escaping (Store<LocalState, LocalAction>) -> V,
update: @escaping(inout LocalState) -> Void
) {
send(action, { state in
update(&state)
let store = Store<LocalState, LocalAction>.init(initialState: state, reducer: .empty, environment: ())
let view = view(store)
assertSnapshot(matching: view, as: .image(layout: .device(config: .iPhone8Plus)))
})
}
}