项目文件夹

文件
2026-07-13 12:22:33 +08:00

893 行
36 KiB
Swift

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
import AppKit
import CodexBarCore
import Foundation
import Testing
@testable import CodexBar
struct CodexBarTests {
@Test
func `icon renderer produces template image`() {
let image = IconRenderer.makeIcon(
primaryRemaining: 50,
weeklyRemaining: 75,
creditsRemaining: 500,
stale: false,
style: .codex)
#expect(image.isTemplate)
#expect(image.size.width > 0)
}
@Test
func `icon renderer renders at pixel aligned size`() {
let image = IconRenderer.makeIcon(
primaryRemaining: 50,
weeklyRemaining: 75,
creditsRemaining: 500,
stale: false,
style: .claude)
let bitmapReps = image.representations.compactMap { $0 as? NSBitmapImageRep }
#expect(bitmapReps.contains { rep in
rep.pixelsWide == 36 && rep.pixelsHigh == 36
})
}
@Test
func `icon renderer caches static icons`() {
let first = IconRenderer.makeIcon(
primaryRemaining: 42,
weeklyRemaining: 17,
creditsRemaining: 250,
stale: false,
style: .codex)
let second = IconRenderer.makeIcon(
primaryRemaining: 42,
weeklyRemaining: 17,
creditsRemaining: 250,
stale: false,
style: .codex)
#expect(first === second)
}
@Test
func `antigravity icon ignores legacy model quota lanes`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 30, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 60, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
tertiary: RateWindow(usedPercent: 80, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
extraRateWindows: [
NamedRateWindow(
id: "antigravity-compact-fallback-model",
title: "New Model",
window: RateWindow(
usedPercent: 64,
windowMinutes: nil,
resetsAt: nil,
resetDescription: nil)),
],
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .antigravity)
#expect(remaining.primary == nil)
#expect(remaining.secondary == nil)
}
@Test
func `antigravity quota summary icon shows session on top and weekly on bottom`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 84, windowMinutes: 10080, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil),
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-gemini-weekly",
title: "Gemini Weekly",
window: RateWindow(usedPercent: 84, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-gemini-5h",
title: "Gemini Session",
window: RateWindow(usedPercent: 97, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-weekly",
title: "Claude + GPT Weekly",
window: RateWindow(usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-5h",
title: "Claude + GPT Session",
window: RateWindow(usedPercent: 98, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let windows = IconRemainingResolver.resolvedWindows(snapshot: snapshot, style: .antigravity)
#expect(windows.primary?.windowMinutes == 300)
#expect(windows.primary?.remainingPercent == 2)
#expect(windows.secondary?.windowMinutes == 10080)
#expect(windows.secondary?.remainingPercent == 1)
}
@Test
func `antigravity renderer draws primary above secondary`() throws {
let image = IconRenderer.makeIcon(
primaryRemaining: 100,
weeklyRemaining: 10,
creditsRemaining: nil,
stale: false,
style: .antigravity)
let bitmapReps = image.representations.compactMap { $0 as? NSBitmapImageRep }
let matchingRep = bitmapReps.first { rep in
rep.pixelsWide == 36 && rep.pixelsHigh == 36
}
let rep = try #require(matchingRep)
func averageAlpha(xRange: ClosedRange<Int>, yRange: ClosedRange<Int>) -> CGFloat {
var total: CGFloat = 0
var count: CGFloat = 0
for y in yRange {
for x in xRange {
total += (rep.colorAt(x: x, y: y) ?? .clear).alphaComponent
count += 1
}
}
return total / count
}
let visualTopRightAlpha = averageAlpha(xRange: 24...30, yRange: 7...10)
let visualBottomRightAlpha = averageAlpha(xRange: 24...30, yRange: 22...28)
#expect(visualTopRightAlpha > visualBottomRightAlpha + 0.2)
}
@Test
func `antigravity quota summary icon uses most constrained quota summary lanes`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-gemini-weekly",
title: "Renamed Weekly",
window: RateWindow(usedPercent: 30, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-gemini-5h",
title: "Renamed Session",
window: RateWindow(usedPercent: 40, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-weekly",
title: "Gemini Weekly",
window: RateWindow(usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-5h",
title: "Gemini Session",
window: RateWindow(usedPercent: 98, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let windows = IconRemainingResolver.resolvedWindows(snapshot: snapshot, style: .antigravity)
#expect(windows.primary?.remainingPercent == 2)
#expect(windows.secondary?.remainingPercent == 1)
}
@Test
func `antigravity quota summary icon can pair gemini session with claude gpt weekly`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-gemini-5h",
title: "Gemini Session",
window: RateWindow(usedPercent: 40, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-weekly",
title: "Claude + GPT Weekly",
window: RateWindow(usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let windows = IconRemainingResolver.resolvedWindows(snapshot: snapshot, style: .antigravity)
#expect(windows.primary?.remainingPercent == 60)
#expect(windows.secondary?.remainingPercent == 1)
}
@Test
func `antigravity quota summary icon ignores unknown rows while ranking known lanes`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-gemini-weekly",
title: "Gemini Weekly",
window: RateWindow(usedPercent: 100, windowMinutes: 10080, resetsAt: nil, resetDescription: nil),
usageKnown: false),
NamedRateWindow(
id: "antigravity-quota-summary-3p-weekly",
title: "Claude + GPT Weekly",
window: RateWindow(usedPercent: 99, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let windows = IconRemainingResolver.resolvedWindows(snapshot: snapshot, style: .antigravity)
#expect(windows.primary == nil)
#expect(windows.secondary?.remainingPercent == 1)
}
@Test
func `antigravity used icon percent matches constrained claude gpt lane`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-gemini-5h",
title: "Gemini Session",
window: RateWindow(usedPercent: 20, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-gemini-weekly",
title: "Gemini Weekly",
window: RateWindow(usedPercent: 30, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-5h",
title: "Claude + GPT Session",
window: RateWindow(usedPercent: 95, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-weekly",
title: "Claude + GPT Weekly",
window: RateWindow(usedPercent: 40, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let percents = IconRemainingResolver.resolvedPercents(
snapshot: snapshot,
style: .antigravity,
showUsed: true)
#expect(percents.primary == 95)
#expect(percents.secondary == 40)
}
@Test
func `antigravity quota summary icon falls back when gemini rows are absent`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-3p-5h",
title: "Claude + GPT Session",
window: RateWindow(usedPercent: 75, windowMinutes: 300, resetsAt: nil, resetDescription: nil)),
NamedRateWindow(
id: "antigravity-quota-summary-3p-weekly",
title: "Claude + GPT Weekly",
window: RateWindow(usedPercent: 88, windowMinutes: 10080, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let windows = IconRemainingResolver.resolvedWindows(snapshot: snapshot, style: .antigravity)
#expect(windows.primary?.remainingPercent == 25)
#expect(windows.secondary?.remainingPercent == 12)
}
@Test
func `antigravity quota summary icon tie break is stable`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: nil,
extraRateWindows: [
NamedRateWindow(
id: "antigravity-quota-summary-gemini-z-5h",
title: "Gemini Session",
window: RateWindow(
usedPercent: 50,
windowMinutes: 300,
resetsAt: nil,
resetDescription: "second-by-id")),
NamedRateWindow(
id: "antigravity-quota-summary-gemini-a-5h",
title: "Gemini Session",
window: RateWindow(
usedPercent: 50,
windowMinutes: 300,
resetsAt: nil,
resetDescription: "first-by-id")),
],
updatedAt: Date())
let windows = IconRemainingResolver.resolvedWindows(snapshot: snapshot, style: .antigravity)
#expect(windows.primary?.resetDescription == "first-by-id")
#expect(windows.secondary == nil)
}
@Test
func `perplexity icon falls back to purchased lane when bonus is exhausted`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: RateWindow(usedPercent: 100, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
tertiary: RateWindow(usedPercent: 20, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .perplexity)
#expect(remaining.primary == 80)
#expect(remaining.secondary == 0)
}
@Test
func `perplexity icon skips exhausted recurring lane when purchased credits remain`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 100, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 100, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
tertiary: RateWindow(usedPercent: 20, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .perplexity)
#expect(remaining.primary == 80)
#expect(remaining.secondary == 0)
}
@Test
func `perplexity icon prefers purchased lane before bonus`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: RateWindow(usedPercent: 20, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
tertiary: RateWindow(usedPercent: 45, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .perplexity)
#expect(remaining.primary == 55)
#expect(remaining.secondary == 80)
}
@Test
func `kimi icon renders primary bar when secondary is nil`() throws {
// Regression: Kimi account connected with usage, but no progress bar shown (issue #1043).
// When secondary (rate limit) is absent, the icon renderer must still show
// the primary (weekly quota) bar.
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 18.3, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: nil,
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .kimi)
guard let primaryRemaining = remaining.primary else {
Issue.record("remaining.primary was nil after IconRemainingResolver check")
return
}
#expect(primaryRemaining > 0) // 81.7% remaining
#expect(remaining.secondary == nil)
let image = IconRenderer.makeIcon(
primaryRemaining: remaining.primary,
weeklyRemaining: remaining.secondary,
creditsRemaining: nil,
stale: false,
style: .kimi)
#expect(image.size.width > 0)
#expect(image.isTemplate)
// Prove the primary bar is actually rendered using pixel inspection.
// Top bar rect: x ∈ [3, 33], y ∈ [19, 31] in the 36×36 canvas (barXPx=3, barWidthPx=30, y=19, h=12).
let bitmapReps = image.representations.compactMap { $0 as? NSBitmapImageRep }
let rep = try #require(bitmapReps.first { $0.pixelsWide == 36 && $0.pixelsHigh == 36 })
func alphaAt(px x: Int, _ y: Int) -> CGFloat {
(rep.colorAt(x: x, y: y) ?? .clear).alphaComponent
}
func regionHasFill(xRange: ClosedRange<Int>, yRange: ClosedRange<Int>) -> Bool {
for y in yRange {
for x in xRange where alphaAt(px: x, y) > 0.05 {
return true
}
}
return false
}
// Primary bar (top track) must have fill to prove the progress bar rendered.
#expect(regionHasFill(xRange: 3...33, yRange: 19...31))
}
@Test
func `copilot icon can use selected budget as secondary lane`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 20, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 30, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
extraRateWindows: [
NamedRateWindow(
id: "copilot-budget-agent",
title: "Budget - Copilot Agent Premium Requests",
window: RateWindow(usedPercent: 65, windowMinutes: nil, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(
snapshot: snapshot,
style: .copilot,
secondaryOverrideWindowID: "copilot-budget-agent")
#expect(remaining.primary == 80)
#expect(remaining.secondary == 35)
}
@Test
func `copying extra rate windows preserves subscription dates`() {
let expiresAt = Date(timeIntervalSince1970: 1_810_656_000)
let renewsAt = Date(timeIntervalSince1970: 1_810_569_600)
let ampUsage = AmpUsageDetails(
individualCredits: 12.5,
workspaceBalances: [AmpWorkspaceBalance(name: "Team", remaining: 7.25)])
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
ampUsage: ampUsage,
subscriptionExpiresAt: expiresAt,
subscriptionRenewsAt: renewsAt,
updatedAt: Date(timeIntervalSince1970: 1_800_000_000))
let copied = snapshot.with(extraRateWindows: [])
#expect(copied.subscriptionExpiresAt == expiresAt)
#expect(copied.subscriptionRenewsAt == renewsAt)
#expect(copied.ampUsage == ampUsage)
}
@Test
func `copying rate windows preserves provider payloads`() {
let updatedAt = Date(timeIntervalSince1970: 1_800_000_000)
let mimoUsage = MiMoUsageSnapshot(
balance: 12.5,
currency: "USD",
tokenUsed: 25,
tokenLimit: 100,
tokenPercent: 0.25,
updatedAt: updatedAt)
let identity = ProviderIdentitySnapshot(
providerID: .codex,
accountEmail: "test@example.com",
accountOrganization: "Example",
loginMethod: "OAuth")
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
tertiary: RateWindow(usedPercent: 30, windowMinutes: 60, resetsAt: nil, resetDescription: nil),
mimoUsage: mimoUsage,
cursorRequests: CursorRequestUsage(used: 10, limit: 50),
subscriptionExpiresAt: updatedAt.addingTimeInterval(100),
subscriptionRenewsAt: updatedAt.addingTimeInterval(200),
updatedAt: updatedAt,
identity: identity)
let copied = snapshot.with(
primary: RateWindow(usedPercent: 40, windowMinutes: 300, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 50, windowMinutes: 10080, resetsAt: nil, resetDescription: nil))
#expect(copied.primary?.usedPercent == 40)
#expect(copied.secondary?.usedPercent == 50)
#expect(copied.tertiary?.usedPercent == 30)
#expect(copied.mimoUsage?.balance == 12.5)
#expect(copied.cursorRequests?.used == 10)
#expect(copied.subscriptionExpiresAt == updatedAt.addingTimeInterval(100))
#expect(copied.subscriptionRenewsAt == updatedAt.addingTimeInterval(200))
#expect(copied.identity?.accountOrganization == "Example")
}
@Test
func `copying identity preserves provider payloads`() {
let updatedAt = Date(timeIntervalSince1970: 1_800_000_000)
let ampUsage = AmpUsageDetails(
individualCredits: 12.5,
workspaceBalances: [AmpWorkspaceBalance(name: "Team", remaining: 7.25)])
let snapshot = UsageSnapshot(
primary: nil,
secondary: nil,
ampUsage: ampUsage,
cursorRequests: CursorRequestUsage(used: 10, limit: 50),
subscriptionExpiresAt: updatedAt.addingTimeInterval(100),
subscriptionRenewsAt: updatedAt.addingTimeInterval(200),
updatedAt: updatedAt)
let identity = ProviderIdentitySnapshot(
providerID: .kilo,
accountEmail: "test@example.com",
accountOrganization: "Example",
loginMethod: "API")
let copied = snapshot.withIdentity(identity)
#expect(copied.ampUsage == ampUsage)
#expect(copied.cursorRequests?.used == 10)
#expect(copied.subscriptionExpiresAt == updatedAt.addingTimeInterval(100))
#expect(copied.subscriptionRenewsAt == updatedAt.addingTimeInterval(200))
#expect(copied.identity?.accountOrganization == "Example")
}
@Test
func `copilot icon falls back to chat lane when selected budget is unavailable`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 20, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 30, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
extraRateWindows: nil,
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(
snapshot: snapshot,
style: .copilot,
secondaryOverrideWindowID: "copilot-budget-agent")
#expect(remaining.primary == 80)
#expect(remaining.secondary == 70)
}
@Test
func `copilot icon uses selected budget in show used mode`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 20, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 30, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
extraRateWindows: [
NamedRateWindow(
id: "copilot-budget-agent",
title: "Budget - Copilot Agent Premium Requests",
window: RateWindow(usedPercent: 65, windowMinutes: nil, resetsAt: nil, resetDescription: nil)),
],
updatedAt: Date())
let percents = IconRemainingResolver.resolvedPercents(
snapshot: snapshot,
style: .copilot,
showUsed: true,
secondaryOverrideWindowID: "copilot-budget-agent")
#expect(percents.primary == 20)
#expect(percents.secondary == 65)
}
@Test
func `warp icon preserves exhausted bonus layout in show used mode`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 10, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 100, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
updatedAt: Date())
let percents = IconRemainingResolver.resolvedPercents(
snapshot: snapshot,
style: .warp,
showUsed: true)
#expect(percents.primary == 10)
#expect(percents.secondary == 0)
}
@Test
func `warp icon keeps unused bonus lane visible in show used mode`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 10, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
updatedAt: Date())
let percents = IconRemainingResolver.resolvedPercents(
snapshot: snapshot,
style: .warp,
showUsed: true)
#expect(percents.primary == 10)
#expect(percents.secondary != nil)
#expect(percents.secondary ?? 1 < 0.01)
}
@Test
func `merged icon keeps exhausted warp bonus fully used`() {
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 10, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: RateWindow(usedPercent: 100, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
updatedAt: Date())
let percents = IconRemainingResolver.resolvedPercents(
snapshot: snapshot,
style: .warp,
showUsed: true,
renderingStyle: .combined)
#expect(percents.primary == 10)
#expect(percents.secondary == 100)
}
@Test
@MainActor
func `status icon accessibility uses percentage scale`() {
#expect(
StatusIconView.accessibilityPercentRemaining(50) ==
String(format: L("%d percent remaining"), 50))
}
@Test
func `codex icon promotes weekly only window into primary display lane`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: RateWindow(usedPercent: 25, windowMinutes: 10080, resetsAt: nil, resetDescription: nil),
tertiary: nil,
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .codex)
#expect(remaining.primary == 75)
#expect(remaining.secondary == nil)
}
@Test
func `codex icon uses semantic projection lanes when durations drift`() {
let snapshot = UsageSnapshot(
primary: nil,
secondary: RateWindow(usedPercent: 25, windowMinutes: 11040, resetsAt: nil, resetDescription: nil),
tertiary: nil,
updatedAt: Date())
let remaining = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .codex)
#expect(remaining.primary == 75)
#expect(remaining.secondary == nil)
}
@Test
func `codex icon caps session only until exhausted weekly lane resets`() {
let now = Date(timeIntervalSince1970: 1_800_000_000)
let weeklyReset = now.addingTimeInterval(3600)
let snapshot = UsageSnapshot(
primary: RateWindow(
usedPercent: 1,
windowMinutes: 300,
resetsAt: now.addingTimeInterval(1800),
resetDescription: nil),
secondary: RateWindow(
usedPercent: 100,
windowMinutes: 10080,
resetsAt: weeklyReset,
resetDescription: nil),
updatedAt: now.addingTimeInterval(-7200))
let capped = IconRemainingResolver.resolvedRemaining(snapshot: snapshot, style: .codex, now: now)
let reset = IconRemainingResolver.resolvedRemaining(
snapshot: snapshot,
style: .codex,
now: weeklyReset)
#expect(capped.primary == 0)
#expect(capped.secondary == 0)
#expect(reset.primary == 99)
#expect(reset.secondary == nil)
}
@Test
func `status overlays cut halos through the quota bar and keep glyphs visible`() throws {
let plain = IconRenderer.makeIcon(
primaryRemaining: 100,
weeklyRemaining: 100,
creditsRemaining: nil,
stale: false,
style: .combined,
statusIndicator: .none)
let plainRep = try #require(plain.representations.compactMap { $0 as? NSBitmapImageRep }.first {
$0.pixelsWide == 36 && $0.pixelsHigh == 36
})
func alpha(_ rep: NSBitmapImageRep, x: Int, y: Int) -> CGFloat {
(rep.colorAt(x: x, y: y) ?? .clear).alphaComponent
}
for indicator in [ProviderStatusIndicator.minor, .major] {
let marked = IconRenderer.makeIcon(
primaryRemaining: 100,
weeklyRemaining: 100,
creditsRemaining: nil,
stale: false,
style: .combined,
statusIndicator: indicator)
let markedRep = try #require(marked.representations.compactMap { $0 as? NSBitmapImageRep }.first {
$0.pixelsWide == 36 && $0.pixelsHigh == 36
})
var cutoutPixels = 0
var glyphPixels = 0
for y in 0..<markedRep.pixelsHigh {
for x in 0..<markedRep.pixelsWide {
let plainAlpha = alpha(plainRep, x: x, y: y)
let markedAlpha = alpha(markedRep, x: x, y: y)
if plainAlpha > 0.5, markedAlpha < 0.05 {
cutoutPixels += 1
}
if plainAlpha < 0.05, markedAlpha > 0.5 {
glyphPixels += 1
}
}
}
#expect(cutoutPixels >= 8, "Expected halo cutout pixels for \(indicator)")
#expect(glyphPixels >= 4, "Expected visible glyph pixels for \(indicator)")
}
}
@Test
func `icon renderer codex eyes punch through when unknown`() {
// Regression: when remaining is nil, CoreGraphics inherits the previous fill alpha which caused
// destinationOut “eyes” to become semi-transparent instead of fully punched through.
let image = IconRenderer.makeIcon(
primaryRemaining: nil,
weeklyRemaining: 1,
creditsRemaining: nil,
stale: false,
style: .codex)
let bitmapReps = image.representations.compactMap { $0 as? NSBitmapImageRep }
let rep = bitmapReps.first(where: { $0.pixelsWide == 36 && $0.pixelsHigh == 36 })
#expect(rep != nil)
guard let rep else { return }
func alphaAt(px x: Int, _ y: Int) -> CGFloat {
(rep.colorAt(x: x, y: y) ?? .clear).alphaComponent
}
let w = rep.pixelsWide
let h = rep.pixelsHigh
let isTransparent: (Int, Int) -> Bool = { x, y in
alphaAt(px: x, y) < 0.05
}
// Flood-fill from the border through transparent pixels to label the "outside".
var visited = Array(repeating: Array(repeating: false, count: w), count: h)
var queue: [(Int, Int)] = []
queue.reserveCapacity(w * 2 + h * 2)
func enqueueIfOutside(_ x: Int, _ y: Int) {
guard x >= 0, x < w, y >= 0, y < h else { return }
guard !visited[y][x], isTransparent(x, y) else { return }
visited[y][x] = true
queue.append((x, y))
}
for x in 0..<w {
enqueueIfOutside(x, 0)
enqueueIfOutside(x, h - 1)
}
for y in 0..<h {
enqueueIfOutside(0, y)
enqueueIfOutside(w - 1, y)
}
while let (x, y) = queue.first {
queue.removeFirst()
enqueueIfOutside(x + 1, y)
enqueueIfOutside(x - 1, y)
enqueueIfOutside(x, y + 1)
enqueueIfOutside(x, y - 1)
}
// Any remaining transparent pixels not reachable from the border are internal holes (i.e. the eyes).
var internalHoles = 0
for y in 0..<h {
for x in 0..<w where isTransparent(x, y) && !visited[y][x] {
internalHoles += 1
}
}
#expect(internalHoles >= 16) // at least one 4×4 eye block, but typically two eyes => 32
}
@Test
func `icon renderer warp eyes cut out at expected centers`() {
// Regression: Warp eyes should be tilted in-place and remain centered on the face.
let image = IconRenderer.makeIcon(
primaryRemaining: 50,
weeklyRemaining: 50,
creditsRemaining: nil,
stale: false,
style: .warp)
let bitmapReps = image.representations.compactMap { $0 as? NSBitmapImageRep }
let rep = bitmapReps.first(where: { $0.pixelsWide == 36 && $0.pixelsHigh == 36 })
#expect(rep != nil)
guard let rep else { return }
func alphaAt(px x: Int, _ y: Int) -> CGFloat {
(rep.colorAt(x: x, y: y) ?? .clear).alphaComponent
}
func minAlphaNear(px cx: Int, _ cy: Int, radius: Int) -> CGFloat {
var minAlpha: CGFloat = 1.0
let x0 = max(0, cx - radius)
let x1 = min(rep.pixelsWide - 1, cx + radius)
let y0 = max(0, cy - radius)
let y1 = min(rep.pixelsHigh - 1, cy + radius)
for y in y0...y1 {
for x in x0...x1 {
minAlpha = min(minAlpha, alphaAt(px: x, y))
}
}
return minAlpha
}
func minAlphaNearEitherOrigin(px cx: Int, _ cy: Int, radius: Int) -> CGFloat {
let flippedY = (rep.pixelsHigh - 1) - cy
return min(minAlphaNear(px: cx, cy, radius: radius), minAlphaNear(px: cx, flippedY, radius: radius))
}
// These are the center pixels for the two Warp eye cutouts in the top bar (36×36 canvas).
// If the eyes are rotated around the wrong origin, these points will not be fully punched out.
let leftEyeCenter = (x: 11, y: 25)
let rightEyeCenter = (x: 25, y: 25)
// The eye ellipse height is even (8 px), so the exact center can land between pixel rows.
// Assert via a small neighborhood search rather than a single pixel.
#expect(minAlphaNearEitherOrigin(px: leftEyeCenter.x, leftEyeCenter.y, radius: 2) < 0.05)
#expect(minAlphaNearEitherOrigin(px: rightEyeCenter.x, rightEyeCenter.y, radius: 2) < 0.05)
// Sanity: nearby top bar track area should remain visible (not everything is transparent).
let midAlpha = max(alphaAt(px: 18, 25), alphaAt(px: 18, (rep.pixelsHigh - 1) - 25))
#expect(midAlpha > 0.05)
}
@Test
func `account info parses snake case auth token`() throws {
let tmp = try FileManager.default.url(
for: .itemReplacementDirectory,
in: .userDomainMask,
appropriateFor: URL(fileURLWithPath: NSTemporaryDirectory()),
create: true)
defer { try? FileManager.default.removeItem(at: tmp) }
let token = Self.fakeJWT(email: "user@example.com", plan: "pro")
let auth = ["tokens": ["id_token": token, "access_token": "access", "refresh_token": "refresh"]]
let data = try JSONSerialization.data(withJSONObject: auth)
let authURL = tmp.appendingPathComponent("auth.json")
try data.write(to: authURL)
let fetcher = UsageFetcher(environment: ["CODEX_HOME": tmp.path])
let account = fetcher.loadAccountInfo()
#expect(account.email == "user@example.com")
#expect(account.plan == "pro")
}
@Test
func `account info parses legacy camel case auth token`() throws {
let tmp = try FileManager.default.url(
for: .itemReplacementDirectory,
in: .userDomainMask,
appropriateFor: URL(fileURLWithPath: NSTemporaryDirectory()),
create: true)
defer { try? FileManager.default.removeItem(at: tmp) }
let token = Self.fakeJWT(email: "user@example.com", plan: "pro")
let auth = ["tokens": ["idToken": token, "accessToken": "access", "refreshToken": "refresh"]]
let data = try JSONSerialization.data(withJSONObject: auth)
let authURL = tmp.appendingPathComponent("auth.json")
try data.write(to: authURL)
let fetcher = UsageFetcher(environment: ["CODEX_HOME": tmp.path])
let account = fetcher.loadAccountInfo()
#expect(account.email == "user@example.com")
#expect(account.plan == "pro")
}
private static func fakeJWT(email: String, plan: String) -> String {
let header = (try? JSONSerialization.data(withJSONObject: ["alg": "none"])) ?? Data()
let payload = (try? JSONSerialization.data(withJSONObject: [
"email": email,
"chatgpt_plan_type": plan,
])) ?? Data()
func b64(_ data: Data) -> String {
data.base64EncodedString()
.replacingOccurrences(of: "=", with: "")
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
}
return "\(b64(header)).\(b64(payload))."
}
}