import CodexBarCoreimport Foundationimport Testing@testable import CodexBar extension CodexAccountScopedRefreshTests { @Test func `credits refresh honors explicit codex oauth source without raw CLI fallback`() async throws { let settings = self.makeSettingsStore(suite: "CodexAccountScopedRefreshTests-oauth-credits-source") settings.refreshFrequency = .manual settings.codexUsageDataSource = .oauth settings._test_liveSystemCodexAccount = self.liveAccount(email: "alpha@example.com") let store = self.makeUsageStore( settings: settings, environmentBase: ["CODEX_CLI_PATH": "/missing/codex"]) let usage = self.codexSnapshot(email: "alpha@example.com", usedPercent: 10) store._setSnapshotForTesting(usage, provider: .codex) let oauthStrategy = TestCodexFetchStrategy( loader: { usage }, credits: self.credits(remaining: 77), id: "codex.oauth", kind: .oauth, sourceLabel: "codex.oauth") let cliStrategy = ThrowingTestCodexFetchStrategy { throw TestRefreshError(message: "CLI strategy should not run for explicit OAuth credits refresh") } let baseSpec = try #require(store.providerSpecs[.codex]) store.providerSpecs[.codex] = Self.makeCodexProviderSpec(baseSpec: baseSpec) { context in switch context.sourceMode { case .oauth: [oauthStrategy] case .cli: [cliStrategy] case .auto: [oauthStrategy, cliStrategy] case .web, .api: [] } } await store.refreshCreditsIfNeeded() #expect(store.credits?.remaining == 77) #expect(store.lastCreditsError == nil) #expect(store.lastCreditsSource == .api) } @Test func `auto credits refresh falls back when oauth usage omits credits`() async throws { let settings = self.makeSettingsStore(suite: "CodexAccountScopedRefreshTests-auto-credits-fallback") settings.refreshFrequency = .manual settings.codexUsageDataSource = .auto settings._test_liveSystemCodexAccount = self.liveAccount(email: "alpha@example.com") let store = self.makeUsageStore(settings: settings) let usage = self.codexSnapshot(email: "alpha@example.com", usedPercent: 10) store._setSnapshotForTesting(usage, provider: .codex) let oauthStrategy = TestCodexFetchStrategy( loader: { usage }, credits: nil, id: "codex.oauth", kind: .oauth, sourceLabel: "codex.oauth") let cliStrategy = TestCodexFetchStrategy( loader: { usage }, credits: self.credits(remaining: 41), id: "codex.cli", kind: .cli, sourceLabel: "codex.cli") let baseSpec = try #require(store.providerSpecs[.codex]) store.providerSpecs[.codex] = Self.makeCodexProviderSpec(baseSpec: baseSpec) { context in switch context.sourceMode { case .auto: [oauthStrategy, cliStrategy] case .oauth: [oauthStrategy] case .cli: [cliStrategy] case .web, .api: [] } } await store.refreshCreditsIfNeeded() #expect(store.credits?.remaining == 41) #expect(store.lastCreditsError == nil) #expect(store.lastCreditsSource == .api) }}
import CodexBarCore
import Foundation
import Testing
@testable import CodexBar
extension CodexAccountScopedRefreshTests {
@Test
func `credits refresh honors explicit codex oauth source without raw CLI fallback`() async throws {
let settings = self.makeSettingsStore(suite: "CodexAccountScopedRefreshTests-oauth-credits-source")
settings.refreshFrequency = .manual
settings.codexUsageDataSource = .oauth
settings._test_liveSystemCodexAccount = self.liveAccount(email: "alpha@example.com")
let store = self.makeUsageStore(
settings: settings,
environmentBase: ["CODEX_CLI_PATH": "/missing/codex"])
let usage = self.codexSnapshot(email: "alpha@example.com", usedPercent: 10)
store._setSnapshotForTesting(usage, provider: .codex)
let oauthStrategy = TestCodexFetchStrategy(
loader: { usage },
credits: self.credits(remaining: 77),
id: "codex.oauth",
kind: .oauth,
sourceLabel: "codex.oauth")
let cliStrategy = ThrowingTestCodexFetchStrategy {
throw TestRefreshError(message: "CLI strategy should not run for explicit OAuth credits refresh")
}
let baseSpec = try #require(store.providerSpecs[.codex])
store.providerSpecs[.codex] = Self.makeCodexProviderSpec(baseSpec: baseSpec) { context in
switch context.sourceMode {
case .oauth:
[oauthStrategy]
case .cli:
[cliStrategy]
case .auto:
[oauthStrategy, cliStrategy]
case .web, .api:
[]
}
}
await store.refreshCreditsIfNeeded()
#expect(store.credits?.remaining == 77)
#expect(store.lastCreditsError == nil)
#expect(store.lastCreditsSource == .api)
}
@Test
func `auto credits refresh falls back when oauth usage omits credits`() async throws {
let settings = self.makeSettingsStore(suite: "CodexAccountScopedRefreshTests-auto-credits-fallback")
settings.refreshFrequency = .manual
settings.codexUsageDataSource = .auto
settings._test_liveSystemCodexAccount = self.liveAccount(email: "alpha@example.com")
let store = self.makeUsageStore(settings: settings)
let usage = self.codexSnapshot(email: "alpha@example.com", usedPercent: 10)
store._setSnapshotForTesting(usage, provider: .codex)
let oauthStrategy = TestCodexFetchStrategy(
loader: { usage },
credits: nil,
id: "codex.oauth",
kind: .oauth,
sourceLabel: "codex.oauth")
let cliStrategy = TestCodexFetchStrategy(
loader: { usage },
credits: self.credits(remaining: 41),
id: "codex.cli",
kind: .cli,
sourceLabel: "codex.cli")
let baseSpec = try #require(store.providerSpecs[.codex])
store.providerSpecs[.codex] = Self.makeCodexProviderSpec(baseSpec: baseSpec) { context in
switch context.sourceMode {
case .auto:
[oauthStrategy, cliStrategy]
case .oauth:
[oauthStrategy]
case .cli:
[cliStrategy]
case .web, .api:
[]
}
}
await store.refreshCreditsIfNeeded()
#expect(store.credits?.remaining == 41)
#expect(store.lastCreditsError == nil)
#expect(store.lastCreditsSource == .api)
}
}