194 lines
8.0 KiB
Swift
194 lines
8.0 KiB
Swift
import CodexBarCore
|
|
import Foundation
|
|
import SwiftUI
|
|
import Testing
|
|
@testable import CodexBar
|
|
|
|
@MainActor
|
|
@Suite(.serialized)
|
|
struct PopupLocalizationTests {
|
|
@Test
|
|
func `descriptor account labels use selected localization`() throws {
|
|
try CodexBarLocalizationOverride.$appLanguage.withValue("zh-Hant") {
|
|
let suite = "PopupLocalizationTests-descriptor"
|
|
let settings = try Self.makeSettingsStore(suite: suite)
|
|
let store = UsageStore(
|
|
fetcher: UsageFetcher(environment: [:]),
|
|
browserDetection: BrowserDetection(cacheTTL: 0),
|
|
settings: settings,
|
|
startupBehavior: .testing)
|
|
store._setSnapshotForTesting(
|
|
UsageSnapshot(
|
|
primary: RateWindow(usedPercent: 12, windowMinutes: 300, resetsAt: nil, resetDescription: nil),
|
|
secondary: nil,
|
|
updatedAt: Date(),
|
|
identity: ProviderIdentitySnapshot(
|
|
providerID: .codex,
|
|
accountEmail: "codex@example.com",
|
|
accountOrganization: nil,
|
|
loginMethod: "free")),
|
|
provider: .codex)
|
|
|
|
let descriptor = MenuDescriptor.build(
|
|
provider: .codex,
|
|
store: store,
|
|
settings: settings,
|
|
account: AccountInfo(email: nil, plan: nil),
|
|
updateReady: false,
|
|
includeContextualActions: false)
|
|
|
|
let lines = Self.textLines(from: descriptor)
|
|
|
|
#expect(lines.contains("帳號: codex@example.com"))
|
|
#expect(lines.contains("方案: Free"))
|
|
#expect(!lines.contains("Account: codex@example.com"))
|
|
#expect(!lines.contains("Plan: Free"))
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `inline dashboard labels use selected localization`() throws {
|
|
try CodexBarLocalizationOverride.$appLanguage.withValue("zh-Hant") {
|
|
let now = Date(timeIntervalSince1970: 1_700_179_200)
|
|
let metadata = try #require(ProviderDefaults.metadata[.openrouter])
|
|
let usage = OpenRouterUsageSnapshot(
|
|
totalCredits: 100,
|
|
totalUsage: 40,
|
|
balance: 60,
|
|
usedPercent: 40,
|
|
keyDataFetched: true,
|
|
keyLimit: 25,
|
|
keyUsage: 10,
|
|
keyUsageDaily: 1.25,
|
|
keyUsageWeekly: 7.5,
|
|
keyUsageMonthly: 18.75,
|
|
rateLimit: OpenRouterRateLimit(requests: 100, interval: "10s"),
|
|
updatedAt: now)
|
|
|
|
let model = UsageMenuCardView.Model.make(.init(
|
|
provider: .openrouter,
|
|
metadata: metadata,
|
|
snapshot: usage.toUsageSnapshot(),
|
|
credits: nil,
|
|
creditsError: nil,
|
|
dashboard: nil,
|
|
dashboardError: nil,
|
|
tokenSnapshot: nil,
|
|
tokenError: nil,
|
|
account: AccountInfo(email: nil, plan: nil),
|
|
isRefreshing: false,
|
|
lastError: nil,
|
|
usageBarsShowUsed: false,
|
|
resetTimeDisplayStyle: .countdown,
|
|
tokenCostUsageEnabled: false,
|
|
showOptionalCreditsAndExtraUsage: true,
|
|
hidePersonalInfo: false,
|
|
now: now))
|
|
|
|
let dashboard = try #require(model.inlineUsageDashboard)
|
|
|
|
#expect(dashboard.kpis.map(\.title) == ["餘額", "今天", "週", "月"])
|
|
#expect(dashboard.points.map(\.label) == ["今天", "週", "月"])
|
|
#expect(dashboard.detailLines.contains("速率限制:100 / 10s"))
|
|
#expect(dashboard.detailLines.contains("金鑰剩餘額度:$15.00"))
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `cookie source dynamic subtitles use selected localization`() {
|
|
CodexBarLocalizationOverride.$appLanguage.withValue("zh-Hant") {
|
|
let subtitle = ProviderCookieSourceUI.subtitle(
|
|
source: .manual,
|
|
keychainDisabled: false,
|
|
auto: "Automatically imports browser cookies.",
|
|
manual: "Paste a Cookie header or cURL capture from T3 Chat settings.",
|
|
off: "T3 Chat cookies are disabled.")
|
|
let disabledSubtitle = ProviderCookieSourceUI.subtitle(
|
|
source: .manual,
|
|
keychainDisabled: true,
|
|
auto: "Automatically imports browser cookies.",
|
|
manual: "Paste a Cookie header or cURL capture from T3 Chat settings.",
|
|
off: "T3 Chat cookies are disabled.")
|
|
let jsonBundleSubtitle = ProviderCookieSourceUI.subtitle(
|
|
source: .manual,
|
|
keychainDisabled: false,
|
|
auto: "Automatically imports browser cookies.",
|
|
manual: "Paste the localStorage JSON bundle from Windsurf session.",
|
|
off: "Windsurf cookies are disabled.")
|
|
|
|
#expect(subtitle.contains("貼上"))
|
|
#expect(!subtitle.contains("Paste a Cookie"))
|
|
#expect(disabledSubtitle.contains("鑰匙圈"))
|
|
#expect(!disabledSubtitle.contains("Keychain access"))
|
|
#expect(jsonBundleSubtitle.contains("來自 Windsurf session 的 localStorage JSON"))
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `settings labels use selected localization`() {
|
|
CodexBarLocalizationOverride.$appLanguage.withValue("zh-Hant") {
|
|
#expect(KiroMenuBarDisplayMode.hidden.label == "隱藏")
|
|
#expect(KiroMenuBarDisplayMode.creditsLeft.label == "剩餘額度")
|
|
#expect(L("(System)") == "(系統)")
|
|
}
|
|
}
|
|
|
|
@Test
|
|
func `provider organization entries preserve provider supplied text`() throws {
|
|
let settings = try Self.makeSettingsStore(suite: "PopupLocalizationTests-organizations")
|
|
settings.kiloKnownOrganizations = [
|
|
KiloOrganization(id: "org_cost", name: "Cost", role: "Today"),
|
|
]
|
|
let store = UsageStore(
|
|
fetcher: UsageFetcher(environment: [:]),
|
|
browserDetection: BrowserDetection(cacheTTL: 0),
|
|
settings: settings,
|
|
startupBehavior: .testing)
|
|
let context = ProviderSettingsContext(
|
|
provider: .kilo,
|
|
settings: settings,
|
|
store: store,
|
|
boolBinding: { keyPath in
|
|
Binding(
|
|
get: { settings[keyPath: keyPath] },
|
|
set: { settings[keyPath: keyPath] = $0 })
|
|
},
|
|
stringBinding: { keyPath in
|
|
Binding(
|
|
get: { settings[keyPath: keyPath] },
|
|
set: { settings[keyPath: keyPath] = $0 })
|
|
},
|
|
statusText: { _ in nil },
|
|
setStatusText: { _, _ in },
|
|
lastAppActiveRunAt: { _ in nil },
|
|
setLastAppActiveRunAt: { _, _ in },
|
|
requestConfirmation: { _ in })
|
|
let descriptor = try #require(KiloProviderImplementation().settingsOrganizations(context: context))
|
|
let orgEntry = try #require(descriptor.entries().first { $0.id == "org_cost" })
|
|
|
|
#expect(orgEntry.title == "Cost")
|
|
#expect(orgEntry.localizesTitle == false)
|
|
#expect(orgEntry.subtitle == "Today")
|
|
#expect(orgEntry.localizesSubtitle == false)
|
|
}
|
|
|
|
private static func makeSettingsStore(suite: String) throws -> SettingsStore {
|
|
let defaults = try #require(UserDefaults(suiteName: suite))
|
|
defaults.removePersistentDomain(forName: suite)
|
|
let settings = SettingsStore(
|
|
userDefaults: defaults,
|
|
configStore: testConfigStore(suiteName: suite),
|
|
zaiTokenStore: NoopZaiTokenStore(),
|
|
syntheticTokenStore: NoopSyntheticTokenStore())
|
|
settings.statusChecksEnabled = false
|
|
return settings
|
|
}
|
|
|
|
private static func textLines(from descriptor: MenuDescriptor) -> [String] {
|
|
descriptor.sections.flatMap(\.entries).compactMap { entry -> String? in
|
|
guard case let .text(text, _) = entry else { return nil }
|
|
return text
|
|
}
|
|
}
|
|
}
|