Files
wenzi/frontend/e2e/fixtures/test-data.ts

213 lines
5.0 KiB
TypeScript
Raw Normal View History

import { test as baseTest, expect, Page, APIRequestContext } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
/**
* E2E测试夹具Fixtures
* API客户端
*/
// 测试数据接口
export interface TestData {
activityId: number;
apiKey: string;
userId: number;
shortCode: string;
baseUrl: string;
apiBaseUrl: string;
}
// API响应类型
export interface ApiResponse<T = any> {
code: number;
message: string;
data: T;
}
// API客户端类
export class ApiClient {
constructor(
private request: APIRequestContext,
private apiKey: string,
private userToken: string,
private baseURL: string
) {}
/**
*
*/
async get<T>(endpoint: string, headers?: Record<string, string>): Promise<ApiResponse<T>> {
const response = await this.request.get(`${this.baseURL}${endpoint}`, {
headers: {
'X-API-Key': this.apiKey,
'Authorization': `Bearer ${this.userToken}`,
...headers,
},
});
return await response.json();
}
/**
* POST请求
*/
async post<T>(endpoint: string, data: any, headers?: Record<string, string>): Promise<ApiResponse<T>> {
const response = await this.request.post(`${this.baseURL}${endpoint}`, {
data,
headers: {
'Content-Type': 'application/json',
'X-API-Key': this.apiKey,
'Authorization': `Bearer ${this.userToken}`,
...headers,
},
});
return await response.json();
}
/**
* API Key
*/
async validateApiKey(apiKey: string): Promise<boolean> {
try {
const response = await this.request.post(`${this.baseURL}/api/v1/api-keys/validate`, {
data: { apiKey },
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.userToken}`,
},
});
return response.status() === 200;
} catch (error) {
return false;
}
}
/**
*
*/
async getActivities(): Promise<ApiResponse<any[]>> {
return this.get('/api/v1/activities');
}
/**
*
*/
async getActivity(activityId: number): Promise<ApiResponse<any>> {
return this.get(`/api/v1/activities/${activityId}`);
}
/**
*
*/
async getActivityStats(activityId: number): Promise<ApiResponse<any>> {
return this.get(`/api/v1/activities/${activityId}/stats`);
}
/**
*
*/
async getLeaderboard(activityId: number, page: number = 0, size: number = 10): Promise<ApiResponse<any>> {
return this.get(`/api/v1/activities/${activityId}/leaderboard?page=${page}&size=${size}`);
}
/**
*
*/
async createShortLink(originalUrl: string, activityId: number): Promise<ApiResponse<any>> {
return this.post('/api/v1/internal/shorten', {
originalUrl,
activityId,
});
}
/**
*
*/
async getShareMetrics(activityId: number): Promise<ApiResponse<any>> {
return this.get(`/api/v1/share/metrics?activityId=${activityId}`);
}
}
/**
*
*/
function loadTestData(): TestData {
// ES模块中获取当前文件目录
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: 'test-api-key',
userId: 10001,
shortCode: 'test123',
baseUrl: process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:5173',
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;
}
/**
*
*/
export interface TestFixtures {
testData: TestData;
apiClient: ApiClient;
authenticatedPage: Page;
}
/**
* test对象
*/
export const test = baseTest.extend<TestFixtures>({
// 测试数据
testData: async ({}, use) => {
const data = loadTestData();
await use(data);
},
// API客户端
apiClient: async ({ request, testData }, use) => {
const client = new ApiClient(
request,
testData.apiKey,
'test-e2e-token',
testData.apiBaseUrl
);
await use(client);
},
// 已认证的页面
authenticatedPage: async ({ page, testData }, use) => {
// 设置localStorage模拟登录状态
await page.addInitScript((data) => {
localStorage.setItem('token', 'test-e2e-token');
localStorage.setItem('userId', data.userId.toString());
localStorage.setItem('apiKey', data.apiKey);
localStorage.setItem('activityId', data.activityId.toString());
}, testData);
await use(page);
},
});
export { expect };