Files
orion/tests/unit/models/schema/test_product.py
Samir Boulahtit 9920430b9e fix: correct tojson|safe usage in templates and update validator
- Remove |safe from |tojson in HTML attributes (x-data) - quotes must
  become " for browsers to parse correctly
- Update LANG-002 and LANG-003 architecture rules to document correct
  |tojson usage patterns:
  - HTML attributes: |tojson (no |safe)
  - Script blocks: |tojson|safe
- Fix validator to warn when |tojson|safe is used in x-data (breaks
  HTML attribute parsing)
- Improve code quality across services, APIs, and tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 22:59:51 +01:00

246 lines
7.8 KiB
Python

# tests/unit/models/schema/test_product.py
"""Unit tests for product Pydantic schemas."""
import pytest
from pydantic import ValidationError
from models.schema.product import (
ProductCreate,
ProductListResponse,
ProductResponse,
ProductUpdate,
)
@pytest.mark.unit
@pytest.mark.schema
class TestProductCreateSchema:
"""Test ProductCreate schema validation."""
def test_valid_product_create(self):
"""Test valid product creation data."""
product = ProductCreate(
marketplace_product_id=1,
vendor_sku="SKU-001",
price=99.99,
currency="EUR",
)
assert product.marketplace_product_id == 1
assert product.vendor_sku == "SKU-001"
assert product.price == 99.99
def test_marketplace_product_id_required(self):
"""Test marketplace_product_id is required."""
with pytest.raises(ValidationError) as exc_info:
ProductCreate(price=99.99)
assert "marketplace_product_id" in str(exc_info.value).lower()
def test_price_must_be_non_negative(self):
"""Test price must be >= 0."""
with pytest.raises(ValidationError) as exc_info:
ProductCreate(
marketplace_product_id=1,
price=-10.00,
)
assert "price" in str(exc_info.value).lower()
def test_price_zero_is_valid(self):
"""Test price of 0 is valid."""
product = ProductCreate(
marketplace_product_id=1,
price=0,
)
assert product.price == 0
def test_sale_price_must_be_non_negative(self):
"""Test sale_price must be >= 0."""
with pytest.raises(ValidationError) as exc_info:
ProductCreate(
marketplace_product_id=1,
sale_price=-5.00,
)
assert "sale_price" in str(exc_info.value).lower()
def test_min_quantity_default(self):
"""Test min_quantity defaults to 1."""
product = ProductCreate(marketplace_product_id=1)
assert product.min_quantity == 1
def test_min_quantity_must_be_at_least_1(self):
"""Test min_quantity must be >= 1."""
with pytest.raises(ValidationError) as exc_info:
ProductCreate(
marketplace_product_id=1,
min_quantity=0,
)
assert "min_quantity" in str(exc_info.value).lower()
def test_max_quantity_must_be_at_least_1(self):
"""Test max_quantity must be >= 1 if provided."""
with pytest.raises(ValidationError) as exc_info:
ProductCreate(
marketplace_product_id=1,
max_quantity=0,
)
assert "max_quantity" in str(exc_info.value).lower()
def test_is_featured_default(self):
"""Test is_featured defaults to False."""
product = ProductCreate(marketplace_product_id=1)
assert product.is_featured is False
def test_all_optional_fields(self):
"""Test product with all optional fields."""
product = ProductCreate(
marketplace_product_id=1,
vendor_sku="SKU-001",
price=100.00,
sale_price=80.00,
currency="EUR",
availability="in_stock",
condition="new",
is_featured=True,
min_quantity=2,
max_quantity=10,
)
assert product.sale_price == 80.00
assert product.availability == "in_stock"
assert product.condition == "new"
assert product.is_featured is True
assert product.max_quantity == 10
@pytest.mark.unit
@pytest.mark.schema
class TestProductUpdateSchema:
"""Test ProductUpdate schema validation."""
def test_partial_update(self):
"""Test partial update with only some fields."""
update = ProductUpdate(price=150.00)
assert update.price == 150.00
assert update.vendor_sku is None
assert update.is_active is None
def test_empty_update_is_valid(self):
"""Test empty update is valid (all fields optional)."""
update = ProductUpdate()
assert update.model_dump(exclude_unset=True) == {}
def test_price_validation(self):
"""Test price must be >= 0 in update."""
with pytest.raises(ValidationError):
ProductUpdate(price=-10.00)
def test_is_active_update(self):
"""Test is_active can be updated."""
update = ProductUpdate(is_active=False)
assert update.is_active is False
def test_is_featured_update(self):
"""Test is_featured can be updated."""
update = ProductUpdate(is_featured=True)
assert update.is_featured is True
@pytest.mark.unit
@pytest.mark.schema
class TestProductResponseSchema:
"""Test ProductResponse schema."""
def test_from_dict(self):
"""Test creating response from dict."""
from datetime import datetime
data = {
"id": 1,
"vendor_id": 1,
"marketplace_product": {
"id": 1,
"marketplace_product_id": "TEST001", # Required field
"gtin": "1234567890123",
"title": "Test Product",
"description": "A test product",
"brand": "Test Brand",
"google_product_category": "Electronics",
"image_link": "https://example.com/image.jpg",
"created_at": datetime.now(),
"updated_at": datetime.now(),
},
"vendor_sku": "SKU-001",
"price": 99.99,
"sale_price": None,
"currency": "EUR",
"availability": "in_stock",
"condition": "new",
"is_featured": False,
"is_active": True,
"display_order": 0,
"min_quantity": 1,
"max_quantity": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
}
response = ProductResponse(**data)
assert response.id == 1
assert response.vendor_id == 1
assert response.is_active is True
def test_optional_inventory_fields(self):
"""Test optional inventory summary fields."""
from datetime import datetime
data = {
"id": 1,
"vendor_id": 1,
"marketplace_product": {
"id": 1,
"marketplace_product_id": "TEST002", # Required field
"gtin": "1234567890123",
"title": "Test Product",
"description": None,
"brand": None,
"google_product_category": None,
"image_link": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
},
"vendor_sku": None,
"price": None,
"sale_price": None,
"currency": None,
"availability": None,
"condition": None,
"is_featured": False,
"is_active": True,
"display_order": 0,
"min_quantity": 1,
"max_quantity": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
"total_inventory": 100,
"available_inventory": 80,
}
response = ProductResponse(**data)
assert response.total_inventory == 100
assert response.available_inventory == 80
@pytest.mark.unit
@pytest.mark.schema
class TestProductListResponseSchema:
"""Test ProductListResponse schema."""
def test_valid_list_response(self):
"""Test valid list response structure."""
response = ProductListResponse(
products=[],
total=0,
skip=0,
limit=10,
)
assert response.products == []
assert response.total == 0
assert response.skip == 0
assert response.limit == 10