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>
432 lines
15 KiB
JavaScript
432 lines
15 KiB
JavaScript
const { test, expect } = require('@playwright/test');
|
||
|
||
/**
|
||
* 统一注册系统端到端测试
|
||
* 测试批量注册功能的完整流程
|
||
*/
|
||
|
||
test.describe('统一注册系统测试', () => {
|
||
test.beforeEach(async ({ page }) => {
|
||
// 设置视口大小
|
||
await page.setViewportSize({ width: 1920, height: 1080 });
|
||
|
||
// 访问系统首页
|
||
await page.goto('http://localhost:8890');
|
||
|
||
// 等待页面加载
|
||
await page.waitForLoadState('networkidle');
|
||
});
|
||
|
||
test('1. 页面访问和布局验证', async ({ page }) => {
|
||
console.log('🧪 测试1: 页面访问和布局验证');
|
||
|
||
// 1.1 导航到统一注册页面
|
||
console.log('📍 步骤 1.1: 查找并点击统一注册系统菜单');
|
||
|
||
// 等待侧边栏加载
|
||
await page.waitForSelector('.ivu-menu', { timeout: 10000 });
|
||
|
||
// 查找账号管理菜单
|
||
const accountManageMenu = page.locator('text=账号管理').first();
|
||
if (await accountManageMenu.isVisible()) {
|
||
await accountManageMenu.click();
|
||
console.log('✅ 账号管理菜单已展开');
|
||
}
|
||
|
||
// 查找统一注册系统菜单项
|
||
const unifiedRegisterMenu = page.locator('text=统一注册系统').first();
|
||
await expect(unifiedRegisterMenu).toBeVisible({ timeout: 5000 });
|
||
await unifiedRegisterMenu.click();
|
||
console.log('✅ 统一注册系统菜单项已点击');
|
||
|
||
// 1.2 验证页面URL
|
||
console.log('📍 步骤 1.2: 验证页面URL');
|
||
await expect(page).toHaveURL(/.*unifiedRegister.*/, { timeout: 5000 });
|
||
console.log('✅ 页面URL正确');
|
||
|
||
// 1.3 验证页面标题
|
||
console.log('📍 步骤 1.3: 验证页面标题和描述');
|
||
await expect(page.locator('h2:has-text("统一注册系统")')).toBeVisible();
|
||
await expect(page.locator('text=基于策略模式的Telegram账号注册系统')).toBeVisible();
|
||
console.log('✅ 页面标题和描述显示正确');
|
||
|
||
// 1.4 验证策略选择区域
|
||
console.log('📍 步骤 1.4: 验证策略选择区域');
|
||
await expect(page.locator('text=选择注册策略')).toBeVisible();
|
||
await expect(page.locator('text=批量注册')).toBeVisible();
|
||
await expect(page.locator('text=连续注册')).toBeVisible();
|
||
console.log('✅ 策略选择区域显示正确');
|
||
|
||
// 1.5 验证配置面板
|
||
console.log('📍 步骤 1.5: 验证配置面板');
|
||
await expect(page.locator('text=注册配置')).toBeVisible();
|
||
await expect(page.locator('text=基础配置')).toBeVisible();
|
||
console.log('✅ 配置面板显示正确');
|
||
|
||
// 1.6 验证操作按钮
|
||
console.log('📍 步骤 1.6: 验证操作按钮');
|
||
await expect(page.locator('button:has-text("开始注册")')).toBeVisible();
|
||
await expect(page.locator('button:has-text("暂停")')).toBeVisible();
|
||
await expect(page.locator('button:has-text("停止注册")')).toBeVisible();
|
||
console.log('✅ 操作按钮显示正确');
|
||
});
|
||
|
||
test('2. 批量注册策略配置测试', async ({ page }) => {
|
||
console.log('🧪 测试2: 批量注册策略配置测试');
|
||
|
||
// 导航到页面
|
||
await navigateToUnifiedRegister(page);
|
||
|
||
// 2.1 选择批量注册策略
|
||
console.log('📍 步骤 2.1: 选择批量注册策略');
|
||
const batchRadio = page.locator('input[type="radio"][value="batch"]');
|
||
await batchRadio.check();
|
||
console.log('✅ 批量注册策略已选择');
|
||
|
||
// 2.2 验证批量注册特定配置显示
|
||
console.log('📍 步骤 2.2: 验证批量注册配置选项');
|
||
await expect(page.locator('text=批量注册配置')).toBeVisible();
|
||
await expect(page.locator('text=注册数量')).toBeVisible();
|
||
await expect(page.locator('text=并发数')).toBeVisible();
|
||
await expect(page.locator('text=任务间隔')).toBeVisible();
|
||
console.log('✅ 批量注册配置选项显示正确');
|
||
|
||
// 2.3 填写基础配置
|
||
console.log('📍 步骤 2.3: 填写基础配置');
|
||
|
||
// 选择国家
|
||
const countrySelect = page.locator('select', { hasText: '选择国家' }).first();
|
||
if (await countrySelect.isVisible()) {
|
||
await countrySelect.selectOption('1'); // 俄罗斯
|
||
console.log('✅ 国家已选择');
|
||
}
|
||
|
||
// 选择用途
|
||
const usageSelect = page.locator('select', { hasText: '选择用途' }).first();
|
||
if (await usageSelect.isVisible()) {
|
||
await usageSelect.selectOption('1'); // 营销推广
|
||
console.log('✅ 用途已选择');
|
||
}
|
||
|
||
// 填写AI名字提示词
|
||
const namePromptInput = page.locator('input[placeholder*="AI生成名字"]');
|
||
if (await namePromptInput.isVisible()) {
|
||
await namePromptInput.fill('生成英文名字');
|
||
console.log('✅ AI名字提示词已填写');
|
||
}
|
||
|
||
// 2.4 配置批量注册参数
|
||
console.log('📍 步骤 2.4: 配置批量注册参数');
|
||
|
||
// 设置注册数量
|
||
const quantityInput = page.locator('input[placeholder*="注册数量"]');
|
||
if (await quantityInput.isVisible()) {
|
||
await quantityInput.fill('5');
|
||
console.log('✅ 注册数量设置为5');
|
||
}
|
||
|
||
// 设置并发数
|
||
const concurrencyInput = page.locator('input[placeholder*="并发数"]');
|
||
if (await concurrencyInput.isVisible()) {
|
||
await concurrencyInput.fill('2');
|
||
console.log('✅ 并发数设置为2');
|
||
}
|
||
|
||
// 设置任务间隔
|
||
const intervalInput = page.locator('input[placeholder*="任务间隔"]');
|
||
if (await intervalInput.isVisible()) {
|
||
await intervalInput.fill('3000');
|
||
console.log('✅ 任务间隔设置为3000ms');
|
||
}
|
||
});
|
||
|
||
test('3. 连续注册策略配置测试', async ({ page }) => {
|
||
console.log('🧪 测试3: 连续注册策略配置测试');
|
||
|
||
// 导航到页面
|
||
await navigateToUnifiedRegister(page);
|
||
|
||
// 3.1 选择连续注册策略
|
||
console.log('📍 步骤 3.1: 选择连续注册策略');
|
||
const continuousRadio = page.locator('input[type="radio"][value="continuous"]');
|
||
await continuousRadio.check();
|
||
console.log('✅ 连续注册策略已选择');
|
||
|
||
// 3.2 验证连续注册特定配置显示
|
||
console.log('📍 步骤 3.2: 验证连续注册配置选项');
|
||
await expect(page.locator('text=连续注册配置')).toBeVisible();
|
||
await expect(page.locator('text=每批数量')).toBeVisible();
|
||
await expect(page.locator('text=每日限制')).toBeVisible();
|
||
await expect(page.locator('text=批次间隔')).toBeVisible();
|
||
console.log('✅ 连续注册配置选项显示正确');
|
||
|
||
// 3.3 配置连续注册参数
|
||
console.log('📍 步骤 3.3: 配置连续注册参数');
|
||
|
||
// 设置每批数量(QPS)
|
||
const qpsInput = page.locator('input[placeholder*="每批注册数量"]');
|
||
if (await qpsInput.isVisible()) {
|
||
await qpsInput.fill('3');
|
||
console.log('✅ 每批数量设置为3');
|
||
}
|
||
|
||
// 设置每日限制
|
||
const dailyLimitInput = page.locator('input[placeholder*="每日最大注册数"]');
|
||
if (await dailyLimitInput.isVisible()) {
|
||
await dailyLimitInput.fill('50');
|
||
console.log('✅ 每日限制设置为50');
|
||
}
|
||
|
||
// 设置批次间隔
|
||
const batchIntervalInput = page.locator('input[placeholder*="批次间隔"]');
|
||
if (await batchIntervalInput.isVisible()) {
|
||
await batchIntervalInput.fill('5000');
|
||
console.log('✅ 批次间隔设置为5000ms');
|
||
}
|
||
});
|
||
|
||
test('4. 注册功能启动测试', async ({ page }) => {
|
||
console.log('🧪 测试4: 注册功能启动测试');
|
||
|
||
// 导航到页面并配置
|
||
await navigateToUnifiedRegister(page);
|
||
await configureBatchRegistration(page);
|
||
|
||
// 4.1 验证开始按钮状态
|
||
console.log('📍 步骤 4.1: 验证开始按钮状态');
|
||
const startButton = page.locator('button:has-text("开始注册")');
|
||
await expect(startButton).toBeEnabled();
|
||
console.log('✅ 开始按钮已启用');
|
||
|
||
// 4.2 点击开始注册(模拟)
|
||
console.log('📍 步骤 4.2: 点击开始注册按钮');
|
||
await startButton.click();
|
||
|
||
// 等待可能的加载状态
|
||
await page.waitForTimeout(2000);
|
||
|
||
// 4.3 检查是否显示错误信息或状态变化
|
||
console.log('📍 步骤 4.3: 检查响应状态');
|
||
|
||
// 检查是否有错误消息
|
||
const errorMessage = page.locator('.ivu-message-error, .error-message');
|
||
if (await errorMessage.isVisible()) {
|
||
const errorText = await errorMessage.textContent();
|
||
console.log('⚠️ 发现错误信息:', errorText);
|
||
}
|
||
|
||
// 检查是否有成功消息
|
||
const successMessage = page.locator('.ivu-message-success, .success-message');
|
||
if (await successMessage.isVisible()) {
|
||
const successText = await successMessage.textContent();
|
||
console.log('✅ 发现成功信息:', successText);
|
||
}
|
||
|
||
// 检查按钮状态变化
|
||
if (await startButton.locator(':text("停止")').isVisible()) {
|
||
console.log('✅ 按钮状态已更新为停止');
|
||
}
|
||
});
|
||
|
||
test('5. 状态监控面板测试', async ({ page }) => {
|
||
console.log('🧪 测试5: 状态监控面板测试');
|
||
|
||
// 导航到页面
|
||
await navigateToUnifiedRegister(page);
|
||
await configureBatchRegistration(page);
|
||
|
||
// 5.1 检查初始状态
|
||
console.log('📍 步骤 5.1: 检查初始状态面板');
|
||
|
||
// 查找状态面板元素
|
||
const statusPanel = page.locator('.status-panel, [class*="status"], [class*="monitor"]');
|
||
if (await statusPanel.isVisible()) {
|
||
console.log('✅ 状态监控面板可见');
|
||
} else {
|
||
console.log('ℹ️ 状态监控面板在初始状态下不可见(正常)');
|
||
}
|
||
|
||
// 5.2 启动注册以触发状态面板
|
||
console.log('📍 步骤 5.2: 启动注册以触发状态面板');
|
||
const startButton = page.locator('button:has-text("开始注册")');
|
||
await startButton.click();
|
||
|
||
// 等待状态面板出现
|
||
await page.waitForTimeout(3000);
|
||
|
||
// 5.3 验证状态统计卡片
|
||
console.log('📍 步骤 5.3: 验证状态统计卡片');
|
||
|
||
const statCards = [
|
||
'已完成',
|
||
'失败',
|
||
'进行中',
|
||
'总计'
|
||
];
|
||
|
||
for (const cardText of statCards) {
|
||
const card = page.locator(`text=${cardText}`);
|
||
if (await card.isVisible()) {
|
||
console.log(`✅ ${cardText} 统计卡片可见`);
|
||
}
|
||
}
|
||
|
||
// 5.4 检查进度条
|
||
console.log('📍 步骤 5.4: 检查进度条');
|
||
const progressBar = page.locator('.ivu-progress, [class*="progress"]');
|
||
if (await progressBar.isVisible()) {
|
||
console.log('✅ 进度条可见');
|
||
}
|
||
|
||
// 5.5 检查日志面板
|
||
console.log('📍 步骤 5.5: 检查注册日志面板');
|
||
const logPanel = page.locator('.log-panel, [class*="log"]');
|
||
if (await logPanel.isVisible()) {
|
||
console.log('✅ 日志面板可见');
|
||
}
|
||
});
|
||
|
||
test('6. 响应式布局测试', async ({ page }) => {
|
||
console.log('🧪 测试6: 响应式布局测试');
|
||
|
||
await navigateToUnifiedRegister(page);
|
||
|
||
// 6.1 桌面尺寸测试
|
||
console.log('📍 步骤 6.1: 桌面尺寸布局测试');
|
||
await page.setViewportSize({ width: 1920, height: 1080 });
|
||
await page.waitForTimeout(1000);
|
||
|
||
const desktopLayout = page.locator('.unified-register');
|
||
await expect(desktopLayout).toBeVisible();
|
||
console.log('✅ 桌面尺寸布局正常');
|
||
|
||
// 6.2 平板尺寸测试
|
||
console.log('📍 步骤 6.2: 平板尺寸布局测试');
|
||
await page.setViewportSize({ width: 1024, height: 768 });
|
||
await page.waitForTimeout(1000);
|
||
|
||
await expect(desktopLayout).toBeVisible();
|
||
console.log('✅ 平板尺寸布局正常');
|
||
|
||
// 6.3 手机尺寸测试
|
||
console.log('📍 步骤 6.3: 手机尺寸布局测试');
|
||
await page.setViewportSize({ width: 375, height: 667 });
|
||
await page.waitForTimeout(1000);
|
||
|
||
await expect(desktopLayout).toBeVisible();
|
||
console.log('✅ 手机尺寸布局正常');
|
||
|
||
// 恢复桌面尺寸
|
||
await page.setViewportSize({ width: 1920, height: 1080 });
|
||
});
|
||
|
||
test('7. 错误处理测试', async ({ page }) => {
|
||
console.log('🧪 测试7: 错误处理测试');
|
||
|
||
await navigateToUnifiedRegister(page);
|
||
|
||
// 7.1 无效配置测试
|
||
console.log('📍 步骤 7.1: 测试无效配置处理');
|
||
|
||
// 选择批量注册但不填写必要信息
|
||
const batchRadio = page.locator('input[type="radio"][value="batch"]');
|
||
await batchRadio.check();
|
||
|
||
// 不填写配置直接点击开始
|
||
const startButton = page.locator('button:has-text("开始注册")');
|
||
|
||
// 检查按钮是否被禁用
|
||
if (await startButton.isDisabled()) {
|
||
console.log('✅ 配置不完整时开始按钮被正确禁用');
|
||
} else {
|
||
// 如果按钮未被禁用,点击后应该显示错误信息
|
||
await startButton.click();
|
||
await page.waitForTimeout(2000);
|
||
|
||
const errorMessage = page.locator('.ivu-message-error, .error-message');
|
||
if (await errorMessage.isVisible()) {
|
||
console.log('✅ 无效配置时显示错误信息');
|
||
}
|
||
}
|
||
});
|
||
|
||
test('8. API连接测试', async ({ page }) => {
|
||
console.log('🧪 测试8: API连接测试');
|
||
|
||
await navigateToUnifiedRegister(page);
|
||
|
||
// 8.1 检查网络请求
|
||
console.log('📍 步骤 8.1: 监控网络请求');
|
||
|
||
const requests = [];
|
||
page.on('request', request => {
|
||
if (request.url().includes('unifiedRegister')) {
|
||
requests.push(request.url());
|
||
console.log('📡 API请求:', request.method(), request.url());
|
||
}
|
||
});
|
||
|
||
page.on('response', response => {
|
||
if (response.url().includes('unifiedRegister')) {
|
||
console.log('📡 API响应:', response.status(), response.url());
|
||
}
|
||
});
|
||
|
||
// 8.2 触发API调用
|
||
await configureBatchRegistration(page);
|
||
const startButton = page.locator('button:has-text("开始注册")');
|
||
await startButton.click();
|
||
|
||
// 等待可能的网络请求
|
||
await page.waitForTimeout(5000);
|
||
|
||
console.log(`✅ 监控到 ${requests.length} 个相关API请求`);
|
||
});
|
||
});
|
||
|
||
// 辅助函数
|
||
async function navigateToUnifiedRegister(page) {
|
||
console.log('🔧 导航到统一注册页面');
|
||
|
||
// 等待侧边栏
|
||
await page.waitForSelector('.ivu-menu', { timeout: 10000 });
|
||
|
||
// 点击账号管理
|
||
const accountMenu = page.locator('text=账号管理').first();
|
||
if (await accountMenu.isVisible()) {
|
||
await accountMenu.click();
|
||
}
|
||
|
||
// 点击统一注册系统
|
||
const unifiedMenu = page.locator('text=统一注册系统').first();
|
||
await unifiedMenu.click();
|
||
|
||
// 等待页面加载
|
||
await page.waitForLoadState('networkidle');
|
||
await page.waitForTimeout(2000);
|
||
}
|
||
|
||
async function configureBatchRegistration(page) {
|
||
console.log('🔧 配置批量注册');
|
||
|
||
// 选择批量注册
|
||
const batchRadio = page.locator('input[type="radio"][value="batch"]');
|
||
await batchRadio.check();
|
||
|
||
// 填写基础配置
|
||
const countrySelect = page.locator('select').first();
|
||
if (await countrySelect.isVisible()) {
|
||
await countrySelect.selectOption('1');
|
||
}
|
||
|
||
const usageSelect = page.locator('select').nth(1);
|
||
if (await usageSelect.isVisible()) {
|
||
await usageSelect.selectOption('1');
|
||
}
|
||
|
||
// 设置数量
|
||
const quantityInput = page.locator('input[type="number"]').first();
|
||
if (await quantityInput.isVisible()) {
|
||
await quantityInput.fill('3');
|
||
}
|
||
} |