882 lines
34 KiB
Swift
882 lines
34 KiB
Swift
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)
|
|
}
|
|
}
|