Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled
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>
This commit is contained in:
366
backend/comprehensive_test.js
Normal file
366
backend/comprehensive_test.js
Normal file
@@ -0,0 +1,366 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 全面测试统一姓名管理系统的所有功能
|
||||
*/
|
||||
|
||||
const { chromium } = require('playwright');
|
||||
|
||||
async function comprehensiveTest() {
|
||||
console.log('🔧 开始全面测试统一姓名管理系统...\n');
|
||||
|
||||
let browser;
|
||||
let page;
|
||||
let testResults = {
|
||||
statusPanel: false,
|
||||
generateFunction: false,
|
||||
addTemplate: false,
|
||||
searchFilter: false,
|
||||
tableOperations: false,
|
||||
editDelete: false,
|
||||
apiEndpoints: {}
|
||||
};
|
||||
|
||||
try {
|
||||
browser = await chromium.launch({
|
||||
headless: false,
|
||||
slowMo: 1000
|
||||
});
|
||||
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1400, height: 900 }
|
||||
});
|
||||
|
||||
page = await context.newPage();
|
||||
|
||||
// 监听API调用和错误
|
||||
const apiCalls = [];
|
||||
page.on('request', request => {
|
||||
const url = request.url();
|
||||
if (url.includes('/nameTemplate/')) {
|
||||
apiCalls.push({
|
||||
method: request.method(),
|
||||
url: url,
|
||||
timestamp: new Date()
|
||||
});
|
||||
console.log(`🔗 ${request.method()} ${url}`);
|
||||
}
|
||||
});
|
||||
|
||||
page.on('response', response => {
|
||||
const url = response.url();
|
||||
if (url.includes('/nameTemplate/')) {
|
||||
console.log(`📡 ${response.status()} ${url}`);
|
||||
|
||||
// 记录API测试结果
|
||||
const endpoint = url.split('/nameTemplate/')[1].split('?')[0];
|
||||
testResults.apiEndpoints[endpoint] = {
|
||||
status: response.status(),
|
||||
success: response.status() >= 200 && response.status() < 300
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
page.on('console', msg => {
|
||||
if (msg.type() === 'error') {
|
||||
console.log(`❌ 前端错误: ${msg.text()}`);
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== 登录 ====================
|
||||
console.log('🚀 登录系统...');
|
||||
await page.goto('http://localhost:8891');
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await page.fill('input[type="text"]', 'admin');
|
||||
await page.fill('input[type="password"]', '111111');
|
||||
await page.click('button:has-text("登录")');
|
||||
await page.waitForLoadState('networkidle');
|
||||
console.log('✅ 登录成功\n');
|
||||
|
||||
// ==================== 测试1:系统状态面板 ====================
|
||||
console.log('📊 测试1:系统状态面板加载...');
|
||||
await page.goto('http://localhost:8891/#/nameManage/unified');
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
const statusPanelTest = await page.evaluate(() => {
|
||||
const statusCards = document.querySelectorAll('.status-card');
|
||||
const generatorItems = document.querySelectorAll('.generator-item');
|
||||
const platformTags = document.querySelectorAll('.platform-tags .ivu-tag');
|
||||
const cultureTags = document.querySelectorAll('.culture-tags .ivu-tag');
|
||||
|
||||
return {
|
||||
hasStatusPanel: !!document.querySelector('.status-panel'),
|
||||
statusCardsCount: statusCards.length,
|
||||
generatorCount: generatorItems.length,
|
||||
platformCount: platformTags.length,
|
||||
cultureCount: cultureTags.length,
|
||||
generatorStates: Array.from(generatorItems).map(item => ({
|
||||
name: item.querySelector('.generator-name')?.textContent,
|
||||
available: item.querySelector('.status-success') !== null
|
||||
}))
|
||||
};
|
||||
});
|
||||
|
||||
testResults.statusPanel = statusPanelTest.hasStatusPanel &&
|
||||
statusPanelTest.statusCardsCount === 3 &&
|
||||
statusPanelTest.generatorCount === 4;
|
||||
|
||||
console.log(`${testResults.statusPanel ? '✅' : '❌'} 状态面板测试:`);
|
||||
console.log(` - 状态面板存在: ${statusPanelTest.hasStatusPanel}`);
|
||||
console.log(` - 状态卡片: ${statusPanelTest.statusCardsCount}/3`);
|
||||
console.log(` - 生成器: ${statusPanelTest.generatorCount}/4`);
|
||||
console.log(` - 平台标签: ${statusPanelTest.platformCount}`);
|
||||
console.log(` - 文化标签: ${statusPanelTest.cultureCount}`);
|
||||
statusPanelTest.generatorStates.forEach(gen => {
|
||||
console.log(` - ${gen.name}: ${gen.available ? '可用' : '不可用'}`);
|
||||
});
|
||||
|
||||
await page.screenshot({ path: 'test_01_status_panel.png', fullPage: true });
|
||||
|
||||
// ==================== 测试2:智能生成功能 ====================
|
||||
console.log('\n🎲 测试2:智能生成功能...');
|
||||
|
||||
const generateTest = await page.evaluate(async () => {
|
||||
const generateBtn = document.querySelector('button:has-text("生成姓名")');
|
||||
const platformSelect = document.querySelector('.generate-panel .ivu-select');
|
||||
|
||||
if (!generateBtn || !platformSelect) {
|
||||
return { hasGeneratePanel: false };
|
||||
}
|
||||
|
||||
// 点击生成按钮
|
||||
generateBtn.click();
|
||||
|
||||
// 等待一下看是否有结果
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
const resultItems = document.querySelectorAll('.name-result-item');
|
||||
|
||||
return {
|
||||
hasGeneratePanel: true,
|
||||
hasGenerateButton: !!generateBtn,
|
||||
resultsCount: resultItems.length,
|
||||
buttonDisabled: generateBtn.disabled
|
||||
};
|
||||
});
|
||||
|
||||
testResults.generateFunction = generateTest.hasGeneratePanel && generateTest.hasGenerateButton;
|
||||
|
||||
console.log(`${testResults.generateFunction ? '✅' : '❌'} 智能生成测试:`);
|
||||
console.log(` - 生成面板存在: ${generateTest.hasGeneratePanel}`);
|
||||
console.log(` - 生成按钮存在: ${generateTest.hasGenerateButton}`);
|
||||
console.log(` - 生成结果数量: ${generateTest.resultsCount}`);
|
||||
|
||||
await page.screenshot({ path: 'test_02_generate_function.png', fullPage: true });
|
||||
|
||||
// ==================== 测试3:添加模板功能 ====================
|
||||
console.log('\n➕ 测试3:添加姓名模板功能...');
|
||||
|
||||
const addButton = await page.locator('button:has-text("添加姓名模板")');
|
||||
if (await addButton.isVisible()) {
|
||||
await addButton.click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
const addModalTest = await page.evaluate(() => {
|
||||
const modal = document.querySelector('.ivu-modal');
|
||||
if (!modal) return { hasModal: false };
|
||||
|
||||
const inputs = modal.querySelectorAll('input');
|
||||
const selects = modal.querySelectorAll('.ivu-select');
|
||||
|
||||
return {
|
||||
hasModal: true,
|
||||
title: modal.querySelector('.ivu-modal-header')?.textContent?.trim(),
|
||||
inputCount: inputs.length,
|
||||
selectCount: selects.length,
|
||||
hasLastNameInput: !!modal.querySelector('input[placeholder*="姓氏"]'),
|
||||
hasFirstNameInput: !!modal.querySelector('input[placeholder*="名字"]'),
|
||||
hasDisplayNameInput: !!modal.querySelector('input[placeholder*="显示名称"]')
|
||||
};
|
||||
});
|
||||
|
||||
testResults.addTemplate = addModalTest.hasModal &&
|
||||
addModalTest.hasLastNameInput &&
|
||||
addModalTest.hasFirstNameInput;
|
||||
|
||||
console.log(`${testResults.addTemplate ? '✅' : '❌'} 添加模板测试:`);
|
||||
console.log(` - 弹窗打开: ${addModalTest.hasModal}`);
|
||||
console.log(` - 弹窗标题: ${addModalTest.title}`);
|
||||
console.log(` - 输入框数量: ${addModalTest.inputCount}`);
|
||||
console.log(` - 下拉选择数量: ${addModalTest.selectCount}`);
|
||||
console.log(` - 姓氏输入框: ${addModalTest.hasLastNameInput}`);
|
||||
console.log(` - 名字输入框: ${addModalTest.hasFirstNameInput}`);
|
||||
console.log(` - 显示名输入框: ${addModalTest.hasDisplayNameInput}`);
|
||||
|
||||
await page.screenshot({ path: 'test_03_add_modal.png', fullPage: true });
|
||||
|
||||
// 关闭弹窗
|
||||
const cancelButton = await page.locator('button:has-text("取消")');
|
||||
if (await cancelButton.isVisible()) {
|
||||
await cancelButton.click();
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 测试4:搜索和过滤功能 ====================
|
||||
console.log('\n🔍 测试4:搜索和过滤功能...');
|
||||
|
||||
const searchTest = await page.evaluate(() => {
|
||||
const keywordInput = document.querySelector('input[placeholder*="搜索姓名"]');
|
||||
const cultureSelect = document.querySelectorAll('form .ivu-select')[1];
|
||||
const platformSelect = document.querySelectorAll('form .ivu-select')[2];
|
||||
const qualitySelect = document.querySelectorAll('form .ivu-select')[3];
|
||||
const searchBtn = document.querySelector('button:has-text("搜索")');
|
||||
const resetBtn = document.querySelector('button:has-text("重置")');
|
||||
|
||||
return {
|
||||
hasKeywordInput: !!keywordInput,
|
||||
hasCultureSelect: !!cultureSelect,
|
||||
hasPlatformSelect: !!platformSelect,
|
||||
hasQualitySelect: !!qualitySelect,
|
||||
hasSearchButton: !!searchBtn,
|
||||
hasResetButton: !!resetBtn
|
||||
};
|
||||
});
|
||||
|
||||
testResults.searchFilter = searchTest.hasKeywordInput &&
|
||||
searchTest.hasSearchButton &&
|
||||
searchTest.hasResetButton;
|
||||
|
||||
console.log(`${testResults.searchFilter ? '✅' : '❌'} 搜索过滤测试:`);
|
||||
console.log(` - 关键词输入框: ${searchTest.hasKeywordInput}`);
|
||||
console.log(` - 文化选择器: ${searchTest.hasCultureSelect}`);
|
||||
console.log(` - 平台选择器: ${searchTest.hasPlatformSelect}`);
|
||||
console.log(` - 质量选择器: ${searchTest.hasQualitySelect}`);
|
||||
console.log(` - 搜索按钮: ${searchTest.hasSearchButton}`);
|
||||
console.log(` - 重置按钮: ${searchTest.hasResetButton}`);
|
||||
|
||||
// ==================== 测试5:数据表格 ====================
|
||||
console.log('\n📋 测试5:数据表格显示和操作...');
|
||||
|
||||
const tableTest = await page.evaluate(() => {
|
||||
const table = document.querySelector('table');
|
||||
if (!table) return { hasTable: false };
|
||||
|
||||
const headers = Array.from(table.querySelectorAll('thead th')).map(th => th.textContent?.trim());
|
||||
const rows = table.querySelectorAll('tbody tr');
|
||||
|
||||
const expectedColumns = ['ID', '显示名称', '姓氏', '名字', '文化', '平台', '性别', '质量', '权重', '使用次数', '创建时间', '操作'];
|
||||
const hasAdvancedColumns = expectedColumns.every(col => headers.includes(col));
|
||||
|
||||
return {
|
||||
hasTable: true,
|
||||
headerCount: headers.length,
|
||||
headers: headers,
|
||||
rowCount: rows.length,
|
||||
hasAdvancedColumns: hasAdvancedColumns,
|
||||
expectedColumns: expectedColumns
|
||||
};
|
||||
});
|
||||
|
||||
testResults.tableOperations = tableTest.hasTable && tableTest.hasAdvancedColumns;
|
||||
|
||||
console.log(`${testResults.tableOperations ? '✅' : '❌'} 数据表格测试:`);
|
||||
console.log(` - 表格存在: ${tableTest.hasTable}`);
|
||||
console.log(` - 列数: ${tableTest.headerCount}`);
|
||||
console.log(` - 数据行: ${tableTest.rowCount}`);
|
||||
console.log(` - 高级列完整: ${tableTest.hasAdvancedColumns}`);
|
||||
if (!tableTest.hasAdvancedColumns) {
|
||||
console.log(` - 实际列: ${tableTest.headers.join(', ')}`);
|
||||
console.log(` - 期望列: ${tableTest.expectedColumns.join(', ')}`);
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test_04_data_table.png', fullPage: true });
|
||||
|
||||
// ==================== 测试6:API端点 ====================
|
||||
console.log('\n🌐 测试6:API端点访问...');
|
||||
|
||||
// 测试公共API端点
|
||||
const publicApiTests = await Promise.all([
|
||||
fetch('http://localhost:3000/nameTemplate/supportedOptions').then(r => ({ endpoint: 'supportedOptions', status: r.status, ok: r.ok })),
|
||||
fetch('http://localhost:3000/nameTemplate/generatorStatus').then(r => ({ endpoint: 'generatorStatus', status: r.status, ok: r.ok }))
|
||||
].map(p => p.catch(err => ({ error: err.message }))));
|
||||
|
||||
console.log('📡 公共API测试结果:');
|
||||
publicApiTests.forEach(result => {
|
||||
if (result.error) {
|
||||
console.log(` ❌ ${result.endpoint || 'Unknown'}: ${result.error}`);
|
||||
} else {
|
||||
console.log(` ${result.ok ? '✅' : '❌'} ${result.endpoint}: ${result.status}`);
|
||||
testResults.apiEndpoints[result.endpoint] = { status: result.status, success: result.ok };
|
||||
}
|
||||
});
|
||||
|
||||
// ==================== 汇总测试结果 ====================
|
||||
console.log('\n📊 测试结果汇总:');
|
||||
console.log('==========================================');
|
||||
|
||||
const allTests = [
|
||||
{ name: '系统状态面板', result: testResults.statusPanel },
|
||||
{ name: '智能生成功能', result: testResults.generateFunction },
|
||||
{ name: '添加模板功能', result: testResults.addTemplate },
|
||||
{ name: '搜索过滤功能', result: testResults.searchFilter },
|
||||
{ name: '数据表格操作', result: testResults.tableOperations }
|
||||
];
|
||||
|
||||
let passedTests = 0;
|
||||
allTests.forEach(test => {
|
||||
console.log(`${test.result ? '✅' : '❌'} ${test.name}: ${test.result ? '通过' : '失败'}`);
|
||||
if (test.result) passedTests++;
|
||||
});
|
||||
|
||||
console.log('\n🌐 API端点测试:');
|
||||
Object.entries(testResults.apiEndpoints).forEach(([endpoint, result]) => {
|
||||
console.log(`${result.success ? '✅' : '❌'} ${endpoint}: ${result.status}`);
|
||||
});
|
||||
|
||||
const successRate = Math.round((passedTests / allTests.length) * 100);
|
||||
console.log(`\n📈 总体测试通过率: ${passedTests}/${allTests.length} (${successRate}%)`);
|
||||
|
||||
if (successRate < 100) {
|
||||
console.log('\n⚠️ 需要修复的问题:');
|
||||
allTests.forEach(test => {
|
||||
if (!test.result) {
|
||||
console.log(` - ${test.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test_05_final_result.png', fullPage: true });
|
||||
|
||||
console.log('\n📂 测试截图已保存:');
|
||||
console.log(' - test_01_status_panel.png');
|
||||
console.log(' - test_02_generate_function.png');
|
||||
console.log(' - test_03_add_modal.png');
|
||||
console.log(' - test_04_data_table.png');
|
||||
console.log(' - test_05_final_result.png');
|
||||
|
||||
console.log('\n⏰ 浏览器将保持打开10秒供检查...');
|
||||
await page.waitForTimeout(10000);
|
||||
|
||||
return testResults;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试失败:', error.message);
|
||||
if (page) {
|
||||
await page.screenshot({ path: 'test_error.png', fullPage: true });
|
||||
}
|
||||
return testResults;
|
||||
} finally {
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
}
|
||||
console.log('🏁 全面测试结束');
|
||||
}
|
||||
}
|
||||
|
||||
// 导出模块和直接运行
|
||||
if (require.main === module) {
|
||||
comprehensiveTest().then(results => {
|
||||
console.log('\n🎯 最终测试结果:', JSON.stringify(results, null, 2));
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
module.exports = comprehensiveTest;
|
||||
Reference in New Issue
Block a user