diff --git a/Tests/AXorcistTests/AXWindowResolverTests.swift b/Tests/AXorcistTests/AXWindowResolverTests.swift new file mode 100644 index 0000000..e41cf40 --- /dev/null +++ b/Tests/AXorcistTests/AXWindowResolverTests.swift @@ -0,0 +1,22 @@ +import AppKit +import CoreGraphics +@testable import AXorcist +import Testing + +@Suite("AXWindowResolver") +struct AXWindowResolverTests { + private let resolver = AXWindowResolver() + + @Test("windowID returns nil for non-window element") + @MainActor + func windowIdNilForNonWindow() async { + let systemWide = AXUIElementCreateSystemWide() + let element = Element(systemWide) + #expect(self.resolver.windowID(from: element) == nil) + } + + @Test("windowExists false for random ID") + func windowExistsFalse() { + #expect(self.resolver.windowExists(windowID: 999_999_999) == false) + } +} diff --git a/Tests/AXorcistTests/AppLocatorTests.swift b/Tests/AXorcistTests/AppLocatorTests.swift new file mode 100644 index 0000000..1376da2 --- /dev/null +++ b/Tests/AXorcistTests/AppLocatorTests.swift @@ -0,0 +1,30 @@ +import AppKit +import CoreGraphics +@testable import AXorcist +import Testing + +@Suite("AppLocator") +struct AppLocatorTests { + @Test("returns frontmost when point is nil and front app has window under mouse") + @MainActor + func frontmostPreferred() async throws { + // Skip on headless CI where NSEvent.mouseLocation is (0,0) and no frontmost app. + guard let front = NSWorkspace.shared.frontmostApplication else { return } + + let app = AppLocator.app(at: nil) + // If we have any frontmost app, AppLocator should return something (frontmost fallback). + #expect(app != nil) + // Best-effort check: if the frontmost app is the only candidate, expect it. + #expect(app?.processIdentifier == front.processIdentifier) + } + + @Test("falls back to frontmost when no window matches point") + @MainActor + func fallbackToFrontmost() async throws { + guard let front = NSWorkspace.shared.frontmostApplication else { return } + // Pick an off-screen point unlikely to hit a window. + let offscreen = CGPoint(x: -10_000, y: -10_000) + let app = AppLocator.app(at: offscreen) + #expect(app?.processIdentifier == front.processIdentifier) + } +} diff --git a/Tests/AXorcistTests/Support/CommonTestHelpers.swift b/Tests/AXorcistTests/Support/CommonTestHelpers.swift new file mode 100644 index 0000000..676a060 --- /dev/null +++ b/Tests/AXorcistTests/Support/CommonTestHelpers.swift @@ -0,0 +1,11 @@ +import Foundation + +enum TestError: Error { + case invalidInput +} + +extension TimeInterval { + static func milliseconds(_ value: Int) -> TimeInterval { + TimeInterval(Double(value) / 1000.0) + } +}