vitest.config.ts 4.8 KB

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