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

141 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
});
}
});