""" 检查学情诊断、错题分析、公告、消息 4 个模块的实际渲染状态 截取截图 + 捕获控制台错误 + 检查页面内容 """ import os import time from playwright.sync_api import sync_playwright BASE_URL = "http://localhost:3000" TEACHER_EMAIL = "t_chinese_1@xiaoxue.edu.cn" TEACHER_PASSWORD = "123456" SCREENSHOT_DIR = os.path.join(os.path.dirname(__file__), "..", "bugs", "screenshots") os.makedirs(SCREENSHOT_DIR, exist_ok=True) ROUTES = [ ("/teacher/diagnostic", "学情诊断"), ("/teacher/error-book", "错题分析"), ("/announcements", "公告"), ("/messages", "消息"), ] def main(): with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context(viewport={"width": 1440, "height": 900}) page = context.new_page() # Login print(">>> 登录...") page.goto(f"{BASE_URL}/login", wait_until="domcontentloaded") page.wait_for_timeout(3000) page.locator('input[name="email"]').fill(TEACHER_EMAIL) page.locator('input[type="password"]').first.fill(TEACHER_PASSWORD) page.evaluate("""() => { const form = document.querySelector('form'); if (form) { const event = new Event('submit', { cancelable: true, bubbles: true }); form.dispatchEvent(event); } }""") page.wait_for_timeout(5000) print(f"登录后 URL: {page.url}") for route, name in ROUTES: print(f"\n{'='*60}") print(f">>> 测试: {name} ({route})") print(f"{'='*60}") console_errors = [] console_warnings = [] def on_console(msg): if msg.type == "error": console_errors.append(msg.text) elif msg.type == "warning": console_warnings.append(msg.text) def on_page_error(err): console_errors.append(f"PageError: {str(err)[:300]}") page.on("console", on_console) page.on("pageerror", on_page_error) try: response = page.goto(f"{BASE_URL}{route}", timeout=30000, wait_until="domcontentloaded") page.wait_for_timeout(3000) # Wait for client-side JS to execute print(f" HTTP Status: {response.status if response else 'N/A'}") print(f" Final URL: {page.url}") # Check for error indicators on page body_text = page.locator("body").text_content() or "" print(f" Body text length: {len(body_text)}") # Check for common error patterns error_elements = page.locator('[role="alert"], .text-destructive, .text-red-500, .text-red-600') error_count = error_elements.count() if error_count > 0: print(f" Error elements on page: {error_count}") for i in range(min(error_count, 5)): try: text = error_elements.nth(i).text_content() if text and text.strip(): print(f" [{i}] {text.strip()[:200]}") except: pass # Check for loading spinners still visible spinners = page.locator('.animate-spin, [role="status"], .loading') spinner_count = spinners.count() if spinner_count > 0: print(f" Loading spinners still visible: {spinner_count}") # Check for empty state if "暂无" in body_text or "No data" in body_text or "没有" in body_text: # Find the context for keyword in ["暂无", "No data", "没有"]: idx = body_text.find(keyword) if idx >= 0: context_text = body_text[max(0, idx-30):idx+80] print(f" Empty state: ...{context_text}...") break # Check for "加载失败" or "error" text for keyword in ["加载失败", "load", "error", "错误", "失败", "Error"]: if keyword.lower() in body_text.lower(): idx = body_text.lower().find(keyword.lower()) context_text = body_text[max(0, idx-30):idx+100] print(f" Found '{keyword}': ...{context_text}...") break # Take screenshot screenshot_name = route.replace("/", "_").strip("_") + ".png" screenshot_path = os.path.join(SCREENSHOT_DIR, screenshot_name) page.screenshot(path=screenshot_path, full_page=True) print(f" Screenshot: {screenshot_path}") # Print console errors if console_errors: print(f"\n Console Errors ({len(console_errors)}):") for err in console_errors[:10]: print(f" - {err[:300]}") else: print(f" Console Errors: 0") if console_warnings: print(f"\n Console Warnings ({len(console_warnings)}):") for w in console_warnings[:5]: print(f" - {w[:200]}") except Exception as e: print(f" EXCEPTION: {type(e).__name__}: {str(e)[:300]}") screenshot_name = route.replace("/", "_").strip("_") + "_error.png" screenshot_path = os.path.join(SCREENSHOT_DIR, screenshot_name) try: page.screenshot(path=screenshot_path, full_page=True) except: pass finally: page.remove_listener("console", on_console) page.remove_listener("pageerror", on_page_error) browser.close() print(f"\n{'='*60}") print("测试完成!") print(f"{'='*60}") if __name__ == "__main__": main()