How to inject DismissAction instance for writing tests

59 Views Asked by At

ContentView.swift

struct ContentView: View {
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        NavigationView {
            ZStack {
                ChildView(parentDismiss: dismiss)
                Button {
                    dismiss()
                } label: {
                    Text("close")
                }
            }
        }
    }
}

ChildView.swift

struct ChildView: View {
    let parentDismiss: DismissAction

    var body: some View {
        Button {
            parentDismiss()
        } label: {
            Text("Close")
        }
    }
}

To write snapshot tests for ChildView, how do I go about creating a DismissAction instance?

class ChildViewSnapshotTests: XCTestCase {
    func testView() {
        let dismissAction = DismissAction()
        let view = ChildView(parentDimiss: dismissAction)
        assertSnapshot(view: view)
    }    
}

I was hoping to be able to do something like above. But DismissAction cant be initialised this way

1

There are 1 best solutions below

0
Sweeper On

From the context, it seems like you don't need a DismissAction that does a particular thing. You just want any instance of DismissAction so that you can create an instance of ChildView. In that case, you can get a "default" DismissAction by using

ChildView(parentDimiss: EnvironmentValues().dismiss)

Alternatively, allow ChildView to take an optional DismissAction. If it is nil, do nothing:

let parentDismiss: DismissAction?

var body: some View {
    Button {
        parentDismiss?()
    } label: {
        Text("Close")
    }
}

If you do need to pass a DismissAction that does a particular thing, you would need to pass a () -> Void to ChildView instead.

struct ContentView: View {
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        NavigationView {
            ZStack {
                ChildView(parentDismiss: {
                    dismiss()
                })
                Button {
                    dismiss()
                } label: {
                    Text("close")
                }
            }
        }
    }
}

struct ChildView: View {
    let parentDismiss: () -> Void
    
    var body: some View {
        Button {
            parentDismiss()
        } label: {
            Text("Close")
        }
    }
}