e2e_crm.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. """
  2. E2E test: Login → navigate all CRM pages via sidebar → screenshot each page.
  3. Verifies the Python backend serves all CRM data correctly through the Vue frontend.
  4. """
  5. import time
  6. import os
  7. from playwright.sync_api import sync_playwright
  8. BASE_URL = "http://localhost:80"
  9. SCREENSHOT_DIR = "/tmp/crm-e2e-screenshots"
  10. os.makedirs(SCREENSHOT_DIR, exist_ok=True)
  11. CRM_PAGES = [
  12. {"menu_text": "线索管理", "path": "/clue", "name": "clue"},
  13. {"menu_text": "客户管理", "path": "/customer", "name": "customer"},
  14. {"menu_text": "公海池", "path": "/pool", "name": "pool"},
  15. {"menu_text": "商机管理", "path": "/opportunity", "name": "opportunity"},
  16. {"menu_text": "报价单管理", "path": "/quote", "name": "quote"},
  17. {"menu_text": "合同列表", "path": "/contract", "name": "contract"},
  18. {"menu_text": "产品分类", "path": "/category", "name": "product-category"},
  19. {"menu_text": "产品列表", "path": "/product", "name": "product"},
  20. ]
  21. results = {"pass": [], "fail": []}
  22. def screenshot_name(page_name):
  23. return os.path.join(SCREENSHOT_DIR, f"{page_name}.png")
  24. with sync_playwright() as p:
  25. browser = p.chromium.launch(headless=True)
  26. page = browser.new_page(viewport={"width": 1440, "height": 900})
  27. # ─── LOGIN ───
  28. print("\n[LOGIN]")
  29. page.goto(f"{BASE_URL}/login", wait_until="networkidle", timeout=30000)
  30. page.wait_for_timeout(1000)
  31. page.locator('input[placeholder="用户名"]').fill("admin")
  32. page.locator('input[placeholder="密码"]').fill("admin123")
  33. page.locator('button:has-text("登")').click()
  34. page.wait_for_url("**/index**", timeout=20000)
  35. page.wait_for_load_state("networkidle", timeout=20000)
  36. page.wait_for_timeout(2000)
  37. print(f" ✅ Login successful - URL: {page.url}")
  38. page.screenshot(path=screenshot_name("home"), full_page=False)
  39. print(f" ✅ Home page screenshot saved")
  40. # ─── NAVIGATE CRM PAGES ───
  41. print("\n[CRM PAGES]")
  42. for page_info in CRM_PAGES:
  43. menu_text = page_info["menu_text"]
  44. page_name = page_info["name"]
  45. try:
  46. # Try clicking sidebar menu item
  47. sidebar_item = page.locator(f'.el-menu-item:has-text("{menu_text}"), .el-sub-menu__title:has-text("{menu_text}")').first
  48. if sidebar_item.count() > 0:
  49. sidebar_item.click()
  50. page.wait_for_load_state("networkidle", timeout=10000)
  51. page.wait_for_timeout(1500)
  52. else:
  53. # Fallback: navigate directly via URL
  54. page.goto(f"{BASE_URL}/{page_info['path']}", wait_until="networkidle", timeout=10000)
  55. page.wait_for_timeout(1500)
  56. # Check for table or content
  57. has_table = page.locator(".el-table").count() > 0
  58. has_content = page.locator(".app-main, .app-container, .page-container").count() > 0
  59. has_error = page.locator(".el-message-box, .el-notification--error").count() > 0
  60. status = "✅"
  61. if has_error:
  62. status = "❌"
  63. results["fail"].append((page_name, "Error notification visible"))
  64. elif has_table or has_content:
  65. results["pass"].append(page_name)
  66. else:
  67. status = "⚠️"
  68. results["fail"].append((page_name, "No table/content found"))
  69. page.screenshot(path=screenshot_name(page_name), full_page=False)
  70. print(f" {status} {menu_text} ({page_name}) - table:{has_table} content:{has_content}")
  71. except Exception as e:
  72. print(f" ❌ {menu_text} ({page_name}) - {e}")
  73. results["fail"].append((page_name, str(e)[:100]))
  74. try:
  75. page.screenshot(path=screenshot_name(f"{page_name}-error"), full_page=False)
  76. except:
  77. pass
  78. # ─── SUMMARY ───
  79. print(f"\n{'='*60}")
  80. total = len(results["pass"]) + len(results["fail"])
  81. print(f"RESULTS: {len(results['pass'])}/{total} PASSED")
  82. if results["fail"]:
  83. print(f"\n❌ FAILURES ({len(results['fail'])}):")
  84. for name, reason in results["fail"]:
  85. print(f" - {name}: {reason}")
  86. else:
  87. print("🎉 ALL CRM PAGES LOADED SUCCESSFULLY!")
  88. print(f"{'='*60}")
  89. print(f"\nScreenshots saved to: {SCREENSHOT_DIR}/")
  90. browser.close()