GroupBox breaks ability of XCTest to find popovers?

I'm using Xcode 14.3.1 on macOS 13.5, and I've managed to reproduce my issue in a trivial application. All the project settings are left at the defaults for a macOS project.

It looks like using a GroupBox breaks the ability of XCTest to find popovers connected to buttons (I suspect any UI element) inside the GroupBox.

The debug console output from the code below lists 15 descendants from my window with the outside-the-GroupBox popover open, and one of them is definitely a popover. With the inside-the-GroupBox popover open, my window only shows nine descendants, and no popover (the rest of the difference is the popover's contents). It's simple enough I don't see what I could be doing wrong:

import SwiftUI

@main
struct GroupBox_Popover_DemoApp: App {
	var body: some Scene {
		WindowGroup {
			ContentView()
		}
	}
}

struct ContentView: View {
	@State var outsidePopoverPresented: Bool = false
	@State var insidePopoverPresented: Bool = false
	var body: some View {
		VStack {
			Button("Outside GroupBox") {
				outsidePopoverPresented = true
			}
			.popover(isPresented: $outsidePopoverPresented,
					 attachmentAnchor: .point(.leading),
					 arrowEdge: .leading) {
				Popover(selected: .constant("Item A"), isPresented: $outsidePopoverPresented)
			}
			.padding()
			GroupBox {
				Button("Inside GroupBox") {
					insidePopoverPresented = true
				}
				.popover(isPresented: $insidePopoverPresented,
						 attachmentAnchor: .point(.leading),
						 arrowEdge: .leading) {
					Popover(selected: .constant("Item B"), isPresented: $insidePopoverPresented)
				}
				.padding()
			}
		}
		.padding()
	}
}

struct Popover: View {
	@Binding var selected: String
	@Binding var isPresented: Bool
	var body: some View {
		VStack(alignment: .leading) {
			Picker("", selection: $selected) {
				Text("Item A").tag("Item A")
				Text("Item B").tag("Item B")
				Text("Item C").tag("Item C")
			}
			.pickerStyle(.radioGroup)
			HStack {
				Spacer()
				Button("Cancel") {
					isPresented = false
				}
			}
		}
		.padding()
		.frame(width: 200)
	}
}

Then in my UI tests:

import XCTest

final class GroupBox_Popover_DemoUITests: XCTestCase {
	let mainWindow = XCUIApplication().windows
	
	override func setUpWithError() throws {
		continueAfterFailure = false
		XCUIApplication().launch()
	}
	
	func testPopovers() {
		let myDescendants = mainWindow.descendants(matching: .any)
		mainWindow.buttons["Outside GroupBox"].click()
		print("Window descendants with outside popover open:")
		print(myDescendants.debugDescription)
		mainWindow.popovers.buttons["Cancel"].click()
		mainWindow.buttons["Inside GroupBox"].click()
		print("Window descendants with inside popover open:")
		print(myDescendants.debugDescription)
		mainWindow.popovers.buttons["Cancel"].click()
		XCTAssert(true, "Test was able to hit cancel on both popovers.")
	}
}

Any ideas? Have I missed unchecking some "Ignore anything in a GroupBox" checkbox somewhere?

  • Forgot to mention that I haven't seen the problem outside of XCTest. VoiceOver properly moves the cursor into either popover and can hit the Cancel button.

Add a Comment

Replies

Still broken with Xcode 15.0 (15A240d) on macOS 14.0 (23A344).