# tests/integration/api/v1/test_store_api_dashboard.py """ Integration tests for store dashboard API endpoints. Tests cover: 1. Dashboard stats retrieval 2. Store-specific data isolation 3. Permission checks 4. Data accuracy """ import pytest @pytest.mark.integration @pytest.mark.api @pytest.mark.store class TestStoreDashboardAPI: """Test store dashboard stats endpoint""" def test_get_dashboard_stats_structure( self, client, store_user_headers, test_store_with_store_user, db ): """Test dashboard stats returns correct data structure""" response = client.get( "/api/v1/store/dashboard/stats", headers=store_user_headers ) assert response.status_code == 200 data = response.json() # Verify top-level structure assert "store" in data assert "products" in data assert "orders" in data assert "customers" in data assert "revenue" in data # Verify store info assert "id" in data["store"] assert "name" in data["store"] assert "store_code" in data["store"] assert data["store"]["id"] == test_store_with_store_user.id # Verify products stats assert "total" in data["products"] assert "active" in data["products"] assert isinstance(data["products"]["total"], int) assert isinstance(data["products"]["active"], int) # Verify orders stats assert "total" in data["orders"] assert "pending" in data["orders"] assert "completed" in data["orders"] # Verify customers stats assert "total" in data["customers"] assert "active" in data["customers"] # Verify revenue stats assert "total" in data["revenue"] assert "this_month" in data["revenue"] def test_dashboard_stats_without_store_association(self, client, db, auth_manager): """Test dashboard stats for user not associated with any store""" import uuid from app.modules.tenancy.models import User # Create store user without store association hashed_password = auth_manager.hash_password("testpass123") orphan_user = User( email=f"orphan_{uuid.uuid4().hex[:8]}@example.com", username=f"orphanstore_{uuid.uuid4().hex[:8]}", hashed_password=hashed_password, role="merchant_owner", is_active=True, ) db.add(orphan_user) db.commit() db.refresh(orphan_user) # Get token token_data = auth_manager.create_access_token(orphan_user) headers = {"Authorization": f"Bearer {token_data['access_token']}"} # Try to get dashboard stats response = client.get("/api/v1/store/dashboard/stats", headers=headers) # Should fail - user not associated with store (401 if no store context, 403 if forbidden) assert response.status_code in [401, 403, 404] def test_dashboard_stats_with_inactive_store( self, client, db, test_store_user, test_merchant, auth_manager ): """Test dashboard stats for inactive store""" import uuid from app.modules.tenancy.models import Store, StoreUser # Create inactive store unique_code = f"INACTIVE_{uuid.uuid4().hex[:8].upper()}" store = Store( store_code=unique_code, subdomain=f"inactive-{uuid.uuid4().hex[:8]}", name="Inactive Store", merchant_id=test_merchant.id, is_active=False, # Inactive is_verified=True, ) db.add(store) db.commit() # Associate with user (ownership determined via Merchant.owner_user_id) store_user = StoreUser( store_id=store.id, user_id=test_store_user.id, is_active=True, ) db.add(store_user) db.commit() # Get token token_data = auth_manager.create_access_token(test_store_user) headers = {"Authorization": f"Bearer {token_data['access_token']}"} # Try to get dashboard stats response = client.get("/api/v1/store/dashboard/stats", headers=headers) # Should fail - store is inactive (could be 401, 403 or 404 depending on implementation) assert response.status_code in [401, 403, 404] def test_dashboard_stats_empty_store( self, client, store_user_headers, test_store_with_store_user ): """Test dashboard stats for store with no data""" response = client.get( "/api/v1/store/dashboard/stats", headers=store_user_headers ) assert response.status_code == 200 data = response.json() # Should return zeros for empty store assert data["products"]["total"] == 0 assert data["products"]["active"] == 0 assert data["orders"]["total"] == 0 assert data["customers"]["total"] == 0 assert data["revenue"]["total"] == 0 def test_dashboard_stats_response_time( self, client, store_user_headers, test_store_with_store_user ): """Test that dashboard stats responds quickly""" import time start_time = time.time() response = client.get( "/api/v1/store/dashboard/stats", headers=store_user_headers ) end_time = time.time() assert response.status_code == 200 # Should respond in less than 2 seconds assert (end_time - start_time) < 2.0 def test_dashboard_stats_caching_behavior( self, client, store_user_headers, test_store_with_store_user ): """Test that dashboard stats can be called multiple times""" # Make multiple requests responses = [] for _ in range(3): response = client.get( "/api/v1/store/dashboard/stats", headers=store_user_headers ) responses.append(response) # All should succeed for response in responses: assert response.status_code == 200 # All should return consistent data data_list = [r.json() for r in responses] for data in data_list[1:]: assert data["store"]["id"] == data_list[0]["store"]["id"] assert data["products"]["total"] == data_list[0]["products"]["total"]