chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,881 @@
|
||||
import CodexBarCore
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import Testing
|
||||
@testable import CodexBar
|
||||
|
||||
struct MenuCardModelCodexProjectionTests {
|
||||
@Test
|
||||
func `codex weekly lane derives pace from its visible window`() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 2,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(4 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 4,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let projection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
let weekly = try #require(model.metrics.first { $0.id == "secondary" })
|
||||
#expect(weekly.detailLeftText == "10% in reserve")
|
||||
#expect(weekly.detailRightText == "Lasts until reset")
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex weekly lane includes workday markers when workDaysPerWeek is set`() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 2,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(4 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 4,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let projection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
quotaWarningThresholds: [.session: [], .weekly: []],
|
||||
workDaysPerWeek: 5,
|
||||
now: now))
|
||||
|
||||
let weekly = try #require(model.metrics.first { $0.id == "secondary" })
|
||||
#expect(weekly.warningMarkerPercents.isEmpty)
|
||||
#expect(weekly.workdayMarkerPercents == [20.0, 40.0, 60.0, 80.0])
|
||||
|
||||
let session = try #require(model.metrics.first { $0.id == "primary" })
|
||||
#expect(session.warningMarkerPercents.isEmpty)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex weekly lane keeps workday and quota warning markers separate`() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 2,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(4 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 4,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let projection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
quotaWarningThresholds: [.session: [], .weekly: [50]],
|
||||
workDaysPerWeek: 5,
|
||||
now: now))
|
||||
|
||||
let weekly = try #require(model.metrics.first { $0.id == "secondary" })
|
||||
#expect(weekly.warningMarkerPercents == [50.0])
|
||||
#expect(weekly.workdayMarkerPercents == [20.0, 40.0, 60.0, 80.0])
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex weekly lane workday markers not inverted by usageBarsShowUsed`() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 2,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(4 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 4,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let projection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: true,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
quotaWarningThresholds: [.session: [], .weekly: []],
|
||||
workDaysPerWeek: 5,
|
||||
now: now))
|
||||
|
||||
let weekly = try #require(model.metrics.first { $0.id == "secondary" })
|
||||
#expect(weekly.warningMarkerPercents.isEmpty)
|
||||
#expect(weekly.workdayMarkerPercents == [20.0, 40.0, 60.0, 80.0])
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex plan only snapshot shows limits unavailable placeholder`() throws {
|
||||
let now = Date()
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: nil,
|
||||
secondary: nil,
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: nil, plan: nil),
|
||||
isRefreshing: false,
|
||||
lastError: UsageError.noRateLimitsFound.errorDescription,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.placeholder == "Limits not available")
|
||||
#expect(model.metrics.isEmpty)
|
||||
#expect(model.subtitleStyle == .info)
|
||||
#expect(!model.subtitleText.contains("Found sessions"))
|
||||
#expect(model.planText == "Pro 20x")
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex plan only snapshot keeps actionable refresh errors visible`() throws {
|
||||
let now = Date()
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: nil,
|
||||
secondary: nil,
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: nil, plan: nil),
|
||||
isRefreshing: false,
|
||||
lastError: "Codex connection failed: timed out.",
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.placeholder == nil)
|
||||
#expect(model.subtitleStyle == .error)
|
||||
#expect(model.subtitleText == "Codex connection failed: timed out.")
|
||||
#expect(model.planText == "Pro 20x")
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex account fallback shows limits unavailable instead of no limits error`() throws {
|
||||
let now = Date()
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: nil,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "pro"),
|
||||
isRefreshing: false,
|
||||
lastError: UsageError.noRateLimitsFound.errorDescription,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.placeholder == "Limits not available")
|
||||
#expect(model.subtitleStyle == .info)
|
||||
#expect(!model.subtitleText.contains("Found sessions"))
|
||||
#expect(model.email == "user@example.com")
|
||||
#expect(model.planText == "Pro 20x")
|
||||
}
|
||||
|
||||
@Test
|
||||
func `codex no account fallback keeps no limits error visible`() throws {
|
||||
let now = Date()
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: nil,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: nil, plan: nil),
|
||||
isRefreshing: false,
|
||||
lastError: UsageError.noRateLimitsFound.errorDescription,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.placeholder == nil)
|
||||
#expect(model.subtitleStyle == .error)
|
||||
#expect(model.subtitleText == UsageError.noRateLimitsFound.errorDescription)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `builds metrics using used percent when enabled`() throws {
|
||||
let now = Date()
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "codex@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Plus Plan")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 22,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(3000),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 40,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6000),
|
||||
resetDescription: nil),
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let dashboard = OpenAIDashboardSnapshot(
|
||||
signedInEmail: "codex@example.com",
|
||||
codeReviewRemainingPercent: 73,
|
||||
codeReviewLimit: RateWindow(
|
||||
usedPercent: 27,
|
||||
windowMinutes: nil,
|
||||
resetsAt: now.addingTimeInterval(3600),
|
||||
resetDescription: nil),
|
||||
creditEvents: [],
|
||||
dailyBreakdown: [],
|
||||
usageBreakdown: [],
|
||||
creditsPurchaseURL: nil,
|
||||
updatedAt: now)
|
||||
let codexProjection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: dashboard,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: true,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: codexProjection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "codex@example.com", plan: "Plus Plan"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: true,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.metrics.first?.title == "Session")
|
||||
#expect(model.metrics.first?.percent == 22)
|
||||
#expect(model.metrics.first?.percentLabel.contains("used") == true)
|
||||
#expect(model.metrics.contains { $0.title == "Code review" && $0.percent == 27 })
|
||||
}
|
||||
|
||||
@Test
|
||||
func `shows code review metric when dashboard present`() throws {
|
||||
let now = Date()
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "codex@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: nil)
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(usedPercent: 0, windowMinutes: 300, resetsAt: nil, resetDescription: nil),
|
||||
secondary: nil,
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let dashboard = OpenAIDashboardSnapshot(
|
||||
signedInEmail: "codex@example.com",
|
||||
codeReviewRemainingPercent: 73,
|
||||
codeReviewLimit: RateWindow(
|
||||
usedPercent: 27,
|
||||
windowMinutes: nil,
|
||||
resetsAt: now.addingTimeInterval(3600),
|
||||
resetDescription: nil),
|
||||
creditEvents: [],
|
||||
dailyBreakdown: [],
|
||||
usageBreakdown: [],
|
||||
creditsPurchaseURL: nil,
|
||||
updatedAt: now)
|
||||
let codexProjection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: dashboard,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: true,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: codexProjection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "codex@example.com", plan: nil),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.metrics.contains { $0.title == "Code review" && $0.percent == 73 })
|
||||
let codeReviewMetric = model.metrics.first { $0.id == "code-review" }
|
||||
#expect(codeReviewMetric?.resetText?.contains("Resets") == true)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `uses semantic codex lanes when weekly duration drifts`() throws {
|
||||
let now = Date()
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "codex@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: nil)
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: nil,
|
||||
secondary: RateWindow(
|
||||
usedPercent: 25,
|
||||
windowMinutes: 11040,
|
||||
resetsAt: now.addingTimeInterval(3600),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let codexProjection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: codexProjection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "codex@example.com", plan: nil),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.metrics.count == 1)
|
||||
#expect(model.metrics.first?.id == "secondary")
|
||||
#expect(model.metrics.first?.title == "Weekly")
|
||||
#expect(model.metrics.first?.percent == 75)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders codex spark as a named extra metric after the core lanes`() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 2,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(4 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 4,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
extraRateWindows: [
|
||||
NamedRateWindow(
|
||||
id: "codex-spark",
|
||||
title: "Codex Spark 5-hour",
|
||||
window: RateWindow(
|
||||
usedPercent: 80,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(2 * 60 * 60),
|
||||
resetDescription: nil)),
|
||||
NamedRateWindow(
|
||||
id: "codex-spark-weekly",
|
||||
title: "Codex Spark Weekly",
|
||||
window: RateWindow(
|
||||
usedPercent: 100,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil)),
|
||||
],
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let projection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: nil,
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: nil,
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
let spark = try #require(model.metrics.first { $0.id == "codex-spark" })
|
||||
#expect(spark.title == "Codex Spark 5-hour")
|
||||
#expect(spark.percent == 20)
|
||||
#expect(spark.percentLabel == "20% left")
|
||||
#expect(spark.resetText != nil)
|
||||
#expect(spark.detailLeftText == "20% in deficit")
|
||||
#expect(spark.detailRightText == "Projected empty in 45m")
|
||||
let sparkWeekly = try #require(model.metrics.first { $0.id == "codex-spark-weekly" })
|
||||
#expect(sparkWeekly.title == "Codex Spark Weekly")
|
||||
#expect(sparkWeekly.percent == 0)
|
||||
#expect(sparkWeekly.percentLabel == "0% left")
|
||||
#expect(sparkWeekly.resetText != nil)
|
||||
#expect(sparkWeekly.detailLeftText == "86% in deficit")
|
||||
#expect(sparkWeekly.detailRightText == "Runs out now")
|
||||
// Spark trails the core session/weekly lanes rather than replacing them.
|
||||
let sparkIndex = try #require(model.metrics.firstIndex { $0.id == "codex-spark" })
|
||||
let sparkWeeklyIndex = try #require(model.metrics.firstIndex { $0.id == "codex-spark-weekly" })
|
||||
let sessionIndex = try #require(model.metrics.firstIndex { $0.id == "primary" })
|
||||
#expect(sparkIndex > sessionIndex)
|
||||
#expect(sparkWeeklyIndex > sparkIndex)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `hides codex credits when disabled`() throws {
|
||||
let now = Date()
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "codex@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: nil)
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(usedPercent: 0, windowMinutes: 300, resetsAt: nil, resetDescription: nil),
|
||||
secondary: nil,
|
||||
tertiary: nil,
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let codexProjection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: CreditsSnapshot(remaining: 12, events: [], updatedAt: now),
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: codexProjection,
|
||||
credits: CreditsSnapshot(remaining: 12, events: [], updatedAt: now),
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "codex@example.com", plan: nil),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: false,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(model.creditsText == nil)
|
||||
}
|
||||
}
|
||||
|
||||
struct MenuCardModelCodexSparkVisibilityTests {
|
||||
@Test
|
||||
func `codex spark visibility hides only spark metrics`() throws {
|
||||
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
||||
let metadata = try #require(ProviderDefaults.metadata[.codex])
|
||||
let identity = ProviderIdentitySnapshot(
|
||||
providerID: .codex,
|
||||
accountEmail: "user@example.com",
|
||||
accountOrganization: nil,
|
||||
loginMethod: "Pro")
|
||||
let snapshot = UsageSnapshot(
|
||||
primary: RateWindow(
|
||||
usedPercent: 2,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(4 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
secondary: RateWindow(
|
||||
usedPercent: 4,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil),
|
||||
tertiary: nil,
|
||||
extraRateWindows: [
|
||||
NamedRateWindow(
|
||||
id: "codex-spark",
|
||||
title: "Codex Spark 5-hour",
|
||||
window: RateWindow(
|
||||
usedPercent: 30,
|
||||
windowMinutes: 300,
|
||||
resetsAt: now.addingTimeInterval(60 * 60),
|
||||
resetDescription: nil)),
|
||||
NamedRateWindow(
|
||||
id: "codex-spark-weekly",
|
||||
title: "Codex Spark Weekly",
|
||||
window: RateWindow(
|
||||
usedPercent: 100,
|
||||
windowMinutes: 10080,
|
||||
resetsAt: now.addingTimeInterval(6 * 24 * 60 * 60),
|
||||
resetDescription: nil)),
|
||||
NamedRateWindow(
|
||||
id: "codex-other-limit",
|
||||
title: "Other Codex limit",
|
||||
window: RateWindow(
|
||||
usedPercent: 25,
|
||||
windowMinutes: 1440,
|
||||
resetsAt: now.addingTimeInterval(12 * 60 * 60),
|
||||
resetDescription: nil)),
|
||||
],
|
||||
updatedAt: now,
|
||||
identity: identity)
|
||||
let projection = CodexConsumerProjection.make(
|
||||
surface: .liveCard,
|
||||
context: CodexConsumerProjection.Context(
|
||||
snapshot: snapshot,
|
||||
rawUsageError: nil,
|
||||
liveCredits: CreditsSnapshot(remaining: 12, events: [], updatedAt: now),
|
||||
rawCreditsError: nil,
|
||||
liveDashboard: nil,
|
||||
rawDashboardError: nil,
|
||||
dashboardAttachmentAuthorized: false,
|
||||
dashboardRequiresLogin: false,
|
||||
now: now))
|
||||
|
||||
let model = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: CreditsSnapshot(remaining: 12, events: [], updatedAt: now),
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: true,
|
||||
codexSparkUsageVisible: false,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(!model.metrics.contains { $0.id == "codex-spark" })
|
||||
#expect(!model.metrics.contains { $0.id == "codex-spark-weekly" })
|
||||
#expect(model.metrics.contains { $0.id == "primary" })
|
||||
#expect(model.metrics.contains { $0.id == "secondary" })
|
||||
#expect(model.metrics.contains { $0.id == "codex-other-limit" })
|
||||
#expect(model.creditsText != nil)
|
||||
|
||||
let globalOffModel = UsageMenuCardView.Model.make(.init(
|
||||
provider: .codex,
|
||||
metadata: metadata,
|
||||
snapshot: snapshot,
|
||||
codexProjection: projection,
|
||||
credits: CreditsSnapshot(remaining: 12, events: [], updatedAt: now),
|
||||
creditsError: nil,
|
||||
dashboard: nil,
|
||||
dashboardError: nil,
|
||||
tokenSnapshot: nil,
|
||||
tokenError: nil,
|
||||
account: AccountInfo(email: "user@example.com", plan: "Pro"),
|
||||
isRefreshing: false,
|
||||
lastError: nil,
|
||||
usageBarsShowUsed: false,
|
||||
resetTimeDisplayStyle: .countdown,
|
||||
tokenCostUsageEnabled: false,
|
||||
showOptionalCreditsAndExtraUsage: false,
|
||||
codexSparkUsageVisible: true,
|
||||
hidePersonalInfo: false,
|
||||
now: now))
|
||||
|
||||
#expect(!globalOffModel.metrics.contains { $0.id == "codex-spark" })
|
||||
#expect(!globalOffModel.metrics.contains { $0.id == "codex-spark-weekly" })
|
||||
#expect(!globalOffModel.metrics.contains { $0.id == "codex-other-limit" })
|
||||
#expect(globalOffModel.creditsText == nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user