74 lines · 3.0 KB · Swift
RawDownload
import AppKitimport CodexBarCoreimport Testing@testable import CodexBar @MainActorstruct AppDelegateTests {    @Test    func `builds status controller after launch`() {        let appDelegate = AppDelegate()        var factoryCalls = 0        var ttyShutdowns = 0        let dummyStatusController = DummyStatusController()        let managedCodexAccountCoordinator = ManagedCodexAccountCoordinator()         let settings = SettingsStore(            configStore: testConfigStore(suiteName: "AppDelegateTests"),            zaiTokenStore: NoopZaiTokenStore(),            syntheticTokenStore: NoopSyntheticTokenStore())        let fetcher = UsageFetcher()        let store = UsageStore(fetcher: fetcher, browserDetection: BrowserDetection(cacheTTL: 0), settings: settings)        let account = fetcher.loadAccountInfo()        let promotionCoordinator = CodexAccountPromotionCoordinator(            settingsStore: settings,            usageStore: store,            managedAccountCoordinator: managedCodexAccountCoordinator)        appDelegate.terminateActiveProcessesForAppShutdown = {            ttyShutdowns += 1        }         // Install a test factory that records invocations without touching NSStatusBar.        StatusItemController.factory = { _, _, _, _, _, receivedManagedCoordinator, receivedPromotionCoordinator in            factoryCalls += 1            #expect(receivedManagedCoordinator === managedCodexAccountCoordinator)            #expect(receivedPromotionCoordinator === promotionCoordinator)            return dummyStatusController        }        defer { StatusItemController.factory = StatusItemController.defaultFactory }         // configure should not eagerly construct the status controller        appDelegate.configure(.init(            store: store,            settings: settings,            account: account,            selection: PreferencesSelection(),            managedCodexAccountCoordinator: managedCodexAccountCoordinator,            codexAccountPromotionCoordinator: promotionCoordinator))        #expect(factoryCalls == 0)         // construction happens once after launch        appDelegate.applicationDidFinishLaunching(Notification(name: NSApplication.didFinishLaunchingNotification))        #expect(factoryCalls == 1)         // idempotent on subsequent calls        appDelegate.applicationDidFinishLaunching(Notification(name: NSApplication.didFinishLaunchingNotification))        #expect(factoryCalls == 1)         // production termination should ask the status controller to detach AppKit status/menu state        appDelegate.applicationWillTerminate(Notification(name: NSApplication.willTerminateNotification))        #expect(dummyStatusController.shutdowns == 1)        #expect(ttyShutdowns == 1)    }} @MainActorprivate final class DummyStatusController: StatusItemControlling {    private(set) var shutdowns = 0     func openMenuFromShortcut() {}    func runLoginFlowFromSettings(provider _: UsageProvider) async {}    func prepareForAppShutdown() {        self.shutdowns += 1    }}