mirror of
http://88.130.71.182:3000/BlitTech/badoHair_be.git
synced 2026-06-13 08:34:29 +00:00
124 lines
4.2 KiB
Python
124 lines
4.2 KiB
Python
"""Order creation, stock deduction, and webhook handling."""
|
|
from unittest.mock import AsyncMock
|
|
from tests.conftest import PRODUCT_ID, ORDER_ID
|
|
|
|
|
|
SAMPLE_PRODUCT_ROW = {
|
|
"id": PRODUCT_ID,
|
|
"name": "Extensions Clip-In Luxe",
|
|
"price": 189.0,
|
|
"stock_quantity": 10,
|
|
}
|
|
|
|
SAMPLE_ORDER_ROW = {
|
|
"id": ORDER_ID,
|
|
"user_id": "11111111-1111-1111-1111-111111111111",
|
|
"status": "pending",
|
|
"total_amount": 189.0,
|
|
"stripe_payment_intent_id": "pi_test123",
|
|
"shipping_address": None,
|
|
"notes": None,
|
|
"created_at": "2026-01-01T00:00:00",
|
|
"updated_at": "2026-01-01T00:00:00",
|
|
}
|
|
|
|
|
|
async def test_create_order_success(auth_client, mock_db):
|
|
mock_db.fetchrow = AsyncMock(side_effect=[
|
|
SAMPLE_PRODUCT_ROW, # product lookup
|
|
{"id": ORDER_ID, **SAMPLE_ORDER_ROW}, # INSERT order
|
|
])
|
|
mock_db.execute = AsyncMock(return_value="UPDATE 1")
|
|
|
|
r = await auth_client.post("/api/v1/orders", json={
|
|
"items": [{"product_id": PRODUCT_ID, "quantity": 1}],
|
|
})
|
|
assert r.status_code == 201
|
|
body = r.json()
|
|
assert body["success"] is True
|
|
assert "client_secret" in body["data"]
|
|
assert "order_id" in body["data"]
|
|
assert body["data"]["amount"] == 189.0
|
|
|
|
|
|
async def test_create_order_requires_auth(anon_client):
|
|
r = await anon_client.post("/api/v1/orders", json={
|
|
"items": [{"product_id": PRODUCT_ID, "quantity": 1}],
|
|
})
|
|
assert r.status_code == 401
|
|
|
|
|
|
async def test_create_order_empty_items_rejected(auth_client):
|
|
r = await auth_client.post("/api/v1/orders", json={"items": []})
|
|
assert r.status_code == 422
|
|
|
|
|
|
async def test_create_order_product_not_found(auth_client, mock_db):
|
|
mock_db.fetchrow = AsyncMock(return_value=None)
|
|
|
|
r = await auth_client.post("/api/v1/orders", json={
|
|
"items": [{"product_id": "00000000-0000-0000-0000-000000000000", "quantity": 1}],
|
|
})
|
|
assert r.status_code == 404
|
|
assert r.json()["error"]["code"] == "PRODUCT_NOT_FOUND"
|
|
|
|
|
|
async def test_create_order_out_of_stock(auth_client, mock_db):
|
|
low_stock = {**SAMPLE_PRODUCT_ROW, "stock_quantity": 0}
|
|
mock_db.fetchrow = AsyncMock(return_value=low_stock)
|
|
|
|
r = await auth_client.post("/api/v1/orders", json={
|
|
"items": [{"product_id": PRODUCT_ID, "quantity": 1}],
|
|
})
|
|
assert r.status_code == 409
|
|
assert r.json()["error"]["code"] == "OUT_OF_STOCK"
|
|
|
|
|
|
async def test_list_my_orders(auth_client, mock_db):
|
|
mock_db.fetchval = AsyncMock(return_value=1)
|
|
mock_db.fetch = AsyncMock(return_value=[SAMPLE_ORDER_ROW])
|
|
|
|
r = await auth_client.get("/api/v1/orders")
|
|
assert r.status_code == 200
|
|
body = r.json()
|
|
assert body["meta"]["total"] == 1
|
|
|
|
|
|
async def test_get_order_by_id(auth_client, mock_db):
|
|
mock_db.fetchrow = AsyncMock(return_value=SAMPLE_ORDER_ROW)
|
|
mock_db.fetch = AsyncMock(return_value=[]) # order items
|
|
|
|
r = await auth_client.get(f"/api/v1/orders/{ORDER_ID}")
|
|
assert r.status_code == 200
|
|
|
|
|
|
async def test_get_order_not_found(auth_client, mock_db):
|
|
mock_db.fetchrow = AsyncMock(return_value=None)
|
|
r = await auth_client.get(f"/api/v1/orders/00000000-0000-0000-0000-000000000000")
|
|
assert r.status_code == 404
|
|
|
|
|
|
# ── Admin order management ────────────────────────────────────────────────────
|
|
|
|
async def test_admin_list_orders(admin_client, mock_db):
|
|
mock_db.fetchval = AsyncMock(return_value=1)
|
|
mock_db.fetch = AsyncMock(return_value=[SAMPLE_ORDER_ROW])
|
|
|
|
r = await admin_client.get("/api/v1/admin/orders")
|
|
assert r.status_code == 200
|
|
|
|
|
|
async def test_admin_update_order_status(admin_client, mock_db):
|
|
updated = {**SAMPLE_ORDER_ROW, "status": "shipped"}
|
|
mock_db.fetchrow = AsyncMock(return_value=updated)
|
|
mock_db.execute = AsyncMock(return_value="INSERT 1")
|
|
|
|
r = await admin_client.patch(f"/api/v1/admin/orders/{ORDER_ID}/status", json={"status": "shipped"})
|
|
assert r.status_code == 200
|
|
assert r.json()["data"]["status"] == "shipped"
|
|
|
|
|
|
async def test_admin_update_order_invalid_status(admin_client):
|
|
r = await admin_client.patch(f"/api/v1/admin/orders/{ORDER_ID}/status", json={"status": "exploded"})
|
|
assert r.status_code == 422
|