248 lines
9.1 KiB
Swift
248 lines
9.1 KiB
Swift
import CodexBarCore
|
|
import Foundation
|
|
import Testing
|
|
@testable import CodexBar
|
|
|
|
struct MenuCardModelCodexDegradedQuotaTests {
|
|
@Test
|
|
func `codex local token usage keeps remote quota unavailable error visible`() throws {
|
|
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
|
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
|
let tokenSnapshot = CostUsageTokenSnapshot(
|
|
sessionTokens: 721_966,
|
|
sessionCostUSD: 1.081155,
|
|
last30DaysTokens: 824_405_060,
|
|
last30DaysCostUSD: 583.1287345,
|
|
daily: [
|
|
.init(
|
|
date: "2026-06-05",
|
|
inputTokens: 710_217,
|
|
outputTokens: 11749,
|
|
totalTokens: 721_966,
|
|
costUSD: 1.081155,
|
|
modelsUsed: ["gpt-5.5"],
|
|
modelBreakdowns: nil),
|
|
],
|
|
updatedAt: now)
|
|
|
|
let model = UsageMenuCardView.Model.make(.init(
|
|
provider: .codex,
|
|
metadata: metadata,
|
|
snapshot: nil,
|
|
credits: nil,
|
|
creditsError: nil,
|
|
dashboard: nil,
|
|
dashboardError: nil,
|
|
tokenSnapshot: tokenSnapshot,
|
|
tokenError: nil,
|
|
account: AccountInfo(email: nil, plan: nil),
|
|
isRefreshing: false,
|
|
lastError: "Codex usage is temporarily unavailable. Try refreshing.",
|
|
usageBarsShowUsed: false,
|
|
resetTimeDisplayStyle: .countdown,
|
|
tokenCostUsageEnabled: true,
|
|
showOptionalCreditsAndExtraUsage: true,
|
|
hidePersonalInfo: false,
|
|
now: now))
|
|
|
|
#expect(model.placeholder == nil)
|
|
#expect(model.subtitleStyle == .error)
|
|
#expect(model.subtitleText == "Codex usage is temporarily unavailable. Try refreshing.")
|
|
#expect(model.usesStackedDetailLayout)
|
|
#expect(model.tokenUsage?.sessionLine.contains("$1.08") == true)
|
|
#expect(model.tokenUsage?.sessionLine.contains("tokens") == true)
|
|
#expect(model.tokenUsage?.monthLine.contains("$583.13") == true)
|
|
#expect(model.tokenUsage?.monthLine.contains("tokens") == true)
|
|
}
|
|
|
|
@Test
|
|
func `codex remote quota unavailable error stays visible when token usage is hidden`() throws {
|
|
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
|
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
|
let tokenSnapshot = CostUsageTokenSnapshot(
|
|
sessionTokens: 721_966,
|
|
sessionCostUSD: 1.081155,
|
|
last30DaysTokens: 824_405_060,
|
|
last30DaysCostUSD: 583.1287345,
|
|
daily: [],
|
|
updatedAt: now)
|
|
let error = "Codex usage is temporarily unavailable. Try refreshing."
|
|
|
|
let model = UsageMenuCardView.Model.make(.init(
|
|
provider: .codex,
|
|
metadata: metadata,
|
|
snapshot: nil,
|
|
credits: nil,
|
|
creditsError: nil,
|
|
dashboard: nil,
|
|
dashboardError: nil,
|
|
tokenSnapshot: tokenSnapshot,
|
|
tokenError: nil,
|
|
account: AccountInfo(email: nil, plan: nil),
|
|
isRefreshing: false,
|
|
lastError: error,
|
|
usageBarsShowUsed: false,
|
|
resetTimeDisplayStyle: .countdown,
|
|
tokenCostUsageEnabled: false,
|
|
showOptionalCreditsAndExtraUsage: true,
|
|
hidePersonalInfo: false,
|
|
now: now))
|
|
|
|
#expect(model.placeholder == nil)
|
|
#expect(model.subtitleStyle == .error)
|
|
#expect(model.subtitleText == error)
|
|
#expect(model.tokenUsage == nil)
|
|
}
|
|
|
|
@Test
|
|
func `codex local token usage preserves limits unavailable placeholder`() throws {
|
|
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
|
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
|
let tokenSnapshot = CostUsageTokenSnapshot(
|
|
sessionTokens: 721_966,
|
|
sessionCostUSD: 1.081155,
|
|
last30DaysTokens: 824_405_060,
|
|
last30DaysCostUSD: 583.1287345,
|
|
daily: [],
|
|
updatedAt: now)
|
|
|
|
let model = UsageMenuCardView.Model.make(.init(
|
|
provider: .codex,
|
|
metadata: metadata,
|
|
snapshot: nil,
|
|
credits: nil,
|
|
creditsError: nil,
|
|
dashboard: nil,
|
|
dashboardError: nil,
|
|
tokenSnapshot: tokenSnapshot,
|
|
tokenError: nil,
|
|
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
|
isRefreshing: false,
|
|
lastError: UsageError.noRateLimitsFound.errorDescription,
|
|
usageBarsShowUsed: false,
|
|
resetTimeDisplayStyle: .countdown,
|
|
tokenCostUsageEnabled: true,
|
|
showOptionalCreditsAndExtraUsage: true,
|
|
hidePersonalInfo: false,
|
|
now: now))
|
|
|
|
#expect(model.placeholder == "Limits not available")
|
|
#expect(model.subtitleStyle == .info)
|
|
#expect(model.tokenUsage != nil)
|
|
#expect(model.usesStackedDetailLayout)
|
|
}
|
|
|
|
@Test
|
|
func `codex local token usage preserves sign-in guidance`() throws {
|
|
let model = try self.makeModel(
|
|
tokenCostUsageEnabled: true,
|
|
lastError: "Codex CLI is not signed in. Run `codex login --device-auth`, then refresh.")
|
|
|
|
#expect(model.subtitleStyle == .error)
|
|
#expect(model.subtitleText.contains("codex login"))
|
|
#expect(model.tokenUsage != nil)
|
|
#expect(model.usesStackedDetailLayout)
|
|
}
|
|
|
|
@Test
|
|
func `codex local token usage preserves mapped transport error`() throws {
|
|
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
|
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
|
let tokenSnapshot = CostUsageTokenSnapshot(
|
|
sessionTokens: 721_966,
|
|
sessionCostUSD: 1.081155,
|
|
last30DaysTokens: 824_405_060,
|
|
last30DaysCostUSD: 583.1287345,
|
|
daily: [],
|
|
updatedAt: now)
|
|
let error = try #require(CodexUIErrorMapper.userFacingMessage("Codex connection failed: timed out."))
|
|
|
|
let model = UsageMenuCardView.Model.make(.init(
|
|
provider: .codex,
|
|
metadata: metadata,
|
|
snapshot: nil,
|
|
credits: nil,
|
|
creditsError: nil,
|
|
dashboard: nil,
|
|
dashboardError: nil,
|
|
tokenSnapshot: tokenSnapshot,
|
|
tokenError: nil,
|
|
account: AccountInfo(email: nil, plan: nil),
|
|
isRefreshing: false,
|
|
lastError: error,
|
|
usageBarsShowUsed: false,
|
|
resetTimeDisplayStyle: .countdown,
|
|
tokenCostUsageEnabled: true,
|
|
showOptionalCreditsAndExtraUsage: true,
|
|
hidePersonalInfo: false,
|
|
now: now))
|
|
|
|
#expect(model.placeholder == nil)
|
|
#expect(model.subtitleStyle == .error)
|
|
#expect(model.subtitleText == "Codex usage is temporarily unavailable. Try refreshing.")
|
|
#expect(model.tokenUsage?.sessionLine.contains("$1.08") == true)
|
|
}
|
|
|
|
@Test
|
|
func `credits select stacked detail layout without quota metrics`() {
|
|
let model = UsageMenuCardView.Model(
|
|
provider: .codex,
|
|
providerName: "Codex",
|
|
email: "user@example.com",
|
|
subtitleText: "Not fetched yet",
|
|
subtitleStyle: .info,
|
|
planText: nil,
|
|
metrics: [],
|
|
usageNotes: [],
|
|
openAIAPIUsage: nil,
|
|
inlineUsageDashboard: nil,
|
|
creditsText: "$12.34 remaining",
|
|
creditsRemaining: 12.34,
|
|
creditsProgressPercent: nil,
|
|
creditsScaleText: nil,
|
|
creditsHintText: nil,
|
|
creditsHintCopyText: nil,
|
|
providerCost: nil,
|
|
tokenUsage: nil,
|
|
placeholder: "No usage yet",
|
|
progressColor: .blue)
|
|
|
|
#expect(model.usesStackedDetailLayout)
|
|
}
|
|
|
|
private func makeModel(
|
|
tokenCostUsageEnabled: Bool,
|
|
lastError: String?) throws -> UsageMenuCardView.Model
|
|
{
|
|
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
|
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
|
let tokenSnapshot = CostUsageTokenSnapshot(
|
|
sessionTokens: 721_966,
|
|
sessionCostUSD: 1.081155,
|
|
last30DaysTokens: 824_405_060,
|
|
last30DaysCostUSD: 583.1287345,
|
|
daily: [],
|
|
updatedAt: now)
|
|
|
|
return UsageMenuCardView.Model.make(.init(
|
|
provider: .codex,
|
|
metadata: metadata,
|
|
snapshot: nil,
|
|
credits: nil,
|
|
creditsError: nil,
|
|
dashboard: nil,
|
|
dashboardError: nil,
|
|
tokenSnapshot: tokenSnapshot,
|
|
tokenError: nil,
|
|
account: AccountInfo(email: nil, plan: nil),
|
|
isRefreshing: false,
|
|
lastError: lastError,
|
|
usageBarsShowUsed: false,
|
|
resetTimeDisplayStyle: .countdown,
|
|
tokenCostUsageEnabled: tokenCostUsageEnabled,
|
|
showOptionalCreditsAndExtraUsage: true,
|
|
hidePersonalInfo: false,
|
|
now: now))
|
|
}
|
|
}
|