# tests/unit/services/test_platform_service.py """Unit tests for PlatformService.""" import uuid import pytest from app.modules.tenancy.exceptions import PlatformNotFoundException from app.modules.tenancy.services.platform_service import platform_service, PlatformStats from app.modules.tenancy.models import Platform, VendorPlatform from app.modules.cms.models import ContentPage # ============================================================================= # FIXTURES # ============================================================================= @pytest.fixture def inactive_platform(db): """Create an inactive test platform.""" unique_id = str(uuid.uuid4())[:8] platform = Platform( code=f"inactive_{unique_id}", name=f"Inactive Platform {unique_id}", description="An inactive test platform", path_prefix=f"inactive{unique_id}", is_active=False, is_public=False, default_language="en", supported_languages=["en"], ) db.add(platform) db.commit() db.refresh(platform) return platform @pytest.fixture def platform_with_vendor(db, test_platform, test_vendor): """Create a vendor-platform assignment.""" vendor_platform = VendorPlatform( vendor_id=test_vendor.id, platform_id=test_platform.id, is_active=True, ) db.add(vendor_platform) db.commit() return test_platform @pytest.fixture def platform_with_pages(db, test_platform): """Create a platform with content pages.""" unique_id = str(uuid.uuid4())[:8] # Platform marketing page (published) platform_page = ContentPage( platform_id=test_platform.id, vendor_id=None, slug=f"platform-page-{unique_id}", page_type="marketing", is_platform_page=True, is_published=True, ) db.add(platform_page) # Vendor default page (draft) default_page = ContentPage( platform_id=test_platform.id, vendor_id=None, slug=f"vendor-default-{unique_id}", page_type="about", is_platform_page=False, is_published=False, ) db.add(default_page) db.commit() return test_platform # ============================================================================= # GET PLATFORM TESTS # ============================================================================= @pytest.mark.unit @pytest.mark.tenancy class TestPlatformServiceGet: """Test suite for getting platforms.""" def test_get_platform_by_code_success(self, db, test_platform): """Test getting a platform by code.""" platform = platform_service.get_platform_by_code(db, test_platform.code) assert platform is not None assert platform.id == test_platform.id assert platform.code == test_platform.code def test_get_platform_by_code_not_found(self, db): """Test getting a non-existent platform raises exception.""" with pytest.raises(PlatformNotFoundException) as exc_info: platform_service.get_platform_by_code(db, "nonexistent_platform") assert "nonexistent_platform" in str(exc_info.value) def test_get_platform_by_code_optional_found(self, db, test_platform): """Test optional get returns platform when found.""" platform = platform_service.get_platform_by_code_optional(db, test_platform.code) assert platform is not None assert platform.id == test_platform.id def test_get_platform_by_code_optional_not_found(self, db): """Test optional get returns None when not found.""" platform = platform_service.get_platform_by_code_optional(db, "nonexistent") assert platform is None def test_get_platform_by_id_success(self, db, test_platform): """Test getting a platform by ID.""" platform = platform_service.get_platform_by_id(db, test_platform.id) assert platform is not None assert platform.code == test_platform.code def test_get_platform_by_id_not_found(self, db): """Test getting a non-existent platform by ID raises exception.""" with pytest.raises(PlatformNotFoundException): platform_service.get_platform_by_id(db, 99999) # ============================================================================= # LIST PLATFORMS TESTS # ============================================================================= @pytest.mark.unit @pytest.mark.tenancy class TestPlatformServiceList: """Test suite for listing platforms.""" def test_list_platforms_active_only(self, db, test_platform, inactive_platform): """Test listing only active platforms.""" platforms = platform_service.list_platforms(db, include_inactive=False) platform_ids = [p.id for p in platforms] assert test_platform.id in platform_ids assert inactive_platform.id not in platform_ids def test_list_platforms_include_inactive(self, db, test_platform, inactive_platform): """Test listing all platforms including inactive.""" platforms = platform_service.list_platforms(db, include_inactive=True) platform_ids = [p.id for p in platforms] assert test_platform.id in platform_ids assert inactive_platform.id in platform_ids # ============================================================================= # COUNT TESTS # ============================================================================= @pytest.mark.unit @pytest.mark.tenancy class TestPlatformServiceCounts: """Test suite for platform counts.""" def test_get_vendor_count_zero(self, db, test_platform): """Test vendor count is zero when no vendors assigned.""" count = platform_service.get_vendor_count(db, test_platform.id) assert count == 0 def test_get_vendor_count_with_vendors(self, db, platform_with_vendor): """Test vendor count with assigned vendors.""" count = platform_service.get_vendor_count(db, platform_with_vendor.id) assert count >= 1 def test_get_platform_pages_count(self, db, platform_with_pages): """Test platform pages count.""" count = platform_service.get_platform_pages_count(db, platform_with_pages.id) assert count >= 1 def test_get_vendor_defaults_count(self, db, platform_with_pages): """Test vendor defaults count.""" count = platform_service.get_vendor_defaults_count(db, platform_with_pages.id) assert count >= 1 def test_get_published_pages_count(self, db, platform_with_pages): """Test published pages count.""" count = platform_service.get_published_pages_count(db, platform_with_pages.id) assert count >= 1 def test_get_draft_pages_count(self, db, platform_with_pages): """Test draft pages count.""" count = platform_service.get_draft_pages_count(db, platform_with_pages.id) assert count >= 1 # ============================================================================= # PLATFORM STATS TESTS # ============================================================================= @pytest.mark.unit @pytest.mark.tenancy class TestPlatformServiceStats: """Test suite for platform statistics.""" def test_get_platform_stats(self, db, platform_with_pages, test_vendor): """Test getting comprehensive platform statistics.""" # Add a vendor to the platform vendor_platform = VendorPlatform( vendor_id=test_vendor.id, platform_id=platform_with_pages.id, is_active=True, ) db.add(vendor_platform) db.commit() stats = platform_service.get_platform_stats(db, platform_with_pages) assert isinstance(stats, PlatformStats) assert stats.platform_id == platform_with_pages.id assert stats.platform_code == platform_with_pages.code assert stats.platform_name == platform_with_pages.name assert stats.vendor_count >= 1 assert stats.platform_pages_count >= 1 assert stats.vendor_defaults_count >= 1 def test_get_platform_stats_empty_platform(self, db, test_platform): """Test stats for a platform with no content.""" stats = platform_service.get_platform_stats(db, test_platform) assert stats.vendor_count == 0 assert stats.platform_pages_count == 0 assert stats.vendor_defaults_count == 0 # ============================================================================= # UPDATE TESTS # ============================================================================= @pytest.mark.unit @pytest.mark.tenancy class TestPlatformServiceUpdate: """Test suite for updating platforms.""" def test_update_platform_name(self, db, test_platform): """Test updating platform name.""" unique_id = str(uuid.uuid4())[:8] new_name = f"Updated Platform {unique_id}" updated = platform_service.update_platform( db, test_platform, {"name": new_name} ) db.commit() assert updated.name == new_name def test_update_platform_multiple_fields(self, db, test_platform): """Test updating multiple platform fields.""" unique_id = str(uuid.uuid4())[:8] update_data = { "name": f"Multi Update {unique_id}", "description": "Updated description", "is_public": False, } updated = platform_service.update_platform(db, test_platform, update_data) db.commit() assert updated.name == f"Multi Update {unique_id}" assert updated.description == "Updated description" assert updated.is_public is False def test_update_platform_ignores_invalid_fields(self, db, test_platform): """Test that invalid fields are ignored during update.""" original_name = test_platform.name update_data = { "nonexistent_field": "value", "name": original_name, # Keep same name } # Should not raise an error updated = platform_service.update_platform(db, test_platform, update_data) assert updated.name == original_name