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

432 lines
14 KiB
TypeScript

/**
* 账号管理功能端到端测试
* 测试账号列表、创建、编辑、删除等功能
*/
import { test, expect, Page } from '@playwright/test';
const TEST_CONFIG = {
baseURL: 'http://localhost:5173',
timeout: 30000,
adminUser: {
username: 'admin',
password: '111111',
},
};
// 测试账号数据
const TEST_ACCOUNT = {
username: 'test_telegram_' + Date.now(),
nickname: '测试账号',
phone: '13800138000',
email: 'test@example.com',
status: 'active',
remark: '这是一个测试账号',
};
test.describe('账号管理功能测试', () => {
test.beforeEach(async ({ page }) => {
test.setTimeout(TEST_CONFIG.timeout);
// 登录系统
await page.goto(TEST_CONFIG.baseURL);
await loginAsAdmin(page);
// 导航到账号管理页面
await page.click('[data-testid="menu-account"]');
await page.click('[data-testid="menu-account-list"]');
await page.waitForURL(/\/account\/list/);
});
test('应该正确显示账号列表页面', async ({ page }) => {
// 检查页面标题
await expect(page.locator('.page-title')).toContainText(
/账号列表|Telegram账号管理/,
);
// 检查搜索表单
await expect(page.locator('[data-testid="search-username"]')).toBeVisible();
await expect(page.locator('[data-testid="search-status"]')).toBeVisible();
await expect(page.locator('[data-testid="search-button"]')).toBeVisible();
await expect(page.locator('[data-testid="reset-button"]')).toBeVisible();
// 检查操作按钮
await expect(
page.locator('[data-testid="add-account-button"]'),
).toBeVisible();
await expect(
page.locator('[data-testid="batch-delete-button"]'),
).toBeVisible();
await expect(page.locator('[data-testid="export-button"]')).toBeVisible();
// 检查表格
await expect(page.locator('.ant-table')).toBeVisible();
await expect(page.locator('.ant-table-thead')).toBeVisible();
});
test('搜索功能应该正常工作', async ({ page }) => {
// 输入搜索条件
await page.fill('[data-testid="search-username"]', 'admin');
await page.selectOption('[data-testid="search-status"]', 'active');
// 点击搜索
await page.click('[data-testid="search-button"]');
// 等待搜索结果加载
await page.waitForTimeout(1000);
// 检查是否显示了搜索结果
await expect(page.locator('.ant-table-tbody tr')).toHaveCount({ min: 1 });
// 检查搜索结果是否包含关键词
const firstRowUsername = await page
.locator('.ant-table-tbody tr:first-child td:nth-child(2)')
.textContent();
expect(firstRowUsername).toContain('admin');
// 测试重置功能
await page.click('[data-testid="reset-button"]');
await expect(page.locator('[data-testid="search-username"]')).toHaveValue(
'',
);
});
test('应该能创建新账号', async ({ page }) => {
// 点击添加账号按钮
await page.click('[data-testid="add-account-button"]');
// 等待弹窗出现
await expect(page.locator('.ant-modal')).toBeVisible();
await expect(page.locator('.ant-modal-title')).toContainText(
/添加账号|新增Telegram账号/,
);
// 填写表单数据
await page.fill('[data-testid="form-username"]', TEST_ACCOUNT.username);
await page.fill('[data-testid="form-nickname"]', TEST_ACCOUNT.nickname);
await page.fill('[data-testid="form-phone"]', TEST_ACCOUNT.phone);
await page.fill('[data-testid="form-email"]', TEST_ACCOUNT.email);
await page.selectOption('[data-testid="form-status"]', TEST_ACCOUNT.status);
await page.fill('[data-testid="form-remark"]', TEST_ACCOUNT.remark);
// 提交表单
await page.click('[data-testid="form-submit"]');
// 等待成功消息
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText(
/创建成功|添加成功/,
);
// 弹窗应该关闭
await expect(page.locator('.ant-modal')).not.toBeVisible();
// 在列表中应该能找到新创建的账号
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
const foundAccount = page
.locator('.ant-table-tbody tr')
.filter({ hasText: TEST_ACCOUNT.username });
await expect(foundAccount).toBeVisible();
});
test('表单验证应该正常工作', async ({ page }) => {
await page.click('[data-testid="add-account-button"]');
await expect(page.locator('.ant-modal')).toBeVisible();
// 不填写必填字段直接提交
await page.click('[data-testid="form-submit"]');
// 应该显示验证错误
await expect(page.locator('.ant-form-item-explain-error')).toContainText(
/请输入用户名|用户名不能为空/,
);
// 输入无效的邮箱格式
await page.fill('[data-testid="form-username"]', 'test_user');
await page.fill('[data-testid="form-email"]', 'invalid-email');
await page.click('[data-testid="form-submit"]');
// 应该显示邮箱格式错误
await expect(page.locator('.ant-form-item-explain-error')).toContainText(
/邮箱格式不正确|请输入有效的邮箱地址/,
);
// 关闭弹窗
await page.click('.ant-modal-close');
});
test('应该能编辑账号信息', async ({ page }) => {
// 先搜索刚才创建的账号
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
// 点击编辑按钮
const editButton = page
.locator('.ant-table-tbody tr')
.filter({ hasText: TEST_ACCOUNT.username })
.locator('[data-testid="edit-button"]');
await editButton.click();
// 等待编辑弹窗出现
await expect(page.locator('.ant-modal')).toBeVisible();
await expect(page.locator('.ant-modal-title')).toContainText(
/编辑账号|修改账号信息/,
);
// 修改昵称
const newNickname = '已修改的测试账号';
await page.fill('[data-testid="form-nickname"]', newNickname);
// 提交修改
await page.click('[data-testid="form-submit"]');
// 等待成功消息
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText(
/修改成功|更新成功/,
);
// 验证修改是否生效
await page.reload();
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
const updatedRow = page
.locator('.ant-table-tbody tr')
.filter({ hasText: TEST_ACCOUNT.username });
await expect(updatedRow).toContainText(newNickname);
});
test('应该能查看账号详情', async ({ page }) => {
// 搜索账号
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
// 点击查看按钮
const viewButton = page
.locator('.ant-table-tbody tr')
.filter({ hasText: TEST_ACCOUNT.username })
.locator('[data-testid="view-button"]');
await viewButton.click();
// 等待详情弹窗出现
await expect(page.locator('.ant-modal')).toBeVisible();
await expect(page.locator('.ant-modal-title')).toContainText(
/账号详情|查看账号信息/,
);
// 检查详情信息是否正确显示
await expect(page.locator('[data-testid="detail-username"]')).toContainText(
TEST_ACCOUNT.username,
);
await expect(page.locator('[data-testid="detail-phone"]')).toContainText(
TEST_ACCOUNT.phone,
);
await expect(page.locator('[data-testid="detail-email"]')).toContainText(
TEST_ACCOUNT.email,
);
// 关闭详情弹窗
await page.click('.ant-modal-close');
});
test('账号状态切换应该正常工作', async ({ page }) => {
// 搜索账号
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
const accountRow = page
.locator('.ant-table-tbody tr')
.filter({ hasText: TEST_ACCOUNT.username });
// 点击状态切换按钮
const statusSwitch = accountRow.locator('[data-testid="status-switch"]');
await statusSwitch.click();
// 确认状态变更
await page.click('[data-testid="confirm-status-change"]');
// 等待成功消息
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText(
/状态更新成功|操作成功/,
);
});
test('批量操作应该正常工作', async ({ page }) => {
// 选择多个账号
const checkboxes = page.locator('.ant-table-tbody .ant-checkbox-input');
await checkboxes.first().check();
await checkboxes.nth(1).check();
// 批量删除按钮应该变为可用状态
await expect(
page.locator('[data-testid="batch-delete-button"]'),
).not.toBeDisabled();
// 点击批量删除
await page.click('[data-testid="batch-delete-button"]');
// 确认删除操作
await expect(page.locator('.ant-modal-confirm')).toBeVisible();
await page.click('.ant-btn-primary');
// 等待操作完成
await expect(page.locator('.ant-message-success')).toBeVisible();
});
test('导出功能应该正常工作', async ({ page }) => {
// 设置下载事件监听
const downloadPromise = page.waitForEvent('download');
// 点击导出按钮
await page.click('[data-testid="export-button"]');
// 等待下载开始
const download = await downloadPromise;
// 验证下载文件名
expect(download.suggestedFilename()).toMatch(/账号列表.*\.xlsx$/);
});
test('分页功能应该正常工作', async ({ page }) => {
// 检查分页组件是否存在
await expect(page.locator('.ant-pagination')).toBeVisible();
// 如果有多页数据,测试分页切换
const nextButton = page.locator('.ant-pagination-next');
const isNextEnabled = await nextButton.isEnabled();
if (isNextEnabled) {
// 点击下一页
await nextButton.click();
await page.waitForTimeout(1000);
// 检查页码是否改变
await expect(page.locator('.ant-pagination-item-active')).toContainText(
'2',
);
// 点击上一页
await page.click('.ant-pagination-prev');
await page.waitForTimeout(1000);
// 检查是否回到第一页
await expect(page.locator('.ant-pagination-item-active')).toContainText(
'1',
);
}
});
test('表格排序功能应该正常工作', async ({ page }) => {
// 点击用户名列的排序按钮
const usernameHeader = page
.locator('.ant-table-thead th')
.filter({ hasText: /用户名|Username/ });
await usernameHeader.locator('.ant-table-column-sorter').click();
// 等待排序完成
await page.waitForTimeout(1000);
// 检查是否有排序指示器
await expect(
usernameHeader.locator(
'.ant-table-column-sorter-up.active, .ant-table-column-sorter-down.active',
),
).toBeVisible();
});
test('应该能删除账号', async ({ page }) => {
// 搜索要删除的测试账号
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
// 点击删除按钮
const deleteButton = page
.locator('.ant-table-tbody tr')
.filter({ hasText: TEST_ACCOUNT.username })
.locator('[data-testid="delete-button"]');
await deleteButton.click();
// 确认删除
await expect(page.locator('.ant-modal-confirm')).toBeVisible();
await page.click('.ant-btn-primary');
// 等待删除成功消息
await expect(page.locator('.ant-message-success')).toBeVisible();
await expect(page.locator('.ant-message-success')).toContainText(
/删除成功|操作成功/,
);
// 验证账号已被删除
await page.reload();
await page.fill('[data-testid="search-username"]', TEST_ACCOUNT.username);
await page.click('[data-testid="search-button"]');
await page.waitForTimeout(1000);
await expect(page.locator('.ant-empty')).toBeVisible();
});
});
test.describe('账号导入功能测试', () => {
test.beforeEach(async ({ page }) => {
await page.goto(TEST_CONFIG.baseURL);
await loginAsAdmin(page);
// 导航到账号导入页面
await page.click('[data-testid="menu-account"]');
await page.click('[data-testid="menu-account-import"]');
await page.waitForURL(/\/account\/import/);
});
test('应该正确显示导入页面', async ({ page }) => {
// 检查页面标题
await expect(page.locator('.page-title')).toContainText(
/账号导入|批量导入/,
);
// 检查上传组件
await expect(page.locator('.ant-upload-dragger')).toBeVisible();
// 检查模板下载链接
await expect(
page.locator('[data-testid="download-template"]'),
).toBeVisible();
// 检查导入记录表格
await expect(page.locator('.ant-table')).toBeVisible();
});
test('应该能下载导入模板', async ({ page }) => {
const downloadPromise = page.waitForEvent('download');
// 点击下载模板
await page.click('[data-testid="download-template"]');
const download = await downloadPromise;
expect(download.suggestedFilename()).toMatch(/账号导入模板.*\.xlsx$/);
});
});
// 辅助函数:管理员登录
async function loginAsAdmin(page: Page) {
await page.fill(
'[data-testid="username-input"]',
TEST_CONFIG.adminUser.username,
);
await page.fill(
'[data-testid="password-input"]',
TEST_CONFIG.adminUser.password,
);
await page.click('[data-testid="login-button"]');
await page.waitForURL(/\/dashboard/, { timeout: 10000 });
}