Files
steipete--codexbar/Tests/CodexBarTests/CodexCLIWindowNormalizationTests.swift
2026-07-13 12:22:33 +08:00

227 lines
8.0 KiB
Swift

import Foundation
import Testing
@testable import CodexBarCore
struct CodexCLIWindowNormalizationTests {
@Test
func `normalizer maps lone weekly window into secondary`() {
let weekly = RateWindow(
usedPercent: 5,
windowMinutes: 10080,
resetsAt: nil,
resetDescription: nil)
let normalized = CodexRateWindowNormalizer._normalizeForTesting(primary: weekly, secondary: nil)
#expect(normalized.primary == nil)
#expect(normalized.secondary?.usedPercent == 5)
#expect(normalized.secondary?.windowMinutes == 10080)
}
@Test
func `normalizer keeps lone session window in primary`() {
let session = RateWindow(
usedPercent: 31,
windowMinutes: 300,
resetsAt: nil,
resetDescription: nil)
let normalized = CodexRateWindowNormalizer._normalizeForTesting(primary: session, secondary: nil)
#expect(normalized.primary?.usedPercent == 31)
#expect(normalized.primary?.windowMinutes == 300)
#expect(normalized.secondary == nil)
}
@Test
func `normalizer keeps session and weekly ordering unchanged`() {
let session = RateWindow(
usedPercent: 31,
windowMinutes: 300,
resetsAt: nil,
resetDescription: nil)
let weekly = RateWindow(
usedPercent: 26,
windowMinutes: 10080,
resetsAt: nil,
resetDescription: nil)
let normalized = CodexRateWindowNormalizer._normalizeForTesting(primary: session, secondary: weekly)
#expect(normalized.primary?.usedPercent == 31)
#expect(normalized.primary?.windowMinutes == 300)
#expect(normalized.secondary?.usedPercent == 26)
#expect(normalized.secondary?.windowMinutes == 10080)
}
@Test
func `normalizer swaps reversed weekly and unknown windows`() {
let weekly = RateWindow(
usedPercent: 43,
windowMinutes: 10080,
resetsAt: nil,
resetDescription: nil)
let unknown = RateWindow(
usedPercent: 17,
windowMinutes: 540,
resetsAt: nil,
resetDescription: nil)
let normalized = CodexRateWindowNormalizer._normalizeForTesting(primary: weekly, secondary: unknown)
#expect(normalized.primary?.usedPercent == 17)
#expect(normalized.primary?.windowMinutes == 540)
#expect(normalized.secondary?.usedPercent == 43)
#expect(normalized.secondary?.windowMinutes == 10080)
}
@Test
func `maps weekly only RPC limits into secondary`() throws {
let snapshot = try UsageFetcher._mapCodexRPCLimitsForTesting(
primary: (usedPercent: 5, windowMinutes: 10080, resetsAt: nil),
secondary: nil)
#expect(snapshot.primary == nil)
#expect(snapshot.secondary?.usedPercent == 5)
#expect(snapshot.secondary?.windowMinutes == 10080)
}
@Test
func `maps session only RPC limits into primary`() throws {
let snapshot = try UsageFetcher._mapCodexRPCLimitsForTesting(
primary: (usedPercent: 31, windowMinutes: 300, resetsAt: nil),
secondary: nil)
#expect(snapshot.primary?.usedPercent == 31)
#expect(snapshot.primary?.windowMinutes == 300)
#expect(snapshot.secondary == nil)
}
@Test
func `maps reversed weekly and unknown RPC limits`() throws {
let snapshot = try UsageFetcher._mapCodexRPCLimitsForTesting(
primary: (usedPercent: 43, windowMinutes: 10080, resetsAt: nil),
secondary: (usedPercent: 17, windowMinutes: 540, resetsAt: nil))
#expect(snapshot.primary?.usedPercent == 17)
#expect(snapshot.primary?.windowMinutes == 540)
#expect(snapshot.secondary?.usedPercent == 43)
#expect(snapshot.secondary?.windowMinutes == 10080)
}
@Test
func `throws when RPC limits contain no windows`() {
#expect(throws: UsageError.noRateLimitsFound) {
try UsageFetcher._mapCodexRPCLimitsForTesting(primary: nil, secondary: nil)
}
}
@Test
func `maps plan only RPC limits into empty identified snapshot`() throws {
let snapshot = try UsageFetcher._mapCodexRPCLimitsForTesting(
primary: nil,
secondary: nil,
planType: "pro")
#expect(snapshot.primary == nil)
#expect(snapshot.secondary == nil)
#expect(snapshot.loginMethod(for: .codex) == "pro")
#expect(snapshot.rateLimitsUnavailable(for: .codex))
}
@Test
func `codex no rate limit error means limits unavailable without snapshot`() {
let availability = UsageLimitsAvailability.resolve(
provider: .codex,
snapshot: nil,
account: AccountInfo(email: "user@example.com", plan: nil),
lastErrorDescription: UsageError.noRateLimitsFound.errorDescription)
#expect(availability == .unavailable)
}
@Test
func `codex no rate limit error stays available without account context`() {
let availability = UsageLimitsAvailability.resolve(
provider: .codex,
snapshot: nil,
account: AccountInfo(email: nil, plan: nil),
lastErrorDescription: UsageError.noRateLimitsFound.errorDescription)
#expect(availability == .available)
}
@Test
func `codex windowed snapshot wins over stale no rate limit error`() {
let identity = ProviderIdentitySnapshot(
providerID: .codex,
accountEmail: "user@example.com",
accountOrganization: nil,
loginMethod: "pro")
let snapshot = UsageSnapshot(
primary: RateWindow(
usedPercent: 25,
windowMinutes: 300,
resetsAt: nil,
resetDescription: nil),
secondary: nil,
updatedAt: Date(),
identity: identity)
let availability = UsageLimitsAvailability.resolve(
provider: .codex,
snapshot: snapshot,
lastErrorDescription: UsageError.noRateLimitsFound.errorDescription)
#expect(availability == .available)
}
@Test
func `maps weekly only status snapshot into secondary`() throws {
let status = CodexStatusSnapshot(
credits: nil,
fiveHourPercentLeft: nil,
weeklyPercentLeft: 95,
fiveHourResetDescription: nil,
weeklyResetDescription: "resets next week",
fiveHourResetsAt: nil,
weeklyResetsAt: nil,
rawText: "Weekly limit: 95% left")
let snapshot = try UsageFetcher._mapCodexStatusForTesting(status)
#expect(snapshot.primary == nil)
#expect(snapshot.secondary?.usedPercent == 5)
#expect(snapshot.secondary?.windowMinutes == 10080)
}
@Test
func `maps five hour only status snapshot into primary`() throws {
let status = CodexStatusSnapshot(
credits: nil,
fiveHourPercentLeft: 69,
weeklyPercentLeft: nil,
fiveHourResetDescription: "resets soon",
weeklyResetDescription: nil,
fiveHourResetsAt: nil,
weeklyResetsAt: nil,
rawText: "5h limit: 69% left")
let snapshot = try UsageFetcher._mapCodexStatusForTesting(status)
#expect(snapshot.primary?.usedPercent == 31)
#expect(snapshot.primary?.windowMinutes == 300)
#expect(snapshot.secondary == nil)
}
@Test
func `throws when status snapshot contains no windows`() {
let status = CodexStatusSnapshot(
credits: nil,
fiveHourPercentLeft: nil,
weeklyPercentLeft: nil,
fiveHourResetDescription: nil,
weeklyResetDescription: nil,
fiveHourResetsAt: nil,
weeklyResetsAt: nil,
rawText: "")
#expect(throws: UsageError.noRateLimitsFound) {
try UsageFetcher._mapCodexStatusForTesting(status)
}
}
}