155 lines · 5.8 KB · Swift
RawDownload
import CodexBarCoreimport Commanderimport Foundationimport Testing@testable import CodexBarCLI struct CLICostTests {    @Test    func `cost json shortcut does not enable json logs`() throws {        let signature = CodexBarCLI._costSignatureForTesting()        let parser = CommandParser(signature: signature)        let parsed = try parser.parse(arguments: ["--json"])         #expect(parsed.flags.contains("jsonShortcut"))        #expect(!parsed.flags.contains("jsonOutput"))        #expect(CodexBarCLI._decodeFormatForTesting(from: parsed) == .json)    }     @Test    func `renders cost text snapshot`() {        let snap = CostUsageTokenSnapshot(            sessionTokens: 1200,            sessionCostUSD: 1.25,            last30DaysTokens: 9000,            last30DaysCostUSD: 9.99,            historyDays: 90,            daily: [],            updatedAt: Date(timeIntervalSince1970: 0))         let output = CodexBarCLI.renderCostText(provider: .claude, snapshot: snap, useColor: false)            .replacingOccurrences(of: "\u{00A0}", with: " ")            .replacingOccurrences(of: "$ ", with: "$")         #expect(output.contains("Claude Cost (API-rate estimate)"))        #expect(output.contains("Today: $1.25 · 1.2K tokens"))        #expect(output.contains("Last 90 days: $9.99 · 9K tokens"))        #expect(output.contains("cache read/write tokens"))        #expect(output.contains("Claude Code /status"))    }     @Test    func `encodes cost payload JSON`() throws {        let payload = CostPayload(            provider: "claude",            source: "local",            updatedAt: Date(timeIntervalSince1970: 1_700_000_000),            sessionTokens: 100,            sessionCostUSD: 0.5,            historyDays: 90,            last30DaysTokens: 200,            last30DaysCostUSD: 1.5,            daily: [                CostDailyEntryPayload(                    date: "2025-12-20",                    inputTokens: 10,                    outputTokens: 5,                    cacheReadTokens: 2,                    cacheCreationTokens: 3,                    totalTokens: 15,                    costUSD: 0.01,                    modelsUsed: ["claude-sonnet-4-20250514"],                    modelBreakdowns: [                        CostModelBreakdownPayload(                            modelName: "claude-sonnet-4-20250514",                            costUSD: 0.01,                            totalTokens: 15),                    ]),            ],            totals: CostTotalsPayload(                totalInputTokens: 10,                totalOutputTokens: 5,                cacheReadTokens: 2,                cacheCreationTokens: 3,                totalTokens: 15,                totalCostUSD: 0.01),            error: nil)         let encoder = JSONEncoder()        encoder.dateEncodingStrategy = .secondsSince1970        let data = try encoder.encode(payload)        guard let json = String(data: data, encoding: .utf8) else {            Issue.record("Failed to decode cost payload JSON")            return        }         #expect(json.contains("\"provider\":\"claude\""))        #expect(json.contains("\"source\":\"local\""))        #expect(json.contains("\"historyDays\":90"))        #expect(json.contains("\"daily\""))        #expect(json.contains("\"totals\""))        #expect(json.contains("\"cacheReadTokens\":2"))        #expect(json.contains("\"cacheCreationTokens\":3"))        #expect(json.contains("\"totalCost\""))        #expect(json.contains("\"totalTokens\":15"))        #expect(json.contains("1700000000"))    }     @Test    func `encodes exact codex model I ds and zero cost breakdowns`() throws {        let payload = CostPayload(            provider: "codex",            source: "local",            updatedAt: Date(timeIntervalSince1970: 1_700_000_000),            sessionTokens: 155,            sessionCostUSD: 0,            historyDays: 30,            last30DaysTokens: 155,            last30DaysCostUSD: 0,            daily: [                CostDailyEntryPayload(                    date: "2025-12-21",                    inputTokens: 120,                    outputTokens: 15,                    cacheReadTokens: 20,                    cacheCreationTokens: nil,                    totalTokens: 155,                    costUSD: 0,                    modelsUsed: ["gpt-5.3-codex-spark", "gpt-5.2-codex"],                    modelBreakdowns: [                        CostModelBreakdownPayload(modelName: "gpt-5.3-codex-spark", costUSD: 0, totalTokens: 15),                        CostModelBreakdownPayload(modelName: "gpt-5.2-codex", costUSD: 1.23, totalTokens: 140),                    ]),            ],            totals: CostTotalsPayload(                totalInputTokens: 120,                totalOutputTokens: 15,                cacheReadTokens: 20,                cacheCreationTokens: nil,                totalTokens: 155,                totalCostUSD: 0),            error: nil)         let encoder = JSONEncoder()        encoder.dateEncodingStrategy = .secondsSince1970        let data = try encoder.encode(payload)        guard let json = String(data: data, encoding: .utf8) else {            Issue.record("Failed to decode cost payload JSON")            return        }         #expect(json.contains("\"gpt-5.3-codex-spark\""))        #expect(json.contains("\"gpt-5.2-codex\""))        #expect(!json.contains("\"gpt-5.2\""))        #expect(json.contains("\"cost\":0"))        #expect(json.contains("\"totalTokens\":140"))    }     @Test    func `cost estimate hint is stable string`() {        let hint = UsageFormatter.costEstimateHint        #expect(!hint.isEmpty)        #expect(hint.contains("Estimated"))        #expect(UsageFormatter.costEstimateHint(provider: .claude).contains("cache read/write tokens"))    }}