135 lines
5.4 KiB
Swift
135 lines
5.4 KiB
Swift
import AppKit
|
|
import CodexBarCore
|
|
import Testing
|
|
@testable import CodexBar
|
|
|
|
@MainActor
|
|
@Suite(.serialized)
|
|
struct StatusMenuLocalizationRefreshTests {
|
|
@Test
|
|
func `open merged menu refreshes localized switcher and cost title when language changes`() async {
|
|
let previousLanguage = UserDefaults.standard.object(forKey: "appLanguage")
|
|
let previousAppleLanguages = UserDefaults.standard.object(forKey: "AppleLanguages")
|
|
defer {
|
|
if let previousLanguage {
|
|
UserDefaults.standard.set(previousLanguage, forKey: "appLanguage")
|
|
} else {
|
|
UserDefaults.standard.removeObject(forKey: "appLanguage")
|
|
}
|
|
if let previousAppleLanguages {
|
|
UserDefaults.standard.set(previousAppleLanguages, forKey: "AppleLanguages")
|
|
} else {
|
|
UserDefaults.standard.removeObject(forKey: "AppleLanguages")
|
|
}
|
|
}
|
|
|
|
Self.disableMenuCardsForTesting()
|
|
let settings = Self.makeSettings()
|
|
settings.statusChecksEnabled = false
|
|
settings.refreshFrequency = .manual
|
|
settings.mergeIcons = true
|
|
settings.switcherShowsIcons = false
|
|
settings.selectedMenuProvider = .codex
|
|
settings.costUsageEnabled = true
|
|
settings.costSummaryDisplayStyle = .both
|
|
|
|
let registry = ProviderRegistry.shared
|
|
for provider in UsageProvider.allCases {
|
|
guard let metadata = registry.metadata[provider] else { continue }
|
|
let shouldEnable = provider == .codex || provider == .claude
|
|
settings.setProviderEnabled(provider: provider, metadata: metadata, enabled: shouldEnable)
|
|
}
|
|
|
|
let fetcher = UsageFetcher()
|
|
let store = UsageStore(fetcher: fetcher, browserDetection: BrowserDetection(cacheTTL: 0), settings: settings)
|
|
store._setTokenSnapshotForTesting(CostUsageTokenSnapshot(
|
|
sessionTokens: 123,
|
|
sessionCostUSD: 0.12,
|
|
last30DaysTokens: 123,
|
|
last30DaysCostUSD: 1.23,
|
|
daily: [
|
|
CostUsageDailyReport.Entry(
|
|
date: "2025-12-23",
|
|
inputTokens: nil,
|
|
outputTokens: nil,
|
|
totalTokens: 123,
|
|
costUSD: 1.23,
|
|
modelsUsed: nil,
|
|
modelBreakdowns: nil),
|
|
],
|
|
updatedAt: Date()), provider: .codex)
|
|
let controller = StatusItemController(
|
|
store: store,
|
|
settings: settings,
|
|
account: fetcher.loadAccountInfo(),
|
|
updater: DisabledUpdaterController(),
|
|
preferencesSelection: PreferencesSelection(),
|
|
statusBar: Self.makeStatusBarForTesting())
|
|
defer { controller.releaseStatusItemsForTesting() }
|
|
|
|
let menu = controller.makeMenu()
|
|
CodexBarLocalizationOverride.$appLanguage.withValue("es") {
|
|
controller.menuWillOpen(menu)
|
|
}
|
|
controller.openMenus[ObjectIdentifier(menu)] = menu
|
|
controller.menuRefreshEnabledOverrideForTesting = true
|
|
|
|
#expect(Self.switcherButtons(in: menu).first?.title == "Resumen")
|
|
#expect(menu.items.first(where: { $0.representedObject as? String == "menuCardCost" })?.title == "Coste")
|
|
|
|
let initialSwitcher = menu.items.first?.view as? ProviderSwitcherView
|
|
let initialSwitcherID = initialSwitcher.map(ObjectIdentifier.init)
|
|
var rebuildCount = 0
|
|
controller._test_openMenuRebuildObserver = { _ in
|
|
rebuildCount += 1
|
|
}
|
|
defer { controller._test_openMenuRebuildObserver = nil }
|
|
|
|
CodexBarLocalizationOverride.$appLanguage.withValue("en") {
|
|
settings.appLanguage = "en"
|
|
controller.handleProviderConfigChange(reason: "appLanguage")
|
|
}
|
|
|
|
for _ in 0..<100 where rebuildCount == 0 {
|
|
await Task.yield()
|
|
try? await Task.sleep(for: .milliseconds(10))
|
|
}
|
|
|
|
#expect(rebuildCount == 1)
|
|
let updatedSwitcher = menu.items.first?.view as? ProviderSwitcherView
|
|
#expect(Self.switcherButtons(in: menu).first?.title == "Overview")
|
|
#expect(menu.items.first(where: { $0.representedObject as? String == "menuCardCost" })?.title == "Cost")
|
|
if let initialSwitcherID, let updatedSwitcher {
|
|
#expect(initialSwitcherID != ObjectIdentifier(updatedSwitcher))
|
|
}
|
|
}
|
|
|
|
private static func disableMenuCardsForTesting() {
|
|
StatusItemController.menuCardRenderingEnabled = false
|
|
StatusItemController.setMenuRefreshEnabledForTesting(false)
|
|
}
|
|
|
|
private static func makeStatusBarForTesting() -> NSStatusBar {
|
|
.system
|
|
}
|
|
|
|
private static func makeSettings() -> SettingsStore {
|
|
let suite = "StatusMenuLocalizationRefreshTests-\(UUID().uuidString)"
|
|
let defaults = UserDefaults(suiteName: suite)!
|
|
defaults.removePersistentDomain(forName: suite)
|
|
let configStore = testConfigStore(suiteName: suite)
|
|
return SettingsStore(
|
|
userDefaults: defaults,
|
|
configStore: configStore,
|
|
zaiTokenStore: NoopZaiTokenStore(),
|
|
syntheticTokenStore: NoopSyntheticTokenStore())
|
|
}
|
|
|
|
private static func switcherButtons(in menu: NSMenu) -> [NSButton] {
|
|
guard let switcherView = menu.items.first?.view as? ProviderSwitcherView else { return [] }
|
|
return switcherView.subviews
|
|
.compactMap { $0 as? NSButton }
|
|
.sorted { $0.tag < $1.tag }
|
|
}
|
|
}
|