import { test, expect, Page } from '@playwright/test'; test.describe('菜单验证测试', () => { let page: Page; test.beforeAll(async ({ browser }) => { page = await browser.newPage(); // 设置视口大小以确保菜单完全可见 await page.setViewportSize({ width: 1920, height: 1080 }); // 访问登录页面 await page.goto('http://localhost:5174'); await page.waitForLoadState('networkidle'); // 登录 await page.fill('input[placeholder="请输入用户名"]', 'admin'); await page.fill('input[placeholder="密码"]', '111111'); await page.click('button:has-text("登录")'); // 等待登录成功,跳转到主页 await page.waitForURL(/dashboard/, { timeout: 30000 }); await page.waitForLoadState('networkidle'); console.log('✅ 登录成功'); }); test.afterAll(async () => { await page.close(); }); test('验证菜单总数和新增菜单项', async () => { // 等待页面完全加载 await page.waitForTimeout(2000); // 展开所有菜单项的函数 const expandAllMenus = async () => { console.log('🔍 开始展开所有菜单项...'); // 找到所有可展开的菜单项 const menuItems = await page.locator('.ant-menu-submenu').all(); console.log(`发现 ${menuItems.length} 个子菜单`); for (let i = 0; i < menuItems.length; i++) { try { const menuItem = menuItems[i]; const isOpen = (await menuItem.locator('.ant-menu-submenu-open').count()) > 0; if (!isOpen) { const menuTitle = await menuItem .locator('.ant-menu-submenu-title') .first(); const titleText = await menuTitle.textContent(); console.log(`📂 展开菜单: ${titleText}`); await menuTitle.click(); await page.waitForTimeout(500); // 等待动画完成 } } catch (error) { console.log(`⚠️ 展开菜单项 ${i} 时出错:`, error); } } // 等待所有菜单展开完成 await page.waitForTimeout(1000); }; // 展开所有菜单 await expandAllMenus(); // 收集所有菜单项 const collectAllMenuItems = async () => { console.log('📝 开始收集菜单项...'); const menuItems: string[] = []; // 获取所有菜单项(包含子菜单标题和叶子菜单项) const allMenuElements = await page .locator('.ant-menu-item, .ant-menu-submenu-title') .all(); for (const element of allMenuElements) { try { const text = await element.textContent(); if (text && text.trim() && !menuItems.includes(text.trim())) { menuItems.push(text.trim()); } } catch (error) { console.log('收集菜单项时出错:', error); } } return menuItems.sort(); }; const allMenuItems = await collectAllMenuItems(); console.log('📊 所有菜单项列表:'); allMenuItems.forEach((item, index) => { console.log(`${index + 1}. ${item}`); }); console.log(`\n📈 菜单总数: ${allMenuItems.length}`); // 验证新增的菜单项 const expectedNewMenus = [ '工具箱', '文件上传', 'Excel导入导出', 'WebSocket调试', '帮助中心', '系统文档', '权限示例', ]; console.log('\n🔍 验证新增菜单项:'); const foundNewMenus: string[] = []; const missingMenus: string[] = []; expectedNewMenus.forEach((menuName) => { const found = allMenuItems.some((item) => item.includes(menuName)); if (found) { foundNewMenus.push(menuName); console.log(`✅ 找到: ${menuName}`); } else { missingMenus.push(menuName); console.log(`❌ 缺失: ${menuName}`); } }); // 统计结果 console.log('\n📊 验证结果总结:'); console.log(`菜单总数: ${allMenuItems.length}`); console.log( `新增菜单找到: ${foundNewMenus.length}/${expectedNewMenus.length}`, ); console.log(`找到的新菜单: ${foundNewMenus.join(', ')}`); if (missingMenus.length > 0) { console.log(`❌ 缺失的菜单: ${missingMenus.join(', ')}`); } // 特别检查工具箱相关菜单 const toolboxMenus = allMenuItems.filter( (item) => item.includes('工具箱') || item.includes('文件上传') || item.includes('Excel') || item.includes('WebSocket'), ); console.log('\n🛠️ 工具箱相关菜单:'); toolboxMenus.forEach((menu) => console.log(` - ${menu}`)); // 特别检查帮助中心相关菜单 const helpMenus = allMenuItems.filter( (item) => item.includes('帮助中心') || item.includes('系统文档') || item.includes('权限示例'), ); console.log('\n❓ 帮助中心相关菜单:'); helpMenus.forEach((menu) => console.log(` - ${menu}`)); // 断言验证 expect(allMenuItems.length).toBeGreaterThan(49); // 应该比49个更多 expect(foundNewMenus.length).toBeGreaterThanOrEqual(5); // 至少找到5个新菜单 // 截图保存 await page.screenshot({ path: 'test-results/screenshots/menu-validation-full.png', fullPage: true, }); console.log('✅ 菜单验证测试完成'); }); test('详细菜单结构分析', async () => { // 等待页面加载 await page.waitForTimeout(2000); console.log('🔍 开始详细菜单结构分析...'); // 获取菜单结构 const menuStructure = await page.evaluate(() => { const getMenuStructure = (element: Element, level = 0): any => { const result: any = {}; if (element.classList.contains('ant-menu-submenu')) { const titleElement = element.querySelector('.ant-menu-submenu-title'); const title = titleElement?.textContent?.trim() || ''; result.title = title; result.type = 'submenu'; result.level = level; result.children = []; const childMenu = element.querySelector('.ant-menu-sub'); if (childMenu) { const childItems = childMenu.children; for (let i = 0; i < childItems.length; i++) { const child = childItems[i]; if ( child.classList.contains('ant-menu-item') || child.classList.contains('ant-menu-submenu') ) { result.children.push(getMenuStructure(child, level + 1)); } } } } else if (element.classList.contains('ant-menu-item')) { const title = element.textContent?.trim() || ''; result.title = title; result.type = 'item'; result.level = level; } return result; }; const menuContainer = document.querySelector('.ant-menu-root'); const structure: any[] = []; if (menuContainer) { const topLevelItems = menuContainer.children; for (let i = 0; i < topLevelItems.length; i++) { const item = topLevelItems[i]; if ( item.classList.contains('ant-menu-item') || item.classList.contains('ant-menu-submenu') ) { structure.push(getMenuStructure(item)); } } } return structure; }); // 打印菜单结构 const printMenuStructure = (items: any[], indent = '') => { items.forEach((item) => { console.log( `${indent}${item.type === 'submenu' ? '📁' : '📄'} ${item.title}`, ); if (item.children && item.children.length > 0) { printMenuStructure(item.children, indent + ' '); } }); }; console.log('\n📋 完整菜单结构:'); printMenuStructure(menuStructure); // 统计菜单数量 const countMenuItems = (items: any[]): number => { let count = 0; items.forEach((item) => { count += 1; if (item.children && item.children.length > 0) { count += countMenuItems(item.children); } }); return count; }; const totalMenuCount = countMenuItems(menuStructure); console.log(`\n📊 菜单结构统计: ${totalMenuCount} 个菜单项`); // 验证特定菜单的存在 const findMenuInStructure = ( items: any[], searchTitle: string, ): boolean => { return items.some((item) => { if (item.title.includes(searchTitle)) { return true; } if (item.children && item.children.length > 0) { return findMenuInStructure(item.children, searchTitle); } return false; }); }; const menuChecks = [ '工具箱', '文件上传', 'Excel导入导出', 'WebSocket调试', '帮助中心', '系统文档', '权限示例', ]; console.log('\n🔍 菜单存在性检查:'); menuChecks.forEach((menuName) => { const exists = findMenuInStructure(menuStructure, menuName); console.log( `${exists ? '✅' : '❌'} ${menuName}: ${exists ? '存在' : '不存在'}`, ); }); }); });