161 lines · 6.0 KB · Swift
RawDownload
import Foundationimport Testing@testable import CodexBarCore struct CodexOAuthResetCreditFetchTests {    @Test    func `app enrichment can rescue reset-credit-only O auth usage`() throws {        let json = #"{"rate_limit":{"primary_window":null,"secondary_window":null}}"#        let result = try CodexOAuthFetchStrategy._mapResultForTesting(            Data(json.utf8),            credentials: Self.credentials(),            allowEmptyUsageForResetCreditEnrichment: true)         #expect(result.usage.primary == nil)        #expect(result.usage.secondary == nil)        #expect(result.usage.codexResetCredits == nil)        #expect(result.credits == nil)        #expect(result.strategyID == "codex.oauth")    }     @Test    func `app defers reset credit GET while CLI attempts it once on failure`() async throws {        let credentials = Self.credentials()        let recorder = CodexOAuthResetCreditFetchRecorder()        let fetcher: @Sendable (CodexOAuthCredentials) async throws -> CodexRateLimitResetCreditsSnapshot = { _ in            await recorder.recordRequest()            throw CodexOAuthFetchError.serverError(500, nil)        }         let appResult = try await CodexOAuthFetchStrategy._fetchResetCreditsForTesting(            context: Self.context(runtime: .app),            credentials: credentials,            fetcher: fetcher)        #expect(appResult == nil)        #expect(await recorder.requestCount() == 0)         let cliResult = try await CodexOAuthFetchStrategy._fetchResetCreditsForTesting(            context: Self.context(runtime: .cli),            credentials: credentials,            fetcher: fetcher)        #expect(cliResult == nil)        #expect(await recorder.requestCount() == 1)    }     @Test    func `CLI reset credit GET preserves cancellation without retry`() async throws {        let recorder = CodexOAuthResetCreditFetchRecorder()         await #expect(throws: CancellationError.self) {            _ = try await CodexOAuthFetchStrategy._fetchResetCreditsForTesting(                context: Self.context(runtime: .cli),                credentials: Self.credentials(),                fetcher: { _ in                    await recorder.recordRequest()                    throw CancellationError()                })        }        #expect(await recorder.requestCount() == 1)    }     @Test    func `reset credit inventory only O auth payload still returns usage result`() throws {        let json = #"{"rate_limit":{"primary_window":null,"secondary_window":null}}"#        let now = Date()        let resetCredits = CodexRateLimitResetCreditsSnapshot(            credits: [                CodexRateLimitResetCredit(                    id: "available-no-expiry",                    resetType: "codex_rate_limits",                    status: .available,                    grantedAt: now,                    expiresAt: nil,                    redeemStartedAt: nil,                    redeemedAt: nil,                    title: nil,                    description: nil),            ],            availableCount: 1,            updatedAt: now)         let result = try CodexOAuthFetchStrategy._mapResultForTesting(            Data(json.utf8),            credentials: Self.credentials(),            resetCredits: resetCredits)         #expect(result.usage.primary == nil)        #expect(result.usage.secondary == nil)        #expect(result.usage.codexResetCredits?.availableInventory(at: now).count == 1)        #expect(result.credits == nil)        #expect(result.sourceLabel == "oauth")    }     @Test    func `empty reset credits do not mask missing O auth usage`() {        let json = #"{"rate_limit":{"primary_window":null,"secondary_window":null}}"#        let resetCredits = CodexRateLimitResetCreditsSnapshot(            credits: [],            availableCount: 0,            updatedAt: Date())         #expect(throws: UsageError.self) {            try CodexOAuthFetchStrategy._mapResultForTesting(                Data(json.utf8),                credentials: Self.credentials(),                resetCredits: resetCredits)        }    }     @Test    func `O auth strategy defers app inventory and CLI follows credits flag`() {        let appContext = Self.context(runtime: .app, includeCredits: false, includeOptionalUsage: false)        let cliNoCreditsContext = Self.context(runtime: .cli, includeCredits: false, includeOptionalUsage: true)        let cliCreditsContext = Self.context(runtime: .cli, includeCredits: true, includeOptionalUsage: false)         #expect(CodexOAuthFetchStrategy._shouldFetchResetCreditsForTesting(appContext) == false)        #expect(CodexOAuthFetchStrategy._shouldFetchResetCreditsForTesting(cliNoCreditsContext) == false)        #expect(CodexOAuthFetchStrategy._shouldFetchResetCreditsForTesting(cliCreditsContext))    }     private static func context(        runtime: ProviderRuntime,        includeCredits: Bool = true,        includeOptionalUsage: Bool = false) -> ProviderFetchContext    {        let browserDetection = BrowserDetection(cacheTTL: 0)        return ProviderFetchContext(            runtime: runtime,            sourceMode: .auto,            includeCredits: includeCredits,            includeOptionalUsage: includeOptionalUsage,            webTimeout: 60,            webDebugDumpHTML: false,            verbose: false,            env: [:],            settings: nil,            fetcher: UsageFetcher(),            claudeFetcher: ClaudeUsageFetcher(browserDetection: browserDetection),            browserDetection: browserDetection)    }     private static func credentials() -> CodexOAuthCredentials {        CodexOAuthCredentials(            accessToken: "access",            refreshToken: "refresh",            idToken: nil,            accountId: "account-123",            lastRefresh: Date())    }} private actor CodexOAuthResetCreditFetchRecorder {    private var count = 0     func recordRequest() {        self.count += 1    }     func requestCount() -> Int {        self.count    }}