Files
2026-07-13 12:22:33 +08:00

153 lines
5.6 KiB
Swift

import Foundation
import Testing
@testable import CodexBar
@testable import CodexBarCore
@Suite(.serialized)
struct TTYIntegrationTests {
@Test
func `codex RPC usage live`() async throws {
guard ProcessInfo.processInfo.environment["LIVE_CODEX_TTY"] == "1" else {
return
}
let fetcher = UsageFetcher()
do {
let snapshot = try await fetcher.loadLatestUsage()
guard let primary = snapshot.primary else {
return
}
let hasData = primary.usedPercent >= 0 && (snapshot.secondary?.usedPercent ?? 0) >= 0
#expect(hasData)
} catch UsageError.noRateLimitsFound {
return
} catch {
return
}
}
@Test
func `claude TTY usage probe live`() async throws {
guard ProcessInfo.processInfo.environment["LIVE_CLAUDE_TTY"] == "1" else {
return
}
guard TTYCommandRunner.which("claude") != nil else {
return
}
let fetcher = ClaudeUsageFetcher(browserDetection: BrowserDetection(cacheTTL: 0), dataSource: .cli)
defer { Task { await ClaudeCLISession.shared.reset() } }
var shouldAssert = true
do {
let snapshot = try await fetcher.loadLatestUsage()
#expect(snapshot.primary.remainingPercent >= 0)
// Weekly is absent for some enterprise accounts.
} catch ClaudeUsageError.parseFailed(_) {
shouldAssert = false
} catch ClaudeStatusProbeError.parseFailed(_) {
shouldAssert = false
} catch ClaudeUsageError.claudeNotInstalled {
shouldAssert = false
} catch ClaudeStatusProbeError.timedOut {
shouldAssert = false
} catch let TTYCommandRunner.Error.launchFailed(message) where message.contains("login") {
shouldAssert = false
} catch {
shouldAssert = false
}
if !shouldAssert { return }
}
@Test
func `claude pty usage waits for values after session label`() async throws {
let cli = try Self.makeSlowUsageClaudeCLI()
defer { Task { await ClaudeCLISession.shared.reset() } }
let snapshot = try await ClaudeCLISession.withIsolatedSessionForTesting {
try await ClaudeStatusProbe(claudeBinary: cli.path, timeout: 10).fetch()
}
#expect(snapshot.sessionPercentLeft == 93)
#expect(snapshot.weeklyPercentLeft == 79)
}
@Test
func `claude pty usage stops on subscription notice`() async throws {
let logURL = FileManager.default.temporaryDirectory
.appendingPathComponent("CodexBarTTYTests-\(UUID().uuidString).log")
let cli = try Self.makeSubscriptionNoticeClaudeCLI(logURL: logURL)
defer {
try? FileManager.default.removeItem(at: logURL)
Task { await ClaudeCLISession.shared.reset() }
}
do {
try await ClaudeCLISession.withIsolatedSessionForTesting {
_ = try await ClaudeStatusProbe(claudeBinary: cli.path, timeout: 3).fetch()
}
#expect(Bool(false), "Subscription notice should fail parsing")
} catch let ClaudeStatusProbeError.parseFailed(message) {
#expect(message.lowercased().contains("subscription"))
} catch {
#expect(Bool(false), "Unexpected error: \(error)")
}
let commands = try String(contentsOf: logURL, encoding: .utf8)
#expect(commands.contains("/usage"))
#expect(!commands.contains("/status"))
}
private static func makeSlowUsageClaudeCLI() throws -> URL {
let dir = FileManager.default.temporaryDirectory
.appendingPathComponent("CodexBarTTYTests-\(UUID().uuidString)", isDirectory: true)
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
let url = dir.appendingPathComponent("claude")
let script = """
#!/bin/sh
while IFS= read -r line; do
case "$line" in
*"/usage"*)
printf '%s\\n' 'Settings Status Config Usage'
printf '%s\\n' 'Current session'
sleep 2
printf '%s\\n' '93% left'
printf '%s\\n' 'Current week (all models)'
printf '%s\\n' '79% left'
;;
*"/status"*)
printf '%s\\n' 'Account: slow-usage@example.com'
;;
esac
done
"""
try script.write(to: url, atomically: true, encoding: .utf8)
try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: url.path)
return url
}
private static func makeSubscriptionNoticeClaudeCLI(logURL: URL) throws -> URL {
let dir = FileManager.default.temporaryDirectory
.appendingPathComponent("CodexBarTTYTests-\(UUID().uuidString)", isDirectory: true)
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
let url = dir.appendingPathComponent("claude")
let script = """
#!/bin/sh
while IFS= read -r line; do
printf '%s\\n' "$line" >> '\(logURL.path)'
case "$line" in
*"/usage"*)
printf '%s\\n' 'You are currently using your subscription to power your Claude Code usage'
;;
*"/status"*)
printf '%s\\n' 'Account: subscription@example.com'
;;
esac
done
"""
try script.write(to: url, atomically: true, encoding: .utf8)
try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: url.path)
return url
}
}