501 lines
22 KiB
Swift
501 lines
22 KiB
Swift
import CodexBarCore
|
|
import Commander
|
|
import Foundation
|
|
import XCTest
|
|
@testable import CodexBarCLI
|
|
|
|
final class CLIEntryTests: XCTestCase {
|
|
func test_effectiveArgvDefaultsToUsage() {
|
|
XCTAssertEqual(CodexBarCLI.effectiveArgv([]), ["usage"])
|
|
XCTAssertEqual(CodexBarCLI.effectiveArgv(["--json"]), ["usage", "--json"])
|
|
XCTAssertEqual(CodexBarCLI.effectiveArgv(["usage", "--json"]), ["usage", "--json"])
|
|
}
|
|
|
|
func test_decodesFormatFromOptionsAndFlags() {
|
|
let jsonOption = ParsedValues(positional: [], options: ["format": ["json"]], flags: [])
|
|
XCTAssertEqual(CodexBarCLI._decodeFormatForTesting(from: jsonOption), .json)
|
|
|
|
let jsonFlag = ParsedValues(positional: [], options: [:], flags: ["json"])
|
|
XCTAssertEqual(CodexBarCLI._decodeFormatForTesting(from: jsonFlag), .json)
|
|
|
|
let textDefault = ParsedValues(positional: [], options: [:], flags: [])
|
|
XCTAssertEqual(CodexBarCLI._decodeFormatForTesting(from: textDefault), .text)
|
|
}
|
|
|
|
func test_providerSelectionPrefersOverride() {
|
|
let selection = CodexBarCLI.providerSelection(rawOverride: "codex", enabled: [.claude, .gemini])
|
|
XCTAssertEqual(selection.asList, [.codex])
|
|
}
|
|
|
|
func test_normalizeVersionExtractsNumeric() {
|
|
XCTAssertEqual(CodexBarCLI.normalizeVersion(raw: "codex 1.2.3 (build 4)"), "1.2.3")
|
|
XCTAssertEqual(CodexBarCLI.normalizeVersion(raw: " v2.0 "), "2.0")
|
|
}
|
|
|
|
func test_makeHeaderIncludesVersionWhenAvailable() {
|
|
let header = CodexBarCLI.makeHeader(provider: .codex, version: "1.2.3", source: "cli")
|
|
XCTAssertTrue(header.contains("Codex"))
|
|
XCTAssertTrue(header.contains("1.2.3"))
|
|
XCTAssertTrue(header.contains("cli"))
|
|
}
|
|
|
|
func test_cliVersionFallsBackToContainingAppBundle() throws {
|
|
let root = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("codexbar-cli-version-\(UUID().uuidString)", isDirectory: true)
|
|
defer { try? FileManager.default.removeItem(at: root) }
|
|
|
|
let appURL = root.appendingPathComponent("CodexBar.app", isDirectory: true)
|
|
let contentsURL = appURL.appendingPathComponent("Contents", isDirectory: true)
|
|
let helpersURL = contentsURL.appendingPathComponent("Helpers", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: helpersURL, withIntermediateDirectories: true)
|
|
|
|
let infoURL = contentsURL.appendingPathComponent("Info.plist")
|
|
let plist: [String: Any] = ["CFBundleShortVersionString": "9.8.7"]
|
|
let data = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)
|
|
try data.write(to: infoURL)
|
|
|
|
let helperURL = helpersURL.appendingPathComponent("CodexBarCLI")
|
|
try Data().write(to: helperURL)
|
|
|
|
XCTAssertEqual(CodexBarCLI.containingAppVersion(for: helperURL), "9.8.7")
|
|
}
|
|
|
|
func test_cliVersionFollowsSymlinkedHelper() throws {
|
|
let root = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("codexbar-cli-version-symlink-\(UUID().uuidString)", isDirectory: true)
|
|
defer { try? FileManager.default.removeItem(at: root) }
|
|
|
|
let appURL = root.appendingPathComponent("CodexBar.app", isDirectory: true)
|
|
let contentsURL = appURL.appendingPathComponent("Contents", isDirectory: true)
|
|
let helpersURL = contentsURL.appendingPathComponent("Helpers", isDirectory: true)
|
|
let binURL = root.appendingPathComponent("bin", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: helpersURL, withIntermediateDirectories: true)
|
|
try FileManager.default.createDirectory(at: binURL, withIntermediateDirectories: true)
|
|
|
|
let infoURL = contentsURL.appendingPathComponent("Info.plist")
|
|
let plist: [String: Any] = ["CFBundleShortVersionString": "2.4.6"]
|
|
let data = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)
|
|
try data.write(to: infoURL)
|
|
|
|
let helperURL = helpersURL.appendingPathComponent("CodexBarCLI")
|
|
try Data().write(to: helperURL)
|
|
|
|
let symlinkURL = binURL.appendingPathComponent("codexbar")
|
|
try FileManager.default.createSymbolicLink(at: symlinkURL, withDestinationURL: helperURL)
|
|
|
|
XCTAssertEqual(CodexBarCLI.currentVersion(bundleVersion: nil, executablePath: symlinkURL.path), "2.4.6")
|
|
}
|
|
|
|
func test_cliVersionFallsBackToAdjacentVersionFile() throws {
|
|
try self.expectAdjacentVersionFile(raw: "v3.2.1\n", expected: "3.2.1")
|
|
try self.expectAdjacentVersionFile(raw: "3.2.2\n", expected: "3.2.2")
|
|
try self.expectAdjacentVersionFile(raw: "version-3.2.3\n", expected: "version-3.2.3")
|
|
}
|
|
|
|
func test_cliVersionPrefersAdjacentVersionOverStandaloneBundleName() throws {
|
|
let root = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("codexbar-cli-version-bundle-\(UUID().uuidString)", isDirectory: true)
|
|
defer { try? FileManager.default.removeItem(at: root) }
|
|
|
|
let binURL = root.appendingPathComponent("bin", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: binURL, withIntermediateDirectories: true)
|
|
|
|
let helperURL = binURL.appendingPathComponent("CodexBarCLI")
|
|
try Data().write(to: helperURL)
|
|
try "4.5.6\n".write(
|
|
to: binURL.appendingPathComponent("VERSION"),
|
|
atomically: false,
|
|
encoding: .utf8)
|
|
|
|
XCTAssertEqual(
|
|
CodexBarCLI.currentVersion(bundleVersion: "CodexBar", executablePath: helperURL.path),
|
|
"4.5.6")
|
|
}
|
|
|
|
private func expectAdjacentVersionFile(raw: String, expected: String) throws {
|
|
let root = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("codexbar-cli-version-file-\(UUID().uuidString)", isDirectory: true)
|
|
defer { try? FileManager.default.removeItem(at: root) }
|
|
|
|
let binURL = root.appendingPathComponent("bin", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: binURL, withIntermediateDirectories: true)
|
|
|
|
let helperURL = binURL.appendingPathComponent("CodexBarCLI")
|
|
try Data().write(to: helperURL)
|
|
try raw.write(
|
|
to: binURL.appendingPathComponent("VERSION"),
|
|
atomically: false,
|
|
encoding: .utf8)
|
|
|
|
XCTAssertEqual(CodexBarCLI.currentVersion(bundleVersion: nil, executablePath: helperURL.path), expected)
|
|
}
|
|
|
|
func test_renderOpenAIWebDashboardTextIncludesSummary() {
|
|
let event = CreditEvent(
|
|
date: Date(timeIntervalSince1970: 1_700_000_000),
|
|
service: "codex",
|
|
creditsUsed: 10)
|
|
let snapshot = OpenAIDashboardSnapshot(
|
|
signedInEmail: "user@example.com",
|
|
codeReviewRemainingPercent: 45,
|
|
codeReviewLimit: RateWindow(
|
|
usedPercent: 55,
|
|
windowMinutes: nil,
|
|
resetsAt: Date().addingTimeInterval(3600),
|
|
resetDescription: nil),
|
|
creditEvents: [event],
|
|
dailyBreakdown: [],
|
|
usageBreakdown: [],
|
|
creditsPurchaseURL: nil,
|
|
updatedAt: Date())
|
|
|
|
let text = CodexBarCLI.renderOpenAIWebDashboardText(snapshot)
|
|
|
|
XCTAssertTrue(text.contains("Web session: user@example.com"))
|
|
XCTAssertTrue(text.contains("Code review: 45% remaining (Resets in "))
|
|
XCTAssertTrue(text.contains("Web history: 1 events"))
|
|
}
|
|
|
|
func test_mapsErrorsToExitCodes() {
|
|
XCTAssertEqual(CodexBarCLI.mapError(CodexStatusProbeError.codexNotInstalled), ExitCode(2))
|
|
XCTAssertEqual(CodexBarCLI.mapError(CodexStatusProbeError.timedOut), ExitCode(4))
|
|
XCTAssertEqual(CodexBarCLI.mapError(ClaudeWebFetchStrategyError.timedOut(seconds: 1)), ExitCode(4))
|
|
XCTAssertEqual(CodexBarCLI.mapError(UsageError.noRateLimitsFound), ExitCode(3))
|
|
}
|
|
|
|
func test_antigravityPlanDebugKeepsOneShotHelperAliveUntilDebugFetch() {
|
|
XCTAssertTrue(CodexBarCLI.holdsAntigravityCLISessionForPlanDebug(
|
|
provider: .antigravity,
|
|
planDebugEnabled: true,
|
|
jsonOnly: false,
|
|
persistsCLISessions: false))
|
|
XCTAssertFalse(CodexBarCLI.holdsAntigravityCLISessionForPlanDebug(
|
|
provider: .codex,
|
|
planDebugEnabled: true,
|
|
jsonOnly: false,
|
|
persistsCLISessions: false))
|
|
XCTAssertFalse(CodexBarCLI.holdsAntigravityCLISessionForPlanDebug(
|
|
provider: .antigravity,
|
|
planDebugEnabled: true,
|
|
jsonOnly: true,
|
|
persistsCLISessions: false))
|
|
XCTAssertFalse(CodexBarCLI.holdsAntigravityCLISessionForPlanDebug(
|
|
provider: .antigravity,
|
|
planDebugEnabled: true,
|
|
jsonOnly: false,
|
|
persistsCLISessions: true))
|
|
}
|
|
|
|
func test_missingCodexBinaryErrorPayloadUsesInstallGuidance() {
|
|
let payload = CodexBarCLI.makeErrorPayload(CodexStatusProbeError.codexNotInstalled, kind: .provider)
|
|
|
|
XCTAssertEqual(payload.code, ExitCode.binaryNotFound.rawValue)
|
|
XCTAssertTrue(payload.message.contains("Codex CLI missing"))
|
|
XCTAssertFalse(payload.message.contains("Codex not running"))
|
|
}
|
|
|
|
func test_providerSelectionFallsBackToBothForPrimaryPair() {
|
|
let selection = CodexBarCLI.providerSelection(rawOverride: nil, enabled: [.codex, .claude])
|
|
switch selection {
|
|
case .both:
|
|
break
|
|
default:
|
|
XCTFail("Expected both selection")
|
|
}
|
|
}
|
|
|
|
func test_providerSelectionFallsBackToCustomWhenNonPrimary() {
|
|
let selection = CodexBarCLI.providerSelection(rawOverride: nil, enabled: [.codex, .gemini])
|
|
switch selection {
|
|
case let .custom(providers):
|
|
XCTAssertEqual(providers, [.codex, .gemini])
|
|
default:
|
|
XCTFail("Expected custom selection")
|
|
}
|
|
}
|
|
|
|
func test_providerSelectionHonorsEmptyEnabledSet() {
|
|
let selection = CodexBarCLI.providerSelection(rawOverride: nil, enabled: [])
|
|
switch selection {
|
|
case let .custom(providers):
|
|
XCTAssertEqual(providers, [])
|
|
default:
|
|
XCTFail("Expected empty custom selection")
|
|
}
|
|
}
|
|
|
|
func test_decodesSourceAndTimeoutOptions() throws {
|
|
let signature = CodexBarCLI._usageSignatureForTesting()
|
|
let parser = CommandParser(signature: signature)
|
|
let parsed = try parser.parse(arguments: ["--web-timeout", "45", "--source", "oauth"])
|
|
XCTAssertEqual(try CodexBarCLI._decodeWebTimeoutForTesting(from: parsed), 45)
|
|
XCTAssertEqual(CodexBarCLI._decodeSourceModeForTesting(from: parsed), .oauth)
|
|
|
|
let parsedWeb = try parser.parse(arguments: ["--web"])
|
|
XCTAssertEqual(CodexBarCLI._decodeSourceModeForTesting(from: parsedWeb), .web)
|
|
}
|
|
|
|
func test_rejectsUnsafeWebTimeoutOptions() throws {
|
|
for value in ["-1", "nan", "inf", "1e300"] {
|
|
let parsed = ParsedValues(positional: [], options: ["webTimeout": [value]], flags: [])
|
|
XCTAssertThrowsError(try CodexBarCLI._decodeWebTimeoutForTesting(from: parsed))
|
|
}
|
|
}
|
|
|
|
func test_shouldUseColorRespectsFormatAndFlags() {
|
|
XCTAssertFalse(CodexBarCLI.shouldUseColor(noColor: true, format: .text))
|
|
XCTAssertFalse(CodexBarCLI.shouldUseColor(noColor: false, format: .json))
|
|
}
|
|
|
|
func test_kiloUsageTextNotesShowFallbackOnlyForAutoResolvedToCLI() {
|
|
XCTAssertEqual(CodexBarCLI.usageTextNotes(
|
|
provider: .kilo,
|
|
sourceMode: .auto,
|
|
resolvedSourceLabel: "cli"), ["Using CLI fallback"])
|
|
XCTAssertTrue(CodexBarCLI.usageTextNotes(
|
|
provider: .kilo,
|
|
sourceMode: .api,
|
|
resolvedSourceLabel: "cli").isEmpty)
|
|
XCTAssertTrue(CodexBarCLI.usageTextNotes(
|
|
provider: .codex,
|
|
sourceMode: .auto,
|
|
resolvedSourceLabel: "cli").isEmpty)
|
|
}
|
|
|
|
func test_kiloAutoFallbackSummaryIncludesOrderedAttemptDetails() {
|
|
let attempts = [
|
|
ProviderFetchAttempt(
|
|
strategyID: "kilo.api",
|
|
kind: .apiToken,
|
|
wasAvailable: true,
|
|
errorDescription: "Kilo authentication failed (401/403)."),
|
|
ProviderFetchAttempt(
|
|
strategyID: "kilo.cli",
|
|
kind: .cli,
|
|
wasAvailable: true,
|
|
errorDescription: "Kilo CLI session not found."),
|
|
]
|
|
|
|
let summary = CodexBarCLI.kiloAutoFallbackSummary(
|
|
provider: .kilo,
|
|
sourceMode: .auto,
|
|
attempts: attempts)
|
|
let expected = [
|
|
"Kilo auto fallback attempts: api: Kilo authentication failed (401/403).",
|
|
" -> cli: Kilo CLI session not found.",
|
|
].joined()
|
|
|
|
XCTAssertEqual(summary, expected)
|
|
}
|
|
|
|
func test_kiloAutoFallbackSummaryIsNilOutsideKiloAutoFailures() {
|
|
let attempts = [
|
|
ProviderFetchAttempt(
|
|
strategyID: "kilo.api",
|
|
kind: .apiToken,
|
|
wasAvailable: true,
|
|
errorDescription: "example"),
|
|
]
|
|
|
|
XCTAssertNil(CodexBarCLI.kiloAutoFallbackSummary(
|
|
provider: .kilo,
|
|
sourceMode: .api,
|
|
attempts: attempts))
|
|
XCTAssertNil(CodexBarCLI.kiloAutoFallbackSummary(
|
|
provider: .codex,
|
|
sourceMode: .auto,
|
|
attempts: attempts))
|
|
}
|
|
|
|
func test_sourceModeRequiresWebSupportIsProviderAware() throws {
|
|
let directory = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("mimo-cli-source-mode-\(UUID().uuidString)", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let validMiMoCache = directory.appendingPathComponent("valid.json")
|
|
let invalidMiMoCache = directory.appendingPathComponent("invalid.json")
|
|
let payload: [String: Any] = [
|
|
"sessions_scanned": 1,
|
|
"windows": [
|
|
"today": [:],
|
|
"week": [:],
|
|
"all_time": [:],
|
|
],
|
|
]
|
|
try JSONSerialization.data(withJSONObject: payload).write(to: validMiMoCache)
|
|
try Data("{}".utf8).write(to: invalidMiMoCache)
|
|
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(.web, provider: .kilo))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.auto, provider: .codex))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.auto, provider: .claude))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(.web, provider: .claude))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.auto, provider: .kilo))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.auto, provider: .grok))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.web, provider: .grok))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.auto, provider: .amp))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(.api, provider: .kilo))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .opencodego,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
opencodego: .init(
|
|
cookieSource: .manual,
|
|
manualCookieHeader: "auth=manual",
|
|
workspaceID: nil))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .opencodego,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
opencodego: .init(
|
|
cookieSource: .manual,
|
|
manualCookieHeader: "auth=manual",
|
|
workspaceID: nil))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .opencodego,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
opencodego: .init(
|
|
cookieSource: .auto,
|
|
manualCookieHeader: nil,
|
|
workspaceID: nil))))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .opencodego,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
opencodego: .init(
|
|
cookieSource: .auto,
|
|
manualCookieHeader: nil,
|
|
workspaceID: nil))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .commandcode,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
commandcode: .init(
|
|
cookieSource: .manual,
|
|
manualCookieHeader: "session=manual"))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .commandcode,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
commandcode: .init(
|
|
cookieSource: .manual,
|
|
manualCookieHeader: "session=manual"))))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .commandcode,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
commandcode: .init(
|
|
cookieSource: .auto,
|
|
manualCookieHeader: nil))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .sakana,
|
|
environment: ["SAKANA_COOKIE": "session=manual"]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .sakana,
|
|
environment: ["SAKANA_COOKIE": "session=manual"]))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .sakana,
|
|
environment: [:]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .qoder,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
qoder: .init(
|
|
cookieSource: .manual,
|
|
manualCookieHeader: "sid=manual"))))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .qoder,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
qoder: .init(
|
|
cookieSource: .auto,
|
|
manualCookieHeader: nil))))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .opencode,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
opencode: .init(
|
|
cookieSource: .manual,
|
|
manualCookieHeader: "auth=manual",
|
|
workspaceID: nil))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .ollama,
|
|
environment: ["OLLAMA_API_KEY": "ollama-test"]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .codex,
|
|
environment: ["OLLAMA_API_KEY": "ollama-test"]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .ollama,
|
|
settings: ProviderSettingsSnapshot.make(
|
|
ollama: .init(cookieSource: .off, manualCookieHeader: nil))))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .kimi,
|
|
environment: ["KIMI_CODE_API_KEY": "kimi-test"]))
|
|
try self.assertKimiCodeCredentialSourceMode(in: directory)
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .mimo,
|
|
environment: ["MIMO_LOCAL_USAGE_PATH": validMiMoCache.path]))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .mimo,
|
|
environment: ["MIMO_LOCAL_USAGE_PATH": validMiMoCache.path]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .mimo,
|
|
environment: ["MIMO_LOCAL_USAGE_PATH": invalidMiMoCache.path]))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .mimo,
|
|
environment: ["MIMO_LOCAL_USAGE_PATH": directory.appendingPathComponent("missing.json").path]))
|
|
}
|
|
|
|
private func assertKimiCodeCredentialSourceMode(in directory: URL) throws {
|
|
let home = directory.appendingPathComponent("kimi-code", isDirectory: true)
|
|
let credentials = home.appendingPathComponent("credentials", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: credentials, withIntermediateDirectories: true)
|
|
let payload: [String: Any] = [
|
|
"access_token": "expired",
|
|
"refresh_token": "refresh",
|
|
"expires_at": Date().addingTimeInterval(-60).timeIntervalSince1970,
|
|
]
|
|
try JSONSerialization.data(withJSONObject: payload)
|
|
.write(to: credentials.appendingPathComponent("kimi-code.json"))
|
|
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .kimi,
|
|
environment: ["KIMI_CODE_HOME": home.path]))
|
|
}
|
|
|
|
func test_sourceModeRequiresWebSupportAllowsFactoryAPIKeyOnLinuxGate() {
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .factory,
|
|
environment: ["FACTORY_API_KEY": "fk-test"]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.cli,
|
|
provider: .factory,
|
|
environment: ["FACTORY_API_KEY": "fk-test"]))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.auto,
|
|
provider: .factory,
|
|
environment: [:]))
|
|
XCTAssertTrue(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.web,
|
|
provider: .factory,
|
|
environment: ["FACTORY_API_KEY": "fk-test"]))
|
|
XCTAssertFalse(CodexBarCLI.sourceModeRequiresWebSupport(
|
|
.api,
|
|
provider: .factory,
|
|
environment: [:]))
|
|
}
|
|
}
|