Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Typ5sXWNMFirr2va2uL8o
75 lines
3.9 KiB
Python
75 lines
3.9 KiB
Python
import json
|
||
import threading
|
||
|
||
import pytest
|
||
|
||
from jira_hub import api, mcp_server, settings
|
||
from jira_hub.client import HubClient
|
||
|
||
|
||
@pytest.fixture
|
||
def live(tmp_path, monkeypatch):
|
||
h = api.Hub(tmp_path / "hub.sqlite", backups_dir=tmp_path / "backups")
|
||
h.claim_wait = 0
|
||
conn = h.conn()
|
||
tok = settings.tokens(conn)
|
||
conn.close()
|
||
srv = api.make_server(h, "127.0.0.1", 0)
|
||
threading.Thread(target=srv.serve_forever, daemon=True).start()
|
||
base = f"http://127.0.0.1:{srv.server_port}"
|
||
monkeypatch.setattr(mcp_server, "_client", lambda: HubClient(base, tok["client"]))
|
||
monkeypatch.setattr(mcp_server, "POLL_SECONDS", 0.05)
|
||
yield {"agent": HubClient(base, tok["agent"])}
|
||
srv.shutdown()
|
||
|
||
|
||
def test_offline_message(monkeypatch):
|
||
monkeypatch.setattr(mcp_server, "_client", lambda: HubClient("http://127.0.0.1:9", "t", timeout=1))
|
||
assert mcp_server.issues() == mcp_server.OFFLINE
|
||
assert mcp_server.agent_status() == mcp_server.OFFLINE
|
||
|
||
|
||
def test_tools_roundtrip(live):
|
||
live["agent"].post("/agent/state", {"issues": [{"key": "A-1", "summary": "Тема раз", "status": "Готово", "duedate": "2026-10-23",
|
||
"assignee": "ivanov", "sprint": "Спринт 2", "labels": ["AWPCA"]}], "links": []})
|
||
out = mcp_server.issues(sprint="Спринт 2")
|
||
assert "A-1" in out and "Тема раз" in out and "ivanov" in out
|
||
assert "В работе" in mcp_server.notes_set("A-1", fact_status="В работе")
|
||
detail = mcp_server.issue("A-1")
|
||
assert "fact_status: В работе" in detail and "Готово" in detail
|
||
created = mcp_server.batch_create("срок", [{"type": "ensure_fields", "params": {"key": "A-1", "duedate": "2026-10-24"}}])
|
||
batch_id = int(created.split("#")[1].split()[0])
|
||
assert "2 команд" in created and "мин" in created
|
||
bad = mcp_server.batch_create("x", [{"type": "ensure_fields", "params": {"key": "A-1"}}])
|
||
assert bad.startswith("ошибка хаба 422")
|
||
cmd = live["agent"].post("/agent/claim", {})["command"]
|
||
live["agent"].post(f"/agent/commands/{cmd['id']}/result", {"status": "failed", "error": "HTTP 400 поле"})
|
||
tail = live["agent"].post("/agent/claim", {})["command"]
|
||
live["agent"].post(f"/agent/commands/{tail['id']}/result", {"status": "done"})
|
||
waited = mcp_server.batch_wait(batch_id, timeout_minutes=1)
|
||
assert "done" in waited and "failed" in waited and "HTTP 400" in waited
|
||
assert f"#{batch_id}" in mcp_server.batches(limit=5)
|
||
assert "Повтор команды" in mcp_server.command_retry(cmd["id"])
|
||
assert "cancelled" in mcp_server.batch_cancel(batch_id + 1)
|
||
r = mcp_server.refresh(full=True, wait=False)
|
||
assert "Обновление" in r or "#" in r
|
||
assert "онлайн" in mcp_server.agent_status()
|
||
assert "A-1" in mcp_server.sync_log(limit=3) or "keys" in mcp_server.sync_log(limit=3)
|
||
assert "120" in mcp_server.settings_get("pacing")
|
||
assert "settings_version" in mcp_server.settings_set("pacing", json.dumps({"refresh": 1}))
|
||
assert mcp_server.settings_set("tokens", '"x"').startswith("ошибка хаба 422")
|
||
|
||
|
||
def test_formatters():
|
||
assert mcp_server.fmt_issues([]) == "задач нет"
|
||
text = mcp_server.fmt_issues([{"key": "A-1", "summary": "x" * 100, "status": "Готово", "duedate": None, "assignee": None,
|
||
"sprint": None, "fact_status": None}])
|
||
assert "x" * 79 + "…" in text and "x" * 80 not in text and "—" in text
|
||
assert "очередь" in mcp_server.fmt_agent({"online": False, "agent_version": None, "current_command_id": None,
|
||
"rate_limited_24h": 0, "stuck": [], "warning": None, "last_seen_at": None,
|
||
"settings_version": None})
|
||
|
||
|
||
def test_settings_set_bad_json(live):
|
||
assert mcp_server.settings_set("pacing", "{не json").startswith("значение не JSON")
|