- 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>
230 lines
7.6 KiB
Python
230 lines
7.6 KiB
Python
# tests/unit/models/database/test_product.py
|
|
"""Unit tests for Product (vendor catalog) database model."""
|
|
|
|
import pytest
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
from models.database.product import Product
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.database
|
|
class TestProductModel:
|
|
"""Test Product (vendor catalog) model."""
|
|
|
|
def test_product_creation(self, db, test_vendor, test_marketplace_product):
|
|
"""Test Product model linking vendor catalog to marketplace product."""
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
vendor_sku="VENDOR_PROD_001",
|
|
price=89.99,
|
|
currency="EUR",
|
|
availability="in stock",
|
|
is_featured=True,
|
|
is_active=True,
|
|
)
|
|
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.id is not None
|
|
assert product.vendor_id == test_vendor.id
|
|
assert product.marketplace_product_id == test_marketplace_product.id
|
|
assert product.price == 89.99
|
|
assert product.is_featured is True
|
|
assert product.vendor.vendor_code == test_vendor.vendor_code
|
|
# Use get_title() method instead of .title attribute
|
|
assert product.marketplace_product.get_title(
|
|
"en"
|
|
) == test_marketplace_product.get_title("en")
|
|
|
|
def test_product_unique_per_vendor(self, db, test_vendor, test_marketplace_product):
|
|
"""Test that same marketplace product can't be added twice to vendor catalog."""
|
|
product1 = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
is_active=True,
|
|
)
|
|
db.add(product1)
|
|
db.commit()
|
|
|
|
# Same marketplace product to same vendor should fail
|
|
with pytest.raises(IntegrityError):
|
|
product2 = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
is_active=True,
|
|
)
|
|
db.add(product2)
|
|
db.commit()
|
|
|
|
def test_product_default_values(self, db, test_vendor, test_marketplace_product):
|
|
"""Test Product model default values."""
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.is_active is True # Default
|
|
assert product.is_featured is False # Default
|
|
assert product.min_quantity == 1 # Default
|
|
assert product.display_order == 0 # Default
|
|
|
|
def test_product_vendor_override_fields(
|
|
self, db, test_vendor, test_marketplace_product
|
|
):
|
|
"""Test Product model vendor-specific override fields."""
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
vendor_sku="CUSTOM_SKU_001",
|
|
price=49.99,
|
|
sale_price=39.99,
|
|
currency="USD",
|
|
availability="limited",
|
|
condition="new",
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.vendor_sku == "CUSTOM_SKU_001"
|
|
assert product.price == 49.99
|
|
assert product.sale_price == 39.99
|
|
assert product.currency == "USD"
|
|
assert product.availability == "limited"
|
|
|
|
def test_product_inventory_settings(
|
|
self, db, test_vendor, test_marketplace_product
|
|
):
|
|
"""Test Product model inventory settings."""
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
min_quantity=2,
|
|
max_quantity=10,
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.min_quantity == 2
|
|
assert product.max_quantity == 10
|
|
|
|
def test_product_relationships(self, db, test_vendor, test_marketplace_product):
|
|
"""Test Product relationships."""
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.vendor is not None
|
|
assert product.marketplace_product is not None
|
|
assert product.inventory_entries == [] # No inventory yet
|
|
|
|
def test_product_effective_properties(
|
|
self, db, test_vendor, test_marketplace_product
|
|
):
|
|
"""Test Product effective properties with override pattern."""
|
|
# First, set some values on the marketplace product
|
|
test_marketplace_product.price_numeric = 100.00
|
|
test_marketplace_product.brand = "SourceBrand"
|
|
db.commit()
|
|
db.refresh(test_marketplace_product)
|
|
|
|
# Create product without overrides
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
# Should inherit from marketplace product
|
|
assert product.effective_price == 100.00
|
|
assert product.effective_brand == "SourceBrand"
|
|
|
|
# Now override the price
|
|
product.price = 89.99
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
# Should use the override
|
|
assert product.effective_price == 89.99
|
|
# Brand still inherited
|
|
assert product.effective_brand == "SourceBrand"
|
|
|
|
def test_product_reset_to_source(self, db, test_vendor, test_marketplace_product):
|
|
"""Test reset_to_source methods."""
|
|
# Set up marketplace product values
|
|
test_marketplace_product.price_numeric = 100.00
|
|
test_marketplace_product.brand = "SourceBrand"
|
|
db.commit()
|
|
|
|
# Create product with overrides
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
price=89.99,
|
|
brand="OverrideBrand",
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.effective_price == 89.99
|
|
assert product.effective_brand == "OverrideBrand"
|
|
|
|
# Reset price to source
|
|
product.reset_field_to_source("price")
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.price is None
|
|
assert product.effective_price == 100.00 # Now inherits
|
|
|
|
# Reset all fields
|
|
product.reset_all_to_source()
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
assert product.brand is None
|
|
assert product.effective_brand == "SourceBrand" # Now inherits
|
|
|
|
def test_product_get_override_info(self, db, test_vendor, test_marketplace_product):
|
|
"""Test get_override_info method."""
|
|
test_marketplace_product.price_numeric = 100.00
|
|
test_marketplace_product.brand = "SourceBrand"
|
|
db.commit()
|
|
|
|
product = Product(
|
|
vendor_id=test_vendor.id,
|
|
marketplace_product_id=test_marketplace_product.id,
|
|
price=89.99, # Override
|
|
# brand not set - will inherit
|
|
)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(product)
|
|
|
|
info = product.get_override_info()
|
|
|
|
# Price is overridden
|
|
assert info["price"] == 89.99
|
|
assert info["price_overridden"] is True
|
|
assert info["price_source"] == 100.00
|
|
|
|
# Brand is inherited
|
|
assert info["brand"] == "SourceBrand"
|
|
assert info["brand_overridden"] is False
|
|
assert info["brand_source"] == "SourceBrand"
|