Skip to main content
Glama
test_media.py22.2 kB
"""Tests for the models.movies and models.shows models.""" from __future__ import annotations from typing import TYPE_CHECKING import pytest from pydantic import ValidationError from models.movies import TraktMovie, TraktPopularMovie, TraktTrendingMovie from models.shows import TraktEpisode, TraktPopularShow, TraktShow, TraktTrendingShow if TYPE_CHECKING: from typing import TypedDict from tests.models.test_data_types import ( EpisodeTestData, MovieTestData, ShowTestData, ) class TrendingShowPayload(TypedDict): """Test payload for TraktTrendingShow.""" watchers: int show: ShowTestData class PopularShowPayload(TypedDict): """Test payload for TraktPopularShow.""" show: ShowTestData class TrendingMoviePayload(TypedDict): """Test payload for TraktTrendingMovie.""" watchers: int movie: MovieTestData class PopularMoviePayload(TypedDict): """Test payload for TraktPopularMovie.""" movie: MovieTestData class TestTraktShow: """Tests for the TraktShow model.""" def test_valid_show_creation(self) -> None: """Test creating a valid TraktShow instance.""" show_data: ShowTestData = { "title": "Breaking Bad", "year": 2008, "ids": { "trakt": "1", "slug": "breaking-bad", "tvdb": "81189", "imdb": "tt0903747", "tmdb": "1396", }, "overview": "A high school chemistry teacher diagnosed with inoperable lung cancer.", } show = TraktShow(**show_data) assert show.title == "Breaking Bad" assert show.year == 2008 assert show.ids == show_data["ids"] assert ( show.overview == "A high school chemistry teacher diagnosed with inoperable lung cancer." ) def test_show_minimal_data(self) -> None: """Test creating show with minimal required data.""" minimal_data: ShowTestData = { "title": "Test Show", "year": 2020, "ids": {"trakt": "123"}, } show = TraktShow(**minimal_data) assert show.title == "Test Show" assert show.year == 2020 assert show.ids == {"trakt": "123"} assert show.overview is None def test_show_missing_title(self) -> None: """Test that title is required.""" with pytest.raises(ValidationError) as exc_info: TraktShow(ids={"trakt": "123"}) # type: ignore[call-arg] # Testing: Missing required 'title' field errors = exc_info.value.errors() assert any(error["loc"] == ("title",) for error in errors) def test_show_missing_ids(self) -> None: """Test that ids field is required.""" with pytest.raises(ValidationError) as exc_info: TraktShow(title="Test Show") # type: ignore[call-arg] # Testing: Missing required 'ids' field errors = exc_info.value.errors() assert any(error["loc"] == ("ids",) for error in errors) def test_show_field_types(self) -> None: """Test that fields have correct types.""" # Test with clearly incompatible title type with pytest.raises(ValidationError): TraktShow(title=["not", "a", "string"], ids={"trakt": "123"}) # type: ignore[arg-type] # Testing: Pydantic validation with invalid types # Test with clearly incompatible year type with pytest.raises(ValidationError): TraktShow(title="Test", year=["not", "an", "int"], ids={"trakt": "123"}) # type: ignore[arg-type] # Testing: Pydantic validation with invalid types # Test with wrong ids type with pytest.raises(ValidationError): TraktShow(title="Test", ids="not_a_dict") # type: ignore[arg-type] # Testing: String where dict expected for 'ids' def test_show_serialization(self) -> None: """Test that TraktShow can be serialized.""" show_data: ShowTestData = { "title": "Breaking Bad", "year": 2008, "ids": {"trakt": "1", "slug": "breaking-bad"}, "overview": "Great show", } show = TraktShow(**show_data) serialized = show.model_dump() assert serialized == show_data def test_show_with_none_values(self) -> None: """Test show with explicit None values.""" show_data: ShowTestData = { "title": "Test Show", "year": 2021, "ids": {"trakt": "123"}, "overview": None, } show = TraktShow(**show_data) assert show.title == "Test Show" assert show.year == 2021 assert show.overview is None class TestTraktMovie: """Tests for the TraktMovie model.""" def test_valid_movie_creation(self) -> None: """Test creating a valid TraktMovie instance.""" movie_data: MovieTestData = { "title": "Inception", "year": 2010, "ids": { "trakt": "1", "slug": "inception-2010", "imdb": "tt1375666", "tmdb": "27205", }, "overview": "A thief who steals corporate secrets through dream-sharing technology.", } movie = TraktMovie(**movie_data) assert movie.title == "Inception" assert movie.year == 2010 assert movie.ids == movie_data["ids"] assert ( movie.overview == "A thief who steals corporate secrets through dream-sharing technology." ) def test_movie_minimal_data(self) -> None: """Test creating movie with minimal required data.""" minimal_data: MovieTestData = { "title": "Test Movie", "year": 2019, "ids": {"trakt": "456"}, } movie = TraktMovie(**minimal_data) assert movie.title == "Test Movie" assert movie.year == 2019 assert movie.ids == {"trakt": "456"} assert movie.overview is None def test_movie_required_fields(self) -> None: """Test that required fields must be provided.""" with pytest.raises(ValidationError) as exc_info: TraktMovie() # type: ignore[call-arg] # Testing: All required fields missing errors = exc_info.value.errors() required_fields = {error["loc"][0] for error in errors} assert "title" in required_fields assert "ids" in required_fields def test_movie_field_types(self) -> None: """Test that fields have correct types.""" # Test with clearly incompatible types with pytest.raises(ValidationError): TraktMovie(title=["not", "a", "string"], ids={"trakt": "123"}) # type: ignore[arg-type] # Testing: Pydantic validation with invalid types with pytest.raises(ValidationError): TraktMovie(title="Test", year=["not", "an", "int"], ids={"trakt": "123"}) # type: ignore[arg-type] # Testing: Pydantic validation with invalid types def test_movie_serialization(self) -> None: """Test that TraktMovie can be serialized.""" movie_data: MovieTestData = { "title": "Inception", "year": 2010, "ids": {"trakt": "1"}, "overview": "Great movie", } movie = TraktMovie(**movie_data) serialized = movie.model_dump() assert serialized == movie_data class TestTraktEpisode: """Tests for the TraktEpisode model.""" def test_valid_episode_creation(self) -> None: """Test creating a valid TraktEpisode instance.""" episode_data: EpisodeTestData = { "season": 1, "number": 1, "title": "Pilot", "ids": {"trakt": "123", "tvdb": "456"}, "last_watched_at": "2023-01-15T20:30:00Z", } episode = TraktEpisode(**episode_data) assert episode.season == 1 assert episode.number == 1 assert episode.title == "Pilot" assert episode.ids == {"trakt": "123", "tvdb": "456"} assert episode.last_watched_at == "2023-01-15T20:30:00Z" def test_episode_minimal_data(self) -> None: """Test creating episode with minimal required data.""" minimal_data: EpisodeTestData = { "season": 2, "number": 5, } episode = TraktEpisode(**minimal_data) assert episode.season == 2 assert episode.number == 5 assert episode.title is None assert episode.ids is None assert episode.last_watched_at is None def test_episode_required_fields(self) -> None: """Test that required fields must be provided.""" with pytest.raises(ValidationError) as exc_info: TraktEpisode() # type: ignore[call-arg] # Testing: All required fields missing errors = exc_info.value.errors() required_fields = {error["loc"][0] for error in errors} assert "season" in required_fields assert "number" in required_fields def test_episode_field_types(self) -> None: """Test that fields have correct types.""" # Test with clearly incompatible types with pytest.raises(ValidationError): TraktEpisode(season=["not", "an", "int"], number=1) # type: ignore[arg-type] # Testing: Pydantic validation with invalid types with pytest.raises(ValidationError): TraktEpisode(season=1, number=["not", "an", "int"]) # type: ignore[arg-type] # Testing: Pydantic validation with invalid types def test_episode_serialization(self) -> None: """Test that TraktEpisode can be serialized.""" episode_data: EpisodeTestData = { "season": 1, "number": 1, "title": "Pilot", "ids": {"trakt": "123"}, "last_watched_at": "2023-01-15T20:30:00Z", } episode = TraktEpisode(**episode_data) serialized = episode.model_dump() assert serialized == episode_data class TestTraktTrendingShow: """Tests for the TraktTrendingShow model.""" def test_valid_trending_show_creation(self) -> None: """Test creating a valid TraktTrendingShow instance.""" trending_data: TrendingShowPayload = { "watchers": 150, "show": { "title": "Breaking Bad", "year": 2008, "ids": {"trakt": "1"}, "overview": "Great show", }, } trending_show = TraktTrendingShow(**trending_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert trending_show.watchers == 150 assert trending_show.show.title == "Breaking Bad" assert trending_show.show.year == 2008 def test_trending_show_required_fields(self) -> None: """Test that required fields must be provided.""" with pytest.raises(ValidationError) as exc_info: TraktTrendingShow() # type: ignore[call-arg] # Testing: All required fields missing errors = exc_info.value.errors() required_fields = {error["loc"][0] for error in errors} assert "watchers" in required_fields assert "show" in required_fields def test_trending_show_nested_validation(self) -> None: """Test that nested show validation works.""" # Missing required show fields with pytest.raises(ValidationError): TraktTrendingShow( # type: ignore[arg-type] # Testing: Incomplete show data missing 'ids' watchers=150, show={"title": "Test"}, # type: ignore[arg-type] # Testing: Incomplete show data missing 'ids' ) def test_trending_show_serialization(self) -> None: """Test that TraktTrendingShow can be serialized.""" trending_data: TrendingShowPayload = { "watchers": 150, "show": { "title": "Breaking Bad", "year": 2008, "ids": {"trakt": "1"}, "overview": "Great show", }, } trending_show = TraktTrendingShow(**trending_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input serialized = trending_show.model_dump() assert serialized == trending_data class TestTraktTrendingMovie: """Tests for the TraktTrendingMovie model.""" def test_valid_trending_movie_creation(self) -> None: """Test creating a valid TraktTrendingMovie instance.""" trending_data: TrendingMoviePayload = { "watchers": 200, "movie": { "title": "Inception", "year": 2010, "ids": {"trakt": "1"}, "overview": "Great movie", }, } trending_movie = TraktTrendingMovie(**trending_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert trending_movie.watchers == 200 assert trending_movie.movie.title == "Inception" assert trending_movie.movie.year == 2010 def test_trending_movie_required_fields(self) -> None: """Test that required fields must be provided.""" with pytest.raises(ValidationError) as exc_info: TraktTrendingMovie() # type: ignore[call-arg] # Testing: All required fields missing errors = exc_info.value.errors() required_fields = {error["loc"][0] for error in errors} assert "watchers" in required_fields assert "movie" in required_fields def test_trending_movie_nested_validation(self) -> None: """Test that nested movie validation works.""" # Missing required movie fields with pytest.raises(ValidationError): TraktTrendingMovie( # type: ignore[arg-type] # Testing: Incomplete movie data missing 'ids' watchers=200, movie={"title": "Test"}, # type: ignore[arg-type] # Testing: Incomplete movie data missing 'ids' ) class TestTraktPopularShow: """Tests for the TraktPopularShow model.""" def test_valid_popular_show_creation(self) -> None: """Test creating a valid TraktPopularShow instance.""" popular_data: PopularShowPayload = { "show": { "title": "Breaking Bad", "year": 2008, "ids": {"trakt": "1"}, "overview": "Great show", } } popular_show = TraktPopularShow(**popular_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert popular_show.show.title == "Breaking Bad" assert popular_show.show.year == 2008 def test_popular_show_from_api_response(self) -> None: """Test creating popular show from API response format.""" # Simulate API response format where show data is at root level api_data = { "title": "Breaking Bad", "year": 2008, "ids": {"trakt": "1"}, "overview": "Great show", } popular_show = TraktPopularShow.from_api_response(api_data) assert popular_show.show.title == "Breaking Bad" assert popular_show.show.year == 2008 assert popular_show.show.ids == {"trakt": "1"} def test_popular_show_required_fields(self) -> None: """Test that required fields must be provided.""" with pytest.raises(ValidationError) as exc_info: TraktPopularShow() # type: ignore[call-arg] # Testing: Missing required 'show' field errors = exc_info.value.errors() assert any(error["loc"] == ("show",) for error in errors) def test_popular_show_serialization(self) -> None: """Test that TraktPopularShow can be serialized.""" popular_data: PopularShowPayload = { "show": { "title": "Breaking Bad", "year": 2008, "ids": {"trakt": "1"}, "overview": "Great show", } } popular_show = TraktPopularShow(**popular_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input serialized = popular_show.model_dump() assert serialized == popular_data class TestTraktPopularMovie: """Tests for the TraktPopularMovie model.""" def test_valid_popular_movie_creation(self) -> None: """Test creating a valid TraktPopularMovie instance.""" popular_data: PopularMoviePayload = { "movie": { "title": "Inception", "year": 2010, "ids": {"trakt": "1"}, "overview": "Great movie", } } popular_movie = TraktPopularMovie(**popular_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert popular_movie.movie.title == "Inception" assert popular_movie.movie.year == 2010 def test_popular_movie_from_api_response(self) -> None: """Test creating popular movie from API response format.""" # Simulate API response format where movie data is at root level api_data = { "title": "Inception", "year": 2010, "ids": {"trakt": "1"}, "overview": "Great movie", } popular_movie = TraktPopularMovie.from_api_response(api_data) assert popular_movie.movie.title == "Inception" assert popular_movie.movie.year == 2010 assert popular_movie.movie.ids == {"trakt": "1"} def test_popular_movie_required_fields(self) -> None: """Test that required fields must be provided.""" with pytest.raises(ValidationError) as exc_info: TraktPopularMovie() # type: ignore[call-arg] # Testing: Missing required 'movie' field errors = exc_info.value.errors() assert any(error["loc"] == ("movie",) for error in errors) def test_popular_movie_serialization(self) -> None: """Test that TraktPopularMovie can be serialized.""" popular_data: PopularMoviePayload = { "movie": { "title": "Inception", "year": 2010, "ids": {"trakt": "1"}, "overview": "Great movie", } } popular_movie = TraktPopularMovie(**popular_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input serialized = popular_movie.model_dump() assert serialized == popular_data class TestMediaModelIntegration: """Integration tests for media models working together.""" def test_complex_show_data_structure(self) -> None: """Test complex show data structure with all fields.""" complex_show_data: ShowTestData = { "title": "Game of Thrones", "year": 2011, "ids": { "trakt": "1390", "slug": "game-of-thrones", "tvdb": "121361", "imdb": "tt0944947", "tmdb": "1399", }, "overview": "Seven noble families fight for control of the mythical land of Westeros.", } # Test direct show creation show = TraktShow(**complex_show_data) assert show.title == "Game of Thrones" # Test in trending context trending_show = TraktTrendingShow(watchers=5000, show=complex_show_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert trending_show.watchers == 5000 assert trending_show.show.title == "Game of Thrones" # Test in popular context popular_show = TraktPopularShow(show=complex_show_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert popular_show.show.title == "Game of Thrones" def test_complex_movie_data_structure(self) -> None: """Test complex movie data structure with all fields.""" complex_movie_data: MovieTestData = { "title": "The Dark Knight", "year": 2008, "ids": { "trakt": "1", "slug": "the-dark-knight-2008", "imdb": "tt0468569", "tmdb": "155", }, "overview": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham.", } # Test direct movie creation movie = TraktMovie(**complex_movie_data) assert movie.title == "The Dark Knight" # Test in trending context trending_movie = TraktTrendingMovie(watchers=3000, movie=complex_movie_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert trending_movie.watchers == 3000 assert trending_movie.movie.title == "The Dark Knight" # Test in popular context popular_movie = TraktPopularMovie(movie=complex_movie_data) # type: ignore[arg-type] # Testing: Pydantic validation with dict input assert popular_movie.movie.title == "The Dark Knight" def test_episode_integration(self) -> None: """Test episode model integration scenarios.""" episode_data: EpisodeTestData = { "season": 1, "number": 1, "title": "Winter Is Coming", "ids": { "trakt": "73640", "tvdb": "349232", "imdb": "tt1596220", "tmdb": "63056", }, "last_watched_at": "2023-12-01T21:00:00Z", } episode = TraktEpisode(**episode_data) assert episode.season == 1 assert episode.number == 1 assert episode.title == "Winter Is Coming" assert episode.ids is not None and "trakt" in episode.ids assert episode.last_watched_at == "2023-12-01T21:00:00Z" # Test serialization round-trip serialized = episode.model_dump() reconstructed = TraktEpisode(**serialized) assert reconstructed.season == episode.season assert reconstructed.number == episode.number assert reconstructed.title == episode.title

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