api-client.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /**
  2. * 统一 API 请求封装
  3. * 提供 GET / POST / PUT / DELETE 方法,自动处理认证和错误
  4. */
  5. import { request, APIRequestContext } from '@playwright/test';
  6. const BASE_URL = 'http://localhost:3000';
  7. let apiContext: APIRequestContext;
  8. let authToken: string | null = null;
  9. let testUserId: string | null = null;
  10. /** 初始化 API 客户端 */
  11. export async function initApiClient() {
  12. apiContext = await request.newContext({ baseURL: BASE_URL });
  13. }
  14. /** 释放 API 客户端 */
  15. export async function disposeApiClient() {
  16. if (apiContext) await apiContext.dispose();
  17. }
  18. /** 设置认证 token */
  19. export function setAuthToken(token: string, userId?: string) {
  20. authToken = token;
  21. if (userId) testUserId = userId;
  22. }
  23. /** 获取当前 token */
  24. export function getAuthToken(): string | null {
  25. return authToken;
  26. }
  27. /** 获取当前测试用户 ID */
  28. export function getTestUserId(): string {
  29. return testUserId || '1';
  30. }
  31. /** 通用请求选项 */
  32. function getOptions(method: string, data?: any): Record<string, any> {
  33. const options: Record<string, any> = {
  34. method,
  35. headers: { 'Content-Type': 'application/json' },
  36. };
  37. if (authToken) {
  38. options.headers['Authorization'] = `Bearer ${authToken}`;
  39. }
  40. if (data) {
  41. options.data = data;
  42. }
  43. return options;
  44. }
  45. /** API 响应类型 */
  46. export interface ApiResponse {
  47. code: number;
  48. message: string;
  49. data: any;
  50. }
  51. /** GET 请求 */
  52. export async function apiGet(path: string, params?: Record<string, string>): Promise<ApiResponse> {
  53. let url = path;
  54. if (params) {
  55. const qs = new URLSearchParams(params).toString();
  56. url = `${path}?${qs}`;
  57. }
  58. const res = await apiContext.get(url);
  59. const body = await res.json();
  60. return { code: body.code ?? res.status(), message: body.message ?? '', data: body.data };
  61. }
  62. /** POST 请求 */
  63. export async function apiPost(path: string, data?: any): Promise<ApiResponse> {
  64. const res = await apiContext.post(path, getOptions('POST', data));
  65. const body = await res.json();
  66. return { code: body.code ?? res.status(), message: body.message ?? '', data: body.data };
  67. }
  68. /** PUT 请求 */
  69. export async function apiPut(path: string, data?: any): Promise<ApiResponse> {
  70. const res = await apiContext.put(path, getOptions('PUT', data));
  71. const body = await res.json();
  72. return { code: body.code ?? res.status(), message: body.message ?? '', data: body.data };
  73. }
  74. /** DELETE 请求 */
  75. export async function apiDelete(path: string): Promise<ApiResponse> {
  76. const res = await apiContext.delete(path, getOptions('DELETE'));
  77. const body = await res.json();
  78. return { code: body.code ?? res.status(), message: body.message ?? '', data: body.data };
  79. }
  80. /** 获取原始响应(用于检查状态码等) */
  81. export async function apiRaw(method: string, path: string, data?: any) {
  82. return apiContext.fetch(path, getOptions(method, data));
  83. }