Files
你的用户名 237c7802e5
Some checks failed
Deploy / deploy (push) Has been cancelled
Initial commit: Telegram Management System
Full-stack web application for Telegram management
- Frontend: Vue 3 + Vben Admin
- Backend: NestJS
- Features: User management, group broadcast, statistics

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 15:37:50 +08:00

306 lines
9.0 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ? '存在' : '不存在'}`,
);
});
});
});