PlatformCoverageTests.swift

4.1 KB · raw

1import AppKit2import Testing34@testable import Haven56@MainActor7private final class PopoverStub: NSPopover {8  var stubShown = false9  var showCount = 010  var closeCount = 011  override var isShown: Bool { stubShown }12  override func show(13    relativeTo positioningRect: NSRect, of positioningView: NSView,14    preferredEdge: NSRectEdge15  ) {16    stubShown = true17    showCount += 118  }19  override func performClose(_ sender: Any?) {20    stubShown = false21    closeCount += 122  }23}2425@MainActor26private final class OpenPanelStub: NSOpenPanel {27  var completion: ((NSApplication.ModalResponse) -> Void)?2829  override func begin(30    completionHandler handler: @escaping (NSApplication.ModalResponse) -> Void31  ) {32    completion = handler33  }34}3536@Suite("AppKit adapters", .serialized)37@MainActor38struct PlatformCoverageTests {39  @Test("Application delegate creates the status item and menu controller")40  func appDelegateLaunch() {41    let delegate = AppDelegate()4243    delegate.applicationDidFinishLaunching(44      Notification(name: NSApplication.didFinishLaunchingNotification)45    )4647    #expect(delegate.statusItem != nil)48    #expect(delegate.menuController != nil)49    #expect(delegate.statusItem.button?.image != nil)50  }5152  @Test("Menu controller exercises popover and modal lifecycle")53  func menuControllerLifecycle() {54    let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)55    let popover = PopoverStub()56    let controller = MenuController(statusItem: statusItem, popover: popover)5758    #expect(MenuController.shared === controller)59    controller.beginModalPresentation()60    #expect(controller.popover.behavior == .applicationDefined)61    controller.endModalPresentation()62    #expect(controller.popover.behavior == .transient)6364    popover.stubShown = true65    controller.endModalPresentation()66    controller.eventMonitor?.handler(nil)67    popover.stubShown = true68    controller.togglePopover(nil)6970    controller.showPopover(sender: nil)71    controller.togglePopover(nil)72    controller.togglePopover(nil)73    controller.closePopover(sender: nil)74    controller.togglePopover(nil)75    controller.closePopover(sender: nil)76    #expect(popover.showCount > 0)77    #expect(popover.closeCount > 0)7879    NSStatusBar.system.removeStatusItem(statusItem)80  }8182  @Test("Event monitor start and stop are idempotent")83  func eventMonitorLifecycle() {84    var eventSeen = false85    let monitor = EventMonitor(mask: [.leftMouseDown]) { _ in eventSeen = true }8687    monitor.start()88    monitor.stop()89    monitor.stop()9091    #expect(!eventSeen)92  }9394  @Test("Screen manager exposes AppKit screen metadata")95  func screenManager() {96    let manager = ScreenManager.shared97    #expect(manager.screens == NSScreen.screens)98    if let screen = manager.screens.first {99      #expect(manager.screenName(for: screen) == screen.localizedName)100    }101  }102103  @Test("Application bootstrap wires the delegate and optional event loop")104  func applicationBootstrap() {105    let delegate = AppDelegate()106    var received: AppDelegate?107    var runs = 0108    HavenApplication.start(109      delegate: delegate, shouldRun: false,110      setDelegate: { received = $0 }, run: { runs += 1 })111    #expect(received === delegate)112    #expect(runs == 0)113114    HavenApplication.start(115      delegate: delegate, shouldRun: true,116      setDelegate: { received = $0 }, run: { runs += 1 })117    #expect(runs == 1)118  }119120  @Test("Folder panel adapter configures directory selection")121  func folderPanel() {122    let directory = URL(fileURLWithPath: "/tmp")123    let configured = AppState.makeFolderPanel(at: directory)124    #expect(!configured.canChooseFiles)125    #expect(configured.canChooseDirectories)126    #expect(configured.canCreateDirectories)127    #expect(!configured.allowsMultipleSelection)128    #expect(configured.directoryURL == directory)129  }130131  @Test("Folder picker adapter forwards cancellation")132  func folderPicker() {133    let panel = OpenPanelStub()134    var result: URL? = URL(fileURLWithPath: "/sentinel")135136    AppState.presentFolderPicker(panel: panel) { result = $0 }137    #expect(panel.completion != nil)138139    panel.completion?(.cancel)140    #expect(result == nil)141  }142}