#!/usr/bin/env python3 """ SSE通知功能集成测试脚本 验证前端页面是否能正确接收和处理积分变动通知 """ import requests import json import time from datetime import datetime # 配置 BASE_URL = "http://localhost:5000" ADMIN_EMAIL = "admin@example.com" ADMIN_PASSWORD = "Admin123!" def log_step(step_num, description, status="INFO"): """记录测试步骤""" timestamp = datetime.now().strftime("%H:%M:%S") status_icon = { "PASS": "✅", "FAIL": "❌", "INFO": "ℹ️", "WARN": "⚠️" } print(f"[{timestamp}] {status_icon.get(status, 'ℹ️')} 步骤 {step_num}: {description}") def get_admin_token(): """获取管理员token""" try: response = requests.post( f"{BASE_URL}/api/admins/login", json={ "email": ADMIN_EMAIL, "password": ADMIN_PASSWORD } ) if response.status_code == 200: data = response.json() return data.get('data', {}).get('token') return None except Exception as e: print(f"获取token失败: {e}") return None def create_test_member(admin_token): """创建测试会员""" try: response = requests.post( f"{BASE_URL}/api/members", headers={"Authorization": f"Bearer {admin_token}"}, json={ "phone": f"13800138{int(time.time()) % 10000:04d}", "nickname": f"测试用户{int(time.time()) % 1000}", "initialPoints": 1000 } ) if response.status_code == 200: data = response.json() member_id = data.get('data', {}).get('id') log_step(1, f"创建测试会员成功: {member_id}", "PASS") return member_id else: log_step(1, f"创建测试会员失败: {response.text}", "FAIL") return None except Exception as e: log_step(1, f"创建测试会员异常: {e}", "FAIL") return None def get_member_token(member_id): """模拟会员登录获取token""" try: # 这里简化处理,实际应该有会员登录接口 # 暂时返回None,因为我们主要测试SSE通知机制 log_step(2, "获取会员token (简化处理)", "INFO") return "test_member_token" except Exception as e: log_step(2, f"获取会员token失败: {e}", "FAIL") return None def trigger_points_event(admin_token, member_id, event_type, amount): """触发积分事件""" try: event_mapping = { "earned": "PointsEarnedSuccess", "consumed": "PointsConsumed", "expired": "PointsExpired", "refunded": "PointsRefunded" } event_data = { "memberId": member_id, "amount": amount, "relatedId": f"test_{int(time.time())}", "source": "测试系统" } if event_type == "consumed": event_data["reason"] = "测试消费" event_data["orderId"] = f"order_{int(time.time())}" response = requests.post( f"{BASE_URL}/api/test/trigger-points-event", headers={"Authorization": f"Bearer {admin_token}"}, json={ "eventType": event_mapping[event_type], "eventData": event_data } ) if response.status_code == 200: log_step(3, f"触发积分{event_type}事件成功: {amount}积分", "PASS") return True else: # 如果测试接口不存在,尝试直接调用积分API log_step(3, f"触发积分{event_type}事件失败,尝试备用方案", "WARN") return trigger_points_via_api(admin_token, member_id, event_type, amount) except Exception as e: log_step(3, f"触发积分事件异常: {e}", "FAIL") return False def trigger_points_via_api(admin_token, member_id, event_type, amount): """通过API触发积分变动""" try: if event_type == "earned": # 通过营销码扫码获得积分 response = requests.post( f"{BASE_URL}/api/marketing-codes/mock-scan", headers={"Authorization": f"Bearer {admin_token}"}, json={ "memberId": member_id, "points": amount } ) elif event_type == "consumed": # 通过创建兑换订单消费积分 response = requests.post( f"{BASE_URL}/api/redemption-orders/mock-consume", headers={"Authorization": f"Bearer {admin_token}"}, json={ "memberId": member_id, "points": amount, "reason": "测试消费" } ) else: log_step(3, f"暂不支持的事件类型: {event_type}", "WARN") return True if response.status_code in [200, 201]: log_step(3, f"通过API触发积分{event_type}成功: {amount}积分", "PASS") return True else: log_step(3, f"通过API触发积分{event_type}失败: {response.text}", "FAIL") return False except Exception as e: log_step(3, f"通过API触发积分事件异常: {e}", "FAIL") return False def verify_frontend_updates(): """验证前端页面更新(模拟)""" log_step(4, "验证前端SSE通知接收", "INFO") print(" 请在前端页面观察以下变化:") print(" - 首页: 积分余额应该自动更新") print(" - 积分明细: 应该显示新的积分记录") print(" - 个人中心: 积分信息应该同步更新") print(" - 购物车/结算页面: 可用积分应该更新") print(" - 通知气泡: 应该显示积分变动提醒") input(" 手动验证完成后按回车继续...") def test_sse_connection(): """测试SSE连接""" log_step(5, "测试SSE连接建立", "INFO") print(" 请在浏览器开发者工具中检查:") print(" - Network标签页应该显示到/api/notifications/sse的连接") print(" - 连接状态应该是CONNECTED") print(" - 应该定期收到心跳消息") input(" 连接验证完成后按回车继续...") def main(): """主测试流程""" print("=" * 60) print("SSE通知功能集成测试") print("=" * 60) # 步骤1: 获取管理员权限 log_step(0, "获取管理员权限") admin_token = get_admin_token() if not admin_token: log_step(0, "无法获取管理员权限,测试终止", "FAIL") return # 步骤2: 创建测试会员 member_id = create_test_member(admin_token) if not member_id: return # 步骤3: 测试各种积分事件 events_to_test = [ ("earned", 100), ("consumed", 50), ("earned", 200), ("expired", 10) ] for event_type, amount in events_to_test: print(f"\n--- 测试积分{event_type}事件 ---") success = trigger_points_event(admin_token, member_id, event_type, amount) if success: # 等待一段时间让前端处理通知 time.sleep(3) verify_frontend_updates() else: log_step(3, f"积分{event_type}事件测试失败", "FAIL") # 步骤4: 测试SSE连接 print(f"\n--- SSE连接测试 ---") test_sse_connection() # 步骤5: 总结 print("\n" + "=" * 60) print("测试完成!") print("请检查前端页面是否正确显示了所有积分变动通知") print("确保通知气泡正常显示且页面数据及时更新") print("=" * 60) if __name__ == "__main__": main()