Files
AegisGitea-MCP/tests/test_repository_tools.py
latte 59e1ea53a8
Some checks failed
docker / lint (push) Has been cancelled
docker / test (push) Has been cancelled
docker / docker-build (push) Has been cancelled
lint / lint (push) Has been cancelled
test / test (push) Has been cancelled
Add OAuth2/OIDC per-user Gitea authentication
Introduce a GiteaOAuthValidator for JWT and userinfo validation and
fallbacks, add /oauth/token proxy, and thread per-user tokens through
the
request context and automation paths. Update config and .env.example for
OAuth-first mode, add OpenAPI, extensive unit/integration tests,
GitHub/Gitea CI workflows, docs, and lint/test enforcement (>=80% cov).
2026-02-25 16:54:01 +01:00

129 lines
4.3 KiB
Python

"""Tests for repository-focused tool handlers."""
from __future__ import annotations
import pytest
from aegis_gitea_mcp.config import reset_settings
from aegis_gitea_mcp.gitea_client import GiteaError
from aegis_gitea_mcp.tools.repository import (
get_file_contents_tool,
get_file_tree_tool,
get_repository_info_tool,
list_repositories_tool,
)
@pytest.fixture(autouse=True)
def repository_tool_env(monkeypatch: pytest.MonkeyPatch) -> None:
"""Provide minimal settings needed by response limit helpers."""
reset_settings()
monkeypatch.setenv("GITEA_URL", "https://gitea.example.com")
monkeypatch.setenv("GITEA_TOKEN", "legacy-token")
monkeypatch.setenv("MCP_API_KEYS", "a" * 64)
monkeypatch.setenv("ENVIRONMENT", "test")
yield
reset_settings()
class RepoStub:
"""Stub Gitea client for repository tools."""
async def list_repositories(self):
return [{"name": "demo", "owner": {"login": "acme"}, "full_name": "acme/demo"}]
async def get_repository(self, owner, repo):
return {"name": repo, "owner": {"login": owner}, "full_name": f"{owner}/{repo}"}
async def get_tree(self, owner, repo, ref, recursive):
return {"tree": [{"path": "README.md", "type": "blob", "size": 11, "sha": "abc"}]}
async def get_file_contents(self, owner, repo, filepath, ref):
return {
"content": "SGVsbG8gV29ybGQ=",
"encoding": "base64",
"size": 11,
"sha": "abc",
"html_url": f"https://example/{owner}/{repo}/{filepath}",
}
class RepoErrorStub(RepoStub):
"""Stub that raises backend errors."""
async def list_repositories(self):
raise GiteaError("backend down")
@pytest.mark.asyncio
async def test_list_repositories_tool_success() -> None:
"""Repository listing tool normalizes output shape."""
result = await list_repositories_tool(RepoStub(), {})
assert result["count"] == 1
assert result["repositories"][0]["owner"] == "acme"
@pytest.mark.asyncio
async def test_list_repositories_tool_failure_mode() -> None:
"""Repository listing tool wraps backend errors."""
with pytest.raises(RuntimeError, match="Failed to list repositories"):
await list_repositories_tool(RepoErrorStub(), {})
@pytest.mark.asyncio
async def test_get_repository_info_tool_success() -> None:
"""Repository info tool returns normalized metadata."""
result = await get_repository_info_tool(RepoStub(), {"owner": "acme", "repo": "demo"})
assert result["full_name"] == "acme/demo"
@pytest.mark.asyncio
async def test_get_file_tree_tool_success() -> None:
"""File tree tool returns bounded tree entries."""
result = await get_file_tree_tool(
RepoStub(),
{"owner": "acme", "repo": "demo", "ref": "main", "recursive": False},
)
assert result["count"] == 1
assert result["tree"][0]["path"] == "README.md"
@pytest.mark.asyncio
async def test_get_file_contents_tool_decodes_base64() -> None:
"""File contents tool decodes UTF-8 base64 payloads."""
result = await get_file_contents_tool(
RepoStub(),
{"owner": "acme", "repo": "demo", "filepath": "README.md", "ref": "main"},
)
assert result["content"] == "Hello World"
@pytest.mark.asyncio
async def test_get_file_contents_tool_handles_invalid_base64() -> None:
"""Invalid base64 payloads are returned safely without crashing."""
class InvalidBase64Stub(RepoStub):
async def get_file_contents(self, owner, repo, filepath, ref):
return {"content": "%%%not-base64%%%", "encoding": "base64", "size": 4, "sha": "abc"}
result = await get_file_contents_tool(
InvalidBase64Stub(),
{"owner": "acme", "repo": "demo", "filepath": "README.md", "ref": "main"},
)
assert result["content"] == "%%%not-base64%%%"
@pytest.mark.asyncio
async def test_get_file_contents_tool_failure_mode() -> None:
"""File contents tool wraps backend failures."""
class ErrorFileStub(RepoStub):
async def get_file_contents(self, owner, repo, filepath, ref):
raise GiteaError("boom")
with pytest.raises(RuntimeError, match="Failed to get file contents"):
await get_file_contents_tool(
ErrorFileStub(),
{"owner": "acme", "repo": "demo", "filepath": "README.md", "ref": "main"},
)