Files
multiAgentTry/frontend/tests/e2e-workflow.spec.ts

268 lines
9.4 KiB
TypeScript
Raw Permalink Normal View History

import { test, expect, Page } from '@playwright/test';
/**
* Swarm Command Center -
*
*/
// 辅助函数:等待页面加载完成
async function waitForPageLoad(page: Page) {
await page.waitForLoadState('networkidle');
await page.waitForSelector('text=Swarm Center', { state: 'visible' });
}
// 辅助函数:导航到指定页面
async function navigateTo(page: Page, menuText: string) {
await page.click(`text=${menuText}`);
await page.waitForLoadState('networkidle');
}
test.describe('端到端工作流测试', () => {
const baseUrl = 'http://localhost:3000';
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await waitForPageLoad(page);
});
test('完整用户旅程 - 从仪表盘到各功能模块', async ({ page }) => {
// 1. 验证仪表盘首页
await expect(page.locator('h1:has-text("仪表盘")')).toBeVisible();
await expect(page.locator('text=系统概览与实时监控')).toBeVisible();
// 2. 点击统计卡片导航到 Agent 管理
await page.click('text=Agent 总数');
await expect(page).toHaveURL(/\/agents/);
await expect(page.locator('h1:has-text("Agent 管理")')).toBeVisible();
// 3. 返回仪表盘
await navigateTo(page, '仪表盘');
await expect(page).toHaveURL(/\/$/);
// 4. 点击会议统计卡片
await page.click('text=今日会议');
await expect(page).toHaveURL(/\/meetings/);
await expect(page.locator('h1:has-text("会议管理")')).toBeVisible();
});
test('Agent 管理 - 完整 CRUD 流程', async ({ page }) => {
await navigateTo(page, 'Agent 管理');
// 1. 检查页面元素
await expect(page.locator('button:has-text("注册 Agent")')).toBeVisible();
await expect(page.locator('input[placeholder="搜索 Agent..."]')).toBeVisible();
// 2. 打开注册对话框
await page.click('button:has-text("注册 Agent")');
await expect(page.locator('text=注册新 Agent')).toBeVisible();
// 3. 填写表单
const testAgentName = `TestAgent-${Date.now()}`;
await page.fill('input[name="name"]', testAgentName);
await page.fill('input[name="model"]', 'gpt-4');
await page.selectOption('select[name="role"]', 'developer');
await page.fill('textarea[name="description"]', 'Playwright 端到端测试用 Agent');
// 4. 验证表单填写成功
await expect(page.locator('input[name="name"]')).toHaveValue(testAgentName);
await expect(page.locator('select[name="role"]')).toHaveValue('developer');
// 5. 关闭对话框(取消提交,避免影响实际数据)
await page.click('button:has-text("取消")');
await expect(page.locator('text=注册新 Agent')).not.toBeVisible();
// 6. 测试搜索功能
await page.fill('input[placeholder="搜索 Agent..."]', 'nonexistent');
await expect(page.locator('text=没有找到匹配的 Agent')).toBeVisible();
});
test('会议管理 - 创建会议流程', async ({ page }) => {
await navigateTo(page, '会议管理');
// 1. 检查页面元素
await expect(page.locator('button:has-text("创建会议")')).toBeVisible();
// 2. 打开创建会议对话框
await page.click('button:has-text("创建会议")');
await expect(page.locator('text=创建新会议')).toBeVisible();
// 3. 填写会议表单
const testMeetingTitle = `TestMeeting-${Date.now()}`;
await page.fill('input[name="title"]', testMeetingTitle);
await page.fill('textarea[name="agenda"]', '测试议程内容\n1. 测试项1\n2. 测试项2');
await page.selectOption('select[name="type"]', 'design_review');
// 4. 添加参与者
await page.click('button:has-text("添加参与者")');
// 注:实际实现可能需要选择具体的 Agent
// 5. 验证表单填写
await expect(page.locator('input[name="title"]')).toHaveValue(testMeetingTitle);
// 6. 关闭对话框
await page.click('button:has-text("取消")');
await expect(page.locator('text=创建新会议')).not.toBeVisible();
});
test('资源监控 - 切换标签页和数据展示', async ({ page }) => {
await navigateTo(page, '资源监控');
// 1. 验证标签页存在
const tabs = ['文件锁', '心跳状态', 'Agent 状态'];
for (const tab of tabs) {
await expect(page.locator(`button:has-text("${tab}")`)).toBeVisible();
}
// 2. 切换标签页
await page.click('button:has-text("心跳状态")');
await page.waitForTimeout(300); // 等待切换动画
await page.click('button:has-text("Agent 状态")');
await page.waitForTimeout(300);
await page.click('button:has-text("文件锁")');
await page.waitForTimeout(300);
// 3. 验证刷新按钮
await expect(page.locator('button:has-text("刷新")')).toBeVisible();
await page.click('button:has-text("刷新")');
await expect(page.locator('text=加载中...')).not.toBeVisible();
});
test('工作流页面 - 工作流操作', async ({ page }) => {
await navigateTo(page, '工作流');
// 1. 验证页面元素
await expect(page.locator('h1:has-text("工作流")')).toBeVisible();
await expect(page.locator('button:has-text("新建工作流")')).toBeVisible();
// 2. 打开新建工作流对话框
await page.click('button:has-text("新建工作流")');
await expect(page.locator('text=新建工作流')).toBeVisible();
// 3. 填写工作流名称
const workflowName = `TestWorkflow-${Date.now()}`;
await page.fill('input[name="name"]', workflowName);
// 4. 关闭对话框
await page.click('button:has-text("取消")');
});
test('系统配置 - 保存设置', async ({ page }) => {
await navigateTo(page, '配置');
// 1. 验证页面元素
await expect(page.locator('h1:has-text("系统配置")')).toBeVisible();
await expect(page.locator('text=API 基础地址')).toBeVisible();
// 2. 修改配置
await page.fill('input[name="apiBaseUrl"]', 'http://localhost:9000');
await page.fill('input[name="heartbeatInterval"]', '15');
// 3. 保存配置
await page.click('button:has-text("保存配置")');
// 4. 验证成功提示
await expect(page.locator('text=配置已保存')).toBeVisible();
// 5. 恢复原始配置
await page.fill('input[name="apiBaseUrl"]', 'http://localhost:8000');
await page.fill('input[name="heartbeatInterval"]', '30');
await page.click('button:has-text("保存配置")');
});
test('响应式布局 - 侧边栏折叠展开', async ({ page }) => {
// 1. 验证侧边栏默认展开
await expect(page.locator('text=仪表盘')).toBeVisible();
await expect(page.locator('text=Agent 管理')).toBeVisible();
// 2. 测试移动端视图(如果支持)
await page.setViewportSize({ width: 375, height: 667 });
await page.waitForTimeout(500);
// 3. 恢复桌面视图
await page.setViewportSize({ width: 1280, height: 720 });
await page.waitForTimeout(500);
// 4. 验证侧边栏仍然可见
await expect(page.locator('text=仪表盘')).toBeVisible();
});
});
test.describe('错误处理和边界情况', () => {
const baseUrl = 'http://localhost:3000';
test('后端连接失败时的错误显示', async ({ page }) => {
// 模拟后端不可用的情况
await page.route('http://localhost:8000/api/**', (route) => {
route.abort('failed');
});
await page.goto(baseUrl);
await waitForPageLoad(page);
// 验证错误提示显示
await expect(page.locator('text=连接后端失败')).toBeVisible();
});
test('404 页面处理', async ({ page }) => {
await page.goto(`${baseUrl}/nonexistent-page`);
await waitForPageLoad(page);
// 应该重定向到首页
await expect(page).toHaveURL(/\/$/);
await expect(page.locator('h1:has-text("仪表盘")')).toBeVisible();
});
test('快速导航切换', async ({ page }) => {
await page.goto(baseUrl);
await waitForPageLoad(page);
// 快速切换多个页面
const pages = ['Agent 管理', '会议管理', '资源监控', '工作流', '配置'];
for (const pageName of pages) {
await navigateTo(page, pageName);
}
// 最后回到仪表盘
await navigateTo(page, '仪表盘');
await expect(page.locator('h1:has-text("仪表盘")')).toBeVisible();
});
});
test.describe('性能和加载测试', () => {
const baseUrl = 'http://localhost:3000';
test('页面加载性能', async ({ page }) => {
const startTime = Date.now();
await page.goto(baseUrl);
await waitForPageLoad(page);
const loadTime = Date.now() - startTime;
// 验证页面加载时间在合理范围内5秒内
expect(loadTime).toBeLessThan(5000);
// 验证关键元素渲染
await expect(page.locator('h1:has-text("仪表盘")')).toBeVisible();
});
test('数据刷新功能', async ({ page }) => {
await page.goto(baseUrl);
await waitForPageLoad(page);
// 等待自动刷新间隔10秒
// 这里我们只是验证初始加载成功
await expect(page.locator('text=自动刷新')).toBeVisible();
await expect(page.locator('text=10 秒')).toBeVisible();
});
test('大量数据渲染性能', async ({ page }) => {
// 这个测试需要后端返回大量数据
// 目前只是验证页面结构可以支持列表渲染
await navigateTo(page, 'Agent 管理');
// 验证列表容器存在
await expect(page.locator('[data-testid="agent-list"]').or(page.locator('text=暂无 Agent 数据'))).toBeVisible();
});
});