- Remove temp-i18n-zh-fix.mjs, test-failing-modules.py, test-teacher-pages.py - Add check-attendance-rules.mjs, check-db-state.mjs, test-modules.py
112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
"""
|
||
验证 6 个模块的页面是否能正常加载。
|
||
检测方式:
|
||
1. HTTP 状态码(非 200 即失败)
|
||
2. JavaScript pageerror
|
||
3. 可见错误边界元素([data-error-boundary], [role="alert"] 中的错误文本)
|
||
注意:不检查 content 中的 i18n 文本(翻译 JSON 会被误判)
|
||
"""
|
||
import sys
|
||
from playwright.sync_api import sync_playwright
|
||
|
||
BASE = "http://localhost:3000"
|
||
EMAIL = "t_chinese_1@xiaoxue.edu.cn"
|
||
PASSWORD = "123456"
|
||
|
||
MODULES = [
|
||
("考勤统计", "/teacher/attendance/stats"),
|
||
("学情诊断", "/teacher/diagnostic"),
|
||
("错题分析", "/teacher/error-book"),
|
||
("选修课", "/teacher/elective"),
|
||
("公告", "/announcements"),
|
||
("消息", "/messages"),
|
||
]
|
||
|
||
|
||
def login(page):
|
||
page.goto(f"{BASE}/login", wait_until="domcontentloaded", timeout=15000)
|
||
page.wait_for_timeout(1000)
|
||
|
||
email_input = page.locator('input[type="email"]')
|
||
if email_input.count() == 0:
|
||
email_input = page.locator('input[name="email"]')
|
||
email_input.fill(EMAIL)
|
||
|
||
pwd_input = page.locator('input[type="password"]')
|
||
pwd_input.fill(PASSWORD)
|
||
|
||
page.get_by_role("button", name="登录").click()
|
||
page.wait_for_url("**/dashboard**", timeout=15000)
|
||
page.wait_for_timeout(2000)
|
||
|
||
|
||
def main():
|
||
results = []
|
||
with sync_playwright() as p:
|
||
browser = p.chromium.launch(headless=True)
|
||
|
||
page = browser.new_page()
|
||
all_errors = []
|
||
page.on("pageerror", lambda err: all_errors.append(str(err)[:300]))
|
||
|
||
print("登录中...")
|
||
login(page)
|
||
print(f"登录成功,URL: {page.url}")
|
||
|
||
for name, path in MODULES:
|
||
url = f"{BASE}{path}"
|
||
all_errors.clear()
|
||
|
||
try:
|
||
response = page.goto(url, wait_until="domcontentloaded", timeout=30000)
|
||
page.wait_for_timeout(4000)
|
||
|
||
http_status = response.status if response else 0
|
||
|
||
# 检查可见错误边界(排除 i18n JSON 文本)
|
||
# 只查找实际渲染的错误提示元素
|
||
visible_error = ""
|
||
error_locators = [
|
||
'text="发生未知错误"',
|
||
'text="Something went wrong"',
|
||
'[data-error-boundary]',
|
||
]
|
||
for sel in error_locators:
|
||
loc = page.locator(sel).first
|
||
if loc.count() > 0 and loc.is_visible():
|
||
visible_error = sel
|
||
break
|
||
|
||
status = "FAIL"
|
||
error_info = ""
|
||
if http_status != 200:
|
||
status = "FAIL"
|
||
error_info = f"HTTP {http_status}"
|
||
elif len(all_errors) > 0:
|
||
status = "FAIL"
|
||
error_info = "PageError: " + " | ".join(all_errors[:2])
|
||
elif visible_error:
|
||
status = "FAIL"
|
||
error_info = f"可见错误: {visible_error}"
|
||
else:
|
||
status = "PASS"
|
||
|
||
results.append((name, status, error_info))
|
||
print(f"[{status}] {name}: {error_info or 'OK'} (HTTP {http_status})")
|
||
except Exception as e:
|
||
results.append((name, "FAIL", str(e)[:100]))
|
||
print(f"[FAIL] {name}: {str(e)[:100]}")
|
||
|
||
browser.close()
|
||
|
||
print("\n=== 汇总 ===")
|
||
pass_count = sum(1 for _, s, _ in results if s == "PASS")
|
||
fail_count = sum(1 for _, s, _ in results if s == "FAIL")
|
||
print(f"总计: {pass_count} PASS, {fail_count} FAIL")
|
||
|
||
sys.exit(0 if fail_count == 0 else 1)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|