"""Tests for the Elytra PIM Client with Pydantic validation""" from unittest.mock import Mock, patch import pytest from pydantic import ValidationError from elytra_client import ElytraClient, SingleNewProductRequestBody, SingleProductResponse from elytra_client.exceptions import ElytraAuthenticationError, ElytraNotFoundError @pytest.fixture def client(): """Create a test client""" return ElytraClient( base_url="https://test.example.com/api/v1", api_key="test-api-key", ) def test_client_initialization(client): """Test client initialization""" assert client.base_url == "https://test.example.com/api/v1" assert client.api_key == "test-api-key" assert client.timeout == 30 def test_client_context_manager(): """Test client context manager""" with ElytraClient( base_url="https://test.example.com/api/v1", api_key="test-api-key", ) as client: assert client is not None @patch("elytra_client.client.requests.Session.request") def test_get_products_with_pydantic_validation(mock_request, client): """Test get_products with Pydantic validation""" mock_response = Mock() mock_response.json.return_value = { "items": [ { "id": 1, "clientId": 231, "productName": "Product 1", "treeId": 0, "created": "2025-04-08T12:00:00Z", "modified": "2025-04-08T12:00:00Z", "creatorUserId": 235, "modifierUserId": 235, "objectStatus": "original", "originalId": 0, "attributes": [], } ], "total": 1, "page": 1, } mock_request.return_value = mock_response result = client.get_products(lang="en", page=1, limit=10) assert result["total"] == 1 assert len(result["items"]) == 1 # Items should be Pydantic models assert isinstance(result["items"][0], SingleProductResponse) assert result["items"][0].productName == "Product 1" mock_request.assert_called_once() @patch("elytra_client.client.requests.Session.request") def test_get_product_returns_pydantic_model(mock_request, client): """Test get_product returns Pydantic model""" mock_response = Mock() mock_response.json.return_value = { "id": 123, "clientId": 231, "productName": "Test Product", "treeId": 0, "created": "2025-04-08T12:00:00Z", "modified": "2025-04-08T12:00:00Z", "creatorUserId": 235, "modifierUserId": 235, "objectStatus": "original", "originalId": 0, "attributes": [], } mock_request.return_value = mock_response result = client.get_product(product_id=123, lang="en") assert isinstance(result, SingleProductResponse) assert result.id == 123 assert result.productName == "Test Product" @patch("elytra_client.client.requests.Session.request") def test_create_product_with_pydantic(mock_request, client): """Test product creation with Pydantic validation""" mock_response = Mock() mock_response.json.return_value = { "id": 999, "clientId": 231, "productName": "NEW-PRODUCT-001", "treeId": 0, "created": "2025-04-08T12:00:00Z", "modified": "2025-04-08T12:00:00Z", "creatorUserId": 235, "modifierUserId": 235, "objectStatus": "original", "originalId": 0, "attributes": [], } mock_request.return_value = mock_response # Create with Pydantic model new_product = SingleNewProductRequestBody( # type: ignore[arg-type] productName="NEW-PRODUCT-001", parentId=1, attributeGroupId=10, ) result = client.create_product(new_product) assert isinstance(result, SingleProductResponse) assert result.id == 999 assert result.productName == "NEW-PRODUCT-001" def test_pydantic_validation_on_creation(): """Test Pydantic validation on model creation""" # Valid model valid_product = SingleNewProductRequestBody( # type: ignore[arg-type] productName="VALID-PRODUCT", parentId=1, attributeGroupId=10, ) assert valid_product.productName == "VALID-PRODUCT" # Invalid model - missing required field with pytest.raises(ValidationError): SingleNewProductRequestBody( # type: ignore[arg-type] productName="INVALID-PRODUCT", # Missing parentId - required attributeGroupId=10, ) @patch("elytra_client.client.requests.Session.request") def test_authentication_error(mock_request, client): """Test authentication error handling""" mock_response = Mock() mock_response.status_code = 401 mock_response.text = "Unauthorized" mock_request.return_value.raise_for_status.side_effect = __import__( "requests" ).exceptions.HTTPError(response=mock_response) with pytest.raises(ElytraAuthenticationError): client.get_products() @patch("elytra_client.client.requests.Session.request") def test_not_found_error(mock_request, client): """Test not found error handling""" mock_response = Mock() mock_response.status_code = 404 mock_response.text = "Not Found" mock_request.return_value.raise_for_status.side_effect = __import__( "requests" ).exceptions.HTTPError(response=mock_response) with pytest.raises(ElytraNotFoundError): client.get_product(product_id=999)