Files
WonderQ-Project/WonderQ-Admin/tests/test_concierge.py
duanshuwen 7ba92f3c5d feat: 新增客片案例与团队共创模块,重构玩法与配置
- 新增客片案例全流程功能,包含前台页面、管理端配置、后端API、数据库迁移与文档
- 新增团队共创详情页面与对应接口
- 重构玩法模块:将静态playData替换为动态API获取,拆分类型定义到playTypes.ts
- 优化vite构建配置与环境变量处理,调整详情页操作栏文案
- 更新全量相关文档与配图,新增客片案例、团队共创API文档
- 新增测试用例,完善数据归一化逻辑
- 调整路由配置与环境变量示例文件
2026-08-19 20:23:04 +08:00

259 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from datetime import datetime
import pytest
from fastapi.testclient import TestClient
from pydantic import ValidationError
from app.auth import require_admin
from app.database import get_db
from app.main import create_app
from app.models import AdminUser, ConciergeAdvisor
from app.schemas import ConciergeAdvisorCreate
class FakeScalarResult:
def __init__(self, items):
self.items = items
def all(self):
return self.items
class FakeDb:
def __init__(self, *, items=None, scalar_values=None):
self.items = list(items or [])
self.scalar_values = list(scalar_values or [])
self.scalar_statements = []
self.added = []
self.deleted = []
self.committed = False
def scalars(self, statement):
self.scalar_statements.append(statement)
return FakeScalarResult(self.items)
def scalar(self, _statement):
return self.scalar_values.pop(0) if self.scalar_values else None
def get(self, model, item_id):
return next((item for item in self.items if isinstance(item, model) and item.id == item_id), None)
def add(self, item):
self.added.append(item)
if isinstance(item, ConciergeAdvisor):
self.items.append(item)
def delete(self, item):
self.deleted.append(item)
if item in self.items:
self.items.remove(item)
def flush(self):
for item in self.added:
if not getattr(item, "id", None):
item.id = "concierge-advisor-test-id"
def commit(self):
self.committed = True
def make_admin_user():
return AdminUser(
id="admin-test",
email="admin@example.test",
name="Admin",
role="admin",
passwordHash="not-used",
isActive=True,
)
def make_advisor(**overrides):
return ConciergeAdvisor(
id=overrides.get("id", "advisor-amanda"),
avatar=overrides.get("avatar", "https://example.test/amanda.jpg"),
name=overrides.get("name", "Amanda"),
role=overrides.get("role", "SENIOR TRAVEL ADVISOR"),
details=overrides.get(
"details",
[
{"icon": "calendar", "label": "服务经验:8年"},
{"icon": "navigate", "label": "擅长领域:瀑降 / 探洞"},
],
),
qrImage=overrides.get("qrImage", "https://example.test/amanda-qr.png"),
isActive=overrides.get("isActive", True),
sortOrder=overrides.get("sortOrder", 0),
createdAt=datetime(2026, 1, 1),
updatedAt=datetime(2026, 1, 2),
)
def admin_app(fake_db):
app = create_app()
app.dependency_overrides[get_db] = lambda: fake_db
app.dependency_overrides[require_admin] = make_admin_user
return app
def test_concierge_schema_normalizes_nested_details():
advisor = ConciergeAdvisorCreate(
avatar=" https://example.test/avatar.jpg ",
name=" Amanda ",
role=" SENIOR TRAVEL ADVISOR ",
details=[{"icon": " calendar ", "label": " 服务经验:8年 "}],
qrImage=" https://example.test/qr.png ",
)
assert advisor.avatar == "https://example.test/avatar.jpg"
assert advisor.name == "Amanda"
assert advisor.details == [{"icon": "calendar", "label": "服务经验:8年"}]
assert advisor.sortOrder is None
def test_concierge_schema_rejects_empty_detail_label():
with pytest.raises(ValidationError):
ConciergeAdvisorCreate(
avatar="https://example.test/avatar.jpg",
name="Amanda",
role="SENIOR TRAVEL ADVISOR",
details=[{"icon": "calendar", "label": " "}],
qrImage="https://example.test/qr.png",
)
def test_concierge_schema_rejects_invalid_image_url():
with pytest.raises(ValidationError):
ConciergeAdvisorCreate(
avatar="/avatar.jpg",
name="Amanda",
role="SENIOR TRAVEL ADVISOR",
details=[],
qrImage="https://example.test/qr.png",
)
def test_admin_concierge_list_returns_full_advisor_record():
fake_db = FakeDb(items=[make_advisor()])
app = admin_app(fake_db)
try:
response = TestClient(app).get("/api/admin/concierge/advisors")
finally:
app.dependency_overrides.clear()
assert response.status_code == 200
advisor = response.json()["advisors"][0]
assert advisor["id"] == "advisor-amanda"
assert advisor["isActive"] is True
assert advisor["sortOrder"] == 0
assert advisor["details"][0] == {"icon": "calendar", "label": "服务经验:8年"}
assert advisor["createdAt"] == "2026-01-01T00:00:00"
def test_admin_concierge_create_appends_to_the_end():
fake_db = FakeDb(scalar_values=[2])
app = admin_app(fake_db)
try:
response = TestClient(app).post(
"/api/admin/concierge/advisors",
json={
"avatar": " https://example.test/mia.jpg ",
"name": " Mia ",
"role": "LIFESTYLE TRAVEL ADVISOR",
"details": [],
"qrImage": "https://example.test/mia-qr.png",
},
)
finally:
app.dependency_overrides.clear()
assert response.status_code == 201
assert response.json()["id"] == "concierge-advisor-test-id"
assert fake_db.added[0].name == "Mia"
assert fake_db.added[0].sortOrder == 3
assert fake_db.committed
def test_admin_concierge_patch_updates_details_and_active_state():
advisor = make_advisor()
fake_db = FakeDb(items=[advisor])
app = admin_app(fake_db)
try:
response = TestClient(app).patch(
"/api/admin/concierge/advisors/advisor-amanda",
json={"details": [{"icon": "navigate", "label": "擅长领域:亲子与自然探索"}], "isActive": False},
)
finally:
app.dependency_overrides.clear()
assert response.status_code == 200
assert response.json()["details"] == [{"icon": "navigate", "label": "擅长领域:亲子与自然探索"}]
assert response.json()["isActive"] is False
assert advisor.isActive is False
assert fake_db.committed
def test_admin_concierge_delete_normalizes_remaining_order():
first = make_advisor(id="advisor-1", sortOrder=0)
second = make_advisor(id="advisor-2", name="Mia", sortOrder=1)
fake_db = FakeDb(items=[first, second])
app = admin_app(fake_db)
try:
response = TestClient(app).delete("/api/admin/concierge/advisors/advisor-1")
finally:
app.dependency_overrides.clear()
assert response.status_code == 200
assert response.json() == {"id": "advisor-1"}
assert second.sortOrder == 0
assert fake_db.deleted == [first]
assert fake_db.committed
def test_admin_concierge_reorder_rejects_incomplete_ids():
fake_db = FakeDb(items=[make_advisor(id="advisor-1"), make_advisor(id="advisor-2", name="Mia", sortOrder=1)])
app = admin_app(fake_db)
try:
response = TestClient(app).patch(
"/api/admin/concierge/advisors/reorder",
json={"itemIds": ["advisor-1"]},
)
finally:
app.dependency_overrides.clear()
assert response.status_code == 400
assert response.json()["code"] == "CONCIERGE_REORDER_INVALID"
assert not fake_db.committed
def test_public_concierge_returns_only_frontend_fields_for_active_advisors():
fake_db = FakeDb(items=[make_advisor()])
app = create_app()
app.dependency_overrides[get_db] = lambda: fake_db
try:
response = TestClient(app).get("/api/public/concierge/advisors")
finally:
app.dependency_overrides.clear()
assert response.status_code == 200
assert response.json() == {
"advisors": [
{
"avatar": "https://example.test/amanda.jpg",
"name": "Amanda",
"role": "SENIOR TRAVEL ADVISOR",
"details": [
{"icon": "calendar", "label": "服务经验:8年"},
{"icon": "navigate", "label": "擅长领域:瀑降 / 探洞"},
],
"qrImage": "https://example.test/amanda-qr.png",
}
]
}