# tests/unit/models/schema/test_vendor.py """Unit tests for vendor Pydantic schemas.""" import pytest from pydantic import ValidationError from models.schema.vendor import ( VendorCreate, VendorDetailResponse, VendorListResponse, VendorResponse, VendorSummary, VendorUpdate, ) @pytest.mark.unit @pytest.mark.schema class TestVendorCreateSchema: """Test VendorCreate schema validation.""" def test_valid_vendor_create(self): """Test valid vendor creation data.""" vendor = VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="techstore", name="Tech Store", ) assert vendor.company_id == 1 assert vendor.vendor_code == "TECHSTORE" assert vendor.subdomain == "techstore" assert vendor.name == "Tech Store" def test_company_id_required(self): """Test company_id is required.""" with pytest.raises(ValidationError) as exc_info: VendorCreate( vendor_code="TECHSTORE", subdomain="techstore", name="Tech Store", ) assert "company_id" in str(exc_info.value).lower() def test_company_id_must_be_positive(self): """Test company_id must be > 0.""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=0, vendor_code="TECHSTORE", subdomain="techstore", name="Tech Store", ) assert "company_id" in str(exc_info.value).lower() def test_vendor_code_required(self): """Test vendor_code is required.""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, subdomain="techstore", name="Tech Store", ) assert "vendor_code" in str(exc_info.value).lower() def test_vendor_code_uppercase_normalized(self): """Test vendor_code is normalized to uppercase.""" vendor = VendorCreate( company_id=1, vendor_code="techstore", subdomain="techstore", name="Tech Store", ) assert vendor.vendor_code == "TECHSTORE" def test_vendor_code_min_length(self): """Test vendor_code minimum length (2).""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, vendor_code="T", subdomain="techstore", name="Tech Store", ) assert "vendor_code" in str(exc_info.value).lower() def test_subdomain_required(self): """Test subdomain is required.""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, vendor_code="TECHSTORE", name="Tech Store", ) assert "subdomain" in str(exc_info.value).lower() def test_subdomain_uppercase_invalid(self): """Test subdomain with uppercase is invalid (validated before normalization).""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="TechStore", name="Tech Store", ) assert "subdomain" in str(exc_info.value).lower() def test_subdomain_valid_format(self): """Test subdomain with valid format.""" vendor = VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="tech-store-123", name="Tech Store", ) assert vendor.subdomain == "tech-store-123" def test_subdomain_invalid_format(self): """Test subdomain with invalid characters raises ValidationError.""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="tech_store!", name="Tech Store", ) assert "subdomain" in str(exc_info.value).lower() def test_name_required(self): """Test name is required.""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="techstore", ) assert "name" in str(exc_info.value).lower() def test_name_min_length(self): """Test name minimum length (2).""" with pytest.raises(ValidationError) as exc_info: VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="techstore", name="T", ) assert "name" in str(exc_info.value).lower() def test_optional_fields(self): """Test optional fields.""" vendor = VendorCreate( company_id=1, vendor_code="TECHSTORE", subdomain="techstore", name="Tech Store", description="Best tech store", letzshop_csv_url_fr="https://example.com/fr.csv", contact_email="contact@techstore.com", website="https://techstore.com", ) assert vendor.description == "Best tech store" assert vendor.letzshop_csv_url_fr == "https://example.com/fr.csv" assert vendor.contact_email == "contact@techstore.com" @pytest.mark.unit @pytest.mark.schema class TestVendorUpdateSchema: """Test VendorUpdate schema validation.""" def test_partial_update(self): """Test partial update with only some fields.""" update = VendorUpdate(name="New Tech Store") assert update.name == "New Tech Store" assert update.subdomain is None assert update.is_active is None def test_empty_update_is_valid(self): """Test empty update is valid.""" update = VendorUpdate() assert update.model_dump(exclude_unset=True) == {} def test_subdomain_normalized_to_lowercase(self): """Test subdomain is normalized to lowercase.""" update = VendorUpdate(subdomain="NewSubdomain") assert update.subdomain == "newsubdomain" def test_subdomain_stripped(self): """Test subdomain is stripped of whitespace.""" update = VendorUpdate(subdomain=" newsubdomain ") assert update.subdomain == "newsubdomain" def test_name_min_length(self): """Test name minimum length (2).""" with pytest.raises(ValidationError): VendorUpdate(name="X") def test_is_active_update(self): """Test is_active can be updated.""" update = VendorUpdate(is_active=False) assert update.is_active is False def test_is_verified_update(self): """Test is_verified can be updated.""" update = VendorUpdate(is_verified=True) assert update.is_verified is True def test_reset_contact_to_company_flag(self): """Test reset_contact_to_company flag.""" update = VendorUpdate(reset_contact_to_company=True) assert update.reset_contact_to_company is True @pytest.mark.unit @pytest.mark.schema class TestVendorResponseSchema: """Test VendorResponse schema.""" def test_from_dict(self): """Test creating response from dict.""" from datetime import datetime data = { "id": 1, "vendor_code": "TECHSTORE", "subdomain": "techstore", "name": "Tech Store", "description": "Best tech store", "company_id": 1, "letzshop_csv_url_fr": None, "letzshop_csv_url_en": None, "letzshop_csv_url_de": None, "is_active": True, "is_verified": False, "created_at": datetime.now(), "updated_at": datetime.now(), } response = VendorResponse(**data) assert response.id == 1 assert response.vendor_code == "TECHSTORE" assert response.is_active is True @pytest.mark.unit @pytest.mark.schema class TestVendorDetailResponseSchema: """Test VendorDetailResponse schema.""" def test_from_dict(self): """Test creating detail response from dict.""" from datetime import datetime data = { "id": 1, "vendor_code": "TECHSTORE", "subdomain": "techstore", "name": "Tech Store", "description": None, "company_id": 1, "letzshop_csv_url_fr": None, "letzshop_csv_url_en": None, "letzshop_csv_url_de": None, "is_active": True, "is_verified": True, "created_at": datetime.now(), "updated_at": datetime.now(), # Additional detail fields "company_name": "Tech Corp", "owner_email": "owner@techcorp.com", "owner_username": "owner", "contact_email": "contact@techstore.com", "contact_email_inherited": False, } response = VendorDetailResponse(**data) assert response.company_name == "Tech Corp" assert response.owner_email == "owner@techcorp.com" assert response.contact_email_inherited is False @pytest.mark.unit @pytest.mark.schema class TestVendorListResponseSchema: """Test VendorListResponse schema.""" def test_valid_list_response(self): """Test valid list response structure.""" response = VendorListResponse( vendors=[], total=0, skip=0, limit=10, ) assert response.vendors == [] assert response.total == 0 @pytest.mark.unit @pytest.mark.schema class TestVendorSummarySchema: """Test VendorSummary schema.""" def test_from_dict(self): """Test creating summary from dict.""" data = { "id": 1, "vendor_code": "TECHSTORE", "subdomain": "techstore", "name": "Tech Store", "company_id": 1, "is_active": True, } summary = VendorSummary(**data) assert summary.id == 1 assert summary.vendor_code == "TECHSTORE" assert summary.is_active is True