import AppKit import CodexBarCore import Testing @testable import CodexBar @MainActor @Suite(.serialized) struct StatusItemAnimationSignatureTests { @Test func `merged render signature changes when unified icon style changes`() { let suite = "StatusItemAnimationSignatureTests-merged-style-signature" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .codex settings.menuBarShowsBrandIconWithPercent = false settings.syntheticAPIToken = "synthetic-test-token" let registry = ProviderRegistry.shared if let codexMeta = registry.metadata[.codex] { settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) } if let syntheticMeta = registry.metadata[.synthetic] { settings.setProviderEnabled(provider: .synthetic, metadata: syntheticMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 50, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .codex) #expect(store.enabledProvidersForDisplay() == [.codex, .synthetic]) #expect(store.enabledProviders() == [.codex, .synthetic]) #expect(store.iconStyle == .combined) controller.applyIcon(phase: nil) let combinedSignature = controller.lastAppliedMergedIconRenderSignature if let syntheticMeta = registry.metadata[.synthetic] { settings.setProviderEnabled(provider: .synthetic, metadata: syntheticMeta, enabled: false) } #expect(store.enabledProvidersForDisplay() == [.codex]) #expect(store.enabledProviders() == [.codex]) #expect(store.iconStyle == .codex) controller.applyIcon(phase: nil) let codexSignature = controller.lastAppliedMergedIconRenderSignature #expect(combinedSignature != nil) #expect(codexSignature != nil) #expect(combinedSignature != codexSignature) #expect(codexSignature?.contains("style=codex") == true) } @Test func `merged antigravity icon resolves quota summary with provider style`() throws { let suite = "StatusItemAnimationSignatureTests-merged-antigravity-provider-style" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .antigravity settings.menuBarShowsBrandIconWithPercent = false settings.usageBarsShowUsed = false settings.syntheticAPIToken = "synthetic-test-token" let registry = ProviderRegistry.shared if let antigravityMeta = registry.metadata[.antigravity] { settings.setProviderEnabled(provider: .antigravity, metadata: antigravityMeta, enabled: true) } if let syntheticMeta = registry.metadata[.synthetic] { settings.setProviderEnabled(provider: .synthetic, metadata: syntheticMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil), secondary: RateWindow(usedPercent: 16, windowMinutes: 10080, resetsAt: nil, resetDescription: nil), tertiary: nil, extraRateWindows: [ NamedRateWindow( id: "antigravity-quota-summary-gemini-5h", title: "Gemini Session", window: RateWindow(usedPercent: 1, windowMinutes: 300, resetsAt: nil, resetDescription: nil)), NamedRateWindow( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Weekly", window: RateWindow( usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)), NamedRateWindow( id: "antigravity-quota-summary-3p-5h", title: "Claude + GPT Session", window: RateWindow(usedPercent: 2, windowMinutes: 300, resetsAt: nil, resetDescription: nil)), NamedRateWindow( id: "antigravity-quota-summary-3p-weekly", title: "Claude + GPT Weekly", window: RateWindow( usedPercent: 16, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)), ], updatedAt: Date()), provider: .antigravity) #expect(store.iconStyle == .combined) #expect(controller.primaryProviderForUnifiedIcon() == .antigravity) controller.applyIcon(phase: nil) let signature = try #require(controller.lastAppliedMergedIconRenderSignature) #expect(signature.contains("provider=antigravity")) #expect(signature.contains("style=combined")) #expect(signature.contains("primary=98.000")) #expect(signature.contains("weekly=1.000")) } @Test func `merged mistral icon uses monthly plan metric when selected`() throws { let suite = "StatusItemAnimationSignatureTests-merged-mistral-monthly-plan" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .mistral settings.menuBarShowsBrandIconWithPercent = false settings.usageBarsShowUsed = true settings.syntheticAPIToken = "synthetic-test-token" settings.setMenuBarMetricPreference(.monthlyPlan, for: .mistral) let registry = ProviderRegistry.shared if let mistralMeta = registry.metadata[.mistral] { settings.setProviderEnabled(provider: .mistral, metadata: mistralMeta, enabled: true) } if let syntheticMeta = registry.metadata[.synthetic] { settings.setProviderEnabled(provider: .synthetic, metadata: syntheticMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } store._setSnapshotForTesting( UsageSnapshot( primary: nil, secondary: nil, extraRateWindows: [ NamedRateWindow( id: "mistral-monthly-plan", title: "Monthly Plan", window: RateWindow(usedPercent: 42, windowMinutes: nil, resetsAt: nil, resetDescription: nil)), ], updatedAt: Date()), provider: .mistral) #expect(store.iconStyle == .combined) #expect(controller.primaryProviderForUnifiedIcon() == .mistral) controller.applyIcon(phase: nil) let signature = try #require(controller.lastAppliedMergedIconRenderSignature) #expect(signature.contains("provider=mistral")) #expect(signature.contains("primary=42.000")) #expect(signature.contains("weekly=nil")) } @Test func `mistral pay as you go icon ignores balance primary percent`() { let suite = "StatusItemAnimationSignatureTests-mistral-payg-balance-percent" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.usageBarsShowUsed = true settings.setMenuBarMetricPreference(.automatic, for: .mistral) 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } let snapshot = UsageSnapshot( primary: RateWindow( usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: "$12.50"), secondary: nil, updatedAt: Date()) let percents = controller.resolvedMenuBarIconPercents( provider: .mistral, snapshot: snapshot, style: .mistral, showUsed: true) #expect(percents?.primary == nil) #expect(percents?.secondary == nil) } @Test func `merged brand percent reapplies title when cached render is skipped`() throws { let suite = "StatusItemAnimationSignatureTests-merged-brand-percent-title-restore" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .codex settings.menuBarShowsBrandIconWithPercent = true settings.menuBarDisplayMode = .percent settings.usageBarsShowUsed = false settings.syntheticAPIToken = "synthetic-test-token" let registry = ProviderRegistry.shared if let codexMeta = registry.metadata[.codex] { settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) } if let syntheticMeta = registry.metadata[.synthetic] { settings.setProviderEnabled(provider: .synthetic, metadata: syntheticMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } let snapshot = UsageSnapshot( primary: RateWindow(usedPercent: 23, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()) store._setSnapshotForTesting(snapshot, provider: .codex) let displayText = try #require(controller.menuBarDisplayText(for: .codex, snapshot: snapshot)) let expectedTitle = StatusItemController.buttonTitle(displayText, hasImage: true) controller.applyIcon(phase: nil) let button = try #require(controller.statusItem.button) #expect(button.title == expectedTitle) #expect(button.imagePosition == .imageLeft) button.title = "" button.imagePosition = .imageOnly let skipped = controller.applyIcon(phase: nil) #expect(skipped) #expect(button.title == expectedTitle) #expect(button.imagePosition == .imageLeft) } @Test func `merged icon render defers while merged menu is tracking`() async throws { let suite = "StatusItemAnimationSignatureTests-merged-icon-defers-during-tracking" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .codex settings.menuBarShowsBrandIconWithPercent = false settings.syntheticAPIToken = "synthetic-test-token" let registry = ProviderRegistry.shared for provider in UsageProvider.allCases { guard let metadata = registry.metadata[provider] else { continue } settings.setProviderEnabled( provider: provider, metadata: metadata, enabled: provider == .codex || provider == .synthetic) } 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } controller.menuRefreshEnabledOverrideForTesting = true func snapshot(usedPercent: Double) -> UsageSnapshot { UsageSnapshot( primary: RateWindow( usedPercent: usedPercent, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()) } store._setSnapshotForTesting(snapshot(usedPercent: 20), provider: .codex) controller.updateIcons() #expect(controller.animationDriver == nil) controller.applyIcon(phase: nil) let initialSignature = try #require(controller.lastAppliedMergedIconRenderSignature) let menu = controller.makeMenu() controller.mergedMenu = menu controller.statusItem.menu = menu controller.menuWillOpen(menu) #expect(controller.isMergedMenuOpen) store._setSnapshotForTesting(nil, provider: .codex) controller.updateIcons() #expect(controller.animationDriver != nil) #expect(controller.deferredMergedIconRenderAfterTracking) store._setSnapshotForTesting(snapshot(usedPercent: 80), provider: .codex) controller.updateIcons() #expect(controller.animationDriver == nil) #expect(controller.deferredMergedIconRenderAfterTracking) #expect(controller.lastAppliedMergedIconRenderSignature == initialSignature) controller.startQuotaWarningFlash(provider: .codex) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("warningFlash=1") == true) let quotaWarningTask = controller.quotaWarningFlashTasks[.codex] controller.clearExpiredQuotaWarningFlash(provider: .codex, now: .distantFuture) quotaWarningTask?.cancel() #expect(controller.lastAppliedMergedIconRenderSignature?.contains("warningFlash=0") == true) controller.menuDidClose(menu) #expect(!controller.deferredMergedIconRenderAfterTracking) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("warningFlash=0") == true) controller.menuWillOpen(menu) settings.selectedMenuProvider = .synthetic #expect(controller.primaryProviderForUnifiedIcon() == .synthetic) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("provider=codex") == true) controller.startQuotaWarningFlash(provider: .codex) let switchedProviderWarningTask = controller.quotaWarningFlashTasks[.codex] #expect(controller.lastAppliedMergedIconRenderSignature?.contains("provider=synthetic") == true) controller.clearExpiredQuotaWarningFlash(provider: .codex, now: .distantFuture) switchedProviderWarningTask?.cancel() controller.menuDidClose(menu) settings.selectedMenuProvider = .codex for _ in 0..<10 where controller.primaryProviderForUnifiedIcon() != .codex { await Task.yield() } controller.menuWillOpen(menu) store._setSnapshotForTesting(nil, provider: .codex) controller.updateAnimationState() controller.applyIcon(phase: controller.animationPhase) #expect(controller.animationDriver != nil) #expect(controller.deferredMergedIconRenderAfterTracking) controller.animationDriver?.stop() controller.animationDriver = nil controller.animationPhase = 0 controller.menuDidClose(menu) #expect(controller.animationDriver == nil) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("primary=nil") == true) } @Test func `merged fallback provider follows enabled provider order`() { let suite = "StatusItemAnimationSignatureTests-merged-provider-order" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.menuBarShowsBrandIconWithPercent = false settings.syntheticAPIToken = "synthetic-test-token" settings.setProviderOrder([.synthetic, .codex]) let registry = ProviderRegistry.shared if let codexMeta = registry.metadata[.codex] { settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) } if let syntheticMeta = registry.metadata[.synthetic] { settings.setProviderEnabled(provider: .synthetic, metadata: syntheticMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } let snapshot = UsageSnapshot( primary: RateWindow(usedPercent: 50, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()) store._setSnapshotForTesting(snapshot, provider: .codex) store._setSnapshotForTesting(snapshot, provider: .synthetic) controller.applyIcon(phase: nil) #expect(store.enabledProviders().prefix(2) == [.synthetic, .codex]) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("provider=synthetic") == true) } @Test func `merged icon status indicator follows rendered provider`() throws { let suite = "StatusItemAnimationSignatureTests-merged-status-provider-scope" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = true settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .codex settings.menuBarShowsBrandIconWithPercent = false let registry = ProviderRegistry.shared let codexMeta = try #require(registry.metadata[.codex]) let claudeMeta = try #require(registry.metadata[.claude]) settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) settings.setProviderEnabled(provider: .claude, metadata: claudeMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } let snapshot = UsageSnapshot( primary: RateWindow(usedPercent: 50, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()) store._setSnapshotForTesting(snapshot, provider: .codex) store._setSnapshotForTesting(snapshot, provider: .claude) store.statuses[.claude] = ProviderStatus( indicator: .major, description: "Claude status issue", updatedAt: Date(timeIntervalSince1970: 20)) controller.applyIcon(phase: nil) #expect(controller.primaryProviderForUnifiedIcon() == .codex) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("provider=codex") == true) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("status=none") == true) settings.selectedMenuProvider = .claude controller.applyIcon(phase: nil) #expect(controller.primaryProviderForUnifiedIcon() == .claude) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("provider=claude") == true) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("status=major") == true) } @Test func `highest usage icon ranks only overview providers`() throws { let suite = "StatusItemAnimationSignatureTests-highest-usage-overview-subset" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.menuBarShowsHighestUsage = true let registry = ProviderRegistry.shared let codexMeta = try #require(registry.metadata[.codex]) let claudeMeta = try #require(registry.metadata[.claude]) settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) settings.setProviderEnabled(provider: .claude, metadata: claudeMeta, enabled: true) let fetcher = UsageFetcher() let store = UsageStore( fetcher: fetcher, browserDetection: BrowserDetection(cacheTTL: 0), settings: settings) settings.setMergedOverviewProviderSelection( provider: .claude, isSelected: false, activeProviders: store.enabledProvidersForDisplay()) let controller = StatusItemController( store: store, settings: settings, account: fetcher.loadAccountInfo(), updater: DisabledUpdaterController(), preferencesSelection: PreferencesSelection(), statusBar: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 25, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .codex) store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 80, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .claude) #expect(store.providerWithHighestUsage()?.provider == .claude) #expect(controller.primaryProviderForUnifiedIcon() == .codex) } @Test(arguments: [nil, 100.0] as [Double?]) func `highest usage icon keeps nonempty overview authoritative when unrankable`( overviewUsedPercent: Double?) throws { let suite = "StatusItemAnimationSignatureTests-highest-usage-overview-fallback" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.menuBarShowsHighestUsage = true settings.selectedMenuProvider = .claude settings.mergedMenuLastSelectedWasOverview = false let registry = ProviderRegistry.shared let codexMeta = try #require(registry.metadata[.codex]) let claudeMeta = try #require(registry.metadata[.claude]) settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) settings.setProviderEnabled(provider: .claude, metadata: claudeMeta, enabled: true) let fetcher = UsageFetcher() let store = UsageStore( fetcher: fetcher, browserDetection: BrowserDetection(cacheTTL: 0), settings: settings) settings.setMergedOverviewProviderSelection( provider: .claude, isSelected: false, activeProviders: store.enabledProvidersForDisplay()) let controller = StatusItemController( store: store, settings: settings, account: fetcher.loadAccountInfo(), updater: DisabledUpdaterController(), preferencesSelection: PreferencesSelection(), statusBar: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } if let overviewUsedPercent { store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow( usedPercent: overviewUsedPercent, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .codex) } store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 80, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .claude) #expect(store.providerWithHighestUsage(candidateProviders: [.codex]) == nil) #expect(controller.primaryProviderForUnifiedIcon() == .codex) } @Test func `highest usage icon allows broad fallback for explicit empty overview`() throws { let suite = "StatusItemAnimationSignatureTests-highest-usage-empty-overview" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.menuBarShowsHighestUsage = true settings.selectedMenuProvider = .claude let registry = ProviderRegistry.shared let codexMeta = try #require(registry.metadata[.codex]) let claudeMeta = try #require(registry.metadata[.claude]) settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) settings.setProviderEnabled(provider: .claude, metadata: claudeMeta, enabled: true) let fetcher = UsageFetcher() let store = UsageStore( fetcher: fetcher, browserDetection: BrowserDetection(cacheTTL: 0), settings: settings) let activeProviders = store.enabledProvidersForDisplay() settings.setMergedOverviewProviderSelection( provider: .codex, isSelected: false, activeProviders: activeProviders) settings.setMergedOverviewProviderSelection( provider: .claude, isSelected: false, activeProviders: activeProviders) let controller = StatusItemController( store: store, settings: settings, account: fetcher.loadAccountInfo(), updater: DisabledUpdaterController(), preferencesSelection: PreferencesSelection(), statusBar: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } #expect(settings.resolvedMergedOverviewProviders(activeProviders: store.enabledProvidersForDisplay()) == []) #expect(controller.primaryProviderForUnifiedIcon() == .claude) } @Test func `merged icon follows overview provider order when first overview provider is loading`() { let suite = "StatusItemAnimationSignatureTests-merged-overview-provider-order" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = true settings.selectedMenuProvider = .codex settings.mergedMenuLastSelectedWasOverview = true settings.menuBarShowsBrandIconWithPercent = false settings.setProviderOrder([.cursor, .codex, .claude]) let registry = ProviderRegistry.shared if let cursorMeta = registry.metadata[.cursor] { settings.setProviderEnabled(provider: .cursor, metadata: cursorMeta, enabled: true) } if let codexMeta = registry.metadata[.codex] { settings.setProviderEnabled(provider: .codex, metadata: codexMeta, enabled: true) } if let claudeMeta = registry.metadata[.claude] { settings.setProviderEnabled(provider: .claude, metadata: claudeMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } let snapshot = UsageSnapshot( primary: RateWindow(usedPercent: 50, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()) store._setSnapshotForTesting(snapshot, provider: .codex) store._setSnapshotForTesting(snapshot, provider: .claude) #expect(store.enabledProvidersForDisplay().prefix(3) == [.cursor, .codex, .claude]) #expect(settings.resolvedMergedOverviewProviders(activeProviders: store.enabledProvidersForDisplay()) == [ .cursor, .codex, .claude, ]) controller.applyIcon(phase: nil) #expect(controller.lastAppliedMergedIconRenderSignature?.contains("provider=cursor") == true) } @Test func `split provider icon skips unchanged render signature`() { let suite = "StatusItemAnimationSignatureTests-split-provider-signature" let settings = testSettingsStore(suiteName: suite) settings.statusChecksEnabled = false settings.refreshFrequency = .manual settings.mergeIcons = false settings.menuBarShowsBrandIconWithPercent = false if let codexMeta = ProviderRegistry.shared.metadata[.codex] { settings.setProviderEnabled(provider: .codex, metadata: codexMeta, 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: testStatusBar()) defer { controller.releaseStatusItemsForTesting() } store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 25, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .codex) #expect(controller.applyIcon(for: .codex, phase: nil) == false) #expect(controller.applyIcon(for: .codex, phase: nil) == true) store._setSnapshotForTesting( UsageSnapshot( primary: RateWindow(usedPercent: 50, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: nil, updatedAt: Date()), provider: .codex) #expect(controller.applyIcon(for: .codex, phase: nil) == false) } }