import pytest import httpx import respx from gitea_mcp import list_commits, get_commit, compare_branches, list_repo_contributors BASE = "https://gitea.test/api/v1" @respx.mock def test_list_commits_defaults(): route = respx.get(f"{BASE}/repos/owner/repo/commits").mock( return_value=httpx.Response(200, json=[{"sha": "abc123"}]) ) result = list_commits("owner", "repo") assert route.called params = dict(route.calls[0].request.url.params) assert params["limit"] == "20" assert params["page"] == "1" assert "sha" not in params assert "path" not in params @respx.mock def test_list_commits_on_branch_and_path(): route = respx.get(f"{BASE}/repos/owner/repo/commits").mock( return_value=httpx.Response(200, json=[]) ) list_commits("owner", "repo", sha="develop", path="server/gitea_mcp.py") params = dict(route.calls[0].request.url.params) assert params["sha"] == "develop" assert params["path"] == "server/gitea_mcp.py" @respx.mock def test_get_commit(): route = respx.get(f"{BASE}/repos/owner/repo/git/commits/abc123").mock( return_value=httpx.Response(200, json={"sha": "abc123", "commit": {"message": "fix bug"}}) ) result = get_commit("owner", "repo", "abc123") assert route.called assert result["sha"] == "abc123" params = dict(route.calls[0].request.url.params) assert params["stat"] == "true" assert params["files"] == "true" @respx.mock def test_get_commit_without_stat(): route = respx.get(f"{BASE}/repos/owner/repo/git/commits/deadbeef").mock( return_value=httpx.Response(200, json={"sha": "deadbeef"}) ) get_commit("owner", "repo", "deadbeef", stat=False, files=False) params = dict(route.calls[0].request.url.params) assert params["stat"] == "false" assert params["files"] == "false" @respx.mock def test_get_commit_not_found(): respx.get(f"{BASE}/repos/owner/repo/git/commits/notacommit").mock( return_value=httpx.Response(404, json={"message": "not found"}) ) with pytest.raises(RuntimeError, match="404"): get_commit("owner", "repo", "notacommit") @respx.mock def test_compare_branches(): route = respx.get(f"{BASE}/repos/owner/repo/compare/main...develop").mock( return_value=httpx.Response(200, json={"total_commits": 3, "commits": []}) ) result = compare_branches("owner", "repo", "main", "develop") assert route.called assert result["total_commits"] == 3 @respx.mock def test_compare_branches_with_slashes(): route = respx.get(f"{BASE}/repos/owner/repo/compare/release%2F1.0...feature%2Fnew").mock( return_value=httpx.Response(200, json={"total_commits": 1}) ) result = compare_branches("owner", "repo", "release/1.0", "feature/new") assert route.called @respx.mock def test_list_repo_contributors(): route = respx.get(f"{BASE}/repos/owner/repo/contributors").mock( return_value=httpx.Response(200, json=[{"login": "alice", "contributions": 42}]) ) result = list_repo_contributors("owner", "repo") assert route.called assert result[0]["login"] == "alice" assert dict(route.calls[0].request.url.params)["limit"] == "20"