""" 侧边栏/底部导航 点击跳转专项测试 统一使用 native click 避免 Playwright strict hit-test 误判 """ import asyncio import sys from playwright.async_api import async_playwright BASE_URL = "http://localhost:8001" CREDENTIALS = {"username": "admin", "password": "admin123"} NAV_ITEMS = [ ("系统概览", "/", ""), ("选题管理", "topics.html", ""), ("数据分析", "metrics.html", "more"), ("内容日历", "calendar.html", ""), ("素材库", "assets.html", "more"), ("创作任务", "tasks.html", ""), ("平台配置", "platforms.html", "more"), ("系统日志", "logs.html", "more"), ("系统管理", "admin.html", "more"), ] def native_click(page, selector): return page.evaluate(f"""() => {{ const el = document.querySelector('{selector}'); if (!el) return false; el.click(); return true; }}""") async def run_nav_test(viewport, label, is_mobile): print(f"\n--- {label} ---") ok, fail = 0, 0 async with async_playwright() as p: browser = await p.chromium.launch(headless=True, channel="chrome", args=["--no-sandbox"]) page = await browser.new_page(viewport=viewport) await page.goto(f"{BASE_URL}/login.html", wait_until="networkidle") await page.wait_for_timeout(500) await page.locator("input.form-input").nth(0).fill(CREDENTIALS["username"]) await page.locator("input.form-input").nth(1).fill(CREDENTIALS["password"]) await page.click("button.login-btn") await page.wait_for_timeout(3000) for name, target, more_group in NAV_ITEMS: try: if is_mobile: sel = f'.mobile-nav-btn[data-page="{target}"]' clicked = await native_click(page, sel) if not clicked: # 打开更多面板后再点 more_sel = "#mobile-more-btn" await native_click(page, more_sel) await page.wait_for_timeout(400) sel = f'.sheet-item[data-page="{target}"]' clicked = await native_click(page, sel) if not clicked: print(f" ⏭ {name}: 按钮未找到") continue else: sel = f'.sidebar-btn[data-page="{target}"]' ok2 = await native_click(page, sel) if not ok2: print(f" ⏭ {name}: 按钮未找到") continue await page.wait_for_timeout(1500) matched = target in page.url if target != "/" else page.url.endswith("/") or "index" in page.url if matched: print(f" ✅ {name} -> {page.url}") ok += 1 else: print(f" ❌ {name} -> {page.url}") fail += 1 except Exception as e: print(f" ❌ {name}: {e}") fail += 1 await browser.close() return ok, fail async def main(): pc_ok, pc_fail = await run_nav_test({"width": 1280, "height": 720}, "PC 侧边栏", False) h5_ok, h5_fail = await run_nav_test({"width": 375, "height": 667}, "H5 底部导航", True) total_ok = pc_ok + h5_ok total_fail = pc_fail + h5_fail print(f"\n{'='*50}") print(f" 导航测试: PC ✅{pc_ok}❌{pc_fail} | H5 ✅{h5_ok}❌{h5_fail} | 总计 ✅{total_ok}❌{total_fail}") print(f"{'='*50}") if total_fail: sys.exit(1) if __name__ == "__main__": asyncio.run(main())