Przeglądaj źródła

chore: format code (feat-api-docs-summary-7a3cb20)

github-actions[bot] 3 miesięcy temu
rodzic
commit
de448637e4

+ 11 - 11
src/app/api/actions/[...route]/route.ts

@@ -54,7 +54,7 @@ app.openAPIRegistry.registerComponent("securitySchemes", "cookieAuth", {
 
 // ==================== 用户管理 ====================
 
-const { route: getUsersRoute, handler: getUsersHandler} = createActionRoute(
+const { route: getUsersRoute, handler: getUsersHandler } = createActionRoute(
   "users",
   "getUsers",
   userActions.getUsers,
@@ -1018,43 +1018,43 @@ HTTP 状态码:
   tags: [
     {
       name: "用户管理",
-      description: "用户账号的创建、编辑、删除和限额配置,支持 RPM、金额限制和并发会话控制"
+      description: "用户账号的创建、编辑、删除和限额配置,支持 RPM、金额限制和并发会话控制",
     },
     {
       name: "密钥管理",
-      description: "为用户生成 API 密钥,支持独立的金额限制、过期时间和 Web UI 登录权限配置"
+      description: "为用户生成 API 密钥,支持独立的金额限制、过期时间和 Web UI 登录权限配置",
     },
     {
       name: "供应商管理",
-      description: "配置上游 API 供应商,包括权重调度、熔断保护、代理设置和健康状态监控"
+      description: "配置上游 API 供应商,包括权重调度、熔断保护、代理设置和健康状态监控",
     },
     {
       name: "模型价格",
-      description: "管理模型价格表,支持手动上传 JSON 或从 LiteLLM 官方仓库同步最新价格"
+      description: "管理模型价格表,支持手动上传 JSON 或从 LiteLLM 官方仓库同步最新价格",
     },
     {
       name: "统计分析",
-      description: "查看用户消费统计、请求量趋势和成本分析,支持多种时间维度的数据汇总"
+      description: "查看用户消费统计、请求量趋势和成本分析,支持多种时间维度的数据汇总",
     },
     {
       name: "使用日志",
-      description: "查询 API 请求日志,支持按用户、模型、时间范围、状态码等多条件过滤"
+      description: "查询 API 请求日志,支持按用户、模型、时间范围、状态码等多条件过滤",
     },
     {
       name: "概览",
-      description: "展示系统运行状态概览,包括并发数、今日统计、活跃用户和时间分布图表"
+      description: "展示系统运行状态概览,包括并发数、今日统计、活跃用户和时间分布图表",
     },
     {
       name: "敏感词管理",
-      description: "配置内容审核规则,支持正则表达式匹配和缓存刷新,用于风险控制"
+      description: "配置内容审核规则,支持正则表达式匹配和缓存刷新,用于风险控制",
     },
     {
       name: "Session 管理",
-      description: "查看活跃会话列表、会话详情和消息内容,用于并发控制和请求追踪"
+      description: "查看活跃会话列表、会话详情和消息内容,用于并发控制和请求追踪",
     },
     {
       name: "通知管理",
-      description: "配置 Webhook 通知,接收系统事件推送(如限额预警、熔断触发等)"
+      description: "配置 Webhook 通知,接收系统事件推送(如限额预警、熔断触发等)",
     },
   ],
   externalDocs: {

+ 3 - 1
tests/api/api-actions-integrity.test.ts

@@ -204,7 +204,9 @@ describe("OpenAPI 端点完整性检查", () => {
       )?.[1];
 
       if (expectedTag && !postOperation.tags.includes(expectedTag)) {
-        pathsWithWrongTags.push(`${path} (期望: ${expectedTag}, 实际: ${postOperation.tags.join(", ")})`);
+        pathsWithWrongTags.push(
+          `${path} (期望: ${expectedTag}, 实际: ${postOperation.tags.join(", ")})`
+        );
       }
     }
 

+ 16 - 3
tests/api/api-endpoints.test.ts

@@ -69,7 +69,12 @@ describe("API 认证测试", () => {
       console.log("⚠️  跳过无效 token 测试(需要 API_E2E_BASE_URL + 可用数据库)");
       return;
     }
-    const { response, data } = await callApi("users", "getUsers", {}, { authToken: "invalid-token" });
+    const { response, data } = await callApi(
+      "users",
+      "getUsers",
+      {},
+      { authToken: "invalid-token" }
+    );
 
     expect(response.status).toBe(401);
     expect(data.ok).toBe(false);
@@ -131,7 +136,12 @@ describe("API 响应格式测试", () => {
       return;
     }
 
-    const { response, data } = await callApi("overview", "getOverviewData", {}, { authToken: mockToken });
+    const { response, data } = await callApi(
+      "overview",
+      "getOverviewData",
+      {},
+      { authToken: mockToken }
+    );
 
     if (response.ok) {
       expect(data).toHaveProperty("ok");
@@ -236,7 +246,10 @@ describe("API 文档 UI 可访问性", () => {
   test("健康检查端点应该正常", async () => {
     if (!E2E_API_BASE_URL) {
       // 进程内调用模式
-      const { response, json } = await callActionsRoute({ method: "GET", pathname: "/api/actions/health" });
+      const { response, json } = await callActionsRoute({
+        method: "GET",
+        pathname: "/api/actions/health",
+      });
       expect(response.ok).toBe(true);
       expect(json).toBeDefined();
       expect((json as any).status).toBe("ok");

+ 1 - 5
tests/api/keys-actions.test.ts

@@ -699,11 +699,7 @@ describe.skip("Key 管理 - 响应格式验证", () => {
   });
 
   test("所有错误响应应符合 ActionResult 格式", async () => {
-    const { response, data } = await callKeysApi(
-      "getKeys",
-      { userId: 1 },
-      USER_TOKEN
-    );
+    const { response, data } = await callKeysApi("getKeys", { userId: 1 }, USER_TOKEN);
 
     expect(response.ok).toBe(true);
     expect(data).toHaveProperty("ok");

+ 5 - 17
tests/api/providers-actions.test.ts

@@ -381,9 +381,7 @@ describe.skip("供应商管理 - 删除供应商 (removeProvider)", () => {
     });
 
     const providers = await callProvidersApi("getProviders");
-    const createdProvider = providers.data.find(
-      (p: any) => p.name.startsWith("待删除供应商_")
-    );
+    const createdProvider = providers.data.find((p: any) => p.name.startsWith("待删除供应商_"));
     testProviderId = createdProvider?.id;
   });
 
@@ -440,11 +438,7 @@ describe.skip("供应商管理 - 熔断器健康状态 (getProvidersHealthStatus
   });
 
   test("非管理员不能查看熔断器状态", async () => {
-    const { response, data } = await callProvidersApi(
-      "getProvidersHealthStatus",
-      {},
-      USER_TOKEN
-    );
+    const { response, data } = await callProvidersApi("getProvidersHealthStatus", {}, USER_TOKEN);
 
     expect(response.ok).toBe(true);
     expect(typeof data).toBe("object");
@@ -465,9 +459,7 @@ describe.skip("供应商管理 - 重置熔断器 (resetProviderCircuit)", () =>
     });
 
     const providers = await callProvidersApi("getProviders");
-    const createdProvider = providers.data.find((p: any) =>
-      p.name.startsWith("熔断器测试供应商_")
-    );
+    const createdProvider = providers.data.find((p: any) => p.name.startsWith("熔断器测试供应商_"));
     testProviderId = createdProvider?.id;
   });
 
@@ -522,9 +514,7 @@ describe.skip("供应商管理 - 获取供应商限额使用情况 (getProviderL
     });
 
     const providers = await callProvidersApi("getProviders");
-    const createdProvider = providers.data.find((p: any) =>
-      p.name.startsWith("限额测试供应商_")
-    );
+    const createdProvider = providers.data.find((p: any) => p.name.startsWith("限额测试供应商_"));
     testProviderId = createdProvider?.id;
   });
 
@@ -622,9 +612,7 @@ describe.skip("供应商管理 - 获取完整密钥 (getUnmaskedProviderKey)", (
     });
 
     const providers = await callProvidersApi("getProviders");
-    const createdProvider = providers.data.find((p: any) =>
-      p.name.startsWith("密钥测试供应商_")
-    );
+    const createdProvider = providers.data.find((p: any) => p.name.startsWith("密钥测试供应商_"));
     testProviderId = createdProvider?.id;
   });
 

+ 1 - 4
tests/cleanup-utils.ts

@@ -31,10 +31,7 @@ export async function cleanupTestUsers(options?: {
       like(users.name, "Test%"),
     ];
 
-    const whereConditions = [
-      or(...testUserConditions),
-      isNull(users.deletedAt),
-    ];
+    const whereConditions = [or(...testUserConditions), isNull(users.deletedAt)];
 
     if (options?.onlyRecent) {
       // 将 Date 转换为 ISO 字符串,避免 postgres 库报错

+ 2 - 10
tests/e2e/users-keys-complete.test.ts

@@ -95,11 +95,7 @@ async function callApi(
  * @example
  * const user = await expectSuccess("users", "addUser", { name: "测试" });
  */
-async function expectSuccess(
-  module: string,
-  action: string,
-  body: Record<string, unknown> = {}
-) {
+async function expectSuccess(module: string, action: string, body: Record<string, unknown> = {}) {
   const { response, data } = await callApi(module, action, body);
 
   // 验证 HTTP 状态码
@@ -127,11 +123,7 @@ async function expectSuccess(
  * const error = await expectError("users", "addUser", { name: "" });
  * expect(error).toContain("用户名");
  */
-async function expectError(
-  module: string,
-  action: string,
-  body: Record<string, unknown> = {}
-) {
+async function expectError(module: string, action: string, body: Record<string, unknown> = {}) {
   const { response, data } = await callApi(module, action, body);
 
   // API 返回 400/401/403 状态码,表示业务错误或权限问题

+ 7 - 4
tests/setup.ts

@@ -34,9 +34,9 @@ beforeAll(async () => {
     if (process.env.ALLOW_NON_TEST_DB !== "true") {
       throw new Error(
         `❌ 安全检查失败: 数据库名称必须包含 'test' 字样\n` +
-        `   当前数据库: ${dbName}\n` +
-        `   建议使用测试专用数据库(如 claude_code_hub_test)\n` +
-        `   如需跳过检查,请设置环境变量: ALLOW_NON_TEST_DB=true`
+          `   当前数据库: ${dbName}\n` +
+          `   建议使用测试专用数据库(如 claude_code_hub_test)\n` +
+          `   如需跳过检查,请设置环境变量: ALLOW_NON_TEST_DB=true`
       );
     }
 
@@ -80,7 +80,10 @@ afterAll(async () => {
         console.log(`✅ 自动清理:删除 ${result.deletedUsers} 个测试用户\n`);
       }
     } catch (error) {
-      console.warn("⚠️  自动清理失败(不影响测试结果):", error instanceof Error ? error.message : error);
+      console.warn(
+        "⚠️  自动清理失败(不影响测试结果):",
+        error instanceof Error ? error.message : error
+      );
     }
   }
 

+ 0 - 1
tests/test-utils.ts

@@ -73,4 +73,3 @@ export async function callActionsRoute(options: ActionsRouteCallOptions): Promis
 
   return { response, text: await response.text() };
 }
-

+ 2 - 10
vitest.config.ts

@@ -27,15 +27,7 @@ export default defineConfig({
       reportsDirectory: "./coverage",
 
       // 排除文件
-      exclude: [
-        "node_modules/",
-        "tests/",
-        "*.config.*",
-        "**/*.d.ts",
-        ".next/",
-        "dist/",
-        "build/",
-      ],
+      exclude: ["node_modules/", "tests/", "*.config.*", "**/*.d.ts", ".next/", "dist/", "build/"],
 
       // 覆盖率阈值(可选)
       thresholds: {
@@ -59,7 +51,7 @@ export default defineConfig({
 
     // ==================== 文件匹配 ====================
     include: [
-      "tests/**/*.test.ts",            // 所有测试文件
+      "tests/**/*.test.ts", // 所有测试文件
       "src/**/*.{test,spec}.{ts,tsx}", // 支持源码中的测试
     ],
     exclude: [