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:
2025-12-28 19:01:54 +01:00
parent beebcb5631
commit 23a5ccbcff
3 changed files with 1016 additions and 0 deletions

View 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