dingdanquanliucheng/backend/tests/test_products.py
2026-06-14 16:20:04 +08:00

135 lines
4.9 KiB
Python

"""PROD-001 ~ PROD-008: 产品与产品分类管理测试。
覆盖功能点:
- 产品分类 CRUD
- 产品 CRUD
- 产品状态校验
"""
from __future__ import annotations
import pytest
@pytest.mark.product
@pytest.mark.p1
class TestProductCategory:
"""PROD-001 ~ PROD-003: 产品分类测试。"""
def test_create_category_success(self, client, admin_headers):
"""PROD-001: 新增产品分类成功。"""
resp = client.post("/api/product-categories", headers=admin_headers, json={
"category_name": "测试分类",
"category_code": "TEST_CAT_001",
"sort_no": 1,
})
assert resp.status_code == 200
data = resp.json()
assert data["code"] == 0
def test_duplicate_category_code(self, client, admin_headers, db_session):
"""PROD-002: 分类编码重复应返回 40006。"""
from backend.app.models.business import ProductCategory
cat = ProductCategory(category_name="已有分类", category_code="EXISTING_CODE", status=1)
db_session.add(cat)
db_session.flush()
resp = client.post("/api/product-categories", headers=admin_headers, json={
"category_name": "新分类",
"category_code": "EXISTING_CODE",
})
assert resp.status_code in (400, 409)
def test_disable_category(self, client, admin_headers, db_session):
"""PROD-003: 停用分类。"""
from backend.app.models.business import ProductCategory
cat = ProductCategory(category_name="待停用", category_code="TO_DISABLE", status=1)
db_session.add(cat)
db_session.flush()
resp = client.put(f"/api/product-categories/{cat.id}", headers=admin_headers, json={
"category_name": "待停用",
"category_code": "TO_DISABLE",
"status": 0,
})
assert resp.status_code == 200
@pytest.mark.product
@pytest.mark.p1
class TestProduct:
"""PROD-004 ~ PROD-008: 产品测试。"""
def test_create_product_success(self, client, admin_headers, db_session):
"""PROD-004: 新增产品成功。
注意: CreateProductRequest 需要 specifications 列表(至少一个规格)
"""
from backend.app.models.business import ProductCategory
cat = ProductCategory(category_name="产品测试分类", category_code="PROD_TEST_CAT", status=1)
db_session.add(cat)
db_session.flush()
resp = client.post("/api/products", headers=admin_headers, json={
"product_name": "测试产品X",
"category_id": cat.id,
"specifications": [{
"specification": "100x100cm",
"unit": "",
"cost_price": 50,
"sale_price": 100,
}],
})
assert resp.status_code == 200
data = resp.json()
assert data["code"] == 0
def test_product_list_filter(self, client, admin_headers, make_product):
"""PROD-005: 产品列表筛选。"""
make_product(product_name="铝板产品")
make_product(product_name="钢材产品")
resp = client.get("/api/products?keyword=铝板", headers=admin_headers)
assert resp.status_code == 200
def test_product_detail(self, client, admin_headers, make_product):
"""PROD-006: 产品详情。"""
product = make_product()
resp = client.get(f"/api/products/{product.id}", headers=admin_headers)
assert resp.status_code == 200
data = resp.json()["data"]
assert data["product_name"] is not None
def test_disabled_product_flag(self, client, admin_headers, make_product):
"""PROD-007: 禁用产品标识。"""
product = make_product(status=0)
resp = client.get(f"/api/products/{product.id}", headers=admin_headers)
assert resp.status_code == 200
# 产品详情接口可能过滤已删除(deleted=1)的产品,但 status=0 的产品应该能查到
data = resp.json()["data"]
# 确认返回的是该产品
assert data["product_name"] == product.product_name
@pytest.mark.product
@pytest.mark.p0
class TestProductOrderConstraint:
"""PROD-007: 禁用产品下单约束测试。"""
def test_disabled_product_cannot_order(self, client, salesman_headers, make_product):
"""PROD-007: 禁用产品不能创建订单。"""
product = make_product(status=0)
resp = client.post("/api/orders", headers=salesman_headers, json={
"customer_name": "禁用产品测试客户",
"customer_mobile": "1380000P007",
"items": [{
"product_id": product.id,
"product_name": product.product_name,
"specification": product.specification,
"unit": product.unit,
"quantity": 1,
"sale_price": 100,
"cost_price": 60,
}],
})
# 应被拒绝或有警告
assert resp.status_code in (400, 200)