import subprocess import pytest from app.adapter import HermesCliKanbanAdapter, HermesCommandError, parse_tasks_payload from app.config import Settings from app.models import TaskCreate def test_hermes_cli_adapter_uses_argv_list_and_no_shell(monkeypatch): calls = [] def fake_run(argv, **kwargs): calls.append((argv, kwargs)) return subprocess.CompletedProcess(argv, 0, stdout='{"tasks": []}', stderr="") monkeypatch.setattr(subprocess, "run", fake_run) adapter = HermesCliKanbanAdapter(Settings(hermes_bin="hermes")) adapter.list_tasks(board="default") argv, kwargs = calls[0] assert argv[:3] == ["hermes", "kanban", "list"] assert isinstance(argv, list) assert kwargs.get("shell") is not True def test_create_task_cli_uses_fixed_subcommand(monkeypatch): calls = [] def fake_run(argv, **kwargs): calls.append(argv) return subprocess.CompletedProcess(argv, 0, stdout='{"id": "t_new"}', stderr="") monkeypatch.setattr(subprocess, "run", fake_run) adapter = HermesCliKanbanAdapter(Settings(hermes_bin="hermes")) adapter.create_task(TaskCreate(title="Hello", assignee="developer", priority=5), board="default") argv = calls[0] assert argv[:4] == ["hermes", "kanban", "create", "Hello"] assert "--assignee" in argv assert "developer" in argv def test_failed_command_raises_sanitized_error(monkeypatch): def fake_run(argv, **kwargs): return subprocess.CompletedProcess(argv, 1, stdout="", stderr="bad token secret") monkeypatch.setattr(subprocess, "run", fake_run) adapter = HermesCliKanbanAdapter(Settings(hermes_bin="hermes")) with pytest.raises(HermesCommandError) as exc: adapter.list_tasks() assert "secret" not in str(exc.value).lower() def test_parse_tasks_payload_accepts_json_list_and_normalizes(): tasks = parse_tasks_payload('[{"id":"t_1","title":"A","status":"ready"}]') assert tasks[0]["id"] == "t_1" assert tasks[0]["assignee"] is None def test_parse_tasks_payload_accepts_cli_text_table(): text = "t_1 ready developer 10 Build thing\n" tasks = parse_tasks_payload(text) assert tasks[0]["id"] == "t_1" assert tasks[0]["status"] == "ready" assert tasks[0]["assignee"] == "developer"