# tests/test_stats_service.py import pytest from app.services.stats_service import StatsService from models.database.marketplace_product import MarketplaceProduct from models.database.inventory import Inventory @pytest.mark.unit @pytest.mark.stats class TestStatsService: """Test suite for StatsService following the application's testing patterns""" def setup_method(self): """Setup method following the same pattern as other service tests""" self.service = StatsService() def test_get_comprehensive_stats_basic(self, db, test_marketplace_product, test_inventory): """Test getting comprehensive stats with basic data""" stats = self.service.get_comprehensive_stats(db) assert "total_products" in stats assert "unique_brands" in stats assert "unique_categories" in stats assert "unique_marketplaces" in stats assert "unique_vendors" in stats assert "total_inventory_entries" in stats assert "total_inventory_quantity" in stats assert stats["total_products"] >= 1 assert stats["total_inventory_entries"] >= 1 assert stats["total_inventory_quantity"] >= 10 # test_inventory has quantity 10 def test_get_comprehensive_stats_multiple_products(self, db, test_marketplace_product): """Test comprehensive stats with multiple products across different dimensions""" # Create products with different brands, categories, marketplaces additional_products = [ MarketplaceProduct( marketplace_product_id="PROD002", title="MarketplaceProduct 2", brand="DifferentBrand", google_product_category="Different Category", marketplace="Amazon", vendor_name="AmazonVendor", price="15.99", currency="EUR", ), MarketplaceProduct( marketplace_product_id="PROD003", title="MarketplaceProduct 3", brand="ThirdBrand", google_product_category="Third Category", marketplace="eBay", vendor_name="eBayVendor", price="25.99", currency="USD", ), MarketplaceProduct( marketplace_product_id="PROD004", title="MarketplaceProduct 4", brand="TestBrand", # Same as test_marketplace_product google_product_category="Different Category", marketplace="Letzshop", # Same as test_marketplace_product vendor_name="DifferentVendor", price="35.99", currency="EUR", ), ] db.add_all(additional_products) db.commit() stats = self.service.get_comprehensive_stats(db) assert stats["total_products"] >= 4 # test_marketplace_product + 3 additional assert stats["unique_brands"] >= 3 # TestBrand, DifferentBrand, ThirdBrand assert stats["unique_categories"] >= 2 # At least 2 different categories assert stats["unique_marketplaces"] >= 3 # Letzshop, Amazon, eBay assert stats["unique_vendors"] >= 3 # At least 3 different vendors def test_get_comprehensive_stats_handles_nulls(self, db): """Test comprehensive stats handles null/empty values correctly""" # Create products with null/empty values products_with_nulls = [ MarketplaceProduct( marketplace_product_id="NULL001", title="MarketplaceProduct with Nulls", brand=None, # Null brand google_product_category=None, # Null category marketplace=None, # Null marketplace vendor_name=None, # Null vendor price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="EMPTY001", title="MarketplaceProduct with Empty Values", brand="", # Empty brand google_product_category="", # Empty category marketplace="", # Empty marketplace vendor_name="", # Empty vendor price="15.00", currency="EUR", ), ] db.add_all(products_with_nulls) db.commit() stats = self.service.get_comprehensive_stats(db) # These products shouldn't contribute to unique counts due to null/empty values assert stats["total_products"] >= 2 # Brands, categories, marketplaces, vendors should not count null/empty values assert isinstance(stats["unique_brands"], int) assert isinstance(stats["unique_categories"], int) assert isinstance(stats["unique_marketplaces"], int) assert isinstance(stats["unique_vendors"], int) def test_get_marketplace_breakdown_stats_basic(self, db, test_marketplace_product): """Test getting marketplace breakdown stats with basic data""" stats = self.service.get_marketplace_breakdown_stats(db) assert isinstance(stats, list) assert len(stats) >= 1 # Find our test marketplace in the results test_marketplace_stat = next( (stat for stat in stats if stat["marketplace"] == test_marketplace_product.marketplace), None, ) assert test_marketplace_stat is not None assert test_marketplace_stat["total_products"] >= 1 assert test_marketplace_stat["unique_vendors"] >= 1 assert test_marketplace_stat["unique_brands"] >= 1 def test_get_marketplace_breakdown_stats_multiple_marketplaces( self, db, test_marketplace_product ): """Test marketplace breakdown with multiple marketplaces""" # Create products for different marketplaces marketplace_products = [ MarketplaceProduct( marketplace_product_id="AMAZON001", title="Amazon MarketplaceProduct 1", brand="AmazonBrand1", marketplace="Amazon", vendor_name="AmazonVendor1", price="20.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="AMAZON002", title="Amazon MarketplaceProduct 2", brand="AmazonBrand2", marketplace="Amazon", vendor_name="AmazonVendor2", price="25.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="EBAY001", title="eBay MarketplaceProduct", brand="eBayBrand", marketplace="eBay", vendor_name="eBayVendor", price="30.00", currency="USD", ), ] db.add_all(marketplace_products) db.commit() stats = self.service.get_marketplace_breakdown_stats(db) # Should have at least 3 marketplaces: test_marketplace_product.marketplace, Amazon, eBay marketplace_names = [stat["marketplace"] for stat in stats] assert "Amazon" in marketplace_names assert "eBay" in marketplace_names assert test_marketplace_product.marketplace in marketplace_names # Check Amazon stats specifically amazon_stat = next(stat for stat in stats if stat["marketplace"] == "Amazon") assert amazon_stat["total_products"] == 2 assert amazon_stat["unique_vendors"] == 2 assert amazon_stat["unique_brands"] == 2 # Check eBay stats specifically ebay_stat = next(stat for stat in stats if stat["marketplace"] == "eBay") assert ebay_stat["total_products"] == 1 assert ebay_stat["unique_vendors"] == 1 assert ebay_stat["unique_brands"] == 1 def test_get_marketplace_breakdown_stats_excludes_nulls(self, db): """Test marketplace breakdown excludes products with null marketplaces""" # Create product with null marketplace null_marketplace_product = MarketplaceProduct( marketplace_product_id="NULLMARKET001", title="MarketplaceProduct without marketplace", marketplace=None, vendor_name="SomeVendor", brand="SomeBrand", price="10.00", currency="EUR", ) db.add(null_marketplace_product) db.commit() stats = self.service.get_marketplace_breakdown_stats(db) # Should not include any stats for null marketplace marketplace_names = [ stat["marketplace"] for stat in stats if stat["marketplace"] is not None ] assert None not in marketplace_names def test_get_product_count(self, db, test_marketplace_product): """Test getting total product count""" count = self.service._get_product_count(db) assert count >= 1 assert isinstance(count, int) def test_get_unique_brands_count(self, db, test_marketplace_product): """Test getting unique brands count""" # Add products with different brands brand_products = [ MarketplaceProduct( marketplace_product_id="BRAND001", title="Brand MarketplaceProduct 1", brand="BrandA", marketplace="Test", vendor_name="TestVendor", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="BRAND002", title="Brand MarketplaceProduct 2", brand="BrandB", marketplace="Test", vendor_name="TestVendor", price="15.00", currency="EUR", ), ] db.add_all(brand_products) db.commit() count = self.service._get_unique_brands_count(db) assert ( count >= 2 ) # At least BrandA and BrandB, plus possibly test_marketplace_product brand assert isinstance(count, int) def test_get_unique_categories_count(self, db, test_marketplace_product): """Test getting unique categories count""" # Add products with different categories category_products = [ MarketplaceProduct( marketplace_product_id="CAT001", title="Category MarketplaceProduct 1", google_product_category="Electronics", marketplace="Test", vendor_name="TestVendor", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="CAT002", title="Category MarketplaceProduct 2", google_product_category="Books", marketplace="Test", vendor_name="TestVendor", price="15.00", currency="EUR", ), ] db.add_all(category_products) db.commit() count = self.service._get_unique_categories_count(db) assert count >= 2 # At least Electronics and Books assert isinstance(count, int) def test_get_unique_marketplaces_count(self, db, test_marketplace_product): """Test getting unique marketplaces count""" # Add products with different marketplaces marketplace_products = [ MarketplaceProduct( marketplace_product_id="MARKET001", title="Marketplace MarketplaceProduct 1", marketplace="Amazon", vendor_name="AmazonVendor", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="MARKET002", title="Marketplace MarketplaceProduct 2", marketplace="eBay", vendor_name="eBayVendor", price="15.00", currency="EUR", ), ] db.add_all(marketplace_products) db.commit() count = self.service._get_unique_marketplaces_count(db) assert count >= 2 # At least Amazon and eBay, plus test_marketplace_product marketplace assert isinstance(count, int) def test_get_unique_vendors_count(self, db, test_marketplace_product): """Test getting unique vendors count""" # Add products with different vendor names products = [ MarketplaceProduct( marketplace_product_id="PRODUCT001", title="Vendor MarketplaceProduct 1", marketplace="Test", vendor_name="VendorA", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="PRODUCT002", title="Vendor MarketplaceProduct 2", marketplace="Test", vendor_name="VendorB", price="15.00", currency="EUR", ), ] db.add_all(products) db.commit() count = self.service._get_unique_vendors_count(db) assert count >= 2 # At least VendorA and VendorB, plus test_marketplace_product vendor assert isinstance(count, int) def test_get_inventory_statistics(self, db, test_inventory): """Test getting inventory statistics""" # Add additional inventory entries additional_inventory = [ Inventory( gtin="1234567890124", location="LOCATION2", quantity=25, reserved_quantity=5, vendor_id=test_inventory.vendor_id, ), Inventory( gtin="1234567890125", location="LOCATION3", quantity=0, # Out of inventory reserved_quantity=0, vendor_id=test_inventory.vendor_id, ), ] db.add_all(additional_inventory) db.commit() stats = self.service.get_inventory_statistics(db) assert "total_inventory_entries" in stats assert "total_inventory_quantity" in stats assert stats["total_inventory_entries"] >= 3 # test_inventory + 2 additional assert stats["total_inventory_quantity"] >= 35 # 10 + 25 + 0 = 35 def test_get_brands_by_marketplace(self, db): """Test getting brands for a specific marketplace""" # Create products for specific marketplace marketplace_products = [ MarketplaceProduct( marketplace_product_id="SPECIFIC001", title="Specific MarketplaceProduct 1", brand="SpecificBrand1", marketplace="SpecificMarket", vendor_name="SpecificVendor1", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="SPECIFIC002", title="Specific MarketplaceProduct 2", brand="SpecificBrand2", marketplace="SpecificMarket", vendor_name="SpecificVendor2", price="15.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="OTHER001", title="Other MarketplaceProduct", brand="OtherBrand", marketplace="OtherMarket", vendor_name="OtherVendor", price="20.00", currency="EUR", ), ] db.add_all(marketplace_products) db.commit() brands = self.service._get_brands_by_marketplace(db, "SpecificMarket") assert len(brands) == 2 assert "SpecificBrand1" in brands assert "SpecificBrand2" in brands assert "OtherBrand" not in brands def test_get_vendors_by_marketplace(self, db): """Test getting vendors for a specific marketplace""" # Create products for specific marketplace marketplace_products = [ MarketplaceProduct( marketplace_product_id="MARKETTEST001", title="Vendor Test MarketplaceProduct 1", brand="TestBrand", marketplace="TestMarketplace", vendor_name="TestVendor1", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="MARKETTEST002", title="Vendor Test MarketplaceProduct 2", brand="TestBrand", marketplace="TestMarketplace", vendor_name="TestVendor2", price="15.00", currency="EUR", ), ] db.add_all(marketplace_products) db.commit() vendors =self.service._get_vendors_by_marketplace(db, "TestMarketplace") assert len(vendors) == 2 assert "TestVendor1" in vendors assert "TestVendor2" in vendors def test_get_products_by_marketplace(self, db): """Test getting product count for a specific marketplace""" # Create products for specific marketplace marketplace_products = [ MarketplaceProduct( marketplace_product_id="COUNT001", title="Count MarketplaceProduct 1", marketplace="CountMarketplace", vendor_name="CountVendor", price="10.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="COUNT002", title="Count MarketplaceProduct 2", marketplace="CountMarketplace", vendor_name="CountVendor", price="15.00", currency="EUR", ), MarketplaceProduct( marketplace_product_id="COUNT003", title="Count MarketplaceProduct 3", marketplace="CountMarketplace", vendor_name="CountVendor", price="20.00", currency="EUR", ), ] db.add_all(marketplace_products) db.commit() count = self.service._get_products_by_marketplace_count(db, "CountMarketplace") assert count == 3 def test_get_products_by_marketplace_not_found(self, db): """Test getting product count for non-existent marketplace""" count = self.service._get_products_by_marketplace_count(db, "NonExistentMarketplace") assert count == 0 def test_empty_database_stats(self, db): """Test stats with empty database""" stats = self.service.get_comprehensive_stats(db) assert stats["total_products"] == 0 assert stats["unique_brands"] == 0 assert stats["unique_categories"] == 0 assert stats["unique_marketplaces"] == 0 assert stats["unique_vendors"] == 0 assert stats["total_inventory_entries"] == 0 assert stats["total_inventory_quantity"] == 0 def test_marketplace_breakdown_empty_database(self, db): """Test marketplace breakdown with empty database""" stats = self.service.get_marketplace_breakdown_stats(db) assert isinstance(stats, list) assert len(stats) == 0