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