| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /**
- * 统一 API 请求封装
- * 提供 GET / POST / PUT / DELETE 方法,自动处理认证和错误
- */
- import { request, APIRequestContext } from '@playwright/test';
- const BASE_URL = 'http://127.0.0.1:3000';
- let apiContext: APIRequestContext;
- let authToken: string | null = null;
- let testUserId: string | null = null;
- /** 初始化 API 客户端 */
- export async function initApiClient() {
- apiContext = await request.newContext({ baseURL: BASE_URL });
- }
- /** 释放 API 客户端 */
- export async function disposeApiClient() {
- if (apiContext) await apiContext.dispose();
- }
- /** 设置认证 token */
- export function setAuthToken(token: string, userId?: string) {
- authToken = token;
- if (userId) testUserId = userId;
- }
- /** 获取当前 token */
- export function getAuthToken(): string | null {
- return authToken;
- }
- /** 获取当前测试用户 ID */
- export function getTestUserId(): string {
- return testUserId || '1';
- }
- /** 通用请求选项 */
- function getOptions(method: string, data?: any): Record<string, any> {
- const options: Record<string, any> = {
- method,
- headers: { 'Content-Type': 'application/json' },
- };
- if (authToken) {
- options.headers['Authorization'] = `Bearer ${authToken}`;
- }
- if (data) {
- options.data = data;
- }
- return options;
- }
- /** API 响应类型 */
- export interface ApiResponse {
- code: number;
- message: string;
- data: any;
- }
- /** 解析 API 响应,自动兼容多种响应格式 */
- function parseApiResponse(body: any, res: any): ApiResponse {
- // 标准格式: { code: 0, message: '...', data: ... }
- if (body && typeof body === 'object' && body.code !== undefined) {
- return { code: body.code, message: body.message ?? '', data: body.data };
- }
- // 兼容格式: { success: true, data: ... } -> code = 0
- if (body && typeof body === 'object' && body.success === true) {
- return { code: 0, message: '', data: body.data };
- }
- // 降级: 使用 HTTP 状态码
- return { code: res.status(), message: '', data: null };
- }
- /** 安全解析 JSON,避免非 JSON 响应崩溃 */
- async function safeJson(res: any): Promise<any> {
- const text = await res.text();
- if (!text || text === 'Not Found' || text === 'Method Not Allowed') {
- return { _raw: text };
- }
- try {
- return JSON.parse(text);
- } catch {
- return { _raw: text };
- }
- }
- /** GET 请求 */
- export async function apiGet(path: string, params?: Record<string, string>): Promise<ApiResponse> {
- let url = path;
- if (params) {
- const qs = new URLSearchParams(params).toString();
- url = `${path}?${qs}`;
- }
- const res = await apiContext.get(url);
- const body = await safeJson(res);
- return parseApiResponse(body, res);
- }
- /** POST 请求 */
- export async function apiPost(path: string, data?: any): Promise<ApiResponse> {
- const res = await apiContext.post(path, getOptions('POST', data));
- const body = await safeJson(res);
- return parseApiResponse(body, res);
- }
- /** PUT 请求 */
- export async function apiPut(path: string, data?: any): Promise<ApiResponse> {
- const res = await apiContext.put(path, getOptions('PUT', data));
- const body = await safeJson(res);
- return parseApiResponse(body, res);
- }
- /** DELETE 请求 */
- export async function apiDelete(path: string): Promise<ApiResponse> {
- const res = await apiContext.delete(path, getOptions('DELETE'));
- const body = await safeJson(res);
- return parseApiResponse(body, res);
- }
- /** 获取原始响应(用于检查状态码等) */
- export async function apiRaw(method: string, path: string, data?: any) {
- return apiContext.fetch(path, getOptions(method, data));
- }
|