Some checks failed
Deploy / deploy (push) Has been cancelled
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>
378 lines
12 KiB
TypeScript
378 lines
12 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
||
|
||
/**
|
||
* 图标修复验证测试
|
||
* 验证以下页面的图标显示和控制台错误:
|
||
* 1. /group-broadcast/log - CalendarOutlined 和 FileTextOutlined 图标
|
||
* 2. /group-broadcast/task - ClockCircleOutlined 图标
|
||
* 3. /name-management/unified - UserAddOutlined 和 ThunderboltOutlined 图标
|
||
*/
|
||
|
||
test.describe('图标修复验证测试', () => {
|
||
test.beforeEach(async ({ page }) => {
|
||
// 监听控制台错误
|
||
page.on('console', (msg) => {
|
||
if (msg.type() === 'error') {
|
||
console.log(`❌ 控制台错误: ${msg.text()}`);
|
||
}
|
||
});
|
||
|
||
// 监听页面错误
|
||
page.on('pageerror', (error) => {
|
||
console.log(`❌ 页面错误: ${error.message}`);
|
||
});
|
||
|
||
// 登录到系统
|
||
await page.goto('/');
|
||
|
||
// 等待登录页面加载
|
||
await page.waitForSelector(
|
||
'input[placeholder*="用户名"], input[placeholder*="邮箱"], input[placeholder*="账号"]',
|
||
{ timeout: 10000 },
|
||
);
|
||
|
||
// 填写登录信息
|
||
await page.fill(
|
||
'input[placeholder*="用户名"], input[placeholder*="邮箱"], input[placeholder*="账号"]',
|
||
'admin',
|
||
);
|
||
await page.fill('input[type="password"]', '111111');
|
||
|
||
// 点击登录按钮
|
||
await page.click(
|
||
'button[type="submit"], button:has-text("登录"), button:has-text("登入")',
|
||
);
|
||
|
||
// 等待登录成功,跳转到主页
|
||
await page.waitForURL(/dashboard|home|工作台/, { timeout: 15000 });
|
||
|
||
console.log('✅ 登录成功');
|
||
});
|
||
|
||
test('验证群发日志页面的图标', async ({ page }) => {
|
||
console.log('🧪 开始测试群发日志页面...');
|
||
|
||
// 记录导航前的控制台错误
|
||
const consoleErrors: string[] = [];
|
||
page.on('console', (msg) => {
|
||
if (msg.type() === 'error' && msg.text().includes('icon')) {
|
||
consoleErrors.push(msg.text());
|
||
}
|
||
});
|
||
|
||
// 导航到群发日志页面
|
||
await page.goto('/group-broadcast/log');
|
||
|
||
// 等待页面加载完成
|
||
await page.waitForLoadState('networkidle');
|
||
await page.waitForSelector('.ant-card', { timeout: 10000 });
|
||
|
||
console.log('📄 群发日志页面已加载');
|
||
|
||
// 等待一段时间让所有资源加载完成
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 验证页面标题
|
||
await expect(page.locator('text=群发日志')).toBeVisible();
|
||
console.log('✅ 页面标题正确显示');
|
||
|
||
// 验证 FileTextOutlined 图标存在
|
||
const fileTextIcon = page
|
||
.locator(
|
||
'.anticon-file-text, [data-icon="file-text"], svg[data-icon="file-text"]',
|
||
)
|
||
.first();
|
||
await expect(fileTextIcon).toBeVisible({ timeout: 5000 });
|
||
console.log('✅ FileTextOutlined 图标显示正常');
|
||
|
||
// 验证 CalendarOutlined 图标存在(在日志项中)
|
||
const calendarIcon = page
|
||
.locator(
|
||
'.anticon-calendar, [data-icon="calendar"], svg[data-icon="calendar"]',
|
||
)
|
||
.first();
|
||
await expect(calendarIcon).toBeVisible({ timeout: 5000 });
|
||
console.log('✅ CalendarOutlined 图标显示正常');
|
||
|
||
// 检查是否有图标相关的控制台错误
|
||
if (consoleErrors.length > 0) {
|
||
console.log('❌ 发现图标相关的控制台错误:', consoleErrors);
|
||
throw new Error(`发现 ${consoleErrors.length} 个图标相关的控制台错误`);
|
||
} else {
|
||
console.log('✅ 没有发现图标相关的控制台错误');
|
||
}
|
||
|
||
// 截图保存
|
||
await page.screenshot({
|
||
path: 'test-results/screenshots/group-broadcast-log.png',
|
||
fullPage: true,
|
||
});
|
||
console.log('📸 已保存群发日志页面截图');
|
||
});
|
||
|
||
test('验证群发任务页面的图标', async ({ page }) => {
|
||
console.log('🧪 开始测试群发任务页面...');
|
||
|
||
// 记录导航前的控制台错误
|
||
const consoleErrors: string[] = [];
|
||
page.on('console', (msg) => {
|
||
if (msg.type() === 'error' && msg.text().includes('icon')) {
|
||
consoleErrors.push(msg.text());
|
||
}
|
||
});
|
||
|
||
// 导航到群发任务页面
|
||
await page.goto('/group-broadcast/task');
|
||
|
||
// 等待页面加载完成
|
||
await page.waitForLoadState('networkidle');
|
||
await page.waitForSelector('.ant-card', { timeout: 10000 });
|
||
|
||
console.log('📄 群发任务页面已加载');
|
||
|
||
// 等待一段时间让所有资源加载完成
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 验证页面标题
|
||
await expect(page.locator('text=群发任务')).toBeVisible();
|
||
console.log('✅ 页面标题正确显示');
|
||
|
||
// 验证 ClockCircleOutlined 图标存在(在表格中的发送频率列)
|
||
const clockIcon = page
|
||
.locator(
|
||
'.anticon-clock-circle, [data-icon="clock-circle"], svg[data-icon="clock-circle"]',
|
||
)
|
||
.first();
|
||
|
||
// 等待表格数据加载
|
||
await page.waitForSelector('.ant-table-tbody tr', { timeout: 10000 });
|
||
|
||
// 如果表格中有数据,应该能看到时钟图标
|
||
const tableRows = await page.locator('.ant-table-tbody tr').count();
|
||
if (tableRows > 0) {
|
||
await expect(clockIcon).toBeVisible({ timeout: 5000 });
|
||
console.log('✅ ClockCircleOutlined 图标显示正常');
|
||
} else {
|
||
console.log('ℹ️ 表格暂无数据,无法验证ClockCircleOutlined图标');
|
||
}
|
||
|
||
// 检查是否有图标相关的控制台错误
|
||
if (consoleErrors.length > 0) {
|
||
console.log('❌ 发现图标相关的控制台错误:', consoleErrors);
|
||
throw new Error(`发现 ${consoleErrors.length} 个图标相关的控制台错误`);
|
||
} else {
|
||
console.log('✅ 没有发现图标相关的控制台错误');
|
||
}
|
||
|
||
// 截图保存
|
||
await page.screenshot({
|
||
path: 'test-results/screenshots/group-broadcast-task.png',
|
||
fullPage: true,
|
||
});
|
||
console.log('📸 已保存群发任务页面截图');
|
||
});
|
||
|
||
test('验证智能姓名管理页面的图标', async ({ page }) => {
|
||
console.log('🧪 开始测试智能姓名管理页面...');
|
||
|
||
// 记录导航前的控制台错误
|
||
const consoleErrors: string[] = [];
|
||
page.on('console', (msg) => {
|
||
if (msg.type() === 'error' && msg.text().includes('icon')) {
|
||
consoleErrors.push(msg.text());
|
||
}
|
||
});
|
||
|
||
// 导航到智能姓名管理页面
|
||
await page.goto('/name-management/unified');
|
||
|
||
// 等待页面加载完成
|
||
await page.waitForLoadState('networkidle');
|
||
await page.waitForSelector('.ant-card', { timeout: 10000 });
|
||
|
||
console.log('📄 智能姓名管理页面已加载');
|
||
|
||
// 等待一段时间让所有资源加载完成
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 验证页面标题
|
||
await expect(page.locator('text=智能姓名管理系统')).toBeVisible();
|
||
console.log('✅ 页面标题正确显示');
|
||
|
||
// 验证 UserAddOutlined 图标存在(在卡片标题的extra区域)
|
||
const userAddIcon = page
|
||
.locator(
|
||
'.anticon-user-add, [data-icon="user-add"], svg[data-icon="user-add"]',
|
||
)
|
||
.first();
|
||
await expect(userAddIcon).toBeVisible({ timeout: 5000 });
|
||
console.log('✅ UserAddOutlined 图标显示正常');
|
||
|
||
// 验证 ThunderboltOutlined 图标存在(在生成姓名按钮中)
|
||
const thunderboltIcon = page
|
||
.locator(
|
||
'.anticon-thunderbolt, [data-icon="thunderbolt"], svg[data-icon="thunderbolt"]',
|
||
)
|
||
.first();
|
||
await expect(thunderboltIcon).toBeVisible({ timeout: 5000 });
|
||
console.log('✅ ThunderboltOutlined 图标显示正常');
|
||
|
||
// 检查是否有图标相关的控制台错误
|
||
if (consoleErrors.length > 0) {
|
||
console.log('❌ 发现图标相关的控制台错误:', consoleErrors);
|
||
throw new Error(`发现 ${consoleErrors.length} 个图标相关的控制台错误`);
|
||
} else {
|
||
console.log('✅ 没有发现图标相关的控制台错误');
|
||
}
|
||
|
||
// 截图保存
|
||
await page.screenshot({
|
||
path: 'test-results/screenshots/name-management-unified.png',
|
||
fullPage: true,
|
||
});
|
||
console.log('📸 已保存智能姓名管理页面截图');
|
||
});
|
||
|
||
test('综合图标验证测试', async ({ page }) => {
|
||
console.log('🧪 开始综合图标验证测试...');
|
||
|
||
const allConsoleErrors: string[] = [];
|
||
page.on('console', (msg) => {
|
||
if (msg.type() === 'error') {
|
||
allConsoleErrors.push(`[${new Date().toISOString()}] ${msg.text()}`);
|
||
}
|
||
});
|
||
|
||
const testPages = [
|
||
{
|
||
url: '/group-broadcast/log',
|
||
name: '群发日志',
|
||
icons: ['file-text', 'calendar'],
|
||
},
|
||
{
|
||
url: '/group-broadcast/task',
|
||
name: '群发任务',
|
||
icons: ['clock-circle'],
|
||
},
|
||
{
|
||
url: '/name-management/unified',
|
||
name: '智能姓名管理',
|
||
icons: ['user-add', 'thunderbolt'],
|
||
},
|
||
];
|
||
|
||
const testResults = [];
|
||
|
||
for (const testPage of testPages) {
|
||
console.log(`\n📋 测试页面: ${testPage.name} (${testPage.url})`);
|
||
|
||
try {
|
||
// 导航到页面
|
||
await page.goto(testPage.url);
|
||
await page.waitForLoadState('networkidle');
|
||
await page.waitForSelector('.ant-card', { timeout: 10000 });
|
||
await page.waitForTimeout(1000);
|
||
|
||
// 验证每个图标
|
||
const iconResults = [];
|
||
for (const iconName of testPage.icons) {
|
||
try {
|
||
const iconSelector = `.anticon-${iconName}, [data-icon="${iconName}"], svg[data-icon="${iconName}"]`;
|
||
await expect(page.locator(iconSelector).first()).toBeVisible({
|
||
timeout: 3000,
|
||
});
|
||
iconResults.push({ icon: iconName, status: '✅ 正常' });
|
||
console.log(` ✅ ${iconName} 图标正常`);
|
||
} catch (error) {
|
||
iconResults.push({
|
||
icon: iconName,
|
||
status: '❌ 异常',
|
||
error: error.message,
|
||
});
|
||
console.log(` ❌ ${iconName} 图标异常: ${error.message}`);
|
||
}
|
||
}
|
||
|
||
testResults.push({
|
||
page: testPage.name,
|
||
url: testPage.url,
|
||
icons: iconResults,
|
||
status: iconResults.every((r) => r.status.includes('✅'))
|
||
? '✅ 通过'
|
||
: '❌ 失败',
|
||
});
|
||
|
||
// 截图
|
||
await page.screenshot({
|
||
path: `test-results/screenshots/comprehensive-${testPage.name.replace(/\s+/g, '-')}.png`,
|
||
fullPage: true,
|
||
});
|
||
} catch (error) {
|
||
console.log(` ❌ 页面加载失败: ${error.message}`);
|
||
testResults.push({
|
||
page: testPage.name,
|
||
url: testPage.url,
|
||
icons: [],
|
||
status: '❌ 页面加载失败',
|
||
error: error.message,
|
||
});
|
||
}
|
||
}
|
||
|
||
// 生成测试报告
|
||
console.log('\n📊 测试结果汇总:');
|
||
console.log('='.repeat(60));
|
||
|
||
let allPassed = true;
|
||
for (const result of testResults) {
|
||
console.log(`\n📄 ${result.page} (${result.url})`);
|
||
console.log(` 状态: ${result.status}`);
|
||
|
||
if (result.icons.length > 0) {
|
||
for (const iconResult of result.icons) {
|
||
console.log(` ${iconResult.status} ${iconResult.icon}`);
|
||
if (iconResult.error) {
|
||
console.log(` 错误: ${iconResult.error}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (result.error) {
|
||
console.log(` 错误: ${result.error}`);
|
||
allPassed = false;
|
||
} else if (result.status.includes('❌')) {
|
||
allPassed = false;
|
||
}
|
||
}
|
||
|
||
// 控制台错误汇总
|
||
if (allConsoleErrors.length > 0) {
|
||
console.log('\n🚨 控制台错误汇总:');
|
||
const iconErrors = allConsoleErrors.filter(
|
||
(error) =>
|
||
error.toLowerCase().includes('icon') ||
|
||
error.toLowerCase().includes('import') ||
|
||
error.toLowerCase().includes('module'),
|
||
);
|
||
|
||
if (iconErrors.length > 0) {
|
||
console.log(`❌ 发现 ${iconErrors.length} 个可能与图标相关的错误:`);
|
||
iconErrors.forEach((error, index) => {
|
||
console.log(` ${index + 1}. ${error}`);
|
||
});
|
||
allPassed = false;
|
||
} else {
|
||
console.log('✅ 没有发现图标相关的控制台错误');
|
||
}
|
||
}
|
||
|
||
console.log('\n' + '='.repeat(60));
|
||
if (allPassed) {
|
||
console.log('🎉 所有图标验证测试通过!');
|
||
} else {
|
||
console.log('❌ 部分图标验证测试失败,请检查上述错误');
|
||
throw new Error('图标验证测试失败');
|
||
}
|
||
});
|
||
});
|