158 lines
5.0 KiB
Python
158 lines
5.0 KiB
Python
"""T6.3 用户管理端点测试。
|
|
|
|
覆盖:
|
|
- 鉴权: /api/admin/users 与 /api/admin/users/{user_key} 401
|
|
- 列表: 按用户聚合、分页骨架、遮罩展示
|
|
- 搜索: 支持手机号 / 姓名关键字
|
|
- 详情: 返回该用户的订单明细,且敏感字段保持遮罩
|
|
- 未命中: 404
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from data.orders.dao import OrdersDAO
|
|
from data.orders.models import Order, generate_order_id
|
|
|
|
|
|
os.environ.setdefault("GAOKAO_ORDERS_FERNET_KEY", "test-secret-for-admin-users")
|
|
|
|
|
|
def _iso_at(dt: datetime) -> str:
|
|
return dt.replace(microsecond=0).isoformat()
|
|
|
|
|
|
def _seed_users(db_path: str) -> None:
|
|
now = datetime.now(timezone.utc).replace(microsecond=0, hour=12, minute=0, second=0)
|
|
with OrdersDAO.connect(db_path) as dao:
|
|
dao.create(
|
|
Order(
|
|
id=generate_order_id(),
|
|
source="web",
|
|
service_version="basic",
|
|
amount_cents=9900,
|
|
status="pending",
|
|
customer_name="李明",
|
|
customer_phone="13800001234",
|
|
customer_wechat="wx-li",
|
|
candidate_name="李小明",
|
|
candidate_id_card="430102200501011234",
|
|
candidate_province="湖南",
|
|
created_at=_iso_at(now - timedelta(days=1)),
|
|
)
|
|
)
|
|
dao.create(
|
|
Order(
|
|
id=generate_order_id(),
|
|
source="wechat",
|
|
service_version="standard",
|
|
amount_cents=12900,
|
|
status="paid",
|
|
customer_name="李明",
|
|
customer_phone="13800001234",
|
|
customer_wechat="wx-li",
|
|
candidate_name="李小明",
|
|
candidate_id_card="430102200501011234",
|
|
candidate_province="湖南",
|
|
created_at=_iso_at(now),
|
|
)
|
|
)
|
|
dao.create(
|
|
Order(
|
|
id=generate_order_id(),
|
|
source="xianyu",
|
|
service_version="premium",
|
|
amount_cents=15900,
|
|
status="serving",
|
|
customer_name="王芳",
|
|
customer_phone="13911112222",
|
|
customer_wechat="wx-wang",
|
|
candidate_name="王小芳",
|
|
candidate_id_card="430102200601019876",
|
|
candidate_province="浙江",
|
|
created_at=_iso_at(now - timedelta(days=2)),
|
|
)
|
|
)
|
|
|
|
|
|
def test_users_requires_auth(client):
|
|
resp = client.get("/api/admin/users")
|
|
assert resp.status_code == 401
|
|
|
|
|
|
def test_users_list_groups_and_masks_pii(client, auth_headers, settings):
|
|
_seed_users(settings.orders_db_path)
|
|
|
|
resp = client.get("/api/admin/users", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
|
|
assert body["total"] == 2
|
|
assert body["limit"] == 50
|
|
assert body["offset"] == 0
|
|
assert body["query"] is None
|
|
assert len(body["items"]) == 2
|
|
|
|
li = next(item for item in body["items"] if item["customer_phone"] == "138****1234")
|
|
assert li["customer_name"] == "李*"
|
|
assert li["customer_wechat"] == "wx*li"
|
|
assert li["candidate_name"] == "李*明"
|
|
assert li["order_count"] == 2
|
|
assert li["latest_status"] == "paid"
|
|
assert li["total_amount_cents"] == 22800
|
|
assert li["latest_order_at"]
|
|
|
|
|
|
def test_users_search_by_phone_and_name(client, auth_headers, settings):
|
|
_seed_users(settings.orders_db_path)
|
|
|
|
by_phone = client.get(
|
|
"/api/admin/users",
|
|
params={"q": "13800001234"},
|
|
headers=auth_headers,
|
|
)
|
|
assert by_phone.status_code == 200
|
|
body = by_phone.json()
|
|
assert body["total"] == 1
|
|
assert len(body["items"]) == 1
|
|
assert body["items"][0]["customer_phone"] == "138****1234"
|
|
|
|
by_name = client.get(
|
|
"/api/admin/users",
|
|
params={"q": "王芳"},
|
|
headers=auth_headers,
|
|
)
|
|
assert by_name.status_code == 200
|
|
body = by_name.json()
|
|
assert body["total"] == 1
|
|
assert body["items"][0]["customer_name"] == "王*"
|
|
|
|
|
|
def test_user_detail_returns_masked_orders(client, auth_headers, settings):
|
|
_seed_users(settings.orders_db_path)
|
|
|
|
listed = client.get("/api/admin/users", headers=auth_headers)
|
|
user_key = next(
|
|
item["user_key"] for item in listed.json()["items"] if item["order_count"] == 2
|
|
)
|
|
|
|
resp = client.get(f"/api/admin/users/{user_key}", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
|
|
assert body["user_key"] == user_key
|
|
assert body["order_count"] == 2
|
|
assert len(body["orders"]) == 2
|
|
assert all(order["customer_phone"] == "138****1234" for order in body["orders"])
|
|
assert all(order["customer_wechat"] == "wx*li" for order in body["orders"])
|
|
assert all(
|
|
order["candidate_id_card"] == "430102********1234" for order in body["orders"]
|
|
)
|
|
|
|
|
|
def test_user_detail_404_for_unknown(client, auth_headers):
|
|
resp = client.get("/api/admin/users/unknown-key", headers=auth_headers)
|
|
assert resp.status_code == 404
|