tokens -> {client, agents: {модуль: токен}}, agent_status по агентам
(ключ agent, last_call_at), настройки агента и маршруты agent-scope по
модулю токена, min_agent_version переехал в модуль jira.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
83 lines
4.5 KiB
Python
83 lines
4.5 KiB
Python
import threading
|
||
|
||
import pytest
|
||
|
||
from jira_hub.core import api, settings
|
||
from jira_hub.core.client import HubClient, HubError
|
||
|
||
|
||
@pytest.fixture
|
||
def live(tmp_path, add_project):
|
||
h = api.Hub(tmp_path / "hub.sqlite", backups_dir=tmp_path / "backups")
|
||
h.claim_wait = 0
|
||
conn = h.conn()
|
||
settings.set_(conn, "link_types", {"связанные": "ASUPR_Связанные"})
|
||
add_project(conn)
|
||
tok = settings.tokens(conn)
|
||
conn.close()
|
||
srv = api.make_server(h, "127.0.0.1", 0)
|
||
th = threading.Thread(target=srv.serve_forever, daemon=True)
|
||
th.start()
|
||
base = f"http://127.0.0.1:{srv.server_port}"
|
||
yield HubClient(base, tok["agents"]["jira"]), HubClient(base, tok["client"])
|
||
srv.shutdown()
|
||
srv.server_close()
|
||
th.join(5)
|
||
|
||
|
||
def test_create_link_sprint_flow(live):
|
||
agent, client = live
|
||
client.put("/issues/new:60/note", {"fact_status": "Ожидание разработки", "work_kind": "разработка", "updated_by": "import"})
|
||
b = client.post("/batches", {"title": "новая задача в спринт", "author": "claude", "commands": [
|
||
{"type": "ensure_issue", "params": {"temp_key": "new:60", "issue_type": "task", "summary": "Новая", "duedate": "2026-10-23",
|
||
"labels": ["AWPCA"]}},
|
||
{"type": "ensure_link", "params": {"source": "new:60", "target": "A-1", "link_type": "связанные"}},
|
||
{"type": "ensure_sprint", "params": {"key": "new:60", "sprint": "Спринт 2"}},
|
||
]})
|
||
assert b["count"] == 4
|
||
bid = b["id"]
|
||
assert client.get(f"/batches/{bid}")["status"] == "queued"
|
||
seen = []
|
||
while True:
|
||
cmd = agent.post("/agent/claim", {"agent_version": 1, "settings_version": 1})["command"]
|
||
if cmd is None:
|
||
break
|
||
seen.append((cmd["type"], cmd["params"]))
|
||
view = client.get(f"/batches/{bid}")
|
||
assert view["status"] == "running" and view["remaining_seconds"] > 0
|
||
if cmd["type"] == "ensure_issue":
|
||
# одна команда в полёте: повторный claim довыдаёт ensure_issue, зависимая ensure_link не выдаётся
|
||
assert agent.post("/agent/claim", {"agent_version": 1, "settings_version": 1})["command"]["id"] == cmd["id"]
|
||
agent.post(f"/agent/commands/{cmd['id']}/result", {"status": "done", "result": {"key": "A-90"}, "jira_calls": 2})
|
||
# done ensure_issue не пишет в зеркало; заметка переехала с new:60 на A-90
|
||
with pytest.raises(HubError) as e:
|
||
client.get("/issues/A-90")
|
||
assert e.value.status == 404
|
||
with pytest.raises(HubError) as e:
|
||
client.get("/issues/new:60")
|
||
assert e.value.status == 404
|
||
view = client.get(f"/batches/{bid}")
|
||
assert view["status"] == "running" and view["remaining_seconds"] > 0
|
||
elif cmd["type"] == "refresh":
|
||
agent.post("/agent/state", {"command_id": cmd["id"], "issues": [
|
||
{"key": "A-90", "summary": "Новая", "duedate": "2026-10-23", "sprint": "Спринт 2", "labels": [],
|
||
"created": "2026-10-11T10:00:00.000+0300"},
|
||
{"key": "A-1", "summary": "Старая", "labels": []}],
|
||
"links": [{"source_key": "A-90", "target_key": "A-1", "link_type": "ASUPR_Связанные"}]})
|
||
assert client.get("/issues/A-90")["summary"] == "Новая"
|
||
agent.post(f"/agent/commands/{cmd['id']}/result", {"status": "done", "jira_calls": 1})
|
||
else:
|
||
agent.post(f"/agent/commands/{cmd['id']}/result", {"status": "done", "jira_calls": 1})
|
||
assert [t for t, _ in seen] == ["ensure_issue", "ensure_link", "ensure_sprint", "refresh"]
|
||
assert seen[1][1]["source"] == "A-90" and seen[2][1]["key"] == "A-90" and seen[2][1]["board_id"] == 4216 and seen[3][1]["keys"] == ["A-90", "A-1"]
|
||
view = client.get(f"/batches/{bid}")
|
||
assert view["status"] == "done" and view["remaining_seconds"] == 0
|
||
assert all(c["status"] == "done" for c in view["commands"])
|
||
issue = client.get("/issues/A-90")
|
||
assert issue["note"]["work_kind"] == "разработка"
|
||
assert len(issue["links_out"]) == 1
|
||
assert issue["links_out"][0]["target_key"] == "A-1" and issue["links_out"][0]["link_type"] == "ASUPR_Связанные"
|
||
links_in = client.get("/issues/A-1")["links_in"]
|
||
assert [(l["source_key"], l["link_type"]) for l in links_in] == [("A-90", "ASUPR_Связанные")]
|
||
assert client.get("/sync-runs")["runs"][0]["issues_count"] == 2
|