Skip to main content
Glama
test_credential_service.py6.58 kB
"""Unit tests for src/services/credential_service.py""" from datetime import datetime import httpx import pytest import respx from src.services.credential_service import check_credential_validity @pytest.mark.asyncio async def test_check_credential_validity_success(): """Test successful credential validation with 200 response""" # Arrange account_id = "test_account_123" secret_key = "test_secret_key" mock_response = { "status": "success", "result": [ { "id": 12345, "name": "Test Listing", } ], } # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(200, json=mock_response) ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is True assert "validated_at" in result assert "error" not in result # Verify timestamp is ISO format validated_at = datetime.fromisoformat(result["validated_at"]) assert isinstance(validated_at, datetime) @pytest.mark.asyncio async def test_check_credential_validity_invalid_credentials(): """Test invalid credentials with 401 response""" # Arrange account_id = "invalid_account" secret_key = "invalid_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(401, json={"error": "Unauthorized"}) ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is False assert result["error"] == "Invalid or expired credentials" assert "validated_at" not in result @pytest.mark.asyncio async def test_check_credential_validity_unexpected_status(): """Test handling of unexpected HTTP status codes""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(500, json={"error": "Internal Server Error"}) ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is False assert "Unexpected status: 500" in result["error"] @pytest.mark.asyncio async def test_check_credential_validity_forbidden(): """Test 403 Forbidden response""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(403, json={"error": "Forbidden"}) ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is False assert "Unexpected status: 403" in result["error"] @pytest.mark.asyncio async def test_check_credential_validity_network_timeout(): """Test network timeout exception handling""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( side_effect=httpx.TimeoutException("Connection timeout") ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is False assert "Connection timeout" in result["error"] @pytest.mark.asyncio async def test_check_credential_validity_network_error(): """Test general network error handling""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( side_effect=httpx.ConnectError("Connection refused") ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is False assert "Connection refused" in result["error"] @pytest.mark.asyncio async def test_check_credential_validity_headers(): """Test that correct headers are sent in the API request""" # Arrange account_id = "test_account" secret_key = "test_secret_key" # Act & Assert with respx.mock as mock_router: route = respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(200, json={"result": []}) ) await check_credential_validity(account_id, secret_key) # Verify the request was made with correct headers assert route.called request = route.calls.last.request assert request.headers["Authorization"] == f"Bearer {secret_key}" assert request.headers["Content-type"] == "application/json" @pytest.mark.asyncio async def test_check_credential_validity_query_params(): """Test that correct query parameters are sent""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act & Assert with respx.mock as mock_router: route = respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(200, json={"result": []}) ) await check_credential_validity(account_id, secret_key) # Verify query parameters assert route.called request = route.calls.last.request assert "limit=1" in str(request.url) @pytest.mark.asyncio async def test_check_credential_validity_empty_response(): """Test handling of empty 200 response""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(200, json={"result": []}) ) result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is True assert "validated_at" in result # Empty results still mean valid credentials @pytest.mark.asyncio async def test_check_credential_validity_malformed_json(): """Test handling of malformed JSON response""" # Arrange account_id = "test_account" secret_key = "test_secret" # Act with respx.mock: respx.get("https://api.hostaway.com/v1/listings").mock( return_value=httpx.Response(200, text="Not JSON") ) # Should still be valid - we only check status code result = await check_credential_validity(account_id, secret_key) # Assert assert result["valid"] is True assert "validated_at" in result

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/darrentmorgan/hostaway-mcp'

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