import pytest import httpx from unittest.mock import AsyncMock, patch from jellyfin_mcp.client import JellyfinClient @pytest.fixture def client(): return JellyfinClient(base_url="http://test-jellyfin.local", api_key="test-api-key") @pytest.mark.asyncio async def test_client_initialization(client): assert client.base_url == "http://test-jellyfin.local" assert client.api_key == "test-api-key" assert client.headers["Authorization"] == 'MediaBrowser Token="test-api-key"' @pytest.mark.asyncio async def test_request_success(client): # Mocking the httpx.AsyncClient context manager and the request method. # In 'async with httpx.AsyncClient(...) as client:', # the '__aenter__' method of AsyncClient returns the client instance. # The 'request' method is what we want to mock. with patch("httpx.AsyncClient.request", new_callable=AsyncMock) as mock_request: # We need to simulate the response object returned by the awaitable. mock_response = AsyncMock(spec=httpx.Response) mock_response.status_code = 200 mock_response.json.return_value = {"test": "data"} # When 'await client.request(...)' is called, it returns mock_response mock_request.return_value = mock_response result = await client._request("GET", "/test-endpoint") assert result == {"test": "data"} @pytest.mark.asyncio async def test_request_failure(client): with patch("httpx.AsyncClient.request", new_callable=AsyncMock) as mock_request: mock_response = AsyncMock(spec=httpx.Response) # Setup side effect for raise_for_status mock_response.raise_for_status.side_effect = httpx.HTTPStatusError( "Error", request=AsyncMock(), response=AsyncMock(status_code=404) ) mock_request.return_value = mock_response with pytest.raises(httpx.HTTPStatusError): await client._request("GET", "/bad-endpoint") @pytest.mark.asyncio async def test_search_items_success(client): mock_data = {"Items": [{"Id": "1", "Name": "Test Movie", "Type": "Movie"}]} with patch("httpx.AsyncClient.request", new_callable=AsyncMock) as mock_request: mock_response = AsyncMock(spec=httpx.Response) mock_response.json.return_value = mock_data mock_request.return_value = mock_response results = await client.search_items("test") assert len(results) == 1 assert results[0]["Name"] == "Test Movie" @pytest.mark.asyncio async def test_search_items_with_types(client): mock_data = {"Items": [{"Id": "1", "Name": "Test Movie", "Type": "Movie"}]} with patch("httpx.AsyncClient.request", new_callable=AsyncMock) as mock_request: mock_response = AsyncMock(spec=httpx.Response) mock_response.json.return_value = mock_data mock_request.return_value = mock_response results = await client.search_items("test", item_types=["Movie"]) assert len(results) == 1 args, kwargs = mock_request.call_args assert kwargs["params"]["IncludeItemTypes"] == "Movie" @pytest.mark.asyncio async def test_list_active_sessions_success(client): mock_data = {"Sessions": [{"UserName": "User1", "DeviceName": "Phone"}]} with patch("httpx.AsyncClient.request", new_callable=AsyncMock) as mock_request: mock_response = AsyncMock(spec=httpx.Response) mock_response.json.return_value = mock_data mock_request.return_value = mock_response sessions = await client.list_active_sessions() assert len(sessions) == 1 assert sessions[0]["UserName"] == "User1"