Files
gitea-platform-mcp/tests/unit/test_files.py
T
a-limasov-ii db5a43b19a refactor: make gitea a self-contained Cline skill
Relocate the script into the skill (skills/gitea/scripts/gitea_mcp.py) and add a
PEP 723 dependency block, so `uv run scripts/gitea_mcp.py` provisions deps with no
install step and the skill folder is portable (drop into ~/.cline/skills/). Drop
the non-standard `metadata` frontmatter — Cline only recognizes name + description.

- .mcp.json points at the relocated script and runs with --no-project (PEP 723)
- SKILL.md uses relative scripts/ paths; metadata block removed
- find_config walks up the tree to locate config.json (skill root or plugin root)
- tests import gitea_mcp via pytest pythonpath; README/CLAUDE paths updated

Tests: 119 passed, 92% coverage. Standalone list-tools verified via uv --no-project.
2026-06-24 14:35:28 +03:00

109 lines
3.7 KiB
Python

import base64
import json
import pytest
import httpx
import respx
from gitea_mcp import list_directory, get_file, create_file, update_file, delete_file
BASE = "https://gitea.test/api/v1"
@respx.mock
def test_list_directory_root():
route = respx.get(f"{BASE}/repos/owner/repo/contents/").mock(
return_value=httpx.Response(200, json=[{"name": "README.md", "type": "file"}])
)
result = list_directory("owner", "repo")
assert route.called
assert result[0]["name"] == "README.md"
@respx.mock
def test_list_directory_with_ref():
route = respx.get(f"{BASE}/repos/owner/repo/contents/src").mock(
return_value=httpx.Response(200, json=[])
)
list_directory("owner", "repo", path="src", ref="develop")
params = dict(route.calls[0].request.url.params)
assert params["ref"] == "develop"
@respx.mock
def test_get_file():
encoded = base64.b64encode(b"hello world").decode()
route = respx.get(f"{BASE}/repos/owner/repo/contents/README.md").mock(
return_value=httpx.Response(200, json={"name": "README.md", "content": encoded, "sha": "abc"})
)
result = get_file("owner", "repo", "README.md")
assert route.called
assert result["content"] == encoded
assert result["sha"] == "abc"
@respx.mock
def test_get_file_with_ref():
route = respx.get(f"{BASE}/repos/owner/repo/contents/README.md").mock(
return_value=httpx.Response(200, json={"name": "README.md"})
)
get_file("owner", "repo", "README.md", ref="v1.0")
params = dict(route.calls[0].request.url.params)
assert params["ref"] == "v1.0"
@respx.mock
def test_get_file_not_found():
respx.get(f"{BASE}/repos/owner/repo/contents/missing.txt").mock(
return_value=httpx.Response(404, json={"message": "not found"})
)
with pytest.raises(RuntimeError, match="404"):
get_file("owner", "repo", "missing.txt")
@respx.mock
def test_create_file():
route = respx.post(f"{BASE}/repos/owner/repo/contents/hello.txt").mock(
return_value=httpx.Response(201, json={"content": {"name": "hello.txt"}})
)
result = create_file("owner", "repo", "hello.txt", "hello world", "add hello")
assert route.called
body = json.loads(route.calls[0].request.content)
assert body["content"] == base64.b64encode(b"hello world").decode()
assert body["message"] == "add hello"
assert "branch" not in body
@respx.mock
def test_create_file_on_branch():
route = respx.post(f"{BASE}/repos/owner/repo/contents/file.py").mock(
return_value=httpx.Response(201, json={"content": {"name": "file.py"}})
)
create_file("owner", "repo", "file.py", "print('hi')", "add file", branch="develop")
body = json.loads(route.calls[0].request.content)
assert body["branch"] == "develop"
@respx.mock
def test_update_file():
new_content = "updated content"
route = respx.put(f"{BASE}/repos/owner/repo/contents/README.md").mock(
return_value=httpx.Response(200, json={"content": {"name": "README.md"}})
)
update_file("owner", "repo", "README.md", new_content, "update readme", sha="deadbeef")
assert route.called
body = json.loads(route.calls[0].request.content)
assert body["content"] == base64.b64encode(new_content.encode()).decode()
assert body["sha"] == "deadbeef"
assert body["message"] == "update readme"
@respx.mock
def test_delete_file():
route = respx.delete(f"{BASE}/repos/owner/repo/contents/old.txt").mock(
return_value=httpx.Response(200, json={"commit": {"sha": "abc"}})
)
result = delete_file("owner", "repo", "old.txt", "remove old file", sha="abc123")
assert route.called
body = json.loads(route.calls[0].request.content)
assert body["message"] == "remove old file"
assert body["sha"] == "abc123"