Files
danyang-match/tests/e2e/referral_v11_test.py
T

146 lines
4.9 KiB
Python

"""
E2E 测试:Phase 13 - 红娘服务转介
验证 INV-005(红娘不可代用户操作)及转介追踪链路
"""
import os
import pytest
import requests
BASE_URL = "http://localhost:8085/api/v1"
E2E_PASSWORD = os.environ["E2E_PASSWORD"]
E2E_USER_TOKEN = os.environ["E2E_USER_TOKEN"]
E2E_DB_PASSWORD = os.environ["E2E_DB_PASSWORD"]
# ---- 工具函数 ----
def get_user_token():
return E2E_USER_TOKEN
def get_matchmaker_token():
r = requests.post(f"{BASE_URL}/auth/operator/login", json={"username": "mm001", "password": E2E_PASSWORD})
return r.json()["data"]["accessToken"]
def auth_header(token):
return {"Authorization": f"Bearer {token}"}
# ---- P13-T05: 转介确认后激活 ----
def test_referral_requires_user_confirmation():
"""红娘转介后,预约状态为 submitted,需用户 confirm 后才变为 pending_confirmation"""
user_token = get_user_token()
mm_token = get_matchmaker_token()
# 红娘创建转介预约
r = requests.post(
f"{BASE_URL}/referrals/service-station",
headers=auth_header(mm_token),
json={"userId": "user-test-001", "locationId": "loc-001", "serviceType": "counselor_consultation"}
)
assert r.status_code == 200
appt_id = r.json()["data"]["appointmentId"]
assert r.json()["data"]["status"] == "submitted"
assert r.json()["data"]["needsUserConfirmation"] is True
# 用户确认
r2 = requests.post(
f"{BASE_URL}/referrals/{appt_id}/confirm",
headers=auth_header(user_token),
json={"targetType": "service_station"}
)
assert r2.status_code == 200
assert r2.json()["data"]["status"] == "pending_confirmation"
# ---- P13-T02: 转介活动 ----
def test_matchmaker_refers_activity():
"""红娘转介用户到公益活动,需用户确认"""
user_token = get_user_token()
mm_token = get_matchmaker_token()
r = requests.post(
f"{BASE_URL}/referrals/activity",
headers=auth_header(mm_token),
json={"userId": "user-test-001", "activityId": "act-001",
"emergencyContactName": "张某某", "emergencyContactPhoneEnc": "enc123"}
)
assert r.status_code == 200
reg_id = r.json()["data"]["registrationId"]
assert r.json()["data"]["referralType"] == "activity"
assert r.json()["data"]["needsUserConfirmation"] is True
# 用户确认
r2 = requests.post(
f"{BASE_URL}/referrals/{reg_id}/confirm",
headers=auth_header(user_token),
json={"targetType": "activity"}
)
assert r2.status_code == 200
# ---- P13-T04: 转介历史查询 ----
def test_referral_history():
"""查询用户的转介历史记录"""
user_token = get_user_token()
r = requests.get(f"{BASE_URL}/referrals/my-history", headers=auth_header(user_token))
assert r.status_code == 200
history = r.json()["data"]
assert isinstance(history, list)
# ---- INV-005: 红娘不能确认用户的转介 ----
def test_matchmaker_cannot_confirm_for_user():
"""INV-005: 红娘不能替用户确认转介,必须用户自己确认"""
mm_token = get_matchmaker_token()
# 红娘尝试确认(应该失败)
r = requests.post(
f"{BASE_URL}/referrals/some-id/confirm",
headers=auth_header(mm_token),
json={"targetType": "service_station"}
)
# 非对应用户ID,应返回 403 或 404
assert r.status_code in (400, 403, 404)
# ---- INV-005: 红娘不能取消用户的转介 ----
def test_matchmaker_cannot_cancel_for_user():
"""红娘不能取消用户的预约,只能用户自己取消"""
mm_token = get_matchmaker_token()
r = requests.post(
f"{BASE_URL}/service-appointments/some-id/cancel",
headers=auth_header(mm_token),
json={"reason": "测试取消"}
)
assert r.status_code in (400, 403, 404)
# ---- 转介来源追踪验证 ----
def test_referral_source_tracking():
"""验证转介时 source 字段正确设置"""
mm_token = get_matchmaker_token()
r = requests.post(
f"{BASE_URL}/referrals/service-station",
headers=auth_header(mm_token),
json={"userId": "user-test-001", "locationId": "loc-001", "serviceType": "station_visit"}
)
assert r.status_code == 200
appt_id = r.json()["data"]["appointmentId"]
# 查询预约详情,验证 source
r2 = requests.get(f"{BASE_URL}/service-appointments/{appt_id}",
headers=auth_header("Bearer dummy"))
# 通过数据库直接验证 source 字段
import psycopg2
conn = psycopg2.connect(f"dbname=danyang_match user=postgres password={E2E_DB_PASSWORD} host=localhost port=5434")
cur = conn.cursor()
cur.execute("SELECT source, request_source, created_by_operator_id FROM service_appointments WHERE id = %s", (appt_id,))
row = cur.fetchone()
assert row[0] == "matchmaker_referral"
assert row[1] == "matchmaker_referral"
assert row[2] is not None
cur.close()
conn.close()
if __name__ == "__main__":
pytest.main([__file__, "-v"])