test: add 106 unit + smoke tests, 93% coverage
- pytest + respx + pytest-cov added as dev dependencies - tests/smoke/test_registration.py: verify all 66 tools registered and unique - tests/unit/: 12 files covering every tool — HTTP method, URL, params/body, errors - tests/config.test.json + conftest.py: zero-network test setup via GITEA_CONFIG - CLAUDE.md: developer guide with testing philosophy, pyramid, and commands - server/gitea_mcp.py: get_commit, list_pr_files tools added - README.md: tool count corrected to 66
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import json
|
||||
import pytest
|
||||
import httpx
|
||||
import respx
|
||||
from server.gitea_mcp import (
|
||||
list_labels, create_label, add_issue_labels, list_milestones, create_milestone,
|
||||
)
|
||||
|
||||
BASE = "https://gitea.test/api/v1"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_labels():
|
||||
route = respx.get(f"{BASE}/repos/owner/repo/labels").mock(
|
||||
return_value=httpx.Response(200, json=[{"id": 1, "name": "bug", "color": "#ee0701"}])
|
||||
)
|
||||
result = list_labels("owner", "repo")
|
||||
assert route.called
|
||||
assert result[0]["name"] == "bug"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_create_label():
|
||||
route = respx.post(f"{BASE}/repos/owner/repo/labels").mock(
|
||||
return_value=httpx.Response(201, json={"id": 5, "name": "enhancement"})
|
||||
)
|
||||
result = create_label("owner", "repo", "enhancement", "#84b6eb")
|
||||
assert route.called
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["name"] == "enhancement"
|
||||
assert body["color"] == "#84b6eb"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_create_label_with_description():
|
||||
route = respx.post(f"{BASE}/repos/owner/repo/labels").mock(
|
||||
return_value=httpx.Response(201, json={"id": 6})
|
||||
)
|
||||
create_label("owner", "repo", "wontfix", "#ffffff", description="Not going to fix")
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["description"] == "Not going to fix"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_create_label_error():
|
||||
respx.post(f"{BASE}/repos/owner/repo/labels").mock(
|
||||
return_value=httpx.Response(422, json={"message": "validation failed"})
|
||||
)
|
||||
with pytest.raises(RuntimeError, match="422"):
|
||||
create_label("owner", "repo", "bad", "notacolor")
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_add_issue_labels():
|
||||
route = respx.post(f"{BASE}/repos/owner/repo/issues/3/labels").mock(
|
||||
return_value=httpx.Response(200, json=[{"id": 1}])
|
||||
)
|
||||
result = add_issue_labels("owner", "repo", 3, [1, 2])
|
||||
assert route.called
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["labels"] == [1, 2]
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_milestones():
|
||||
route = respx.get(f"{BASE}/repos/owner/repo/milestones").mock(
|
||||
return_value=httpx.Response(200, json=[{"id": 1, "title": "v1.0"}])
|
||||
)
|
||||
result = list_milestones("owner", "repo")
|
||||
assert route.called
|
||||
assert result[0]["title"] == "v1.0"
|
||||
assert dict(route.calls[0].request.url.params)["state"] == "open"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_milestones_closed():
|
||||
route = respx.get(f"{BASE}/repos/owner/repo/milestones").mock(
|
||||
return_value=httpx.Response(200, json=[])
|
||||
)
|
||||
list_milestones("owner", "repo", state="closed")
|
||||
assert dict(route.calls[0].request.url.params)["state"] == "closed"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_create_milestone():
|
||||
route = respx.post(f"{BASE}/repos/owner/repo/milestones").mock(
|
||||
return_value=httpx.Response(201, json={"id": 2, "title": "v2.0"})
|
||||
)
|
||||
result = create_milestone("owner", "repo", "v2.0")
|
||||
assert route.called
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["title"] == "v2.0"
|
||||
assert "description" not in body
|
||||
assert "due_on" not in body
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_create_milestone_with_due_date():
|
||||
route = respx.post(f"{BASE}/repos/owner/repo/milestones").mock(
|
||||
return_value=httpx.Response(201, json={"id": 3})
|
||||
)
|
||||
create_milestone("owner", "repo", "v3.0", description="Major release", due_on="2025-12-31T00:00:00Z")
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["description"] == "Major release"
|
||||
assert body["due_on"] == "2025-12-31T00:00:00Z"
|
||||
Reference in New Issue
Block a user