Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.find using ViewType and accessibilityIdentifier no longer works #336

Closed
AlexanderMarchant opened this issue Sep 25, 2024 · 2 comments
Closed

Comments

@AlexanderMarchant
Copy link

AlexanderMarchant commented Sep 25, 2024

I have the following overloads for convince where I want to find a view by its type and accessibilityIdentifier (since I may have multiple views of the same type in one view) which both worked up until Xcode 16 / ViewInspector 10.0.0.

extension InspectableView
{
    func find<V>(_ inspectable: V.Type,
                 accessibilityIdentifier: String
    )
    throws -> InspectableView<ViewType.View<V>>
    {
        return try find(
            ViewType.View<V>.self,
            where: { view in
                try view.accessibilityIdentifier() == accessibilityIdentifier
            }
        )
    }
    
    func findAll<V>(_ inspectable: V.Type,
                 accessibilityIdentifier: String
    ) -> [InspectableView<ViewType.View<V>>]
    {
        return findAll(
            ViewType.View<V>.self,
            where: { view in
                try view.accessibilityIdentifier() == accessibilityIdentifier
            }
        )
    }
}
import XCTest
import ViewInspector
import SwiftUI

struct TestView: View {
    var body: some View {
        VStack(spacing: 20) {
            VStack(spacing: 5) {
                Text("This is my header")
                    .font(.title)
                Text("Smaller text")
                    .font(.caption2)
            }
            .accessibilityIdentifier("headerVStack")
            Text("Body text")
                .font(.body)
        }
        .padding(5)
        .accessibilityIdentifier("containerVStack")
    }
}

class TestViewTests: XCTestCase {
    
    func testVStack() throws
    {
        // Arrange/Act
        let sut = TestView()
        
        // Assert
        let containerVStack = try sut.inspect().find(ViewType.VStack.self, accessibilityIdentifier: "containerVStack")
        XCTAssertEqual(5, try containerVStack.padding().top)
    }
}

Screenshot 2024-09-25 at 21 41 07

Using .find(ViewType.VStack.self) works, but I have no idea if I have the correct view that I actually want.

Using .find(viewWithAccessibilityIdentifier: "containerVStack") works, but I cannot use .actualView() to get any further information on it (for the cases I am using it for custom view types and want to inspect its properties).

Is the where clause broken or has something changed that means it no longer works as expected?

@AlexanderMarchant AlexanderMarchant changed the title Find using ViewType and accessibilityIdentifier no longer works .find using ViewType and accessibilityIdentifier no longer works Sep 25, 2024
@nalexn
Copy link
Owner

nalexn commented Sep 26, 2024

Is the where clause broken or has something changed that means it no longer works as expected?

Xcode 16 started to mess up with the view hierarchy, filling it with AnyView at arbitrary places. It broke tests for many people.

Using .find(viewWithAccessibilityIdentifier: "containerVStack") works, but I cannot use .actualView() to get any further information on it (for the cases I am using it for custom view types and want to inspect its properties).

Locating the view by a11yId should give you the most precise location in the view hierarchy, I'd suggest you use that as a base call, and then either do .vStack(), if the modifier is applied to VStack, or .view(MyCustomView.self) if it's a custom view. If it's exactly the place where Xcode inserts an implicit AnyView, you'll see that in the thrown error, where it'd say "Found AnyView instead of VStack". Try this out and lmk.

Using .find(ViewType.VStack.self) works, but I have no idea if I have the correct view that I actually want.

At least for troubleshooting purposes, you can call .pathToRoot to see if that's the expected VStack. Not intended to be used in the final revision of the test

@AlexanderMarchant
Copy link
Author

@nalexn thank you for the information, I did get it working with what you mentioned.

My custom find function now looks like this (ugly, but it covers the basis of various options).

func find<V: SwiftUI.View>(_ inspectable: V.Type, accessibilityIdentifier: String) throws -> InspectableView<ViewType.View<V>>
    {
        do {
            return try find(viewWithAccessibilityIdentifier: accessibilityIdentifier).view(V.self)
        } catch {
            do {
                return try find(viewWithAccessibilityIdentifier: accessibilityIdentifier).implicitAnyView().view(V.self)
            } catch {
                do {
                    return try find(viewWithAccessibilityIdentifier: accessibilityIdentifier).find(ViewType.View<V>.self)
                } catch {
                    return try find(viewWithAccessibilityIdentifier: accessibilityIdentifier).implicitAnyView().find(ViewType.View<V>.self)
                }
            }
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants