vitest.config.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import path from "node:path";
  2. import { defineConfig } from "vitest/config";
  3. const isIntegrationFileFilterRequested = process.argv.some((arg) =>
  4. /tests[\\/]+integration[\\/].+\.(test|spec)\.[cm]?[jt]sx?$/.test(arg)
  5. );
  6. export default defineConfig({
  7. test: {
  8. // ==================== 全局配置 ====================
  9. globals: true, // 使用全局 API (describe, test, expect)
  10. projects: [
  11. {
  12. extends: true,
  13. test: {
  14. environment: "happy-dom",
  15. include: [
  16. "tests/unit/**/*.{test,spec}.tsx",
  17. "tests/security/**/*.{test,spec}.{ts,tsx}",
  18. "tests/api/**/*.{test,spec}.tsx",
  19. "src/**/*.{test,spec}.tsx",
  20. ],
  21. },
  22. },
  23. ],
  24. // 测试前置脚本
  25. setupFiles: ["./tests/setup.ts"],
  26. // UI 配置
  27. // Vitest UI/Server 使用的是 test.api(不是 Vite 的 server 配置)
  28. // 默认仅允许本机访问,避免浏览器尝试连接 0.0.0.0 导致 UI 显示 Disconnected
  29. api: {
  30. host: process.env.VITEST_API_HOST || "127.0.0.1",
  31. port: Number(process.env.VITEST_API_PORT || 51204),
  32. strictPort: false,
  33. },
  34. open: false, // 不自动打开浏览器(手动访问 http://localhost:51204/__vitest__/)
  35. // ==================== 覆盖率配置 ====================
  36. coverage: {
  37. provider: "v8",
  38. reporter: ["text", "html", "lcov", "json"],
  39. reportsDirectory: "./coverage",
  40. // 排除文件
  41. exclude: [
  42. "node_modules/",
  43. "tests/",
  44. "*.config.*",
  45. "**/*.d.ts",
  46. ".next/",
  47. "dist/",
  48. "build/",
  49. // 单元测试覆盖率仅统计「可纯函数化/可隔离」模块,避免把需要 DB/Redis/Next/Bull 的集成逻辑算进阈值
  50. "src/actions/**",
  51. "src/repository/**",
  52. "src/app/v1/_lib/**",
  53. "src/lib/provider-testing/**",
  54. "src/lib/notification/**",
  55. "src/lib/redis/**",
  56. "src/lib/utils/**",
  57. "src/lib/rate-limit/**",
  58. "src/components/quota/**",
  59. // 依赖外部系统或目前无单测覆盖的重模块(避免拉低全局阈值)
  60. "src/lib/session-manager.ts",
  61. "src/lib/session-tracker.ts",
  62. "src/lib/circuit-breaker.ts",
  63. "src/lib/error-override-validator.ts",
  64. "src/lib/error-rule-detector.ts",
  65. "src/lib/sensitive-word-detector.ts",
  66. "src/lib/price-sync.ts",
  67. "src/lib/proxy-status-tracker.ts",
  68. "src/hooks/useCountdown.ts",
  69. ],
  70. // 覆盖率阈值(可选)
  71. thresholds: {
  72. lines: 50,
  73. functions: 50,
  74. branches: 40,
  75. statements: 50,
  76. },
  77. },
  78. // ==================== 超时配置 ====================
  79. testTimeout: 10000, // 单个测试超时 10 秒
  80. hookTimeout: 10000, // 钩子函数超时 10 秒
  81. // ==================== 并发配置 ====================
  82. maxConcurrency: 5, // 最大并发测试数
  83. pool: "threads", // 使用线程池(推荐)
  84. // ==================== 文件匹配 ====================
  85. include: [
  86. "tests/unit/**/*.{test,spec}.ts", // 单元测试
  87. "tests/security/**/*.{test,spec}.ts",
  88. "tests/api/**/*.{test,spec}.ts", // API 测试
  89. "src/**/*.{test,spec}.ts", // 支持源码中的测试
  90. ...(isIntegrationFileFilterRequested
  91. ? ["tests/integration/**/*.{test,spec}.ts", "tests/integration/**/*.{test,spec}.tsx"]
  92. : []),
  93. ],
  94. exclude: [
  95. "node_modules",
  96. ".next",
  97. "dist",
  98. "build",
  99. "coverage",
  100. "**/*.d.ts",
  101. ...(isIntegrationFileFilterRequested ? [] : ["tests/integration/**"]),
  102. "tests/api/users-actions.test.ts",
  103. "tests/api/providers-actions.test.ts",
  104. "tests/api/keys-actions.test.ts",
  105. "tests/api/my-usage-readonly.test.ts",
  106. ],
  107. // ==================== 监听模式配置 ====================
  108. // 不在配置文件中强制 watch=false,否则 vitest --ui 可能会在执行完一次后退出,UI 显示 Disconnected
  109. // 通过命令行参数控制:vitest(watch)/ vitest run(单次运行)
  110. // ==================== 报告器配置 ====================
  111. reporters: ["verbose"], // 详细输出
  112. // ==================== 隔离配置 ====================
  113. isolate: true, // 每个测试文件在独立环境中运行
  114. // ==================== Mock 配置 ====================
  115. mockReset: true, // 每个测试后重置 mock
  116. restoreMocks: true, // 每个测试后恢复原始实现
  117. clearMocks: true, // 每个测试后清除 mock 调用记录
  118. // ==================== 快照配置 ====================
  119. resolveSnapshotPath: (testPath, snapExtension) => {
  120. return testPath.replace(/\.test\.([tj]sx?)$/, `${snapExtension}.$1`);
  121. },
  122. },
  123. // ==================== 路径别名(与 tsconfig.json 保持一致)====================
  124. resolve: {
  125. alias: {
  126. "@": path.resolve(__dirname, "./src"),
  127. "@messages": path.resolve(__dirname, "./messages"),
  128. // Mock server-only 包,避免测试环境报错
  129. "server-only": path.resolve(__dirname, "./tests/server-only.mock.ts"),
  130. },
  131. },
  132. });