- Update E2E tests: announcements, auth, auth-business-flow, full-route-regression, grades, navigation, smoke-auth, teacher-web-test - Update integration tests: api-ai-chat, api-onboarding-complete, api-onboarding-status, proxy-guard, integration setup - Update visual regression tests: admin-dashboard, homepage, student-dashboard, teacher-dashboard, visual config, helpers - Update webapp tests: admin, parent, student full tests and debug scripts - Add new webapp tests: announcements_messages, settings_profile, debug scripts - Add webtest directory with test plans, screenshots, and diagnostic scripts
105 lines
3.6 KiB
Python
105 lines
3.6 KiB
Python
"""直接访问页面并捕获服务端错误"""
|
|
import re
|
|
import urllib.request
|
|
import urllib.error
|
|
import http.cookiejar
|
|
|
|
BASE_URL = "http://localhost:3000"
|
|
|
|
# 创建 cookie jar
|
|
cookie_jar = http.cookiejar.CookieJar()
|
|
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie_jar))
|
|
|
|
# 1. 获取 CSRF token
|
|
print(">>> 获取 CSRF token...")
|
|
try:
|
|
resp = opener.open(f"{BASE_URL}/api/auth/csrf", timeout=10)
|
|
csrf_data = resp.read().decode()
|
|
print(f"CSRF 响应: {csrf_data[:200]}")
|
|
import json
|
|
csrf_json = json.loads(csrf_data)
|
|
csrf_token = csrf_json.get("csrfToken", "")
|
|
print(f"CSRF token: {csrf_token[:20]}...")
|
|
except Exception as e:
|
|
print(f"获取 CSRF 失败: {e}")
|
|
exit(1)
|
|
|
|
# 2. 登录
|
|
print("\n>>> 登录...")
|
|
login_data = urllib.parse.urlencode({
|
|
"email": "t_chinese_1@xiaoxue.edu.cn",
|
|
"password": "123456",
|
|
"csrfToken": csrf_token,
|
|
"callbackUrl": "/teacher/dashboard",
|
|
"json": "true",
|
|
}).encode()
|
|
|
|
try:
|
|
req = urllib.request.Request(
|
|
f"{BASE_URL}/api/auth/callback/credentials",
|
|
data=login_data,
|
|
method="POST",
|
|
)
|
|
resp = opener.open(req, timeout=15)
|
|
print(f"登录响应状态: {resp.status}")
|
|
print(f"登录响应 URL: {resp.url}")
|
|
except urllib.error.HTTPError as e:
|
|
print(f"登录 HTTP 错误: {e.code} {e.reason}")
|
|
body = e.read().decode()
|
|
print(f"响应: {body[:500]}")
|
|
except Exception as e:
|
|
print(f"登录失败: {e}")
|
|
|
|
# 3. 访问备课列表页
|
|
print("\n>>> 访问 /teacher/lesson-plans...")
|
|
try:
|
|
req = urllib.request.Request(f"{BASE_URL}/teacher/lesson-plans")
|
|
resp = opener.open(req, timeout=30)
|
|
body = resp.read().decode()
|
|
print(f"HTTP 状态: {resp.status}")
|
|
print(f"响应长度: {len(body)}")
|
|
|
|
# 找到错误消息
|
|
error_messages = re.findall(r'data-next-error-message="([^"]+)"', body)
|
|
if error_messages:
|
|
print(f"\n=== 错误消息 ({len(error_messages)} 条) ===")
|
|
for msg in error_messages:
|
|
msg = msg.replace("<", "<").replace(">", ">").replace(""", '"').replace("'", "'").replace("&", "&")
|
|
print(f"\n{msg[:2000]}")
|
|
|
|
# 找到错误堆栈
|
|
error_stacks = re.findall(r'data-next-error-stack="([^"]+)"', body)
|
|
if error_stacks:
|
|
print(f"\n=== 错误堆栈 ===")
|
|
for stack in error_stacks[:1]:
|
|
stack = stack.replace("<", "<").replace(">", ">").replace(""", '"').replace("'", "'").replace("&", "&")
|
|
print(stack[:5000])
|
|
else:
|
|
# 输出前 2000 字符
|
|
print(f"\n响应前 2000 字符:\n{body[:2000]}")
|
|
|
|
except urllib.error.HTTPError as e:
|
|
print(f"HTTP 错误: {e.code} {e.reason}")
|
|
body = e.read().decode()
|
|
print(f"响应长度: {len(body)}")
|
|
|
|
# 找到错误消息
|
|
error_messages = re.findall(r'data-next-error-message="([^"]+)"', body)
|
|
if error_messages:
|
|
print(f"\n=== 错误消息 ({len(error_messages)} 条) ===")
|
|
for msg in error_messages:
|
|
msg = msg.replace("<", "<").replace(">", ">").replace(""", '"').replace("'", "'").replace("&", "&")
|
|
print(f"\n{msg[:2000]}")
|
|
|
|
# 找到错误堆栈
|
|
error_stacks = re.findall(r'data-next-error-stack="([^"]+)"', body)
|
|
if error_stacks:
|
|
print(f"\n=== 错误堆栈 ===")
|
|
for stack in error_stacks[:1]:
|
|
stack = stack.replace("<", "<").replace(">", ">").replace(""", '"').replace("'", "'").replace("&", "&")
|
|
print(stack[:5000])
|
|
else:
|
|
print(f"\n响应前 2000 字符:\n{body[:2000]}")
|
|
except Exception as e:
|
|
print(f"访问失败: {e}")
|