vitest.config.ts 5.2 KB

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