import Foundationimport Testing@testable import CodexBarCore@testable import CodexBarWidget struct CodexBarWidgetProviderTests { @Test func `usage display follows remaining and used preference`() { #expect(WidgetUsageDisplay.percent(fromRemaining: 48, showUsed: false) == 48) #expect(WidgetUsageDisplay.percent(fromRemaining: 48, showUsed: true) == 52) #expect(WidgetUsageDisplay.percent(fromRemaining: nil, showUsed: true) == nil) } @Test func `small widget falls back to local cost when quota rows are unavailable`() { let tokenUsage = WidgetSnapshot.TokenUsageSummary( sessionCostUSD: 1.25, sessionTokens: 4200, last30DaysCostUSD: 12.50, last30DaysTokens: 42000, currencyCode: "USD", sessionLabel: "Today", last30DaysLabel: "30d") let entry = WidgetSnapshot.ProviderEntry( provider: .claude, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: tokenUsage, dailyUsage: []) let windowedEntry = WidgetSnapshot.ProviderEntry( provider: .claude, updatedAt: Date(), primary: RateWindow(usedPercent: 25, windowMinutes: 300, resetsAt: nil, resetDescription: nil), secondary: nil, tertiary: nil, usageRows: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: tokenUsage, dailyUsage: []) #expect(WidgetUsageRow.compactTokenUsage(for: entry)?.sessionTokens == 4200) #expect(WidgetUsageRow.compactTokenUsage(for: windowedEntry) == nil) } @Test func `small widget limits custom usage rows`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot(id: "one", title: "One", percentLeft: 90), WidgetSnapshot.WidgetUsageRowSnapshot(id: "two", title: "Two", percentLeft: 80), WidgetSnapshot.WidgetUsageRowSnapshot(id: "three", title: "Three", percentLeft: 70), WidgetSnapshot.WidgetUsageRowSnapshot(id: "four", title: "Four", percentLeft: 60), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) #expect(WidgetUsageRow.rows(for: entry, limit: 2).map(\.id) == ["one", "two"]) #expect(WidgetUsageRow.rows(for: entry).count == 4) } @Test func `small antigravity widget keeps one row per quota family`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-session", title: "Gemini Models Five Hour Limit", percentLeft: 80), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Models Weekly Limit", percentLeft: 20), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-third-party-session", title: "Claude and GPT models Five Hour Limit", percentLeft: 5), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-third-party-weekly", title: "Claude and GPT models Weekly Limit", percentLeft: 60), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.title) == ["Gemini Models Weekly Limit", "Claude and GPT models Five Hour Limit"]) #expect(rows.compactMap(\.percentLeft) == [20, 5]) #expect(WidgetUsageRow.smallWidgetRowLimit(for: entry) == 2) #expect(WidgetUsageRow.mediumWidgetRowLimit(for: entry) == 3) let mediumRows = WidgetUsageRow.rows( for: entry, limit: WidgetUsageRow.mediumWidgetRowLimit(for: entry)) #expect(mediumRows.map(\.title) == [ "Gemini Models Weekly Limit", "Claude and GPT models Five Hour Limit", "Claude and GPT models Weekly Limit", ]) } @Test func `small antigravity widget keeps claude gpt family when fallback rows are more constrained`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-5h", title: "Gemini Models Five Hour Limit", percentLeft: 40), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Models Weekly Limit", percentLeft: 70), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-3p-5h", title: "Claude and GPT models Five Hour Limit", percentLeft: 60), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-other-5h", title: "Other Five Hour Limit", percentLeft: 1), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.id) == [ "antigravity-quota-summary-gemini-5h", "antigravity-quota-summary-3p-5h", ]) } @Test func `small widget preserves tertiary rows for other providers`() { let entry = WidgetSnapshot.ProviderEntry( provider: .cursor, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot(id: "one", title: "One", percentLeft: 90), WidgetSnapshot.WidgetUsageRowSnapshot(id: "two", title: "Two", percentLeft: 80), WidgetSnapshot.WidgetUsageRowSnapshot(id: "three", title: "Three", percentLeft: 70), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let limit = WidgetUsageRow.smallWidgetRowLimit(for: entry) #expect(limit == nil) #expect(WidgetUsageRow.rows(for: entry, limit: limit).map(\.id) == ["one", "two", "three"]) } @Test func `small antigravity widget prefers known quota rows`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-session", title: "Gemini Models Five Hour Limit", percentLeft: nil), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Models Weekly Limit", percentLeft: 100), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-third-party-session", title: "Claude and GPT models Five Hour Limit", percentLeft: 80), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.title) == ["Gemini Models Weekly Limit", "Claude and GPT models Five Hour Limit"]) } @Test func `small antigravity widget keeps nonstandard quota groups visible`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-other-session", title: "Other Session", percentLeft: 70), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-other-weekly", title: "Other Weekly", percentLeft: 40), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.title) == ["Other Weekly", "Other Session"]) } @Test func `provider choice supports alibaba`() { #expect(ProviderChoice(provider: .alibaba) == .alibaba) #expect(ProviderChoice.alibaba.provider == .alibaba) } @Test func `provider choice supports alibaba token plan`() { #expect(ProviderChoice(provider: .alibabatokenplan) == .alibabatokenplan) #expect(ProviderChoice.alibabatokenplan.provider == .alibabatokenplan) } @Test func `provider choice supports opencode go`() { #expect(ProviderChoice(provider: .opencodego) == .opencodego) #expect(ProviderChoice.opencodego.provider == .opencodego) } @Test func `provider choice supports devin`() { #expect(ProviderChoice(provider: .devin) == .devin) #expect(ProviderChoice.devin.provider == .devin) } @Test func `widget entry carries devin overage balance through providerCost`() { let entry = WidgetSnapshot.ProviderEntry( provider: .devin, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 48.0, limit: 0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) let encoded = try? JSONEncoder().encode(entry) #expect(encoded != nil) let decoded = encoded.flatMap { try? JSONDecoder().decode(WidgetSnapshot.ProviderEntry.self, from: $0) } #expect(decoded?.providerCost?.period == "Extra usage balance") #expect(decoded?.providerCost?.used == 48.0) #expect(decoded?.providerCost?.limit == 0) #expect(decoded?.provider == .devin) } @Test func `widget balance formatter renders devin extra usage balance`() { let entry = WidgetSnapshot.ProviderEntry( provider: .devin, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 48.0, limit: 0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) let line = WidgetBalanceFormatter.extraUsageBalance(for: entry) #expect(line?.title == "Extra usage") #expect(line?.value.hasPrefix("Balance: ") == true) #expect(line?.value.contains("48") == true) } @Test func `compact credits render Devin extra usage balance`() { let entry = WidgetSnapshot.ProviderEntry( provider: .devin, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 48.0, limit: 0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) let display = CompactMetricFormatter.display(for: entry, metric: .credits) #expect(display.value.contains("48")) #expect(display.label == "Extra usage balance") #expect(display.detail == nil) } @Test func `widget balance formatter does not leak another provider balance`() { let entry = WidgetSnapshot.ProviderEntry( provider: .factory, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 12.0, limit: 100.0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) #expect(WidgetBalanceFormatter.extraUsageBalance(for: entry) == nil) } @Test func `provider choice supports Mistral`() { #expect(ProviderChoice(provider: .mistral) == .mistral) #expect(ProviderChoice.mistral.provider == .mistral) } @Test func `provider choice supports Kimi`() { #expect(ProviderChoice(provider: .kimi) == .kimi) #expect(ProviderChoice.kimi.provider == .kimi) } @Test func `compact Kimi widgets keep established row fit while large widgets show all quotas`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .kimi, updatedAt: now, primary: RateWindow(usedPercent: 25, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: RateWindow(usedPercent: 50, windowMinutes: 300, resetsAt: nil, resetDescription: nil), tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot(id: "primary", title: "Weekly", percentLeft: 75), WidgetSnapshot.WidgetUsageRowSnapshot(id: "secondary", title: "Rate Limit", percentLeft: 50), WidgetSnapshot.WidgetUsageRowSnapshot(id: "kimi-monthly", title: "Monthly", percentLeft: 25), WidgetSnapshot.WidgetUsageRowSnapshot(id: "kimi-code-7d", title: "Code 7-day", percentLeft: 90), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let smallRows = WidgetUsageRow.rows( for: entry, limit: WidgetUsageRow.smallWidgetRowLimit(for: entry)) let mediumRows = WidgetUsageRow.rows( for: entry, limit: WidgetUsageRow.mediumWidgetRowLimit(for: entry)) let largeRows = WidgetUsageRow.rows(for: entry) #expect(WidgetUsageRow.smallWidgetRowLimit(for: entry) == 3) #expect(WidgetUsageRow.mediumWidgetRowLimit(for: entry) == 3) #expect(smallRows.map(\.id) == ["primary", "secondary", "kimi-monthly"]) #expect(mediumRows == smallRows) #expect(largeRows.map(\.id) == ["primary", "secondary", "kimi-monthly", "kimi-code-7d"]) } @Test func `provider choice excludes unsupported Chutes widgets`() { #expect(ProviderChoice(provider: .chutes) == nil) #expect(ProviderChoice(provider: .sub2api) == nil) } @Test func `supported providers fall back to codex when snapshot is empty`() { let snapshot = WidgetSnapshot(entries: [], enabledProviders: [], generatedAt: Date()) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.codex]) } @Test func `supported providers keep alibaba when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .alibaba, updatedAt: now, primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.alibaba], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.alibaba]) } @Test func `supported providers keep alibaba token plan when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .alibabatokenplan, updatedAt: now, primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.alibabatokenplan], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.alibabatokenplan]) } @Test func `supported providers keep Mistral when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .mistral, updatedAt: now, primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.mistral], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.mistral]) } @Test func `supported providers keep Kimi when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .kimi, updatedAt: now, primary: RateWindow(usedPercent: 25, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: RateWindow(usedPercent: 50, windowMinutes: 300, resetsAt: nil, resetDescription: nil), tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.kimi], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.kimi]) } @Test func `codex weekly only widget rows omit session`() { let now = Date(timeIntervalSince1970: 1_700_000_000)Lines 1–500 of 980. Load more
import Foundation import Testing @testable import CodexBarCore @testable import CodexBarWidget struct CodexBarWidgetProviderTests { @Test func `usage display follows remaining and used preference`() { #expect(WidgetUsageDisplay.percent(fromRemaining: 48, showUsed: false) == 48) #expect(WidgetUsageDisplay.percent(fromRemaining: 48, showUsed: true) == 52) #expect(WidgetUsageDisplay.percent(fromRemaining: nil, showUsed: true) == nil) } @Test func `small widget falls back to local cost when quota rows are unavailable`() { let tokenUsage = WidgetSnapshot.TokenUsageSummary( sessionCostUSD: 1.25, sessionTokens: 4200, last30DaysCostUSD: 12.50, last30DaysTokens: 42000, currencyCode: "USD", sessionLabel: "Today", last30DaysLabel: "30d") let entry = WidgetSnapshot.ProviderEntry( provider: .claude, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: tokenUsage, dailyUsage: []) let windowedEntry = WidgetSnapshot.ProviderEntry( provider: .claude, updatedAt: Date(), primary: RateWindow(usedPercent: 25, windowMinutes: 300, resetsAt: nil, resetDescription: nil), secondary: nil, tertiary: nil, usageRows: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: tokenUsage, dailyUsage: []) #expect(WidgetUsageRow.compactTokenUsage(for: entry)?.sessionTokens == 4200) #expect(WidgetUsageRow.compactTokenUsage(for: windowedEntry) == nil) } @Test func `small widget limits custom usage rows`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot(id: "one", title: "One", percentLeft: 90), WidgetSnapshot.WidgetUsageRowSnapshot(id: "two", title: "Two", percentLeft: 80), WidgetSnapshot.WidgetUsageRowSnapshot(id: "three", title: "Three", percentLeft: 70), WidgetSnapshot.WidgetUsageRowSnapshot(id: "four", title: "Four", percentLeft: 60), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) #expect(WidgetUsageRow.rows(for: entry, limit: 2).map(\.id) == ["one", "two"]) #expect(WidgetUsageRow.rows(for: entry).count == 4) } @Test func `small antigravity widget keeps one row per quota family`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-session", title: "Gemini Models Five Hour Limit", percentLeft: 80), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Models Weekly Limit", percentLeft: 20), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-third-party-session", title: "Claude and GPT models Five Hour Limit", percentLeft: 5), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-third-party-weekly", title: "Claude and GPT models Weekly Limit", percentLeft: 60), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.title) == ["Gemini Models Weekly Limit", "Claude and GPT models Five Hour Limit"]) #expect(rows.compactMap(\.percentLeft) == [20, 5]) #expect(WidgetUsageRow.smallWidgetRowLimit(for: entry) == 2) #expect(WidgetUsageRow.mediumWidgetRowLimit(for: entry) == 3) let mediumRows = WidgetUsageRow.rows( for: entry, limit: WidgetUsageRow.mediumWidgetRowLimit(for: entry)) #expect(mediumRows.map(\.title) == [ "Gemini Models Weekly Limit", "Claude and GPT models Five Hour Limit", "Claude and GPT models Weekly Limit", ]) } @Test func `small antigravity widget keeps claude gpt family when fallback rows are more constrained`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-5h", title: "Gemini Models Five Hour Limit", percentLeft: 40), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Models Weekly Limit", percentLeft: 70), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-3p-5h", title: "Claude and GPT models Five Hour Limit", percentLeft: 60), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-other-5h", title: "Other Five Hour Limit", percentLeft: 1), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.id) == [ "antigravity-quota-summary-gemini-5h", "antigravity-quota-summary-3p-5h", ]) } @Test func `small widget preserves tertiary rows for other providers`() { let entry = WidgetSnapshot.ProviderEntry( provider: .cursor, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot(id: "one", title: "One", percentLeft: 90), WidgetSnapshot.WidgetUsageRowSnapshot(id: "two", title: "Two", percentLeft: 80), WidgetSnapshot.WidgetUsageRowSnapshot(id: "three", title: "Three", percentLeft: 70), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let limit = WidgetUsageRow.smallWidgetRowLimit(for: entry) #expect(limit == nil) #expect(WidgetUsageRow.rows(for: entry, limit: limit).map(\.id) == ["one", "two", "three"]) } @Test func `small antigravity widget prefers known quota rows`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-session", title: "Gemini Models Five Hour Limit", percentLeft: nil), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-gemini-weekly", title: "Gemini Models Weekly Limit", percentLeft: 100), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-third-party-session", title: "Claude and GPT models Five Hour Limit", percentLeft: 80), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.title) == ["Gemini Models Weekly Limit", "Claude and GPT models Five Hour Limit"]) } @Test func `small antigravity widget keeps nonstandard quota groups visible`() { let entry = WidgetSnapshot.ProviderEntry( provider: .antigravity, updatedAt: Date(), primary: nil, secondary: nil, tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-other-session", title: "Other Session", percentLeft: 70), WidgetSnapshot.WidgetUsageRowSnapshot( id: "antigravity-quota-summary-other-weekly", title: "Other Weekly", percentLeft: 40), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let rows = WidgetUsageRow.rows(for: entry, limit: 2) #expect(rows.map(\.title) == ["Other Weekly", "Other Session"]) } @Test func `provider choice supports alibaba`() { #expect(ProviderChoice(provider: .alibaba) == .alibaba) #expect(ProviderChoice.alibaba.provider == .alibaba) } @Test func `provider choice supports alibaba token plan`() { #expect(ProviderChoice(provider: .alibabatokenplan) == .alibabatokenplan) #expect(ProviderChoice.alibabatokenplan.provider == .alibabatokenplan) } @Test func `provider choice supports opencode go`() { #expect(ProviderChoice(provider: .opencodego) == .opencodego) #expect(ProviderChoice.opencodego.provider == .opencodego) } @Test func `provider choice supports devin`() { #expect(ProviderChoice(provider: .devin) == .devin) #expect(ProviderChoice.devin.provider == .devin) } @Test func `widget entry carries devin overage balance through providerCost`() { let entry = WidgetSnapshot.ProviderEntry( provider: .devin, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 48.0, limit: 0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) let encoded = try? JSONEncoder().encode(entry) #expect(encoded != nil) let decoded = encoded.flatMap { try? JSONDecoder().decode(WidgetSnapshot.ProviderEntry.self, from: $0) } #expect(decoded?.providerCost?.period == "Extra usage balance") #expect(decoded?.providerCost?.used == 48.0) #expect(decoded?.providerCost?.limit == 0) #expect(decoded?.provider == .devin) } @Test func `widget balance formatter renders devin extra usage balance`() { let entry = WidgetSnapshot.ProviderEntry( provider: .devin, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 48.0, limit: 0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) let line = WidgetBalanceFormatter.extraUsageBalance(for: entry) #expect(line?.title == "Extra usage") #expect(line?.value.hasPrefix("Balance: ") == true) #expect(line?.value.contains("48") == true) } @Test func `compact credits render Devin extra usage balance`() { let entry = WidgetSnapshot.ProviderEntry( provider: .devin, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 48.0, limit: 0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) let display = CompactMetricFormatter.display(for: entry, metric: .credits) #expect(display.value.contains("48")) #expect(display.label == "Extra usage balance") #expect(display.detail == nil) } @Test func `widget balance formatter does not leak another provider balance`() { let entry = WidgetSnapshot.ProviderEntry( provider: .factory, updatedAt: Date(timeIntervalSince1970: 1_700_000_000), primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: [], providerCost: ProviderCostSnapshot( used: 12.0, limit: 100.0, currencyCode: "USD", period: "Extra usage balance", updatedAt: Date(timeIntervalSince1970: 1_700_000_000))) #expect(WidgetBalanceFormatter.extraUsageBalance(for: entry) == nil) } @Test func `provider choice supports Mistral`() { #expect(ProviderChoice(provider: .mistral) == .mistral) #expect(ProviderChoice.mistral.provider == .mistral) } @Test func `provider choice supports Kimi`() { #expect(ProviderChoice(provider: .kimi) == .kimi) #expect(ProviderChoice.kimi.provider == .kimi) } @Test func `compact Kimi widgets keep established row fit while large widgets show all quotas`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .kimi, updatedAt: now, primary: RateWindow(usedPercent: 25, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: RateWindow(usedPercent: 50, windowMinutes: 300, resetsAt: nil, resetDescription: nil), tertiary: nil, usageRows: [ WidgetSnapshot.WidgetUsageRowSnapshot(id: "primary", title: "Weekly", percentLeft: 75), WidgetSnapshot.WidgetUsageRowSnapshot(id: "secondary", title: "Rate Limit", percentLeft: 50), WidgetSnapshot.WidgetUsageRowSnapshot(id: "kimi-monthly", title: "Monthly", percentLeft: 25), WidgetSnapshot.WidgetUsageRowSnapshot(id: "kimi-code-7d", title: "Code 7-day", percentLeft: 90), ], creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let smallRows = WidgetUsageRow.rows( for: entry, limit: WidgetUsageRow.smallWidgetRowLimit(for: entry)) let mediumRows = WidgetUsageRow.rows( for: entry, limit: WidgetUsageRow.mediumWidgetRowLimit(for: entry)) let largeRows = WidgetUsageRow.rows(for: entry) #expect(WidgetUsageRow.smallWidgetRowLimit(for: entry) == 3) #expect(WidgetUsageRow.mediumWidgetRowLimit(for: entry) == 3) #expect(smallRows.map(\.id) == ["primary", "secondary", "kimi-monthly"]) #expect(mediumRows == smallRows) #expect(largeRows.map(\.id) == ["primary", "secondary", "kimi-monthly", "kimi-code-7d"]) } @Test func `provider choice excludes unsupported Chutes widgets`() { #expect(ProviderChoice(provider: .chutes) == nil) #expect(ProviderChoice(provider: .sub2api) == nil) } @Test func `supported providers fall back to codex when snapshot is empty`() { let snapshot = WidgetSnapshot(entries: [], enabledProviders: [], generatedAt: Date()) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.codex]) } @Test func `supported providers keep alibaba when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .alibaba, updatedAt: now, primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.alibaba], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.alibaba]) } @Test func `supported providers keep alibaba token plan when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .alibabatokenplan, updatedAt: now, primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.alibabatokenplan], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.alibabatokenplan]) } @Test func `supported providers keep Mistral when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .mistral, updatedAt: now, primary: nil, secondary: nil, tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.mistral], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.mistral]) } @Test func `supported providers keep Kimi when it is the only enabled provider`() { let now = Date(timeIntervalSince1970: 1_700_000_000) let entry = WidgetSnapshot.ProviderEntry( provider: .kimi, updatedAt: now, primary: RateWindow(usedPercent: 25, windowMinutes: nil, resetsAt: nil, resetDescription: nil), secondary: RateWindow(usedPercent: 50, windowMinutes: 300, resetsAt: nil, resetDescription: nil), tertiary: nil, creditsRemaining: nil, codeReviewRemainingPercent: nil, tokenUsage: nil, dailyUsage: []) let snapshot = WidgetSnapshot(entries: [entry], enabledProviders: [.kimi], generatedAt: now) #expect(CodexBarSwitcherTimelineProvider.supportedProviders(from: snapshot) == [.kimi]) } @Test func `codex weekly only widget rows omit session`() { let now = Date(timeIntervalSince1970: 1_700_000_000)