Add basic AppLocator and AXWindowResolver coverage

This commit is contained in:
Peter Steinberger 2025-11-19 04:16:38 +01:00
parent 39e300e216
commit cbfcf3d263
3 changed files with 63 additions and 0 deletions

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -0,0 +1,11 @@
import Foundation
enum TestError: Error {
case invalidInput
}
extension TimeInterval {
static func milliseconds(_ value: Int) -> TimeInterval {
TimeInterval(Double(value) / 1000.0)
}
}