97 lines · 3.3 KB · Swift
RawDownload
import Foundationimport Testing@testable import CodexBarCore #if os(macOS) /// Regression tests for #474: verify that CLI timeout errors trigger fallback/// to the web strategy instead of stalling the refresh cycle.struct AugmentCLIFetchStrategyFallbackTests {    private struct StubClaudeFetcher: ClaudeUsageFetching {        func loadLatestUsage(model _: String) async throws -> ClaudeUsageSnapshot {            throw ClaudeUsageError.parseFailed("stub")        }         func debugRawProbe(model _: String) async -> String {            "stub"        }         func detectVersion() -> String? {            nil        }    }     private func makeContext(sourceMode: ProviderSourceMode = .auto) -> ProviderFetchContext {        let env: [String: String] = [:]        return ProviderFetchContext(            runtime: .app,            sourceMode: sourceMode,            includeCredits: false,            webTimeout: 1,            webDebugDumpHTML: false,            verbose: false,            env: env,            settings: nil,            fetcher: UsageFetcher(environment: env),            claudeFetcher: StubClaudeFetcher(),            browserDetection: BrowserDetection(cacheTTL: 0))    }     // SubprocessRunnerError is not an AuggieCLIError, so it hits the default    // fallback=true path — the desired behavior for infrastructure errors.     @Test    func `timeout error falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        let error = SubprocessRunnerError.timedOut("auggie-account-status")        #expect(strategy.shouldFallback(on: error, context: context) == true)    }     @Test    func `binary not found falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        let error = SubprocessRunnerError.binaryNotFound("/usr/local/bin/auggie")        #expect(strategy.shouldFallback(on: error, context: context) == true)    }     @Test    func `launch failed falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        let error = SubprocessRunnerError.launchFailed("permission denied")        #expect(strategy.shouldFallback(on: error, context: context) == true)    }     @Test    func `not authenticated falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        #expect(strategy.shouldFallback(on: AuggieCLIError.notAuthenticated, context: context) == true)    }     @Test    func `no output falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        #expect(strategy.shouldFallback(on: AuggieCLIError.noOutput, context: context) == true)    }     @Test    func `parse error falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        #expect(strategy.shouldFallback(on: AuggieCLIError.parseError("bad data"), context: context) == true)    }     @Test    func `non zero exit falls back to web`() {        let strategy = AugmentCLIFetchStrategy()        let context = self.makeContext()        let error = SubprocessRunnerError.nonZeroExit(code: 1, stderr: "crash")        #expect(strategy.shouldFallback(on: error, context: context) == true)    }} #endif