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

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))
}
}