87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
"""Tests for :mod:`metin_release_mcp.cli_runner`."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
import pytest
|
|
|
|
from metin_release_mcp import cli_runner
|
|
from metin_release_mcp.errors import CliNotFoundError, CliUnparseableOutputError
|
|
|
|
from .conftest import make_runner
|
|
|
|
|
|
def test_run_cli_success_parses_envelope():
|
|
runner = make_runner({"ok": True, "command": "release inspect", "status": "inspected", "stats": {"file_count": 3}})
|
|
result = cli_runner.run_cli(
|
|
["release", "inspect", "--json", "--source", "/tmp/x"],
|
|
binary="/fake/metin-release",
|
|
runner=runner,
|
|
)
|
|
assert result.ok is True
|
|
assert result.envelope["status"] == "inspected"
|
|
assert result.envelope["stats"]["file_count"] == 3
|
|
assert result.returncode == 0
|
|
assert runner.calls[0][0] == "/fake/metin-release"
|
|
assert "--json" in runner.calls[0]
|
|
|
|
|
|
def test_run_cli_error_envelope_passed_through():
|
|
err = {
|
|
"ok": False,
|
|
"command": "release sign",
|
|
"status": "failed",
|
|
"error": {"code": "key_permission", "message": "key must be mode 600"},
|
|
}
|
|
runner = make_runner(err, stderr="error: key_permission\n", returncode=3)
|
|
result = cli_runner.run_cli(["release", "sign"], binary="/fake/mr", runner=runner)
|
|
assert result.ok is False
|
|
assert result.returncode == 3
|
|
assert result.envelope["error"]["code"] == "key_permission"
|
|
assert "key_permission" in result.stderr
|
|
|
|
|
|
def test_run_cli_unparseable_output_raises():
|
|
runner = make_runner(stdout="not-json-at-all", returncode=0)
|
|
with pytest.raises(CliUnparseableOutputError):
|
|
cli_runner.run_cli(["release", "inspect"], binary="/fake/mr", runner=runner)
|
|
|
|
|
|
def test_run_cli_empty_stdout_raises():
|
|
runner = make_runner(stdout=" \n", stderr="boom", returncode=2)
|
|
with pytest.raises(CliUnparseableOutputError):
|
|
cli_runner.run_cli(["release", "inspect"], binary="/fake/mr", runner=runner)
|
|
|
|
|
|
def test_run_cli_non_object_json_raises():
|
|
runner = make_runner(stdout=json.dumps([1, 2, 3]))
|
|
with pytest.raises(CliUnparseableOutputError):
|
|
cli_runner.run_cli(["release", "inspect"], binary="/fake/mr", runner=runner)
|
|
|
|
|
|
def test_run_cli_file_not_found_raises():
|
|
def boom(*args, **kwargs):
|
|
raise FileNotFoundError("no such file")
|
|
|
|
with pytest.raises(CliNotFoundError):
|
|
cli_runner.run_cli(["release", "inspect"], binary="/does/not/exist", runner=boom)
|
|
|
|
|
|
def test_resolve_binary_env_override(monkeypatch):
|
|
monkeypatch.setenv("METIN_RELEASE_BINARY", "/custom/path/metin-release")
|
|
assert cli_runner.resolve_binary() == "/custom/path/metin-release"
|
|
|
|
|
|
def test_resolve_binary_which_fallback(monkeypatch):
|
|
monkeypatch.delenv("METIN_RELEASE_BINARY", raising=False)
|
|
monkeypatch.setattr(cli_runner.shutil, "which", lambda name: "/usr/bin/metin-release")
|
|
assert cli_runner.resolve_binary() == "/usr/bin/metin-release"
|
|
|
|
|
|
def test_resolve_binary_missing_raises(monkeypatch):
|
|
monkeypatch.delenv("METIN_RELEASE_BINARY", raising=False)
|
|
monkeypatch.setattr(cli_runner.shutil, "which", lambda name: None)
|
|
with pytest.raises(CliNotFoundError):
|
|
cli_runner.resolve_binary()
|