'Menu Bar Popover is missing from application's elements tree on macOS

I'm currently trying to write simple UI Tests for an App that comes with a popover in the macOS menu bar. One of the tests is supposed to open the menu bar popover and interact with its content. The problem is that the content seems to be completely absence from the application's element tree.

I'm creating the pop-up like so:

let view = MenuBarPopUp()

self.popover.animates = false
self.popover.behavior = .transient
self.popover.contentViewController = NSHostingController(rootView: view)

…and show/hide it on menu bar, click like this:

if let button = statusItem.button {
  button.image = NSImage(named: NSImage.Name("MenuBarButtonImage"))
  button.action = #selector(togglePopover(_:))
}

@objc func togglePopover(_ sender: AnyObject?) {
  if self.popover.isShown {
    popover.performClose(sender)
  } else {
    openToolbar()
  }
}

func openToolbar() {
  guard let button = menuBarItem.menuBarItem.button else { return }
  self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
  NSApp.activate(ignoringOtherApps: true)
}

When I dump the element tree, the popover is not present:

[…]
MenuBar, 0x7fef747219d0, {{1089.0, 1.0}, {34.0, 22.0}}
      StatusItem, 0x7fef74721b00, {{1089.0, 1.0}, {34.0, 22.0}}
[…]

Everything works when I compile the app and click around, I just can't make it work when it comes to automated UI testing. Any ideas?



Solution 1:[1]

Okay, after spending a lot of time with it, this solved my problem.

First, I had to add the Popover to the app's accessibility children like so:

var accessibilityChildren = NSApp.accessibilityChildren() ?? [Any]()
accessibilityChildren.append(popover.contentViewController?.view as Any)
NSApp.setAccessibilityChildren(accessibilityChildren)

However, this didn't seem to solve my problem at first. I'm using an App Delegate in a SwiftUI application. After tinkering with it for quite some time, I figured out that the commands I've added in my App.swift didn't go too well with my changes to the accessibility children in the App Delegate. After removing the commands from the Window Group, everything worked as expected.

@main
struct MyApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
          ContentView()
        }
//      .commands {
//            CommandGroup(replacing: CommandGroupPlacement.appSettings) {
//                Button("Preferences...") { showPreferences() }
//            }
//      }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Schurigeln