import AppKit import ConjureKit import Testing @testable import Conjure @Test @MainActor func activationAlwaysTargetsRequestedViewAndClearsPreviousTool() throws { _ = NSApplication.shared let suite = "ConjureDestination.\(UUID().uuidString)" let defaults = UserDefaults(suiteName: suite)! defer { defaults.removePersistentDomain(forName: suite) } let launcher = LauncherWindowController(history: LaunchHistory(defaults: defaults, now: { Date(timeIntervalSinceReferenceDate: 12_000) })) let window = try #require(launcher.window) defer { window.orderOut(nil) } func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.flatMap(descendants) } let content = try #require(window.contentView) let search = try #require(descendants(content).compactMap { $0 as? NSSearchField }.first) launcher.present(command: .emoji) #expect(descendants(content).contains { $0 is NSCollectionView }) search.stringValue = "happy" launcher.controlTextDidChange(Notification(name: NSControl.textDidChangeNotification, object: search)) window.orderOut(nil) launcher.toggle() #expect(!descendants(content).contains { $0 is NSCollectionView }) #expect(search.stringValue.isEmpty) #expect(search.accessibilityLabel() == "Search applications, calculate, or convert units and currencies") launcher.toggle(command: .translate) #expect(search.accessibilityLabel() == "English text to translate into Japanese") launcher.toggle(command: .emoji) #expect(search.accessibilityLabel() == "Search emoji") #expect(search.stringValue.isEmpty) launcher.present() #expect(!descendants(content).contains { $0 is NSCollectionView }) #expect(search.accessibilityLabel() == "Search applications, calculate, or convert units and currencies") } @Test(arguments: Application.Command.allCases, [true, false]) @MainActor func commandsAreFullyVisibleImmediately(_ command: Application.Command, _ fromShortcut: Bool) throws { _ = NSApplication.shared let suite = "ConjurePresentation.\(UUID().uuidString)" let defaults = UserDefaults(suiteName: suite)! defer { defaults.removePersistentDomain(forName: suite) } let launcher = LauncherWindowController( history: LaunchHistory(defaults: defaults, now: { Date(timeIntervalSinceReferenceDate: 12_000) }), defaults: defaults) let window = try #require(launcher.window) defer { window.orderOut(nil) } let content = try #require(window.contentView) func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.flatMap(descendants) } if fromShortcut { launcher.toggle(command: command) } else { launcher.present() let search = try #require(descendants(content).compactMap { $0 as? NSSearchField }.first) search.stringValue = command.rawValue launcher.controlTextDidChange(Notification(name: NSControl.textDidChangeNotification, object: search)) _ = launcher.control(search, textView: NSTextView(), doCommandBy: #selector(NSResponder.insertNewline(_:))) } let tool = try #require(content.subviews.first { view in descendants(view).contains { switch command { case .emoji: $0 is NSCollectionView case .translate: $0.accessibilityLabel() == "Japanese translation" } } }) #expect(window.isVisible) #expect(!tool.isHidden) #expect(tool.alphaValue == 1) }