Skip to main content
Glama
test_shows_pagination.py17.7 kB
"""Tests for show client pagination functionality.""" import os from unittest.mock import AsyncMock, MagicMock, patch import pytest from client.shows.popular import PopularShowsClient from client.shows.stats import ShowStatsClient from client.shows.trending import TrendingShowsClient from models.types.pagination import PaginatedResponse @pytest.mark.asyncio async def test_trending_shows_no_page_returns_all(): """Test that trending shows with no page parameter auto-paginates all results.""" # Mock first page response mock_response_page1 = MagicMock() mock_response_page1.json.return_value = [ {"watchers": 100, "show": {"title": "Show 1", "year": 2024}}, {"watchers": 90, "show": {"title": "Show 2", "year": 2024}}, ] mock_response_page1.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "2", "X-Pagination-Page-Count": "2", "X-Pagination-Item-Count": "4", } mock_response_page1.raise_for_status = MagicMock() # Mock second page response mock_response_page2 = MagicMock() mock_response_page2.json.return_value = [ {"watchers": 80, "show": {"title": "Show 3", "year": 2024}}, {"watchers": 70, "show": {"title": "Show 4", "year": 2024}}, ] mock_response_page2.headers = { "X-Pagination-Page": "2", "X-Pagination-Limit": "2", "X-Pagination-Page-Count": "2", "X-Pagination-Item-Count": "4", } mock_response_page2.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock( side_effect=[mock_response_page1, mock_response_page2] ) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=2, page=None) # Should return a plain list with all 4 shows assert isinstance(result, list) assert len(result) == 4 show_0 = result[0].get("show") assert show_0 is not None assert show_0["title"] == "Show 1" show_3 = result[3].get("show") assert show_3 is not None assert show_3["title"] == "Show 4" @pytest.mark.asyncio async def test_trending_shows_with_page_returns_paginated(): """Test that trending shows with page parameter returns PaginatedResponse.""" mock_response = MagicMock() mock_response.json.return_value = [ {"watchers": 100, "show": {"title": "Show 1", "year": 2024}}, {"watchers": 90, "show": {"title": "Show 2", "year": 2024}}, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "2", "X-Pagination-Page-Count": "2", "X-Pagination-Item-Count": "4", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=2, page=1) # Should return PaginatedResponse assert isinstance(result, PaginatedResponse) assert len(result.data) == 2 assert result.pagination.current_page == 1 assert result.pagination.total_pages == 2 assert result.pagination.total_items == 4 @pytest.mark.asyncio async def test_trending_shows_pagination_metadata(): """Test that pagination metadata is correctly parsed and exposed.""" mock_response = MagicMock() mock_response.json.return_value = [ {"watchers": 80, "show": {"title": "Show 3", "year": 2024}}, {"watchers": 70, "show": {"title": "Show 4", "year": 2024}}, ] mock_response.headers = { "X-Pagination-Page": "2", "X-Pagination-Limit": "2", "X-Pagination-Page-Count": "3", "X-Pagination-Item-Count": "6", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=2, page=2) # Check metadata properties assert result.pagination.current_page == 2 assert result.pagination.items_per_page == 2 assert result.pagination.total_pages == 3 assert result.pagination.total_items == 6 @pytest.mark.asyncio async def test_trending_shows_navigation_properties(): """Test that navigation properties work correctly.""" mock_response = MagicMock() mock_response.json.return_value = [ {"watchers": 80, "show": {"title": "Show 3", "year": 2024}}, ] mock_response.headers = { "X-Pagination-Page": "2", "X-Pagination-Limit": "1", "X-Pagination-Page-Count": "3", "X-Pagination-Item-Count": "3", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=1, page=2) # Check navigation properties assert result.pagination.has_previous_page assert result.pagination.has_next_page assert result.pagination.previous_page() == 1 assert result.pagination.next_page() == 3 @pytest.mark.asyncio async def test_popular_shows_no_page_returns_all(): """Test that popular shows with no page parameter auto-paginates.""" # Mock single page response mock_response = MagicMock() mock_response.json.return_value = [ {"title": "Popular 1", "year": 2024}, {"title": "Popular 2", "year": 2024}, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "2", "X-Pagination-Page-Count": "1", "X-Pagination-Item-Count": "2", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = PopularShowsClient() result = await client.get_popular_shows(limit=2, page=None) # Should return a plain list assert isinstance(result, list) assert len(result) == 2 assert result[0]["title"] == "Popular 1" @pytest.mark.asyncio async def test_popular_shows_with_page_returns_paginated(): """Test that popular shows with page parameter returns PaginatedResponse.""" mock_response = MagicMock() mock_response.json.return_value = [ {"title": "Popular 1", "year": 2024}, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "1", "X-Pagination-Page-Count": "2", "X-Pagination-Item-Count": "2", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = PopularShowsClient() result = await client.get_popular_shows(limit=1, page=1) assert isinstance(result, PaginatedResponse) assert len(result.data) == 1 assert result.pagination.total_pages == 2 @pytest.mark.asyncio async def test_favorited_shows_pagination(): """Test favorited shows pagination.""" mock_response = MagicMock() mock_response.json.return_value = [ {"user_count": 500, "show": {"title": "Favorited 1", "year": 2024}}, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "1", "X-Pagination-Page-Count": "1", "X-Pagination-Item-Count": "1", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = ShowStatsClient() result = await client.get_favorited_shows(limit=1, period="weekly", page=1) assert isinstance(result, PaginatedResponse) assert len(result.data) == 1 show_0 = result.data[0].get("show") assert show_0 is not None assert show_0["title"] == "Favorited 1" @pytest.mark.asyncio async def test_played_shows_pagination(): """Test played shows pagination.""" mock_response = MagicMock() mock_response.json.return_value = [ { "watcher_count": 1000, "play_count": 5000, "show": {"title": "Played 1", "year": 2024}, }, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "1", "X-Pagination-Page-Count": "1", "X-Pagination-Item-Count": "1", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = ShowStatsClient() result = await client.get_played_shows(limit=1, period="weekly", page=1) assert isinstance(result, PaginatedResponse) assert len(result.data) == 1 @pytest.mark.asyncio async def test_watched_shows_pagination(): """Test watched shows pagination.""" mock_response = MagicMock() mock_response.json.return_value = [ {"watcher_count": 2000, "show": {"title": "Watched 1", "year": 2024}}, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "1", "X-Pagination-Page-Count": "1", "X-Pagination-Item-Count": "1", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = ShowStatsClient() result = await client.get_watched_shows(limit=1, period="weekly", page=1) assert isinstance(result, PaginatedResponse) assert len(result.data) == 1 @pytest.mark.asyncio async def test_single_page_result(): """Test pagination with a single page of results.""" mock_response = MagicMock() mock_response.json.return_value = [ {"watchers": 100, "show": {"title": "Only Show", "year": 2024}}, ] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "10", "X-Pagination-Page-Count": "1", "X-Pagination-Item-Count": "1", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=10, page=1) assert isinstance(result, PaginatedResponse) assert result.is_single_page assert not result.pagination.has_next_page assert not result.pagination.has_previous_page @pytest.mark.asyncio async def test_empty_result(): """Test pagination with empty results.""" mock_response = MagicMock() mock_response.json.return_value = [] mock_response.headers = { "X-Pagination-Page": "1", "X-Pagination-Limit": "10", "X-Pagination-Page-Count": "1", # Changed from "0" to "1" - minimum valid value "X-Pagination-Item-Count": "0", } mock_response.raise_for_status = MagicMock() with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # For auto-pagination (page=None), mock should return empty result on first call # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(return_value=mock_response) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=10, page=None) # Auto-pagination with empty results should return empty list assert isinstance(result, list) assert len(result) == 0 @pytest.mark.asyncio async def test_multiple_pages_auto_paginate(): """Test auto-pagination fetches all pages correctly.""" # Create 3 pages of mock responses responses: list[MagicMock] = [] for page_num in range(1, 4): mock_response = MagicMock() mock_response.json.return_value = [ { "watchers": 100 - (page_num - 1) * 10, "show": {"title": f"Show {page_num}", "year": 2024}, } ] mock_response.headers = { "X-Pagination-Page": str(page_num), "X-Pagination-Limit": "1", "X-Pagination-Page-Count": "3", "X-Pagination-Item-Count": "3", } mock_response.raise_for_status = MagicMock() responses.append(mock_response) with ( patch("httpx.AsyncClient") as mock_client, patch.dict( os.environ, {"TRAKT_CLIENT_ID": "test_id", "TRAKT_CLIENT_SECRET": "test_secret"}, ), ): # Create mock instance with async methods mock_instance = MagicMock() mock_instance.get = AsyncMock(side_effect=responses) mock_instance.post = AsyncMock() mock_instance.aclose = AsyncMock() mock_client.return_value = mock_instance client = TrendingShowsClient() result = await client.get_trending_shows(limit=1, page=None) # Should fetch all 3 pages and return flat list assert isinstance(result, list) assert len(result) == 3 show_0 = result[0].get("show") assert show_0 is not None assert show_0["title"] == "Show 1" show_1 = result[1].get("show") assert show_1 is not None assert show_1["title"] == "Show 2" show_2 = result[2].get("show") assert show_2 is not None assert show_2["title"] == "Show 3"

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