- Auto-fixed 4,496 lint issues (import sorting, modern syntax, etc.) - Added ignore rules for patterns intentional in this codebase: E402 (late imports), E712 (SQLAlchemy filters), B904 (raise from), SIM108/SIM105/SIM117 (readability preferences) - Added per-file ignores for tests and scripts - Excluded broken scripts/rename_terminology.py (has curly quotes) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
275 lines
9.9 KiB
Python
275 lines
9.9 KiB
Python
# tests/unit/models/test_merchant_domain.py
|
|
"""Unit tests for MerchantDomain model and related model properties."""
|
|
|
|
import uuid
|
|
from datetime import UTC, datetime
|
|
|
|
import pytest
|
|
|
|
from app.modules.tenancy.models.merchant_domain import MerchantDomain
|
|
from app.modules.tenancy.models.store_domain import StoreDomain
|
|
|
|
# =============================================================================
|
|
# MODEL TESTS
|
|
# =============================================================================
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.tenancy
|
|
class TestMerchantDomainModel:
|
|
"""Test suite for MerchantDomain model."""
|
|
|
|
def test_create_merchant_domain(self, db, test_merchant):
|
|
"""Test creating a MerchantDomain with required fields."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"test{unique_id}.example.com",
|
|
is_primary=True,
|
|
verification_token=f"token_{unique_id}",
|
|
)
|
|
db.add(domain)
|
|
db.commit()
|
|
db.refresh(domain)
|
|
|
|
assert domain.id is not None
|
|
assert domain.merchant_id == test_merchant.id
|
|
assert domain.is_primary is True
|
|
assert domain.is_active is True # default
|
|
assert domain.is_verified is False # default
|
|
assert domain.ssl_status == "pending" # default
|
|
assert domain.verified_at is None
|
|
assert domain.platform_id is None
|
|
|
|
def test_merchant_domain_defaults(self, db, test_merchant):
|
|
"""Test default values for MerchantDomain."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"defaults{unique_id}.example.com",
|
|
verification_token=f"dtoken_{unique_id}",
|
|
)
|
|
db.add(domain)
|
|
db.commit()
|
|
db.refresh(domain)
|
|
|
|
assert domain.is_primary is True
|
|
assert domain.is_active is True
|
|
assert domain.is_verified is False
|
|
assert domain.ssl_status == "pending"
|
|
|
|
def test_merchant_domain_repr(self, db, test_merchant):
|
|
"""Test string representation."""
|
|
domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain="repr.example.com",
|
|
)
|
|
assert "repr.example.com" in repr(domain)
|
|
assert str(test_merchant.id) in repr(domain)
|
|
|
|
def test_merchant_domain_full_url(self):
|
|
"""Test full_url property."""
|
|
domain = MerchantDomain(domain="test.example.com")
|
|
assert domain.full_url == "https://test.example.com"
|
|
|
|
def test_normalize_domain_removes_protocol(self):
|
|
"""Test normalize_domain strips protocols."""
|
|
assert MerchantDomain.normalize_domain("https://example.com") == "example.com"
|
|
assert MerchantDomain.normalize_domain("http://example.com") == "example.com"
|
|
|
|
def test_normalize_domain_removes_trailing_slash(self):
|
|
"""Test normalize_domain strips trailing slashes."""
|
|
assert MerchantDomain.normalize_domain("example.com/") == "example.com"
|
|
|
|
def test_normalize_domain_lowercases(self):
|
|
"""Test normalize_domain converts to lowercase."""
|
|
assert MerchantDomain.normalize_domain("EXAMPLE.COM") == "example.com"
|
|
|
|
def test_unique_domain_constraint(self, db, test_merchant):
|
|
"""Test that domain must be unique across all merchant domains."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
domain_name = f"unique{unique_id}.example.com"
|
|
|
|
domain1 = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=domain_name,
|
|
verification_token=f"t1_{unique_id}",
|
|
)
|
|
db.add(domain1)
|
|
db.commit()
|
|
|
|
domain2 = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=domain_name,
|
|
verification_token=f"t2_{unique_id}",
|
|
)
|
|
db.add(domain2)
|
|
with pytest.raises(Exception): # IntegrityError
|
|
db.commit()
|
|
db.rollback()
|
|
|
|
|
|
# =============================================================================
|
|
# MERCHANT.primary_domain PROPERTY TESTS
|
|
# =============================================================================
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.tenancy
|
|
class TestMerchantPrimaryDomain:
|
|
"""Test Merchant.primary_domain property."""
|
|
|
|
def test_primary_domain_returns_active_verified_primary(self, db, test_merchant):
|
|
"""Test primary_domain returns domain when active, verified, and primary."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"primary{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=True,
|
|
is_verified=True,
|
|
verified_at=datetime.now(UTC),
|
|
verification_token=f"pt_{unique_id}",
|
|
)
|
|
db.add(domain)
|
|
db.commit()
|
|
db.refresh(test_merchant)
|
|
|
|
assert test_merchant.primary_domain == f"primary{unique_id}.example.com"
|
|
|
|
def test_primary_domain_returns_none_when_no_domains(self, db, test_merchant):
|
|
"""Test primary_domain returns None when merchant has no domains."""
|
|
db.refresh(test_merchant)
|
|
# Fresh merchant without any domains added in this test
|
|
# Need to check if it may have domains from other fixtures
|
|
# Just verify the property works without error
|
|
result = test_merchant.primary_domain
|
|
assert result is None or isinstance(result, str)
|
|
|
|
def test_primary_domain_returns_none_when_inactive(self, db, test_merchant):
|
|
"""Test primary_domain returns None when domain is inactive."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"inactive{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=False,
|
|
is_verified=True,
|
|
verified_at=datetime.now(UTC),
|
|
verification_token=f"it_{unique_id}",
|
|
)
|
|
db.add(domain)
|
|
db.commit()
|
|
db.refresh(test_merchant)
|
|
|
|
assert test_merchant.primary_domain is None
|
|
|
|
def test_primary_domain_returns_none_when_unverified(self, db, test_merchant):
|
|
"""Test primary_domain returns None when domain is unverified."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"unverified{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=True,
|
|
is_verified=False,
|
|
verification_token=f"ut_{unique_id}",
|
|
)
|
|
db.add(domain)
|
|
db.commit()
|
|
db.refresh(test_merchant)
|
|
|
|
assert test_merchant.primary_domain is None
|
|
|
|
|
|
# =============================================================================
|
|
# STORE.effective_domain PROPERTY TESTS
|
|
# =============================================================================
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.tenancy
|
|
class TestStoreEffectiveDomain:
|
|
"""Test Store.effective_domain inheritance chain."""
|
|
|
|
def test_effective_domain_returns_store_domain_when_present(self, db, test_store):
|
|
"""Test effective_domain returns store's own custom domain (highest priority)."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
store_domain = StoreDomain(
|
|
store_id=test_store.id,
|
|
domain=f"storeover{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=True,
|
|
is_verified=True,
|
|
verified_at=datetime.now(UTC),
|
|
verification_token=f"sd_{unique_id}",
|
|
)
|
|
db.add(store_domain)
|
|
db.commit()
|
|
db.refresh(test_store)
|
|
|
|
assert test_store.effective_domain == f"storeover{unique_id}.example.com"
|
|
|
|
def test_effective_domain_returns_merchant_domain_when_no_store_domain(
|
|
self, db, test_store, test_merchant
|
|
):
|
|
"""Test effective_domain returns merchant domain when no store domain."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
merchant_domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"merchant{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=True,
|
|
is_verified=True,
|
|
verified_at=datetime.now(UTC),
|
|
verification_token=f"md_{unique_id}",
|
|
)
|
|
db.add(merchant_domain)
|
|
db.commit()
|
|
db.refresh(test_store)
|
|
db.refresh(test_merchant)
|
|
|
|
assert test_store.effective_domain == f"merchant{unique_id}.example.com"
|
|
|
|
def test_effective_domain_returns_subdomain_fallback(self, db, test_store):
|
|
"""Test effective_domain returns subdomain fallback when no custom domains."""
|
|
db.refresh(test_store)
|
|
# With no store or merchant domains, should fall back to subdomain
|
|
result = test_store.effective_domain
|
|
assert test_store.subdomain in result
|
|
|
|
def test_effective_domain_store_domain_overrides_merchant_domain(
|
|
self, db, test_store, test_merchant
|
|
):
|
|
"""Test that store domain takes priority over merchant domain."""
|
|
unique_id = str(uuid.uuid4())[:8]
|
|
|
|
# Add merchant domain
|
|
merchant_domain = MerchantDomain(
|
|
merchant_id=test_merchant.id,
|
|
domain=f"merchantpri{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=True,
|
|
is_verified=True,
|
|
verified_at=datetime.now(UTC),
|
|
verification_token=f"mpri_{unique_id}",
|
|
)
|
|
db.add(merchant_domain)
|
|
|
|
# Add store domain (should take priority)
|
|
store_domain = StoreDomain(
|
|
store_id=test_store.id,
|
|
domain=f"storepri{unique_id}.example.com",
|
|
is_primary=True,
|
|
is_active=True,
|
|
is_verified=True,
|
|
verified_at=datetime.now(UTC),
|
|
verification_token=f"spri_{unique_id}",
|
|
)
|
|
db.add(store_domain)
|
|
db.commit()
|
|
db.refresh(test_store)
|
|
db.refresh(test_merchant)
|
|
|
|
assert test_store.effective_domain == f"storepri{unique_id}.example.com"
|