153 lines
5.6 KiB
Swift
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
|
|
}
|
|
}
|