test: add integration tests for vendor orders API and background tasks
Add comprehensive integration tests for: - Vendor orders API (list, detail, status updates, pagination, filtering) - Letzshop historical import background task (success, errors, progress) - Subscription background tasks (period reset, trial expiration, Stripe sync) These 39 new tests improve coverage for background task functionality and vendor order management. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
313
tests/integration/api/v1/vendor/test_orders.py
vendored
Normal file
313
tests/integration/api/v1/vendor/test_orders.py
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
# tests/integration/api/v1/vendor/test_orders.py
|
||||
"""Integration tests for vendor orders API endpoints."""
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from models.database.order import Order, OrderItem
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_order(db, test_vendor_with_vendor_user, test_customer):
|
||||
"""Create a test order for the vendor."""
|
||||
order = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
customer_id=test_customer.id,
|
||||
order_number="ORD-TEST-001",
|
||||
status="pending",
|
||||
channel="direct",
|
||||
order_date=datetime.now(UTC),
|
||||
subtotal_cents=10000,
|
||||
tax_amount_cents=1700,
|
||||
shipping_amount_cents=500,
|
||||
total_amount_cents=12200,
|
||||
currency="EUR",
|
||||
customer_email="customer@test.com",
|
||||
customer_first_name="Test",
|
||||
customer_last_name="Customer",
|
||||
ship_first_name="Test",
|
||||
ship_last_name="Customer",
|
||||
ship_address_line_1="123 Test St",
|
||||
ship_city="Test City",
|
||||
ship_postal_code="12345",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="Customer",
|
||||
bill_address_line_1="123 Test St",
|
||||
bill_city="Test City",
|
||||
bill_postal_code="12345",
|
||||
bill_country_iso="LU",
|
||||
)
|
||||
db.add(order)
|
||||
db.commit()
|
||||
db.refresh(order)
|
||||
return order
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_orders(db, test_vendor_with_vendor_user, test_customer):
|
||||
"""Create multiple test orders."""
|
||||
orders = []
|
||||
for i, status in enumerate(["pending", "processing", "shipped", "delivered", "cancelled"]):
|
||||
order = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
customer_id=test_customer.id,
|
||||
order_number=f"ORD-TEST-{i+1:03d}",
|
||||
status=status,
|
||||
channel="direct" if i % 2 == 0 else "letzshop",
|
||||
order_date=datetime.now(UTC),
|
||||
subtotal_cents=10000 * (i + 1),
|
||||
tax_amount_cents=1700 * (i + 1),
|
||||
shipping_amount_cents=500,
|
||||
total_amount_cents=12200 * (i + 1),
|
||||
currency="EUR",
|
||||
customer_email=f"customer{i}@test.com",
|
||||
customer_first_name="Test",
|
||||
customer_last_name=f"Customer{i}",
|
||||
ship_first_name="Test",
|
||||
ship_last_name=f"Customer{i}",
|
||||
ship_address_line_1="123 Test St",
|
||||
ship_city="Test City",
|
||||
ship_postal_code="12345",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name=f"Customer{i}",
|
||||
bill_address_line_1="123 Test St",
|
||||
bill_city="Test City",
|
||||
bill_postal_code="12345",
|
||||
bill_country_iso="LU",
|
||||
)
|
||||
db.add(order)
|
||||
orders.append(order)
|
||||
db.commit()
|
||||
for order in orders:
|
||||
db.refresh(order)
|
||||
return orders
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_order_with_items(db, test_vendor_with_vendor_user, test_customer):
|
||||
"""Create a test order with order items."""
|
||||
order = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
customer_id=test_customer.id,
|
||||
order_number="ORD-ITEMS-001",
|
||||
status="pending",
|
||||
channel="direct",
|
||||
order_date=datetime.now(UTC),
|
||||
subtotal_cents=20000,
|
||||
tax_amount_cents=3400,
|
||||
shipping_amount_cents=500,
|
||||
total_amount_cents=23900,
|
||||
currency="EUR",
|
||||
customer_email="customer@test.com",
|
||||
customer_first_name="Test",
|
||||
customer_last_name="Customer",
|
||||
ship_first_name="Test",
|
||||
ship_last_name="Customer",
|
||||
ship_address_line_1="123 Test St",
|
||||
ship_city="Test City",
|
||||
ship_postal_code="12345",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="Customer",
|
||||
bill_address_line_1="123 Test St",
|
||||
bill_city="Test City",
|
||||
bill_postal_code="12345",
|
||||
bill_country_iso="LU",
|
||||
)
|
||||
db.add(order)
|
||||
db.flush()
|
||||
|
||||
# Add order items
|
||||
item = OrderItem(
|
||||
order_id=order.id,
|
||||
product_id=1, # Placeholder, no product FK constraint in test
|
||||
product_sku="TEST-SKU-001",
|
||||
product_name="Test Product",
|
||||
quantity=2,
|
||||
unit_price_cents=10000,
|
||||
total_price_cents=20000,
|
||||
)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
db.refresh(order)
|
||||
return order
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.api
|
||||
@pytest.mark.vendor
|
||||
class TestVendorOrdersListAPI:
|
||||
"""Test vendor orders list endpoint."""
|
||||
|
||||
def test_list_orders_success(self, client, vendor_user_headers, test_orders):
|
||||
"""Test listing vendor orders."""
|
||||
response = client.get("/api/v1/vendor/orders", headers=vendor_user_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "orders" in data
|
||||
assert "total" in data
|
||||
assert data["total"] == 5
|
||||
assert len(data["orders"]) == 5
|
||||
|
||||
def test_list_orders_with_pagination(self, client, vendor_user_headers, test_orders):
|
||||
"""Test orders list with pagination."""
|
||||
response = client.get(
|
||||
"/api/v1/vendor/orders?skip=2&limit=2", headers=vendor_user_headers
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data["orders"]) == 2
|
||||
assert data["skip"] == 2
|
||||
assert data["limit"] == 2
|
||||
|
||||
def test_list_orders_filter_by_status(self, client, vendor_user_headers, test_orders):
|
||||
"""Test filtering orders by status."""
|
||||
response = client.get(
|
||||
"/api/v1/vendor/orders?status=pending", headers=vendor_user_headers
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data["orders"]) == 1
|
||||
assert data["orders"][0]["status"] == "pending"
|
||||
|
||||
def test_list_orders_filter_by_customer(
|
||||
self, client, vendor_user_headers, test_orders, test_customer
|
||||
):
|
||||
"""Test filtering orders by customer ID."""
|
||||
response = client.get(
|
||||
f"/api/v1/vendor/orders?customer_id={test_customer.id}",
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["total"] == 5 # All orders belong to test_customer
|
||||
|
||||
def test_list_orders_empty(self, client, vendor_user_headers):
|
||||
"""Test empty orders list."""
|
||||
response = client.get("/api/v1/vendor/orders", headers=vendor_user_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["orders"] == []
|
||||
assert data["total"] == 0
|
||||
|
||||
def test_list_orders_unauthorized(self, client):
|
||||
"""Test orders list without authentication."""
|
||||
response = client.get("/api/v1/vendor/orders")
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.api
|
||||
@pytest.mark.vendor
|
||||
class TestVendorOrderDetailAPI:
|
||||
"""Test vendor order detail endpoint."""
|
||||
|
||||
def test_get_order_detail(self, client, vendor_user_headers, test_order_with_items):
|
||||
"""Test getting order details."""
|
||||
response = client.get(
|
||||
f"/api/v1/vendor/orders/{test_order_with_items.id}",
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["order_number"] == "ORD-ITEMS-001"
|
||||
assert data["status"] == "pending"
|
||||
assert "items" in data
|
||||
assert len(data["items"]) == 1
|
||||
assert data["items"][0]["quantity"] == 2
|
||||
|
||||
def test_get_order_not_found(self, client, vendor_user_headers):
|
||||
"""Test getting non-existent order."""
|
||||
response = client.get(
|
||||
"/api/v1/vendor/orders/99999", headers=vendor_user_headers
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_get_order_unauthorized(self, client, test_order):
|
||||
"""Test getting order without authentication."""
|
||||
response = client.get(f"/api/v1/vendor/orders/{test_order.id}")
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.api
|
||||
@pytest.mark.vendor
|
||||
class TestVendorOrderStatusUpdateAPI:
|
||||
"""Test vendor order status update endpoint."""
|
||||
|
||||
def test_update_order_status_to_processing(
|
||||
self, client, vendor_user_headers, test_order
|
||||
):
|
||||
"""Test updating order status to processing."""
|
||||
response = client.put(
|
||||
f"/api/v1/vendor/orders/{test_order.id}/status",
|
||||
json={"status": "processing"},
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "processing"
|
||||
|
||||
def test_update_order_status_to_shipped(
|
||||
self, client, vendor_user_headers, test_order
|
||||
):
|
||||
"""Test updating order status to shipped with tracking."""
|
||||
response = client.put(
|
||||
f"/api/v1/vendor/orders/{test_order.id}/status",
|
||||
json={
|
||||
"status": "shipped",
|
||||
"tracking_number": "TRACK123456",
|
||||
"tracking_url": "https://tracking.example.com/TRACK123456",
|
||||
},
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "shipped"
|
||||
|
||||
def test_update_order_status_to_cancelled(
|
||||
self, client, vendor_user_headers, test_order
|
||||
):
|
||||
"""Test updating order status to cancelled."""
|
||||
response = client.put(
|
||||
f"/api/v1/vendor/orders/{test_order.id}/status",
|
||||
json={"status": "cancelled"},
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "cancelled"
|
||||
|
||||
def test_update_order_not_found(self, client, vendor_user_headers):
|
||||
"""Test updating non-existent order."""
|
||||
response = client.put(
|
||||
"/api/v1/vendor/orders/99999/status",
|
||||
json={"status": "processing"},
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_update_order_unauthorized(self, client, test_order):
|
||||
"""Test updating order without authentication."""
|
||||
response = client.put(
|
||||
f"/api/v1/vendor/orders/{test_order.id}/status",
|
||||
json={"status": "processing"},
|
||||
)
|
||||
|
||||
assert response.status_code == 401
|
||||
Reference in New Issue
Block a user