Files
steipete--codexbar/Tests/CodexBarTests/StatusItemBalanceDisplayTests.swift
2026-07-13 12:22:33 +08:00

760 lines
30 KiB
Swift

import AppKit
import CodexBarCore
import Testing
@testable import CodexBar
@Suite(.serialized)
@MainActor
struct StatusItemBalanceDisplayTests {
@Test
func `menu bar display text uses open router balance`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-openrouter-balance",
provider: .openrouter)
settings.setMenuBarMetricPreference(.automatic, for: .openrouter)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.openRouterSnapshot()
store._setSnapshotForTesting(snapshot, provider: .openrouter)
store._setErrorForTesting(nil, provider: .openrouter)
let displayText = controller.menuBarDisplayText(for: .openrouter, snapshot: snapshot)
#expect(displayText == "$12.34")
}
@Test
func `reset time mode preserves automatic open router balance`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-openrouter-reset-time",
provider: .openrouter)
settings.menuBarDisplayMode = .resetTime
settings.setMenuBarMetricPreference(.automatic, for: .openrouter)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.openRouterSnapshot()
store._setSnapshotForTesting(snapshot, provider: .openrouter)
store._setErrorForTesting(nil, provider: .openrouter)
let displayText = controller.menuBarDisplayText(for: .openrouter, snapshot: snapshot)
#expect(displayText == "$12.34")
}
@Test
func `menu bar display text uses crossmodel balance currency`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-crossmodel-eur-balance",
provider: .crossmodel)
settings.setMenuBarMetricPreference(.automatic, for: .crossmodel)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = CrossModelUsageSnapshot(
currency: "EUR",
balance: 8.059489,
uncollected: 0,
daily: nil,
weekly: nil,
monthly: nil,
updatedAt: Date())
.toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .crossmodel)
store._setErrorForTesting(nil, provider: .crossmodel)
let displayText = controller.menuBarDisplayText(for: .crossmodel, snapshot: snapshot)
#expect(displayText == "€8.06")
}
@Test
func `menu bar display text uses zen balance when open code has no subscription`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-opencodego-zen-only",
provider: .opencodego)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
providerCost: ProviderCostSnapshot(
used: 23.75,
limit: 0,
currencyCode: "USD",
period: "Zen balance",
updatedAt: Date()),
updatedAt: Date())
store._setSnapshotForTesting(snapshot, provider: .opencodego)
store._setErrorForTesting(nil, provider: .opencodego)
let displayText = controller.menuBarDisplayText(for: .opencodego, snapshot: snapshot)
#expect(displayText == "$23.75")
}
@Test
func `menu bar display text uses negative zen balance when open code is in deficit`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-opencodego-zen-deficit",
provider: .opencodego)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
providerCost: ProviderCostSnapshot(
used: -4.25,
limit: 0,
currencyCode: "USD",
period: "Zen balance",
updatedAt: Date()),
updatedAt: Date())
store._setSnapshotForTesting(snapshot, provider: .opencodego)
store._setErrorForTesting(nil, provider: .opencodego)
let displayText = controller.menuBarDisplayText(for: .opencodego, snapshot: snapshot)
#expect(displayText == "-$4.25")
}
@Test
func `menu bar display text keeps open code subscription percentage`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-opencodego-subscription",
provider: .opencodego)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 12, windowMinutes: 300, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 34, windowMinutes: 10080, resetsAt: nil, resetDescription: nil),
providerCost: ProviderCostSnapshot(
used: 23.75,
limit: 0,
currencyCode: "USD",
period: "Zen balance",
updatedAt: Date()),
updatedAt: Date())
store._setSnapshotForTesting(snapshot, provider: .opencodego)
store._setErrorForTesting(nil, provider: .opencodego)
let displayText = controller.menuBarDisplayText(for: .opencodego, snapshot: snapshot)
#expect(displayText == "12%")
}
@Test
func `reset time mode preserves balance when provider has no quota window`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-moonshot-reset-time",
provider: .moonshot)
settings.menuBarDisplayMode = .resetTime
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
updatedAt: Date(),
identity: ProviderIdentitySnapshot(
providerID: .moonshot,
accountEmail: nil,
accountOrganization: nil,
loginMethod: "Balance: $49.58 · $0.42 in deficit"))
store._setSnapshotForTesting(snapshot, provider: .moonshot)
store._setErrorForTesting(nil, provider: .moonshot)
let displayText = controller.menuBarDisplayText(for: .moonshot, snapshot: snapshot)
#expect(displayText == "$49.58")
}
@Test
func `menu bar display text respects open router primary metric preference`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-openrouter-primary-metric",
provider: .openrouter)
settings.setMenuBarMetricPreference(.primary, for: .openrouter)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.openRouterSnapshot()
store._setSnapshotForTesting(snapshot, provider: .openrouter)
store._setErrorForTesting(nil, provider: .openrouter)
let displayText = controller.menuBarDisplayText(for: .openrouter, snapshot: snapshot)
#expect(displayText == "25%")
}
@Test
func `menu bar display text skips exhausted cursor api subquota when total remains usable`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-cursor-exhausted-api",
provider: .cursor)
settings.usageBarsShowUsed = false
settings.setMenuBarMetricPreference(.automatic, for: .cursor)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 67, windowMinutes: 30 * 24 * 60, resetsAt: nil, resetDescription: "Total"),
secondary: RateWindow(
usedPercent: 34,
windowMinutes: 30 * 24 * 60,
resetsAt: nil,
resetDescription: "Auto"),
tertiary: RateWindow(usedPercent: 100, windowMinutes: 30 * 24 * 60, resetsAt: nil, resetDescription: "API"),
updatedAt: Date())
store._setSnapshotForTesting(snapshot, provider: .cursor)
store._setErrorForTesting(nil, provider: .cursor)
let displayText = controller.menuBarDisplayText(for: .cursor, snapshot: snapshot)
#expect(displayText == "33%")
}
@Test
func `menu bar display text uses deepseek balance`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-deepseek-balance",
provider: .deepseek)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: RateWindow(
usedPercent: 0,
windowMinutes: nil,
resetsAt: nil,
resetDescription: "$9.32 (Paid: $9.32 / Granted: $0.00)"),
secondary: nil,
updatedAt: Date())
store._setSnapshotForTesting(snapshot, provider: .deepseek)
store._setErrorForTesting(nil, provider: .deepseek)
let displayText = controller.menuBarDisplayText(for: .deepseek, snapshot: snapshot)
#expect(displayText == "$9.32")
}
@Test
func `menu bar display text uses mimo balance without token plan`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-mimo-balance",
provider: .mimo)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = MiMoUsageSnapshot(
balance: 25.51,
currency: "USD",
cashBalance: 20,
giftBalance: 5.51,
updatedAt: Date())
.toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .mimo)
store._setErrorForTesting(nil, provider: .mimo)
let displayText = controller.menuBarDisplayText(for: .mimo, snapshot: snapshot)
#expect(displayText == "$25.51")
}
@Test
func `menu bar display text uses selected mimo balance with token plan`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-mimo-token-plan",
provider: .mimo)
settings.setMenuBarMetricPreference(.secondary, for: .mimo)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = MiMoUsageSnapshot(
balance: 25.51,
currency: "USD",
planCode: "standard",
tokenUsed: 10,
tokenLimit: 100,
tokenPercent: 0.1,
updatedAt: Date())
.toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .mimo)
store._setErrorForTesting(nil, provider: .mimo)
let displayText = controller.menuBarDisplayText(for: .mimo, snapshot: snapshot)
#expect(displayText == "$25.51")
}
@Test
func `menu bar display text uses moonshot balance`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-moonshot-balance",
provider: .moonshot)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
updatedAt: Date(),
identity: ProviderIdentitySnapshot(
providerID: .moonshot,
accountEmail: nil,
accountOrganization: nil,
loginMethod: "Balance: $49.58 · $0.42 in deficit"))
store._setSnapshotForTesting(snapshot, provider: .moonshot)
store._setErrorForTesting(nil, provider: .moonshot)
let displayText = controller.menuBarDisplayText(for: .moonshot, snapshot: snapshot)
#expect(snapshot.primary == nil)
#expect(displayText == "$49.58")
}
@Test
func `menu bar display text uses mistral current month api spend`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-mistral-spend",
provider: .mistral)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = MistralUsageSnapshot(
totalCost: 1.2345,
currency: "EUR",
currencySymbol: "€",
totalInputTokens: 10000,
totalOutputTokens: 5000,
totalCachedTokens: 0,
modelCount: 2,
startDate: nil,
endDate: nil,
updatedAt: Date()).toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .mistral)
store._setErrorForTesting(nil, provider: .mistral)
let displayText = controller.menuBarDisplayText(for: .mistral, snapshot: snapshot)
#expect(snapshot.primary == nil)
#expect(snapshot.identity?.loginMethod == "API spend: €1.2345 this month")
#expect(displayText == "€1.2345")
}
@Test
func `menu bar display text uses mistral monthly plan when selected`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-mistral-monthly-plan",
provider: .mistral)
settings.setMenuBarMetricPreference(.monthlyPlan, for: .mistral)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = MistralUsageSnapshot(
totalCost: 1.2345,
currency: "EUR",
currencySymbol: "€",
totalInputTokens: 10000,
totalOutputTokens: 5000,
totalCachedTokens: 0,
modelCount: 2,
startDate: nil,
endDate: nil,
updatedAt: Date())
.toUsageSnapshot()
.with(extraRateWindows: [
NamedRateWindow(
id: "mistral-monthly-plan",
title: "Monthly Plan",
window: RateWindow(
usedPercent: 42,
windowMinutes: nil,
resetsAt: nil,
resetDescription: nil)),
])
store._setSnapshotForTesting(snapshot, provider: .mistral)
store._setErrorForTesting(nil, provider: .mistral)
let displayText = controller.menuBarDisplayText(for: .mistral, snapshot: snapshot)
#expect(snapshot.identity?.loginMethod == "API spend: €1.2345 this month")
#expect(displayText == "42%")
}
@Test
func `menu bar display text falls back to mistral spend when monthly plan is missing`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-mistral-monthly-plan-missing",
provider: .mistral)
settings.setMenuBarMetricPreference(.monthlyPlan, for: .mistral)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = MistralUsageSnapshot(
totalCost: 1.2345,
currency: "EUR",
currencySymbol: "€",
totalInputTokens: 10000,
totalOutputTokens: 5000,
totalCachedTokens: 0,
modelCount: 2,
startDate: nil,
endDate: nil,
updatedAt: Date())
.toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .mistral)
store._setErrorForTesting(nil, provider: .mistral)
let displayText = controller.menuBarDisplayText(for: .mistral, snapshot: snapshot)
#expect(snapshot.identity?.loginMethod == "API spend: €1.2345 this month")
#expect(displayText == "€1.2345")
}
@Test
func `menu bar display text uses kimi k2 api key credits`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kimik2-credits",
provider: .kimik2)
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = KimiK2UsageSummary(
consumed: 75,
remaining: 1234.5,
averageTokens: nil,
updatedAt: Date()).toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kimik2)
store._setErrorForTesting(nil, provider: .kimik2)
let displayText = controller.menuBarDisplayText(for: .kimik2, snapshot: snapshot)
#expect(snapshot.primary == nil)
#expect(snapshot.identity?.loginMethod == "Credits: 1234.5 left")
#expect(displayText == "1234.5")
}
@Test
func `kiro menu bar automatic uses credits left`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-automatic",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .automatic
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.kiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "49.83")
}
@Test
func `kiro menu bar credits and percent combines values`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-both",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .creditsAndPercent
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.kiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "49.83 · 0%")
}
@Test
func `kiro menu bar hidden suppresses text value`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-hidden",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .hidden
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.kiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == nil)
}
@Test
func `kiro menu bar used and total formats credits`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-used-total",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .usedAndTotal
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.kiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "0.17 / 50")
}
@Test
func `kiro menu bar overage credits mode shows overage credits when exhausted`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-overage-credits",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .overageCreditsWhenExhausted
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.exhaustedKiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "40.29 over")
}
@Test
func `kiro menu bar overage cost mode shows cost when exhausted`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-overage-cost",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .overageCostWhenExhausted
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.exhaustedKiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "$1.61 over")
}
@Test
func `kiro menu bar overage credits and cost mode shows both when exhausted`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-overage-both",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .overageCreditsAndCostWhenExhausted
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.exhaustedKiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "40.29 · $1.61")
}
@Test
func `kiro menu bar overage mode keeps credits left before exhaustion`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-overage-not-exhausted",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .overageCreditsAndCostWhenExhausted
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.kiroSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "49.83")
}
@Test
func `kiro menu bar overage mode ignores disabled overage values`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-overage-disabled",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .overageCreditsAndCostWhenExhausted
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = Self.exhaustedKiroSnapshot(overagesStatus: "Disabled")
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "0")
}
@Test
func `kiro managed plan display falls back to percent`() {
let settings = self.makeSettings(
suiteName: "StatusItemBalanceDisplayTests-kiro-managed",
provider: .kiro)
settings.kiroMenuBarDisplayMode = .automatic
settings.usageBarsShowUsed = false
let (store, controller) = self.makeStoreAndController(settings: settings)
defer { controller.releaseStatusItemsForTesting() }
let snapshot = KiroUsageSnapshot(
planName: "Q Developer Pro",
creditsUsed: 0,
creditsTotal: 0,
creditsPercent: 0,
bonusCreditsUsed: nil,
bonusCreditsTotal: nil,
bonusExpiryDays: nil,
resetsAt: nil,
updatedAt: Date()).toUsageSnapshot()
store._setSnapshotForTesting(snapshot, provider: .kiro)
store._setErrorForTesting(nil, provider: .kiro)
let displayText = controller.menuBarDisplayText(for: .kiro, snapshot: snapshot)
#expect(displayText == "100%")
}
@Test
func `mistral primary window is nil without credits even when billing end date is set`() {
let endDate = Date(timeIntervalSinceNow: 3600)
let snapshot = MistralUsageSnapshot(
totalCost: 0.5,
currency: "USD",
currencySymbol: "$",
totalInputTokens: 1000,
totalOutputTokens: 500,
totalCachedTokens: 0,
modelCount: 1,
startDate: nil,
endDate: endDate,
updatedAt: Date()).toUsageSnapshot()
// Billing end date alone is not a quota window; credits are what populate primary.
#expect(snapshot.primary == nil)
}
@Test
func `button title spacing only applies when image is present`() {
#expect(StatusItemController.buttonTitle("42%", hasImage: true) == " 42%")
#expect(StatusItemController.buttonTitle("42%", hasImage: false) == "42%")
#expect(StatusItemController.buttonTitle(nil, hasImage: true).isEmpty)
#expect(StatusItemController.buttonTitle("", hasImage: true).isEmpty)
}
@Test
func `debug button title stays visible with or without a usage value`() {
#expect(StatusItemController.buttonTitle(nil, hasImage: true, isDebugApp: true) == " D")
#expect(StatusItemController.buttonTitle("42%", hasImage: true, isDebugApp: true) == " 42% D")
#expect(StatusItemController.buttonTitle("42%", hasImage: false, isDebugApp: true) == "42% D")
}
@Test
func `debug bundle identity updates status item accessibility`() {
#expect(StatusItemController.isDebugApp(bundleIdentifier: "com.steipete.codexbar.debug"))
#expect(!StatusItemController.isDebugApp(bundleIdentifier: "com.steipete.codexbar"))
#expect(!StatusItemController.isDebugApp(bundleIdentifier: nil))
#expect(StatusItemController.statusItemAccessibilityTitle(isDebugApp: true) == "CodexBar Debug")
#expect(StatusItemController.statusItemAccessibilityTitle(isDebugApp: false) == "CodexBar")
}
private func makeSettings(suiteName: String, provider: UsageProvider) -> SettingsStore {
let settings = testSettingsStore(suiteName: suiteName)
settings.statusChecksEnabled = false
settings.refreshFrequency = .manual
settings.mergeIcons = true
settings.selectedMenuProvider = provider
settings.menuBarDisplayMode = .both
settings.usageBarsShowUsed = true
let registry = ProviderRegistry.shared
if let metadata = registry.metadata[provider] {
settings.setProviderEnabled(provider: provider, metadata: metadata, enabled: true)
}
return settings
}
private func makeStoreAndController(settings: SettingsStore) -> (UsageStore, StatusItemController) {
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())
return (store, controller)
}
private static func openRouterSnapshot() -> UsageSnapshot {
OpenRouterUsageSnapshot(
totalCredits: 50,
totalUsage: 37.66,
balance: 12.34,
usedPercent: 75.32,
keyLimit: 20,
keyUsage: 5,
rateLimit: nil,
updatedAt: Date()).toUsageSnapshot()
}
private static func kiroSnapshot() -> UsageSnapshot {
KiroUsageSnapshot(
planName: "KIRO FREE",
accountEmail: "person@example.com",
authMethod: "Google",
creditsUsed: 0.17,
creditsTotal: 50,
creditsPercent: 0,
bonusCreditsUsed: 45.53,
bonusCreditsTotal: 2000,
bonusExpiryDays: 19,
overagesStatus: "Disabled",
manageURL: "https://app.kiro.dev/account/usage",
contextUsage: KiroContextUsageSnapshot(
totalPercentUsed: 1.3,
contextFilesPercent: 0.5,
toolsPercent: 0.8,
kiroResponsesPercent: 0,
promptsPercent: 0),
resetsAt: Date(),
updatedAt: Date()).toUsageSnapshot()
}
private static func exhaustedKiroSnapshot(overagesStatus: String = "Enabled billed at $0.04 per request")
-> UsageSnapshot
{
KiroUsageSnapshot(
planName: "KIRO FREE",
accountEmail: "person@example.com",
authMethod: "Google",
creditsUsed: 50,
creditsTotal: 50,
creditsPercent: 100,
bonusCreditsUsed: nil,
bonusCreditsTotal: nil,
bonusExpiryDays: nil,
overagesStatus: overagesStatus,
overageCreditsUsed: 40.29,
estimatedOverageCostUSD: 1.61,
manageURL: "https://app.kiro.dev/account/usage",
resetsAt: Date(),
updatedAt: Date()).toUsageSnapshot()
}
}