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,90 @@
|
||||
import pytest
|
||||
import httpx
|
||||
import respx
|
||||
from server.gitea_mcp import (
|
||||
get_user, search_users, list_my_orgs, get_org,
|
||||
list_org_repos, list_org_members, list_org_teams,
|
||||
)
|
||||
|
||||
BASE = "https://gitea.test/api/v1"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_get_user():
|
||||
route = respx.get(f"{BASE}/users/alice").mock(
|
||||
return_value=httpx.Response(200, json={"login": "alice", "id": 42})
|
||||
)
|
||||
result = get_user("alice")
|
||||
assert route.called
|
||||
assert result["login"] == "alice"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_get_user_not_found():
|
||||
respx.get(f"{BASE}/users/nobody").mock(
|
||||
return_value=httpx.Response(404, json={"message": "not found"})
|
||||
)
|
||||
with pytest.raises(RuntimeError, match="404"):
|
||||
get_user("nobody")
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_search_users():
|
||||
route = respx.get(f"{BASE}/users/search").mock(
|
||||
return_value=httpx.Response(200, json={"data": [{"login": "alice"}]})
|
||||
)
|
||||
result = search_users("ali")
|
||||
assert route.called
|
||||
params = dict(route.calls[0].request.url.params)
|
||||
assert params["q"] == "ali"
|
||||
assert params["limit"] == "10"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_my_orgs():
|
||||
route = respx.get(f"{BASE}/user/orgs").mock(
|
||||
return_value=httpx.Response(200, json=[{"name": "myorg"}])
|
||||
)
|
||||
result = list_my_orgs()
|
||||
assert route.called
|
||||
assert result[0]["name"] == "myorg"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_get_org():
|
||||
route = respx.get(f"{BASE}/orgs/myorg").mock(
|
||||
return_value=httpx.Response(200, json={"name": "myorg", "full_name": "My Org"})
|
||||
)
|
||||
result = get_org("myorg")
|
||||
assert route.called
|
||||
assert result["name"] == "myorg"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_org_repos():
|
||||
route = respx.get(f"{BASE}/orgs/myorg/repos").mock(
|
||||
return_value=httpx.Response(200, json=[{"name": "repo1"}])
|
||||
)
|
||||
result = list_org_repos("myorg")
|
||||
assert route.called
|
||||
assert dict(route.calls[0].request.url.params)["limit"] == "50"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_org_members():
|
||||
route = respx.get(f"{BASE}/orgs/myorg/members").mock(
|
||||
return_value=httpx.Response(200, json=[{"login": "bob"}])
|
||||
)
|
||||
result = list_org_members("myorg")
|
||||
assert route.called
|
||||
assert result[0]["login"] == "bob"
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_list_org_teams():
|
||||
route = respx.get(f"{BASE}/orgs/myorg/teams").mock(
|
||||
return_value=httpx.Response(200, json=[{"id": 1, "name": "developers"}])
|
||||
)
|
||||
result = list_org_teams("myorg")
|
||||
assert route.called
|
||||
assert result[0]["name"] == "developers"
|
||||
Reference in New Issue
Block a user