PyGithub MCP Server
by AstroMined
"""Tests for base schema models.
This module tests the base schema models used across multiple domains.
"""
import pytest
from pydantic import ValidationError
from pygithub_mcp_server.schemas.base import RepositoryRef, FileContent
class TestRepositoryRef:
"""Tests for the RepositoryRef schema."""
def test_valid_data(self, valid_repository_ref_data):
"""Test that valid data passes validation."""
repo_ref = RepositoryRef(**valid_repository_ref_data)
assert repo_ref.owner == valid_repository_ref_data["owner"]
assert repo_ref.repo == valid_repository_ref_data["repo"]
def test_minimal_valid_data(self):
"""Test with minimal valid data."""
repo_ref = RepositoryRef(owner="octocat", repo="hello-world")
assert repo_ref.owner == "octocat"
assert repo_ref.repo == "hello-world"
def test_missing_required_fields(self):
"""Test that missing required fields raise validation errors."""
# Missing owner
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(repo="hello-world")
assert "owner" in str(exc_info.value).lower()
# Missing repo
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner="octocat")
assert "repo" in str(exc_info.value).lower()
def test_invalid_field_types(self):
"""Test that invalid field types raise validation errors."""
# Invalid owner type
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner=123, repo="hello-world")
assert "owner" in str(exc_info.value).lower()
# Invalid repo type
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner="octocat", repo=123)
assert "repo" in str(exc_info.value).lower()
def test_empty_strings(self):
"""Test that empty strings raise validation errors."""
# Empty owner
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner="", repo="hello-world")
assert "owner cannot be empty" in str(exc_info.value).lower()
# Empty repo
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner="octocat", repo="")
assert "repo cannot be empty" in str(exc_info.value).lower()
# Whitespace-only owner
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner=" ", repo="hello-world")
assert "owner cannot be empty" in str(exc_info.value).lower()
# Whitespace-only repo
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner="octocat", repo=" ")
assert "repo cannot be empty" in str(exc_info.value).lower()
def test_none_values(self):
"""Test that None values raise validation errors."""
# None owner
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner=None, repo="hello-world")
assert "owner" in str(exc_info.value).lower()
# None repo
with pytest.raises(ValidationError) as exc_info:
RepositoryRef(owner="octocat", repo=None)
assert "repo" in str(exc_info.value).lower()
def test_extra_fields(self):
"""Test that extra fields are ignored."""
repo_ref = RepositoryRef(
owner="octocat",
repo="hello-world",
extra_field="ignored"
)
assert repo_ref.owner == "octocat"
assert repo_ref.repo == "hello-world"
assert not hasattr(repo_ref, "extra_field")
class TestFileContent:
"""Tests for the FileContent schema."""
def test_valid_data(self, valid_file_content_data):
"""Test that valid data passes validation."""
file_content = FileContent(**valid_file_content_data)
assert file_content.path == valid_file_content_data["path"]
assert file_content.content == valid_file_content_data["content"]
def test_minimal_valid_data(self):
"""Test with minimal valid data."""
file_content = FileContent(path="README.md", content="# Hello World")
assert file_content.path == "README.md"
assert file_content.content == "# Hello World"
def test_missing_required_fields(self):
"""Test that missing required fields raise validation errors."""
# Missing path
with pytest.raises(ValidationError) as exc_info:
FileContent(content="# Hello World")
assert "path" in str(exc_info.value).lower()
# Missing content
with pytest.raises(ValidationError) as exc_info:
FileContent(path="README.md")
assert "content" in str(exc_info.value).lower()
def test_invalid_field_types(self):
"""Test that invalid field types raise validation errors."""
# Invalid path type
with pytest.raises(ValidationError) as exc_info:
FileContent(path=123, content="# Hello World")
assert "path" in str(exc_info.value).lower()
# Invalid content type
with pytest.raises(ValidationError) as exc_info:
FileContent(path="README.md", content=123)
assert "content" in str(exc_info.value).lower()
def test_empty_strings(self):
"""Test behavior with empty strings."""
# Empty path - should raise error
with pytest.raises(ValidationError) as exc_info:
FileContent(path="", content="# Hello World")
assert "path cannot be empty" in str(exc_info.value).lower()
# Whitespace-only path - should raise error
with pytest.raises(ValidationError) as exc_info:
FileContent(path=" ", content="# Hello World")
assert "path cannot be empty" in str(exc_info.value).lower()
# Empty content - should be valid (empty files are allowed)
file_content = FileContent(path="README.md", content="")
assert file_content.path == "README.md"
assert file_content.content == ""
def test_none_values(self):
"""Test that None values raise validation errors."""
# None path
with pytest.raises(ValidationError) as exc_info:
FileContent(path=None, content="# Hello World")
assert "path" in str(exc_info.value).lower()
# None content
with pytest.raises(ValidationError) as exc_info:
FileContent(path="README.md", content=None)
assert "content" in str(exc_info.value).lower()
def test_extra_fields(self):
"""Test that extra fields are ignored."""
file_content = FileContent(
path="README.md",
content="# Hello World",
extra_field="ignored"
)
assert file_content.path == "README.md"
assert file_content.content == "# Hello World"
assert not hasattr(file_content, "extra_field")
def test_binary_content(self):
"""Test with binary content encoded as base64 string."""
# Base64 encoded content should be valid
file_content = FileContent(
path="image.png",
content="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
)
assert file_content.path == "image.png"
assert file_content.content.startswith("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ")