Is it possible to assert Snapshot in between TestStore .send and .receive asserts?

Hi,

Is there a way to do SnapshotTesting by using the .do function when asserting on the TestStore in between .send and .receive ?

    testStore.assert([
      .do { assertSnapshot(matching: view, as: .windowedImage, named: "initialState") },
      .send(.mapContainer(.mapView(.locationManager(.didUpdateLocations([parisLocation]))))) {
        $0.mapContainer.mapView.userLocationCoordinate = parisLocation
      },
      .receive(.mapContainer(.mapView(.centerOnUserReceived))) {
        $0.mapContainer.mapView.mapCenter = parisLocation.coordinate
      },
      .do { assertSnapshot(matching: view, as: .windowedImage, named: "afterDidUpdateLocations(\(parisLocation)") },
      .send(.mapContainer(.floatingButtonView(.searchAgainTapped))),
      .receive(.refreshItemsFromMapCoordsReceived),
      .receive(.overlayContainer(.overlayLocal(.updateLevelReceived(.minimum)))),
      .receive(.mapContainer(.floatingButtonView(.hideSearchAgainReceived(true)))),
      .receive(.overlayContainer(.overlayLocal(.refreshPositionReceived))) {
        $0.overlayContainer.overlayLocal.position.height = -60
      },
      .do { assertSnapshot(matching: view, as: .windowedImage, named: "afterSearchAgainTapped") },
      .send(.mapContainer(.mapView(.userTappedPOI(selectedPro)))) {
        $0.selectedPro = selectedPro
        $0.content = .fd
      },
      .receive(.overlayContainer(.overlayLocal(.updateLevelReceived(.half)))) {
        $0.overlayContainer.overlayLocal.level = .half
      },
      .receive(.mapContainer(.mapView(.centerOnSelectedProReceived))) {
        $0.mapContainer.mapView.mapCenter = selectedPro?.coordinates
      },
      .receive(.overlayContainer(.overlayLocal(.refreshPositionReceived))) {
        $0.overlayContainer.overlayLocal.position.height = 0
      },
      .do { assertSnapshot(matching: view, as: .windowedImage, named: "afterUserTappedPOI\(selectedPro)") },
    ])

For this to work we need TestStore to provide a way to return a proper Store and feed TestStore to the View.

1 Like

I would love to see something like this baked right in. But for now, how about an extension like this?

import SwiftUI
import ComposableArchitecture
import SnapshotTesting

extension TestStore.Step {
    static func receive<V: View>(
        _ action: Action,
        view: @escaping (Store<LocalState, LocalAction>) -> V,
        _ update: @escaping(inout LocalState) -> Void
    ) -> Self {
        .receive(action, { state in
            let store = Store<LocalState, LocalAction>.init(initialState: state, reducer: .empty, environment: ())
            let view = view(store)
            assertSnapshot(matching: view, as: .image(layout: .device(config: .iPhone8Plus)))
            update(&state)
            
        })
    }
    
    static func send<V: View>(
        _ action: LocalAction,
        view: @escaping (Store<LocalState, LocalAction>) -> V,
        _ update: @escaping(inout LocalState) -> Void
    ) -> Self {
        .send(action, { state in
            let store = Store<LocalState, LocalAction>.init(initialState: state, reducer: .empty, environment: ())
            let view = view(store)
            assertSnapshot(matching: view, as: .image(layout: .device(config: .iPhone8Plus)))
            update(&state)
            
        })
    }
}

I would love to see if we can improve ergonomics on this function even more. An obvious start would be to parameterize the Snapshotting strategy.

Terms of Service

Privacy Policy

Cookie Policy