#!/usr/bin/env python3 """ Novalon管理系统全面业务流程测试 - 最终版 确保在同一个浏览器上下文中保持登录状态 """ import time import json from datetime import datetime from playwright.sync_api import sync_playwright, Page class TestResult: def __init__(self): self.total = 0 self.passed = 0 self.failed = 0 self.errors = [] self.start_time = datetime.now() def add_pass(self, test_name): self.total += 1 self.passed += 1 print(f"✅ {test_name} - 通过") def add_fail(self, test_name, error): self.total += 1 self.failed += 1 self.errors.append({"test": test_name, "error": str(error)}) print(f"❌ {test_name} - 失败: {error}") def print_summary(self): duration = (datetime.now() - self.start_time).total_seconds() print("\n" + "="*80) print("测试总结") print("="*80) print(f"总测试数: {self.total}") print(f"通过: {self.passed} ✅") print(f"失败: {self.failed} ❌") print(f"成功率: {(self.passed/self.total*100):.2f}%") print(f"耗时: {duration:.2f}秒") if self.errors: print("\n失败详情:") for error in self.errors: print(f" - {error['test']}: {error['error']}") print("="*80) result = TestResult() def login_and_keep_session(page: Page): """登录并保持会话""" try: page.goto("http://localhost:3002/login") page.wait_for_load_state("networkidle") page.fill('input[placeholder="请输入用户名"]', 'admin') page.fill('input[placeholder="请输入密码"]', 'admin123') page.click('button:has-text("登录")') # 等待Token保存到localStorage for i in range(10): time.sleep(1) token = page.evaluate("localStorage.getItem('token')") if token: print(f"✅ 登录成功,Token: {token[:50]}...") return True return False except Exception as e: print(f"登录失败: {e}") return False def test_page_load(page: Page, name: str, url: str): """测试页面加载""" print(f"\n📋 测试{name}...") try: # 使用点击导航而不是goto,保持会话 # 先回到首页 if page.url != 'http://localhost:3002/dashboard': page.goto("http://localhost:3002/dashboard") page.wait_for_load_state("networkidle") time.sleep(1) # 通过侧边栏导航 try: # 尝试点击侧边栏菜单 menu_item = page.locator(f'text="{name}"').first if menu_item.is_visible(): menu_item.click() page.wait_for_load_state("networkidle") time.sleep(2) else: # 如果菜单不可见,直接导航 page.goto(url) page.wait_for_load_state("networkidle") time.sleep(2) except: # 如果点击失败,直接导航 page.goto(url) page.wait_for_load_state("networkidle") time.sleep(2) # 检查是否被重定向到登录页 if '/login' in page.url: result.add_fail(f"{name}-页面加载", "被重定向到登录页,会话丢失") return # 验证页面加载 page.wait_for_selector('table, [class*="card"], [class*="stats"], [class*="tree"]', timeout=5000) result.add_pass(f"{name}-页面加载") except Exception as e: result.add_fail(f"{name}-页面加载", e) def main(): print("="*80) print("Novalon管理系统全面业务流程测试") print("="*80) print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("="*80) with sync_playwright() as p: # 启动浏览器 browser = p.chromium.launch(headless=True) context = browser.new_context() page = context.new_page() try: # 登录并保持会话 print("\n🔐 测试登录...") if login_and_keep_session(page): result.add_pass("登录功能") else: result.add_fail("登录功能", "登录失败") return # 测试仪表板 test_page_load(page, "仪表板", "http://localhost:3002/dashboard") # 测试用户管理 test_page_load(page, "用户管理", "http://localhost:3002/users") # 测试角色管理 test_page_load(page, "角色管理", "http://localhost:3002/roles") # 测试菜单管理 test_page_load(page, "菜单管理", "http://localhost:3002/menus") # 测试字典管理 test_page_load(page, "字典管理", "http://localhost:3002/dict") # 测试系统配置 test_page_load(page, "系统配置", "http://localhost:3002/sys/config") # 测试文件管理 test_page_load(page, "文件管理", "http://localhost:3002/files") # 测试通知管理 test_page_load(page, "通知管理", "http://localhost:3002/notice") # 测试操作日志 test_page_load(page, "操作日志", "http://localhost:3002/oplog") # 测试登录日志 test_page_load(page, "登录日志", "http://localhost:3002/loginlog") except Exception as e: print(f"\n❌ 测试执行出错: {e}") import traceback traceback.print_exc() finally: browser.close() # 打印测试总结 result.print_summary() # 返回退出码 return 0 if result.failed == 0 else 1 if __name__ == "__main__": exit(main())