sdlc-hub/tests/test_cli.py
Andrey Epifancev a88bb1e6e8 refactor(sdlc-rename): пакет sdlc_hub, CLI sdlc-hub, каталог данных sdlc-hub
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 11:27:17 +04:00

107 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import os
from pathlib import Path
from sdlc_hub.core import api, cli, paths, release, settings
FIXTURE = Path(__file__).parent / "fixtures" / "config.example.json"
def test_init_import_tokens(tmp_path, monkeypatch, capsys, open_db):
monkeypatch.setenv("SDLC_HUB_HOME", str(tmp_path / "home"))
assert cli.main(["init", "--config", str(FIXTURE)]) == 0
out = capsys.readouterr().out
assert "transitions_map" in out and "агент jira: " in out
assert cli.main(["init", "--config", str(FIXTURE)]) == 1
assert "уже инициализирован" in capsys.readouterr().err
conn = open_db(paths.db_path())
assert [(x["label"], x["name"], x["board_id"]) for x in api.project_rows(conn)] == [("AWPCA", "АРМ КА", 4216)]
assert settings.get(conn, "board_id") is None
assert "проект AWPCA «АРМ КА», доска 4216" in out
assert cli.main(["init", "--config", str(FIXTURE), "--force"]) == 0
capsys.readouterr()
assert [(x["label"], x["board_id"]) for x in api.project_rows(conn)] == [("AWPCA", 4216)]
(tmp_path / "pkg").mkdir()
(tmp_path / "pkg" / "tasks.csv").write_text("Код,Статус по факту,Вид работы\nAURORA-1,В работе,UI\n", encoding="utf-8")
assert cli.main(["import", str(tmp_path / "pkg")]) == 0
rep = json.loads(capsys.readouterr().out)
assert rep["notes"] == 1 and rep["missing_keys"] == ["AURORA-1"]
assert cli.main(["tokens"]) == 0
assert settings.tokens(conn)["client"] in capsys.readouterr().out
def test_agent_publish(tmp_path, monkeypatch, capsys):
monkeypatch.setenv("SDLC_HUB_HOME", str(tmp_path / "home"))
src = tmp_path / "agent.py"
src.write_text("AGENT_VERSION = 6\n", encoding="utf-8")
assert cli.main(["agent", "publish", str(src)]) == 0
out = capsys.readouterr().out
assert out.startswith("опубликована v6, sha256 ") and "…, 18 байт" in out
assert (release.module_dir(paths.release_root(), "jira") / "manifest.json").exists()
assert cli.main(["agent", "publish", str(src)]) == 1
assert "опубликована v6, новая должна быть больше" in capsys.readouterr().err
def test_agent_publish_write_failure(tmp_path, monkeypatch, capsys):
"""Диск полон при записи манифеста: сообщение и код 1 без трейсбека, опубликованной остаётся v8 (M-1 #25)."""
monkeypatch.setenv("SDLC_HUB_HOME", str(tmp_path / "home"))
src = tmp_path / "agent.py"
src.write_text("AGENT_VERSION = 8\n", encoding="utf-8")
assert cli.main(["agent", "publish", str(src)]) == 0
capsys.readouterr()
real = os.replace
def fake(s, d, *a, **kw):
if Path(d).name == "manifest.json":
raise OSError(28, "No space left on device")
return real(s, d, *a, **kw)
monkeypatch.setattr(os, "replace", fake)
src.write_text("AGENT_VERSION = 9\n", encoding="utf-8")
assert cli.main(["agent", "publish", str(src)]) == 1
err = capsys.readouterr().err
assert err.startswith("не удалось записать публикацию: ") and "Traceback" not in err
monkeypatch.setattr(os, "replace", real)
assert release.load(release.module_dir(paths.release_root(), "jira"))["version"] == 8
assert sorted(p.name for p in release.module_dir(paths.release_root(), "jira").iterdir()) == ["agent.py", "manifest.json"]
def test_mcp_default_module(monkeypatch):
from sdlc_hub.core import mcp as core_mcp
from sdlc_hub.modules.jira import mcp as jira_mcp
seen = []
monkeypatch.setattr(core_mcp, "PROJECT", None)
monkeypatch.setattr(jira_mcp.mcp, "run", lambda transport="stdio": seen.append((transport, core_mcp.PROJECT)))
assert cli.main(["mcp", "--project", "AWPCA"]) == 0
assert cli.main(["mcp", "jira", "--project", "AWPCA"]) == 0
assert seen == [("stdio", "AWPCA"), ("stdio", "AWPCA")]
# без --project сессия не привязана к проекту
monkeypatch.setattr(core_mcp, "PROJECT", "STALE")
assert cli.main(["mcp"]) == 0
assert seen[-1] == ("stdio", None)
def test_mcp_unknown_module(monkeypatch, capsys):
from sdlc_hub.modules.jira import mcp as jira_mcp
seen = []
monkeypatch.setattr(jira_mcp.mcp, "run", lambda transport="stdio": seen.append(transport))
assert cli.main(["mcp", "nope"]) == 2
err = capsys.readouterr().err
assert "неизвестный модуль nope" in err and "jira" in err
assert seen == []
def test_agent_publish_migrates_old_layout(tmp_path, monkeypatch, capsys):
"""M-3: корневые agent.py/manifest.json прежней раскладки переезжают в release/jira/ до проверки «только вверх»."""
monkeypatch.setenv("SDLC_HUB_HOME", str(tmp_path))
rel = tmp_path / "release"
rel.mkdir()
old = tmp_path / "old.py"
old.write_text("AGENT_VERSION = 14\n", encoding="utf-8")
release.publish(rel, old) # прежняя раскладка: release/agent.py + manifest.json
new = tmp_path / "new.py"
new.write_text("AGENT_VERSION = 13\n", encoding="utf-8")
assert cli.main(["agent", "publish", str(new)]) == 1 # v13 < v14: «только вверх» видит прежнюю публикацию
assert not (rel / "agent.py").exists() and not (rel / "manifest.json").exists()
assert json.loads((rel / "jira" / "manifest.json").read_text(encoding="utf-8"))["version"] == 14