Files
wenzi/frontend/e2e/tests/user-journey-fixed.spec.ts

141 lines
4.4 KiB
TypeScript
Raw Normal View History

import { test, expect } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
/**
* -
*
*
* - test.skip
* - 2xx/3xx
*/
const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:8080';
const FRONTEND_URL = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:5176';
const DEFAULT_TEST_API_KEY = 'test-api-key-000000000000';
const DEFAULT_TEST_USER_TOKEN = 'test-e2e-token';
interface TestData {
activityId: number;
apiKey: string;
userToken: string;
userId: number;
shortCode: string;
baseUrl: string;
apiBaseUrl: string;
}
function loadTestData(): TestData {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const testDataPath = path.join(__dirname, '..', '.e2e-test-data.json');
const defaultData: TestData = {
activityId: 1,
apiKey: DEFAULT_TEST_API_KEY,
userToken: process.env.E2E_USER_TOKEN || DEFAULT_TEST_USER_TOKEN,
userId: 10001,
shortCode: 'test123',
baseUrl: process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:5176',
apiBaseUrl: process.env.API_BASE_URL || 'http://localhost:8080',
};
try {
if (fs.existsSync(testDataPath)) {
const data = JSON.parse(fs.readFileSync(testDataPath, 'utf-8'));
return { ...defaultData, ...data };
}
} catch (error) {
console.warn('无法加载测试数据,使用默认值');
}
return defaultData;
}
function hasRealApiCredentials(data: TestData): boolean {
return Boolean(
data.apiKey &&
data.userToken &&
data.apiKey !== DEFAULT_TEST_API_KEY &&
data.userToken !== DEFAULT_TEST_USER_TOKEN
);
}
// 加载测试数据
const testData = loadTestData();
const useRealCredentials = hasRealApiCredentials(testData);
const E2E_STRICT = process.env.E2E_STRICT === 'true';
test.describe('🎯 用户核心旅程测试(严格模式)', () => {
// 首页不需要凭证,始终执行
test('🏠 首页应可访问(无需凭证)', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('#app')).toBeAttached();
});
if (!useRealCredentials) {
// 严格模式下无真实凭证时必须失败,非严格模式才跳过
if (E2E_STRICT) {
test('📊 活动列表API需要真实凭证', async () => {
throw new Error('严格模式需要真实凭证E2E_USER_TOKEN但未提供有效凭证测试失败');
});
} else {
test.skip('📊 活动列表API需要真实凭证', async ({ request }) => {
// 此测试需要真实凭证,无凭证时跳过
});
}
} else {
// 有真实凭证时严格断言
test('📊 活动列表API - 严格断言', async ({ request }) => {
const response = await request.get(`${API_BASE_URL}/api/v1/activities`, {
headers: {
'X-API-Key': testData.apiKey,
'Authorization': `Bearer ${testData.userToken}`,
},
});
const status = response.status();
// 严格断言:只接受 2xx/3xx
expect(
status,
`活动列表API应返回2xx/3xx实际${status}`
).toBeGreaterThanOrEqual(200);
expect(
status,
`活动列表API应返回2xx/3xx实际${status}`
).toBeLessThan(400);
});
test('后端健康检查应正常 - 严格断言', async ({ request }) => {
const response = await request.get(`${API_BASE_URL}/actuator/health`);
expect(
response.status(),
`健康检查应返回200实际${response.status()}`
).toBe(200);
const body = await response.json();
expect(
body.status,
`健康检查状态应为UP实际${body.status}`
).toBe('UP');
});
test('前端服务应可访问 - 严格断言', async ({ page }) => {
const response = await page.goto(FRONTEND_URL);
expect(
response,
'页面响应不应为null'
).not.toBeNull();
expect(
response?.status(),
`前端应返回2xx/3xx实际${response?.status()}`
).toBeGreaterThanOrEqual(200);
expect(
response?.status(),
`前端应返回2xx/3xx实际${response?.status()}`
).toBeLessThan(400);
});
}
});