190 lines · 6.9 KB · Swift
RawDownload
import AppKitimport CodexBarCoreimport Foundationimport Testing@testable import CodexBar /// Regression coverage for battery drain caused by fallback-provider animation./// See GitHub issues #269, #139.@MainActor@Suite(.serialized)struct BatteryDrainDiagnosticTests {    private func ensureAppKitInitialized() {        _ = NSApplication.shared    }     private func makeStatusBarForTesting() -> NSStatusBar {        // Use the real system status bar in tests. Creating standalone NSStatusBar instances        // has caused AppKit teardown crashes under swiftpm-testing-helper.        .system    }     @Test    func `Fallback provider should not animate when all providers are disabled`() {        self.ensureAppKitInitialized()         let settings = SettingsStore(            configStore: testConfigStore(suiteName: "BatteryDrain-AllDisabled"),            zaiTokenStore: NoopZaiTokenStore(),            syntheticTokenStore: NoopSyntheticTokenStore())         settings.statusChecksEnabled = false        settings.refreshFrequency = .manual        settings.mergeIcons = false         let registry = ProviderRegistry.shared        for provider in UsageProvider.allCases {            if let meta = registry.metadata[provider] {                settings.setProviderEnabled(provider: provider, metadata: meta, enabled: false)            }        }         let fetcher = UsageFetcher()        let store = UsageStore(            fetcher: fetcher,            browserDetection: BrowserDetection(cacheTTL: 0),            settings: settings)         let controller = StatusItemController(            store: store,            settings: settings,            account: fetcher.loadAccountInfo(),            updater: DisabledUpdaterController(),            preferencesSelection: PreferencesSelection(),            statusBar: self.makeStatusBarForTesting())        defer { controller.releaseStatusItemsForTesting() }         #expect(            controller.needsMenuBarIconAnimation() == false,            "Should not animate when only fallback provider is visible")        #expect(            controller.animationDriver == nil,            "Animation driver should not start for fallback provider")    }     @Test    func `Enabled provider with data should not animate`() {        self.ensureAppKitInitialized()         let settings = SettingsStore(            configStore: testConfigStore(suiteName: "BatteryDrain-HasData"),            zaiTokenStore: NoopZaiTokenStore(),            syntheticTokenStore: NoopSyntheticTokenStore())         settings.statusChecksEnabled = false        settings.refreshFrequency = .manual        settings.mergeIcons = true        settings.selectedMenuProvider = .codex         let registry = ProviderRegistry.shared        if let meta = registry.metadata[.codex] {            settings.setProviderEnabled(provider: .codex, metadata: meta, enabled: true)        }         let fetcher = UsageFetcher()        let store = UsageStore(            fetcher: fetcher,            browserDetection: BrowserDetection(cacheTTL: 0),            settings: settings)         let snapshot = UsageSnapshot(            primary: RateWindow(usedPercent: 50, windowMinutes: nil, resetsAt: nil, resetDescription: nil),            secondary: RateWindow(usedPercent: 30, windowMinutes: nil, resetsAt: nil, resetDescription: nil),            updatedAt: Date())        store._setSnapshotForTesting(snapshot, provider: .codex)         let controller = StatusItemController(            store: store,            settings: settings,            account: fetcher.loadAccountInfo(),            updater: DisabledUpdaterController(),            preferencesSelection: PreferencesSelection(),            statusBar: self.makeStatusBarForTesting())        defer { controller.releaseStatusItemsForTesting() }         #expect(            controller.needsMenuBarIconAnimation() == false,            "Should not animate when provider has data")        #expect(            controller.animationDriver == nil,            "Animation driver should be nil when data is present")    }     @Test    func `Enabled provider without data should animate`() {        self.ensureAppKitInitialized()         let settings = SettingsStore(            configStore: testConfigStore(suiteName: "BatteryDrain-NoData"),            zaiTokenStore: NoopZaiTokenStore(),            syntheticTokenStore: NoopSyntheticTokenStore())         settings.statusChecksEnabled = false        settings.refreshFrequency = .manual        settings.mergeIcons = false         let registry = ProviderRegistry.shared        if let meta = registry.metadata[.codex] {            settings.setProviderEnabled(provider: .codex, metadata: meta, enabled: true)        }         let fetcher = UsageFetcher()        let store = UsageStore(            fetcher: fetcher,            browserDetection: BrowserDetection(cacheTTL: 0),            settings: settings)         let controller = StatusItemController(            store: store,            settings: settings,            account: fetcher.loadAccountInfo(),            updater: DisabledUpdaterController(),            preferencesSelection: PreferencesSelection(),            statusBar: self.makeStatusBarForTesting())        defer { controller.releaseStatusItemsForTesting() }         #expect(            controller.needsMenuBarIconAnimation() == true,            "Should animate when enabled provider has no data")    }     @Test    func `Enabled provider with error should not animate`() {        self.ensureAppKitInitialized()         let settings = SettingsStore(            configStore: testConfigStore(suiteName: "BatteryDrain-ErrorStops"),            zaiTokenStore: NoopZaiTokenStore(),            syntheticTokenStore: NoopSyntheticTokenStore())         settings.statusChecksEnabled = false        settings.refreshFrequency = .manual        settings.mergeIcons = false         let registry = ProviderRegistry.shared        if let meta = registry.metadata[.codex] {            settings.setProviderEnabled(provider: .codex, metadata: meta, enabled: true)        }         let fetcher = UsageFetcher()        let store = UsageStore(            fetcher: fetcher,            browserDetection: BrowserDetection(cacheTTL: 0),            settings: settings)        store._setErrorForTesting("simulated Codex RPC timeout", provider: .codex)         let controller = StatusItemController(            store: store,            settings: settings,            account: fetcher.loadAccountInfo(),            updater: DisabledUpdaterController(),            preferencesSelection: PreferencesSelection(),            statusBar: self.makeStatusBarForTesting())         #expect(store.isStale(provider: .codex) == true)        #expect(            controller.needsMenuBarIconAnimation() == false,            "Should not animate when provider has recorded an error")        #expect(controller.animationDriver == nil)    }}