Files
ai-agent/sidecar/test_claude_cli.py
Gabriel Vidal 30a9d98c36 feat(sidecar): headless claude login/logout + typed launch errors
POST /accounts/{id}/login drives `claude auth login --claudeai` without a
TTY (URL scraped, code#state piped to stdin, #state checked first);
/login/code, DELETE /login and /logout complete the flow. Launch failures
are read from the CLI's JSON result line and classified (auth, rate_limit,
cli_outdated, …) into {message, kind, hint, account}.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 12:04:52 +02:00

48 lines
1.8 KiB
Python

"""Unit tests for claude_cli's pure helpers (no CLI is spawned)."""
import json
import claude_cli as c
def test_normalize_code_accepts_code_hash_state():
assert c.normalize_code(" abcdefgh12#STATE_abc-9 \n") == ("abcdefgh12", "STATE_abc-9")
def test_normalize_code_accepts_callback_url():
url = "https://platform.claude.com/oauth/code/callback?code=abcdefgh12&state=zyxwvuts99"
assert c.normalize_code(url) == ("abcdefgh12", "zyxwvuts99")
def test_normalize_code_rejects_bare_code():
assert c.normalize_code("abcdefgh12") is None
assert c.normalize_code("") is None
def test_run_failure_reads_the_json_result_line():
line = json.dumps({"type": "result", "is_error": True,
"result": "Not logged in · Please run /login"})
msg, kind = c.run_failure(f"some noise\n{line}\n")
assert msg == "Not logged in · Please run /login"
assert kind == "auth"
def test_run_failure_falls_back_to_the_last_line():
msg, kind = c.run_failure("boot\nNo conversation found with session ID: x\n")
assert msg.startswith("No conversation found")
assert kind == "unknown"
def test_classify_kinds():
assert c.classify("Failed to authenticate: OAuth session expired and could not be refreshed") == "auth"
assert c.classify("You've hit your session limit · resets 9pm") == "rate_limit"
assert c.classify("API Error: 400 Claude Code 2.1.238 does not support this model; "
"version 2.1.251 or newer is required") == "cli_outdated"
assert c.classify("API Error: Connection lost mid-response.") == "network"
assert c.classify("whatever", "authentication_failed") == "auth"
def test_error_detail_carries_a_hint():
d = c.error_detail("nope", kind="auth", account="work")
assert d["kind"] == "auth" and d["account"] == "work" and d["hint"]