Add mixins for various Lobster REST API client functionalities

- Implement JobsMixin for job-related operations including job overview, execution, and control.
- Implement MediaMixin for media management, including creation, updating, and file uploads.
- Implement ProductGroupsMixin for handling product groups, including bulk operations and hierarchy retrieval.
- Implement ProductsMixin for product management, including bulk creation and updates.
- Implement ProtocolsMixin for protocol-related operations, including retrieval by job ID and category.
- Implement TextMixin for managing text entries, including bulk operations.
- Implement TreeGroupsMixin for tree group management, including bulk operations and hierarchy retrieval.
This commit is contained in:
claudi 2026-03-24 16:12:58 +01:00
parent 310a4fe2f8
commit aa7db1a3ab
16 changed files with 2019 additions and 2612 deletions

View file

@ -1,14 +1,11 @@
"""Tests for the Elytra PIM Client with Pydantic validation"""
import pytest
from unittest.mock import Mock, patch
import pytest
from pydantic import ValidationError
from elytra_client import (
ElytraClient,
SingleProductResponse,
SingleNewProductRequestBody,
)
from elytra_client import ElytraClient, SingleNewProductRequestBody, SingleProductResponse
from elytra_client.exceptions import ElytraAuthenticationError, ElytraNotFoundError
@ -118,11 +115,11 @@ def test_create_product_with_pydantic(mock_request, client):
mock_request.return_value = mock_response
# Create with Pydantic model
new_product = SingleNewProductRequestBody(
new_product = SingleNewProductRequestBody( # type: ignore[arg-type]
productName="NEW-PRODUCT-001",
parentId=1,
attributeGroupId=10,
) # type: ignore - validation happens automatically, so type checker should recognize this as valid
)
result = client.create_product(new_product)
@ -134,20 +131,20 @@ def test_create_product_with_pydantic(mock_request, client):
def test_pydantic_validation_on_creation():
"""Test Pydantic validation on model creation"""
# Valid model
valid_product = SingleNewProductRequestBody(
valid_product = SingleNewProductRequestBody( # type: ignore[arg-type]
productName="VALID-PRODUCT",
parentId=1,
attributeGroupId=10,
) # type: ignore - validation happens automatically, so type checker should recognize this as valid
)
assert valid_product.productName == "VALID-PRODUCT"
# Invalid model - missing required field
with pytest.raises(ValidationError):
SingleNewProductRequestBody(
SingleNewProductRequestBody( # type: ignore[arg-type]
productName="INVALID-PRODUCT",
# Missing parentId - required
attributeGroupId=10,
) # type: ignore - this will raise a ValidationError, so type checker should recognize this as invalid
)
@patch("elytra_client.client.requests.Session.request")
@ -156,9 +153,9 @@ def test_authentication_error(mock_request, client):
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)
)
mock_request.return_value.raise_for_status.side_effect = __import__(
"requests"
).exceptions.HTTPError(response=mock_response)
with pytest.raises(ElytraAuthenticationError):
client.get_products()
@ -170,9 +167,9 @@ def test_not_found_error(mock_request, client):
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)
)
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)