""" E2E test: Login → navigate all CRM pages via sidebar → screenshot each page. Verifies the Python backend serves all CRM data correctly through the Vue frontend. """ import time import os from playwright.sync_api import sync_playwright BASE_URL = "http://localhost:80" SCREENSHOT_DIR = "/tmp/crm-e2e-screenshots" os.makedirs(SCREENSHOT_DIR, exist_ok=True) CRM_PAGES = [ {"menu_text": "线索管理", "path": "/clue", "name": "clue"}, {"menu_text": "客户管理", "path": "/customer", "name": "customer"}, {"menu_text": "公海池", "path": "/pool", "name": "pool"}, {"menu_text": "商机管理", "path": "/opportunity", "name": "opportunity"}, {"menu_text": "报价单管理", "path": "/quote", "name": "quote"}, {"menu_text": "合同列表", "path": "/contract", "name": "contract"}, {"menu_text": "产品分类", "path": "/category", "name": "product-category"}, {"menu_text": "产品列表", "path": "/product", "name": "product"}, ] results = {"pass": [], "fail": []} def screenshot_name(page_name): return os.path.join(SCREENSHOT_DIR, f"{page_name}.png") with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={"width": 1440, "height": 900}) # ─── LOGIN ─── print("\n[LOGIN]") page.goto(f"{BASE_URL}/login", wait_until="networkidle", timeout=30000) page.wait_for_timeout(1000) page.locator('input[placeholder="用户名"]').fill("admin") page.locator('input[placeholder="密码"]').fill("admin123") page.locator('button:has-text("登")').click() page.wait_for_url("**/index**", timeout=20000) page.wait_for_load_state("networkidle", timeout=20000) page.wait_for_timeout(2000) print(f" ✅ Login successful - URL: {page.url}") page.screenshot(path=screenshot_name("home"), full_page=False) print(f" ✅ Home page screenshot saved") # ─── NAVIGATE CRM PAGES ─── print("\n[CRM PAGES]") for page_info in CRM_PAGES: menu_text = page_info["menu_text"] page_name = page_info["name"] try: # Try clicking sidebar menu item sidebar_item = page.locator(f'.el-menu-item:has-text("{menu_text}"), .el-sub-menu__title:has-text("{menu_text}")').first if sidebar_item.count() > 0: sidebar_item.click() page.wait_for_load_state("networkidle", timeout=10000) page.wait_for_timeout(1500) else: # Fallback: navigate directly via URL page.goto(f"{BASE_URL}/{page_info['path']}", wait_until="networkidle", timeout=10000) page.wait_for_timeout(1500) # Check for table or content has_table = page.locator(".el-table").count() > 0 has_content = page.locator(".app-main, .app-container, .page-container").count() > 0 has_error = page.locator(".el-message-box, .el-notification--error").count() > 0 status = "✅" if has_error: status = "❌" results["fail"].append((page_name, "Error notification visible")) elif has_table or has_content: results["pass"].append(page_name) else: status = "⚠️" results["fail"].append((page_name, "No table/content found")) page.screenshot(path=screenshot_name(page_name), full_page=False) print(f" {status} {menu_text} ({page_name}) - table:{has_table} content:{has_content}") except Exception as e: print(f" ❌ {menu_text} ({page_name}) - {e}") results["fail"].append((page_name, str(e)[:100])) try: page.screenshot(path=screenshot_name(f"{page_name}-error"), full_page=False) except: pass # ─── SUMMARY ─── print(f"\n{'='*60}") total = len(results["pass"]) + len(results["fail"]) print(f"RESULTS: {len(results['pass'])}/{total} PASSED") if results["fail"]: print(f"\n❌ FAILURES ({len(results['fail'])}):") for name, reason in results["fail"]: print(f" - {name}: {reason}") else: print("🎉 ALL CRM PAGES LOADED SUCCESSFULLY!") print(f"{'='*60}") print(f"\nScreenshots saved to: {SCREENSHOT_DIR}/") browser.close()