Files
AegisGitea-MCP/tests/test_catalog_model.py
Latte b82e2866cb feat: new settings, CLI skeleton and interface skeletons
Adds the pydantic-settings Settings with validated GITEA_URL, OAuth scopes
and toolsets, the argparse CLI skeleton, catalog.model, identity and
GiteaAPIError. Test fixtures now isolate env, cwd and state paths in tmp.
2026-10-14 15:40:37 +02:00

118 lines
3.4 KiB
Python

"""Tests for the catalog data model."""
from __future__ import annotations
import json
from typing import Any
import pytest
from aegis_gitea_mcp.catalog import Operation, Parameter
def sample_dict() -> dict[str, Any]:
return {
"tool_name": "gitea_issue_create",
"domain": "issue",
"operation_id": "issueCreateIssue",
"method": "POST",
"path": "/repos/{owner}/{repo}/issues",
"summary": "Create an issue",
"description": "",
"parameters": [
{
"name": "owner",
"arg_name": "owner",
"location": "path",
"required": True,
"schema": {"type": "string"},
"is_file": False,
},
{
"name": "body",
"arg_name": "body",
"location": "body",
"required": False,
"schema": {"type": "object"},
},
],
"input_schema": {"type": "object", "additionalProperties": False},
"consumes": ["application/json"],
"produces": ["application/json"],
"read_only": False,
"destructive": False,
"idempotent": False,
"paginated": False,
}
def test_operation_round_trip_through_json() -> None:
data = sample_dict()
operation = Operation.from_dict(data)
assert operation.method == "POST"
assert isinstance(operation.parameters, tuple)
assert isinstance(operation.consumes, tuple)
assert operation.parameters[0].location == "path"
assert operation.parameters[1].is_file is False
rebuilt = Operation.from_dict(json.loads(json.dumps(operation.to_dict())))
assert rebuilt == operation
def test_to_dict_uses_lists_and_is_json_serializable() -> None:
dumped = Operation.from_dict(sample_dict()).to_dict()
assert isinstance(dumped["parameters"], list)
assert isinstance(dumped["consumes"], list)
json.dumps(dumped)
def test_method_is_upper_cased() -> None:
data = sample_dict()
data["method"] = "post"
assert Operation.from_dict(data).method == "POST"
def test_optional_fields_default() -> None:
data = sample_dict()
del data["summary"], data["description"], data["consumes"], data["produces"]
operation = Operation.from_dict(data)
assert operation.summary == ""
assert operation.consumes == ()
assert operation.produces == ()
def test_invalid_location_rejected() -> None:
with pytest.raises(ValueError, match="location"):
Parameter.from_dict(
{"name": "x", "arg_name": "x", "location": "header", "required": True, "schema": {}}
)
def test_missing_required_key_raises() -> None:
data = sample_dict()
del data["tool_name"]
with pytest.raises(KeyError):
Operation.from_dict(data)
def test_operation_is_frozen() -> None:
operation = Operation.from_dict(sample_dict())
with pytest.raises(AttributeError):
operation.method = "GET" # type: ignore[misc]
def test_file_parameter() -> None:
parameter = Parameter.from_dict(
{
"name": "attachment",
"arg_name": "attachment",
"location": "formData",
"required": True,
"schema": {"type": "string", "contentEncoding": "base64"},
"is_file": True,
}
)
assert parameter.is_file is True
assert parameter.to_dict()["location"] == "formData"