Skip to main content
Glama
test_user_rating_identifier.py7.41 kB
"""Tests for UserRatingIdentifier validation (removal operations).""" from typing import Any import pytest from pydantic import ValidationError from server.sync.tools import UserRatingIdentifier class TestUserRatingIdentifierValidation: """Test validation logic for UserRatingIdentifier (removal operations).""" @pytest.mark.parametrize( "kwargs,expected", [ pytest.param( {"trakt_id": "123"}, { "trakt_id": "123", "imdb_id": None, "tmdb_id": None, "title": None, "year": None, }, id="trakt_id_only", ), pytest.param( {"imdb_id": "tt1234567"}, { "trakt_id": None, "imdb_id": "tt1234567", "tmdb_id": None, "title": None, "year": None, }, id="imdb_id_only", ), pytest.param( {"tmdb_id": "456"}, { "trakt_id": None, "imdb_id": None, "tmdb_id": "456", "title": None, "year": None, }, id="tmdb_id_only", ), pytest.param( {"title": "Inception", "year": 2010}, { "trakt_id": None, "imdb_id": None, "tmdb_id": None, "title": "Inception", "year": 2010, }, id="title_and_year", ), pytest.param( {"trakt_id": "123", "imdb_id": "tt1234567", "tmdb_id": "456"}, { "trakt_id": "123", "imdb_id": "tt1234567", "tmdb_id": "456", "title": None, "year": None, }, id="multiple_identifiers", ), pytest.param( {"trakt_id": "123", "title": "Inception", "year": 2010}, { "trakt_id": "123", "imdb_id": None, "tmdb_id": None, "title": "Inception", "year": 2010, }, id="identifier_and_title_year", ), ], ) def test_valid_identifiers( self, kwargs: dict[str, Any], expected: dict[str, Any] ) -> None: """Test valid identifier configurations.""" item = UserRatingIdentifier(**kwargs) for field, expected_value in expected.items(): assert getattr(item, field) == expected_value def test_invalid_no_identifiers_no_title_year(self) -> None: """Test validation error when no identifiers or title/year provided.""" with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier() error = exc_info.value.errors()[0] assert error["type"] == "value_error" error_msg = error["msg"] assert "Rating item must include either an identifier" in error_msg assert "trakt_id, imdb_id, or tmdb_id" in error_msg assert "or both title and year" in error_msg def test_invalid_title_without_year(self) -> None: """Test validation error when title provided without year.""" with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(title="Inception") error = exc_info.value.errors()[0] assert error["type"] == "value_error" error_msg = error["msg"] assert "Rating item must include either an identifier" in error_msg def test_invalid_year_without_title(self) -> None: """Test validation error when year provided without title.""" with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(year=2010) error = exc_info.value.errors()[0] assert error["type"] == "value_error" error_msg = error["msg"] assert "Rating item must include either an identifier" in error_msg def test_invalid_empty_strings_no_title_year(self) -> None: """Test validation error when identifiers are empty strings and no title/year.""" with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(trakt_id="", imdb_id="", tmdb_id="") # Empty strings should be caught by min_length validation on fields errors = exc_info.value.errors() assert len(errors) >= 1 # At least one validation error def test_valid_after_string_stripping(self) -> None: """Test validation passes after string stripping.""" item = UserRatingIdentifier(trakt_id=" 123 ") assert item.trakt_id == "123" # Should be stripped def test_field_validation_year_bounds(self) -> None: """Test field validation for year bounds.""" # Valid year item = UserRatingIdentifier(title="Movie", year=2023) assert item.year == 2023 # Invalid year too low with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(title="Movie", year=1800) error = exc_info.value.errors()[0] assert error["type"] == "greater_than" assert error["loc"] == ("year",) def test_field_validation_string_min_length(self) -> None: """Test field validation for string minimum length.""" # Test empty string validation for identifiers with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(trakt_id="") error = exc_info.value.errors()[0] assert error["type"] == "string_too_short" assert error["loc"] == ("trakt_id",) # Test empty string validation for title with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(title="", year=2023) error = exc_info.value.errors()[0] assert error["type"] == "string_too_short" assert error["loc"] == ("title",) def test_cross_field_validation_precedence(self) -> None: """Test that cross-field validation runs after field validation.""" # Field validation should catch empty strings first with pytest.raises(ValidationError) as exc_info: UserRatingIdentifier(trakt_id="", title="", year=2023) # Should get field validation errors first errors = exc_info.value.errors() error_types = [error["type"] for error in errors] assert "string_too_short" in error_types # Cross-field validation may not even run if field validation fails def test_no_rating_field_for_removal(self) -> None: """Test that UserRatingIdentifier doesn't have a rating field (removal only).""" # This should work - no rating field required for removal item = UserRatingIdentifier(trakt_id="123") # Verify no rating field exists assert not hasattr(item, "rating") # Verify the model only has the expected fields expected_fields = {"trakt_id", "imdb_id", "tmdb_id", "title", "year"} actual_fields = set(UserRatingIdentifier.model_fields.keys()) assert actual_fields == expected_fields

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wwiens/trakt_mcpserver'

If you have feedback or need assistance with the MCP directory API, please join our Discord server