80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
"""Write tools that Gitea refuses: the status and error kind reach the client intact."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import secrets
|
|
|
|
from tests.integration.conftest import McpSession, RepoRef, b64
|
|
from tests.integration.harness import GiteaInstance
|
|
|
|
|
|
async def test_creating_in_a_missing_repository_is_not_found(
|
|
mcp: McpSession, gitea: GiteaInstance
|
|
) -> None:
|
|
missing = {"owner": gitea.admin_login, "repo": "missing-" + secrets.token_hex(4)}
|
|
issue = await mcp.fail("gitea_issue_create_issue", 404, body={"title": "x"}, **missing)
|
|
assert issue.error_kind == "not_found"
|
|
label = await mcp.fail(
|
|
"gitea_issue_create_label", 404, body={"name": "x", "color": "#ffffff"}, **missing
|
|
)
|
|
assert label.error_kind == "not_found"
|
|
# The audit log records the failure with the same kind.
|
|
failed = [e for e in mcp.audit_entries() if e["tool_name"] == "gitea_issue_create_issue"]
|
|
assert failed and failed[-1]["outcome"] == "not_found"
|
|
assert failed[-1]["result_status"] == "error"
|
|
|
|
|
|
async def test_invalid_values_are_validation_errors(mcp: McpSession, fresh_repo: RepoRef) -> None:
|
|
repo = fresh_repo.args
|
|
bad_color = await mcp.call(
|
|
"gitea_issue_create_label", body={"name": "bad", "color": "not-a-color"}, **repo
|
|
)
|
|
assert bad_color.is_error
|
|
assert bad_color.error_kind in ("validation_failed", "bad_request")
|
|
assert bad_color.status in (400, 422)
|
|
|
|
# Gitea itself refuses a missing body.
|
|
missing_body = await mcp.call("gitea_issue_create_issue", **repo)
|
|
assert missing_body.is_error and missing_body.status == 422
|
|
assert missing_body.error_kind == "validation_failed"
|
|
|
|
# A field of the wrong type never reaches Gitea: the schema rejects it first.
|
|
wrong_type = await mcp.call(
|
|
"gitea_issue_create_issue", body={"title": ["not", "a", "string"]}, **repo
|
|
)
|
|
assert wrong_type.is_error and wrong_type.status is None
|
|
assert wrong_type.error_kind == "invalid_argument"
|
|
|
|
|
|
async def test_conflicting_writes_are_conflicts(
|
|
mcp: McpSession, gitea: GiteaInstance, fresh_repo: RepoRef
|
|
) -> None:
|
|
repo = fresh_repo.args
|
|
duplicate = await mcp.fail(
|
|
"gitea_user_current_create_repo", 409, body={"name": fresh_repo.name}
|
|
)
|
|
assert duplicate.error_kind == "conflict"
|
|
|
|
await mcp.ok(
|
|
"gitea_repo_create_file",
|
|
status=201,
|
|
filepath="a.txt",
|
|
body={"content": b64("one"), "message": "one"},
|
|
**repo,
|
|
)
|
|
again = await mcp.call(
|
|
"gitea_repo_create_file",
|
|
filepath="a.txt",
|
|
body={"content": b64("two"), "message": "two"},
|
|
**repo,
|
|
)
|
|
assert again.is_error and again.status in (409, 422)
|
|
|
|
stale = await mcp.call(
|
|
"gitea_repo_update_file",
|
|
filepath="a.txt",
|
|
body={"content": b64("three"), "message": "three", "sha": "0" * 40},
|
|
**repo,
|
|
)
|
|
assert stale.is_error and stale.status in (409, 422)
|