2026-03-02 13:31:54 +08:00
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 🖱️ 用户前端操作测试
|
|
|
|
|
|
* 模拟真实用户查看和操作前端界面
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('👤 用户前端操作测试', () => {
|
2026-03-23 13:02:36 +08:00
|
|
|
|
|
2026-03-23 18:42:57 +08:00
|
|
|
|
const FRONTEND_URL = process.env.H5_BASE_URL || 'http://localhost:5176';
|
2026-03-02 13:31:54 +08:00
|
|
|
|
const API_BASE_URL = 'http://localhost:8080';
|
2026-03-23 13:02:36 +08:00
|
|
|
|
|
2026-03-02 13:31:54 +08:00
|
|
|
|
test.beforeEach(async ({ page }) => {
|
2026-03-23 13:02:36 +08:00
|
|
|
|
// 先设置localStorage,然后访问页面
|
|
|
|
|
|
await page.addInitScript(() => {
|
2026-03-02 13:31:54 +08:00
|
|
|
|
localStorage.setItem('test-mode', 'true');
|
|
|
|
|
|
localStorage.setItem('user-token', 'test-token-' + Date.now());
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('📄 用户查看前端页面内容', async ({ page }) => {
|
|
|
|
|
|
await test.step('访问前端首页', async () => {
|
|
|
|
|
|
await page.goto(FRONTEND_URL);
|
|
|
|
|
|
|
|
|
|
|
|
// 等待页面加载
|
|
|
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
|
|
|
|
|
|
// 验证页面有标题
|
|
|
|
|
|
const title = await page.title();
|
|
|
|
|
|
console.log(' 页面标题:', title);
|
|
|
|
|
|
|
|
|
|
|
|
// 截图记录页面状态
|
|
|
|
|
|
await page.screenshot({
|
|
|
|
|
|
path: 'test-results/user-frontend-initial.png',
|
|
|
|
|
|
fullPage: true
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await test.step('检查页面基本元素', async () => {
|
2026-03-23 13:02:36 +08:00
|
|
|
|
// 等待Vue应用渲染
|
|
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
|
|
// 检查页面是否有Vue应用挂载
|
|
|
|
|
|
await expect(page.locator('#app')).toBeAttached();
|
2026-03-02 13:31:54 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取页面文本内容
|
|
|
|
|
|
const pageText = await page.textContent('body');
|
|
|
|
|
|
if (pageText && pageText.trim()) {
|
|
|
|
|
|
console.log(' 页面内容预览:', pageText.substring(0, 100) + '...');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('🖱️ 用户点击页面元素', async ({ page }) => {
|
|
|
|
|
|
await test.step('查找可点击元素', async () => {
|
|
|
|
|
|
await page.goto(FRONTEND_URL);
|
|
|
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
|
|
|
|
|
|
// 查找所有按钮
|
|
|
|
|
|
const buttons = page.locator('button');
|
|
|
|
|
|
const buttonCount = await buttons.count();
|
|
|
|
|
|
console.log(` 找到 ${buttonCount} 个按钮`);
|
|
|
|
|
|
|
|
|
|
|
|
// 查找所有链接
|
|
|
|
|
|
const links = page.locator('a');
|
|
|
|
|
|
const linkCount = await links.count();
|
|
|
|
|
|
console.log(` 找到 ${linkCount} 个链接`);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有按钮,尝试点击第一个
|
|
|
|
|
|
if (buttonCount > 0) {
|
|
|
|
|
|
const firstButton = buttons.first();
|
|
|
|
|
|
const buttonText = await firstButton.textContent();
|
|
|
|
|
|
console.log(` 第一个按钮文本: ${buttonText}`);
|
|
|
|
|
|
|
|
|
|
|
|
// 截图点击前
|
|
|
|
|
|
await page.screenshot({
|
|
|
|
|
|
path: 'test-results/user-frontend-before-click.png',
|
|
|
|
|
|
fullPage: true
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('📱 响应式布局测试', async ({ page }) => {
|
|
|
|
|
|
const viewports = [
|
|
|
|
|
|
{ width: 375, height: 667, name: 'mobile' },
|
|
|
|
|
|
{ width: 768, height: 1024, name: 'tablet' },
|
|
|
|
|
|
{ width: 1280, height: 720, name: 'desktop' }
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
for (const viewport of viewports) {
|
|
|
|
|
|
await test.step(`检查${viewport.name}端布局`, async () => {
|
|
|
|
|
|
await page.setViewportSize({
|
|
|
|
|
|
width: viewport.width,
|
|
|
|
|
|
height: viewport.height
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await page.goto(FRONTEND_URL);
|
|
|
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
|
|
|
|
|
|
// 截图记录不同设备的显示效果
|
|
|
|
|
|
await page.screenshot({
|
|
|
|
|
|
path: `test-results/user-frontend-${viewport.name}.png`,
|
|
|
|
|
|
fullPage: true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log(` ${viewport.name}端截图完成`);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('🔗 验证前后端API连通性', async ({ request }) => {
|
|
|
|
|
|
await test.step('测试后端健康检查API', async () => {
|
|
|
|
|
|
const response = await request.get(`${API_BASE_URL}/actuator/health`);
|
|
|
|
|
|
|
|
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
|
|
|
|
|
|
|
|
const body = await response.json();
|
|
|
|
|
|
expect(body.status).toBe('UP');
|
|
|
|
|
|
|
|
|
|
|
|
console.log(' ✅ 后端API连通性正常');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('⏱️ 页面加载性能测试', async ({ page }) => {
|
|
|
|
|
|
await test.step('测量页面加载时间', async () => {
|
|
|
|
|
|
const startTime = Date.now();
|
|
|
|
|
|
|
|
|
|
|
|
await page.goto(FRONTEND_URL);
|
|
|
|
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
|
|
|
|
|
|
|
|
const endTime = Date.now();
|
|
|
|
|
|
const loadTime = endTime - startTime;
|
|
|
|
|
|
|
|
|
|
|
|
console.log(` 页面加载时间: ${loadTime}ms`);
|
|
|
|
|
|
|
2026-03-26 15:59:53 +08:00
|
|
|
|
// 验证加载时间在合理范围内(小于15秒,放宽限制以适应E2E环境波动)
|
|
|
|
|
|
expect(loadTime).toBeLessThan(15000);
|
2026-03-02 13:31:54 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|