diff --git a/Sources/ViewInspector/ViewSearch.swift b/Sources/ViewInspector/ViewSearch.swift index 38109f83..ad3127de 100644 --- a/Sources/ViewInspector/ViewSearch.swift +++ b/Sources/ViewInspector/ViewSearch.swift @@ -493,8 +493,10 @@ private extension UnwrappedView { func recursionAbsenceCheck() -> Bool { guard content.isCustomView else { return true } let typeRef = type(of: content.view) + var isDirectParent = true return (try? findParent(condition: { parent in - return typeRef == type(of: parent.content.view) && parent.parentView != nil + defer { isDirectParent = false } + return typeRef == type(of: parent.content.view) && !isDirectParent }, skipFound: 0)) == nil } } diff --git a/Tests/ViewInspectorTests/SwiftUI/NavigationLinkTests.swift b/Tests/ViewInspectorTests/SwiftUI/NavigationLinkTests.swift index 6b6ee353..d80959f7 100644 --- a/Tests/ViewInspectorTests/SwiftUI/NavigationLinkTests.swift +++ b/Tests/ViewInspectorTests/SwiftUI/NavigationLinkTests.swift @@ -72,10 +72,14 @@ final class NavigationLinkTests: XCTestCase { func testSearchWithBindings() throws { let selection = Binding(wrappedValue: nil) let sut = try TestViewBinding(selection: selection).inspect() + XCTAssertNoThrow(try sut.find(text: "GoTo 1")) + XCTAssertNoThrow(try sut.find(text: "GoTo 2")) let notFoundError = "Search did not find a match" XCTAssertThrows(try sut.find(text: "Screen 1"), notFoundError) XCTAssertThrows(try sut.find(text: "Screen 2"), notFoundError) try sut.navigationView().navigationLink(0).activate() + XCTAssertNoThrow(try sut.find(text: "GoTo 1")) + XCTAssertNoThrow(try sut.find(text: "GoTo 2")) XCTAssertNoThrow(try sut.find(text: "Screen 1")) XCTAssertThrows(try sut.find(text: "Screen 2"), notFoundError) try sut.navigationView().navigationLink(1).activate() @@ -196,12 +200,17 @@ final class NavigationLinkTests: XCTestCase { "Search did not find a match") XCTAssertThrows(try sut.find(ViewType.Text.self, traversal: .depthFirst, where: { _ in false }), "Search did not find a match") - XCTAssertEqual( - try sut.find(text: "B to A").pathToRoot, - """ - view(TestRecursiveLinksView.self).navigationView().view(ViewAtoB.self)\ - .navigationLink().view(ViewBtoA.self).navigationLink().labelView().text() - """) + XCTAssertNoThrow(try sut.find(text: "B to A")) + } + + func testRecursiveGenericReferenceView() throws { + let view = TestRecursiveGenericView + .init(view: TestRecursiveGenericView + .init(view: TestRecursiveGenericView + .init(view: Text("test")))) + let container = "view(TestRecursiveGenericView.self)." + XCTAssertEqual(try view.inspect().find(text: "test").pathToRoot, + container + container + container + "text()") } } @@ -259,15 +268,22 @@ extension TestViewState { @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 7.0, *) private struct TestRecursiveLinksView: View { + struct NavLabel: View { + let text: String + var body: some View { + Text(text) + } + } + struct ViewAtoB: View { var body: some View { - NavigationLink(destination: ViewBtoA()) { Text("A to B") } + NavigationLink(destination: ViewBtoA()) { NavLabel(text: "A to B") } } } struct ViewBtoA: View { var body: some View { - NavigationLink(destination: ViewAtoB()) { Text("B to A") } + NavigationLink(destination: ViewAtoB()) { NavLabel(text: "B to A") } } } @@ -275,3 +291,11 @@ private struct TestRecursiveLinksView: View { NavigationView { ViewAtoB() } } } + +@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 7.0, *) +private struct TestRecursiveGenericView: View { + let view: T + var body: some View { + view + } +} diff --git a/ViewInspector.podspec b/ViewInspector.podspec index 5201c5b8..97fd7e41 100644 --- a/ViewInspector.podspec +++ b/ViewInspector.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = "ViewInspector" - s.version = "0.9.4" + s.version = "0.9.5" s.summary = "ViewInspector is a library for unit testing SwiftUI views." s.homepage = "https://github.com/nalexn/ViewInspector" s.license = { :type => "MIT", :file => "LICENSE" }