Files
orion/tests/integration/api/v1/vendor/test_dashboard.py
Samir Boulahtit 21c13ca39b style: apply black and isort formatting across entire codebase
- Standardize quote style (single to double quotes)
- Reorder and group imports alphabetically
- Fix line breaks and indentation for consistency
- Apply PEP 8 formatting standards

Also updated Makefile to exclude both venv and .venv from code quality checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:30:17 +01:00

291 lines
9.3 KiB
Python

# tests/integration/api/v1/test_vendor_api_dashboard.py
"""
Integration tests for vendor dashboard API endpoints.
Tests cover:
1. Dashboard stats retrieval
2. Vendor-specific data isolation
3. Permission checks
4. Data accuracy
"""
import pytest
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorDashboardAPI:
"""Test vendor dashboard stats endpoint"""
def test_get_dashboard_stats_structure(
self, client, vendor_user_headers, test_vendor_with_vendor_user, db
):
"""Test dashboard stats returns correct data structure"""
response = client.get(
"/api/v1/vendor/dashboard/stats", headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
# Verify top-level structure
assert "vendor" in data
assert "products" in data
assert "orders" in data
assert "customers" in data
assert "revenue" in data
# Verify vendor info
assert "id" in data["vendor"]
assert "name" in data["vendor"]
assert "vendor_code" in data["vendor"]
assert data["vendor"]["id"] == test_vendor_with_vendor_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_vendor_isolation(
self, client, db, test_vendor_user, auth_manager
):
"""Test that dashboard stats only show data for the authenticated vendor"""
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
from models.database.vendor import Vendor, VendorUser
# Create two separate vendors with different data
vendor1 = Vendor(
vendor_code="VENDOR1",
subdomain="vendor1",
name="Vendor One",
owner_user_id=test_vendor_user.id,
is_active=True,
is_verified=True,
)
db.add(vendor1)
db.commit()
db.refresh(vendor1)
# Associate vendor1 with test_vendor_user
vendor_user1 = VendorUser(
vendor_id=vendor1.id,
user_id=test_vendor_user.id,
is_owner=True,
is_active=True,
)
db.add(vendor_user1)
db.commit()
# Create marketplace product for vendor1
mp1 = MarketplaceProduct(
gtin="1234567890123",
title="Product for Vendor 1",
is_active=True,
)
db.add(mp1)
db.commit()
# Create products for vendor1
for i in range(3):
product = Product(
vendor_id=vendor1.id,
marketplace_product_id=mp1.id,
price=10.0 + i,
is_active=True,
)
db.add(product)
db.commit()
# Get token for vendor1 user
token_data = auth_manager.create_access_token(test_vendor_user)
vendor1_headers = {"Authorization": f"Bearer {token_data['access_token']}"}
# Get stats for vendor1
response = client.get("/api/v1/vendor/dashboard/stats", headers=vendor1_headers)
assert response.status_code == 200
data = response.json()
# Should show 3 products for vendor1
assert data["vendor"]["id"] == vendor1.id
assert data["products"]["total"] == 3
def test_dashboard_stats_without_vendor_association(self, client, db, auth_manager):
"""Test dashboard stats for user not associated with any vendor"""
from models.database.user import User
# Create vendor user without vendor association
hashed_password = auth_manager.hash_password("testpass123")
orphan_user = User(
email="orphan@example.com",
username="orphanvendor",
hashed_password=hashed_password,
role="vendor",
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/vendor/dashboard/stats", headers=headers)
# Should fail - user not associated with vendor
assert response.status_code == 403
data = response.json()
assert "not associated with any vendor" in data["message"]
def test_dashboard_stats_with_inactive_vendor(
self, client, db, test_vendor_user, auth_manager
):
"""Test dashboard stats for inactive vendor"""
from models.database.vendor import Vendor, VendorUser
# Create inactive vendor
vendor = Vendor(
vendor_code="INACTIVE",
subdomain="inactive",
name="Inactive Vendor",
owner_user_id=test_vendor_user.id,
is_active=False, # Inactive
is_verified=True,
)
db.add(vendor)
db.commit()
# Associate with user
vendor_user = VendorUser(
vendor_id=vendor.id,
user_id=test_vendor_user.id,
is_owner=True,
is_active=True,
)
db.add(vendor_user)
db.commit()
# Get token
token_data = auth_manager.create_access_token(test_vendor_user)
headers = {"Authorization": f"Bearer {token_data['access_token']}"}
# Try to get dashboard stats
response = client.get("/api/v1/vendor/dashboard/stats", headers=headers)
# Should fail - vendor is inactive
assert response.status_code == 404
data = response.json()
assert "not found or inactive" in data["message"]
def test_dashboard_stats_empty_vendor(
self, client, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test dashboard stats for vendor with no data"""
response = client.get(
"/api/v1/vendor/dashboard/stats", headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
# Should return zeros for empty vendor
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_with_products(
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test dashboard stats accuracy with actual products"""
from models.database.marketplace_product import MarketplaceProduct
from models.database.product import Product
# Create marketplace products
mp = MarketplaceProduct(
gtin="1234567890124",
title="Test Product",
is_active=True,
)
db.add(mp)
db.commit()
# Create products (3 active, 2 inactive)
for i in range(5):
product = Product(
vendor_id=test_vendor_with_vendor_user.id,
marketplace_product_id=mp.id,
price=10.0 + i,
is_active=(i < 3), # First 3 are active
)
db.add(product)
db.commit()
# Get stats
response = client.get(
"/api/v1/vendor/dashboard/stats", headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
assert data["products"]["total"] == 5
assert data["products"]["active"] == 3
def test_dashboard_stats_response_time(
self, client, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test that dashboard stats responds quickly"""
import time
start_time = time.time()
response = client.get(
"/api/v1/vendor/dashboard/stats", headers=vendor_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, vendor_user_headers, test_vendor_with_vendor_user
):
"""Test that dashboard stats can be called multiple times"""
# Make multiple requests
responses = []
for _ in range(3):
response = client.get(
"/api/v1/vendor/dashboard/stats", headers=vendor_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["vendor"]["id"] == data_list[0]["vendor"]["id"]
assert data["products"]["total"] == data_list[0]["products"]["total"]