dd-trace 6.7.0 → 6.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/ci/diagnose.js +27 -25
  2. package/ci/init.js +6 -6
  3. package/ci/runbook.md +114 -20
  4. package/ci/test-optimization-validation/approval-artifacts.js +36 -3
  5. package/ci/test-optimization-validation/approval.js +78 -22
  6. package/ci/test-optimization-validation/blocker-category.js +24 -0
  7. package/ci/test-optimization-validation/ci-discovery.js +23 -17
  8. package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
  9. package/ci/test-optimization-validation/ci-remediation.js +1 -1
  10. package/ci/test-optimization-validation/cli.js +280 -52
  11. package/ci/test-optimization-validation/command-blocker.js +159 -20
  12. package/ci/test-optimization-validation/command-output-policy.js +14 -8
  13. package/ci/test-optimization-validation/command-runner.js +9 -7
  14. package/ci/test-optimization-validation/environment.js +4 -2
  15. package/ci/test-optimization-validation/executable.js +15 -13
  16. package/ci/test-optimization-validation/execution-lock.js +70 -0
  17. package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
  18. package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
  19. package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
  20. package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
  21. package/ci/test-optimization-validation/generated-files.js +47 -37
  22. package/ci/test-optimization-validation/generated-test-contract.js +9 -7
  23. package/ci/test-optimization-validation/generated-verifier.js +24 -17
  24. package/ci/test-optimization-validation/literal-glob.js +52 -0
  25. package/ci/test-optimization-validation/manifest-loader.js +3 -0
  26. package/ci/test-optimization-validation/manifest-scaffold.js +301 -52
  27. package/ci/test-optimization-validation/manifest-schema.js +80 -17
  28. package/ci/test-optimization-validation/offline-fixtures.js +13 -4
  29. package/ci/test-optimization-validation/offline-output.js +6 -6
  30. package/ci/test-optimization-validation/package-check.js +94 -0
  31. package/ci/test-optimization-validation/plan-writer.js +183 -10
  32. package/ci/test-optimization-validation/preflight-runner.js +110 -31
  33. package/ci/test-optimization-validation/project-build-artifact.js +31 -0
  34. package/ci/test-optimization-validation/redaction.js +18 -27
  35. package/ci/test-optimization-validation/report-writer.js +182 -48
  36. package/ci/test-optimization-validation/result-semantics.js +20 -3
  37. package/ci/test-optimization-validation/runner-command.js +41 -21
  38. package/ci/test-optimization-validation/runner-contract.js +79 -43
  39. package/ci/test-optimization-validation/safe-files.js +4 -4
  40. package/ci/test-optimization-validation/scenarios/basic-reporting.js +60 -6
  41. package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
  42. package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
  43. package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
  44. package/ci/test-optimization-validation/static-diagnosis.js +10 -3
  45. package/ci/test-optimization-validation/test-output.js +2 -1
  46. package/ci/test-optimization-validation/validation-blocker.js +21 -0
  47. package/ci/vitest-no-worker-init-setup.mjs +377 -84
  48. package/index.d.ts +175 -14
  49. package/init.js +1 -17
  50. package/initialize.mjs +11 -0
  51. package/loader-hook.mjs +6 -4
  52. package/package.json +12 -4
  53. package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
  54. package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
  55. package/packages/datadog-esbuild/index.js +4 -2
  56. package/packages/datadog-esbuild/src/utils.js +17 -2
  57. package/packages/datadog-instrumentations/src/ai.js +61 -34
  58. package/packages/datadog-instrumentations/src/bluebird.js +6 -6
  59. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +85 -9
  60. package/packages/datadog-instrumentations/src/cucumber.js +131 -51
  61. package/packages/datadog-instrumentations/src/dns.js +21 -2
  62. package/packages/datadog-instrumentations/src/electron.js +1 -0
  63. package/packages/datadog-instrumentations/src/fastify.js +3 -1
  64. package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
  65. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
  66. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
  67. package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
  68. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  69. package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
  70. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
  71. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  72. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +175 -0
  73. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
  74. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
  75. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
  76. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
  77. package/packages/datadog-instrumentations/src/helpers/router-helper.js +38 -7
  78. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
  79. package/packages/datadog-instrumentations/src/http/client.js +1 -3
  80. package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
  81. package/packages/datadog-instrumentations/src/jest.js +986 -246
  82. package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
  83. package/packages/datadog-instrumentations/src/mocha/main.js +109 -51
  84. package/packages/datadog-instrumentations/src/mocha/utils.js +120 -32
  85. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +44 -0
  86. package/packages/datadog-instrumentations/src/mocha/worker.js +441 -43
  87. package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
  88. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  89. package/packages/datadog-instrumentations/src/next.js +155 -23
  90. package/packages/datadog-instrumentations/src/openai.js +14 -0
  91. package/packages/datadog-instrumentations/src/pg.js +180 -6
  92. package/packages/datadog-instrumentations/src/playwright.js +176 -81
  93. package/packages/datadog-instrumentations/src/promise-js.js +4 -4
  94. package/packages/datadog-instrumentations/src/promise.js +3 -3
  95. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  96. package/packages/datadog-instrumentations/src/router.js +195 -19
  97. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +567 -65
  98. package/packages/datadog-instrumentations/src/vitest-main.js +438 -54
  99. package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
  100. package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
  101. package/packages/datadog-instrumentations/src/webdriverio.js +1090 -0
  102. package/packages/datadog-instrumentations/src/when.js +3 -3
  103. package/packages/datadog-instrumentations/src/ws.js +5 -1
  104. package/packages/datadog-plugin-aerospike/src/index.js +1 -3
  105. package/packages/datadog-plugin-amqplib/src/client.js +1 -1
  106. package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
  107. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
  108. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  109. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
  110. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
  111. package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
  112. package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
  113. package/packages/datadog-plugin-child_process/src/index.js +3 -3
  114. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -11
  115. package/packages/datadog-plugin-cucumber/src/index.js +5 -1
  116. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
  117. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
  118. package/packages/datadog-plugin-cypress/src/support.js +7 -4
  119. package/packages/datadog-plugin-electron/src/net.js +10 -4
  120. package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
  121. package/packages/datadog-plugin-fs/src/index.js +0 -4
  122. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
  123. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
  124. package/packages/datadog-plugin-graphql/src/execute.js +1 -0
  125. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
  126. package/packages/datadog-plugin-http/src/client.js +3 -2
  127. package/packages/datadog-plugin-http2/src/client.js +1 -1
  128. package/packages/datadog-plugin-jest/src/index.js +3 -21
  129. package/packages/datadog-plugin-jest/src/util.js +4 -1
  130. package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
  131. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  132. package/packages/datadog-plugin-mocha/src/index.js +342 -6
  133. package/packages/datadog-plugin-next/src/index.js +57 -9
  134. package/packages/datadog-plugin-openai/src/tracing.js +4 -0
  135. package/packages/datadog-plugin-pg/src/index.js +65 -1
  136. package/packages/datadog-plugin-playwright/src/index.js +1 -1
  137. package/packages/datadog-plugin-prisma/src/index.js +5 -1
  138. package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
  139. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  140. package/packages/datadog-plugin-undici/src/index.js +2 -1
  141. package/packages/datadog-plugin-vitest/src/index.js +179 -18
  142. package/packages/datadog-shimmer/src/shimmer.js +6 -2
  143. package/packages/datadog-webpack/index.js +2 -2
  144. package/packages/dd-trace/src/aiguard/sdk.js +3 -0
  145. package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
  146. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
  147. package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
  148. package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
  149. package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
  150. package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
  151. package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
  152. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  153. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
  154. package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
  155. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  156. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
  157. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +2 -2
  158. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
  159. package/packages/dd-trace/src/appsec/index.js +48 -476
  160. package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -1
  161. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  162. package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
  163. package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
  164. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
  165. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -15
  166. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +19 -1
  167. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +25 -1
  168. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
  169. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
  170. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
  171. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
  172. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
  173. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
  174. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +2 -2
  175. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
  176. package/packages/dd-trace/src/config/defaults.js +14 -6
  177. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
  178. package/packages/dd-trace/src/config/helper.js +2 -0
  179. package/packages/dd-trace/src/config/index.js +31 -5
  180. package/packages/dd-trace/src/config/parsers.js +19 -1
  181. package/packages/dd-trace/src/config/remote_config.js +1 -1
  182. package/packages/dd-trace/src/config/supported-configurations.json +13 -6
  183. package/packages/dd-trace/src/datastreams/encoding.js +3 -4
  184. package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
  185. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
  186. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
  187. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  188. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
  189. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  190. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  191. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  192. package/packages/dd-trace/src/exporters/common/url.js +3 -5
  193. package/packages/dd-trace/src/exporters/electron/index.js +4 -1
  194. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  195. package/packages/dd-trace/src/flare/index.js +2 -2
  196. package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
  197. package/packages/dd-trace/src/guardrails/log.js +1 -10
  198. package/packages/dd-trace/src/id.js +1 -1
  199. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
  200. package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
  201. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
  202. package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
  203. package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
  204. package/packages/dd-trace/src/llmobs/experiments/index.js +66 -19
  205. package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
  206. package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
  207. package/packages/dd-trace/src/llmobs/experiments/util.js +220 -0
  208. package/packages/dd-trace/src/llmobs/noop.js +2 -0
  209. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
  210. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
  211. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
  212. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
  213. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
  214. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  215. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  216. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  217. package/packages/dd-trace/src/llmobs/sdk.js +152 -78
  218. package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
  219. package/packages/dd-trace/src/llmobs/tagger.js +1 -2
  220. package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
  221. package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
  222. package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
  223. package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
  224. package/packages/dd-trace/src/log/channels.js +1 -9
  225. package/packages/dd-trace/src/log/levels.js +12 -0
  226. package/packages/dd-trace/src/noop/proxy.js +2 -2
  227. package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
  228. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  229. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
  230. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
  231. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  232. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
  233. package/packages/dd-trace/src/opentelemetry/span.js +4 -0
  234. package/packages/dd-trace/src/opentracing/span.js +1 -1
  235. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  236. package/packages/dd-trace/src/plugins/ci_plugin.js +124 -23
  237. package/packages/dd-trace/src/plugins/index.js +2 -0
  238. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  239. package/packages/dd-trace/src/plugins/tracing.js +1 -0
  240. package/packages/dd-trace/src/plugins/util/ci.js +13 -6
  241. package/packages/dd-trace/src/plugins/util/git.js +7 -5
  242. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +3 -3
  243. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
  244. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  245. package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
  246. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  247. package/packages/dd-trace/src/plugins/util/test.js +356 -86
  248. package/packages/dd-trace/src/plugins/util/url.js +5 -5
  249. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  250. package/packages/dd-trace/src/plugins/util/web.js +24 -2
  251. package/packages/dd-trace/src/priority_sampler.js +6 -3
  252. package/packages/dd-trace/src/profiler.js +1 -1
  253. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
  254. package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
  255. package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
  256. package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
  257. package/packages/dd-trace/src/proxy.js +1 -0
  258. package/packages/dd-trace/src/ritm.js +10 -20
  259. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
  260. package/packages/dd-trace/src/sampling_rule.js +4 -2
  261. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
  262. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
  263. package/packages/dd-trace/src/startup-log.js +3 -0
  264. package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
  265. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
  266. package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
  267. package/packages/dd-trace/src/util.js +16 -0
  268. package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
  269. package/vendor/dist/pprof-format/index.js +1 -1
  270. package/vendor/dist/source-map/index.js +1 -1
  271. package/version.js +10 -8
  272. /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
@@ -6,18 +6,24 @@ const { MessagePort } = require('node:worker_threads')
6
6
 
7
7
  const shimmer = require('../../datadog-shimmer')
8
8
  const log = require('../../dd-trace/src/log')
9
+ const { EMPTY_EFD_RETRY_POLICY } = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
9
10
  const {
10
11
  VITEST_WORKER_TRACE_PAYLOAD_CODE,
12
+ VITEST_WORKER_COVERAGE_PAYLOAD_CODE,
11
13
  VITEST_WORKER_LOGS_PAYLOAD_CODE,
12
- getMaxEfdRetryCount,
14
+ VITEST_WORKER_TELEMETRY_PAYLOAD_CODE,
13
15
  collectTestOptimizationSummariesFromTraces,
14
16
  logTestOptimizationSummary,
17
+ TEST_IMPACT_ANALYSIS_ALL_TESTS_SKIPPED_MESSAGE,
15
18
  getTestOptimizationRequestResults,
16
19
  getTestSuitePath,
17
20
  isModifiedTest,
21
+ recordTestManagementExecution,
22
+ recordAttemptToFixExecution,
18
23
  } = require('../../dd-trace/src/plugins/util/test')
24
+ const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
19
25
  const { getChannelPromise } = require('./helpers/channel')
20
- const { addHook } = require('./helpers/instrument')
26
+ const { addHook, channel } = require('./helpers/instrument')
21
27
  const noWorkerInit = require('./vitest-main-no-worker-init')
22
28
  const {
23
29
  testStartCh,
@@ -36,8 +42,11 @@ const {
36
42
  testManagementTestsCh,
37
43
  modifiedFilesCh,
38
44
  workerReportTraceCh,
45
+ workerReportCoverageCh,
39
46
  workerReportLogsCh,
47
+ workerReportTelemetryCh,
40
48
  codeCoverageReportCh,
49
+ realpath,
41
50
  findExportByName,
42
51
  getTypeTasks,
43
52
  getWorkspaceProject,
@@ -51,32 +60,46 @@ const workerProcesses = new WeakSet()
51
60
  const mainProcessSetupStates = new WeakMap()
52
61
  const coverageWrappedProviders = new WeakSet()
53
62
  const finishWrappedContexts = new WeakSet()
63
+ const runFilesWrappedPrototypes = new WeakSet()
64
+ const activeRunFilesContexts = new WeakSet()
54
65
  let isFlakyTestRetriesEnabled = false
55
66
  let flakyTestRetriesCount = 0
56
67
  let isEarlyFlakeDetectionEnabled = false
57
- let earlyFlakeDetectionNumRetries = 0
58
- let earlyFlakeDetectionSlowTestRetries = {}
68
+ let earlyFlakeDetectionRetryPolicy = EMPTY_EFD_RETRY_POLICY
59
69
  let isEarlyFlakeDetectionFaulty = false
60
70
  let isKnownTestsEnabled = false
61
71
  let isTestManagementTestsEnabled = false
62
72
  let isImpactedTestsEnabled = false
73
+ let isCodeCoverageEnabled = false
74
+ let isSuitesSkippingEnabled = false
75
+ let isSessionCodeCoverageEnabled = false
76
+ let isSessionSuitesSkippingEnabled = false
63
77
  let testManagementAttemptToFixRetries = 0
64
78
  let isDiEnabled = false
65
79
  let testCodeCoverageLinesTotal
66
80
  let coverageRootDir
67
81
  let requestErrorTags = {}
68
82
  let isSessionStarted = false
83
+ let isTestImpactAnalysisDisabled = false
69
84
  let isVitestNoWorkerInitActive = false
85
+ let isVitestBrowserModeActive = false
70
86
  let vitestPool = null
71
87
  let isMessagePortWrapped = false
88
+ let skippableSuites = []
89
+ let skippedSuites = []
90
+ let unskippableSuites = {}
91
+ let forcedToRunSuites = {}
92
+ let hasUnskippableSuites = false
93
+ let hasForcedToRunSuites = false
94
+ let areAllSuitesSkipped = false
95
+ let hasLoggedAllTestsSkippedMessage = false
96
+ let hasRunnableSuites = false
97
+ let hasSelectedSuites = false
98
+ let itrCorrelationId
99
+ let tiaRepositoryRoot = process.cwd()
72
100
  const tinyPoolClassWrappers = new WeakMap()
73
-
74
- function getConfiguredEfdRetryCount (slowTestRetries, fallbackRetryCount) {
75
- if (!slowTestRetries || !Object.keys(slowTestRetries).length) {
76
- return fallbackRetryCount
77
- }
78
- return getMaxEfdRetryCount(slowTestRetries)
79
- }
101
+ const itrSkippedSuitesCh = channel('ci:vitest:itr:skipped-suites')
102
+ const skippableSuitesCh = channel('ci:vitest:test-suite:skippable')
80
103
 
81
104
  function getTestCommand () {
82
105
  return `vitest ${process.argv.slice(2).join(' ')}`
@@ -197,7 +220,171 @@ function getTestFilepaths (ctx, testSpecifications) {
197
220
  */
198
221
  function getNormalizedTestSuitePath (testFilepath, repositoryRoot) {
199
222
  const testSuiteAbsolutePath = path.isAbsolute(testFilepath) ? testFilepath : path.join(repositoryRoot, testFilepath)
200
- return getTestSuitePath(testSuiteAbsolutePath, repositoryRoot)
223
+ return getTestSuitePath(realpath(testSuiteAbsolutePath), realpath(repositoryRoot))
224
+ }
225
+
226
+ function resetSuiteSkippingRunState () {
227
+ skippableSuites = []
228
+ resetAppliedSuiteSkippingState()
229
+ itrCorrelationId = undefined
230
+ }
231
+
232
+ function resetAppliedSuiteSkippingState () {
233
+ unskippableSuites = {}
234
+ forcedToRunSuites = {}
235
+ }
236
+
237
+ function resetSessionSuiteSkippingState () {
238
+ skippedSuites = []
239
+ hasUnskippableSuites = false
240
+ hasForcedToRunSuites = false
241
+ areAllSuitesSkipped = false
242
+ hasLoggedAllTestsSkippedMessage = false
243
+ hasRunnableSuites = false
244
+ hasSelectedSuites = false
245
+ isSessionCodeCoverageEnabled = false
246
+ isSessionSuitesSkippingEnabled = false
247
+ isTestImpactAnalysisDisabled = false
248
+ }
249
+
250
+ /**
251
+ * Returns the file path from Vitest's version-dependent test specification shape.
252
+ *
253
+ * @param {unknown} testSpecification
254
+ * @returns {string|undefined}
255
+ */
256
+ function getTestSpecificationFilepath (testSpecification) {
257
+ const testFile = Array.isArray(testSpecification) ? testSpecification[1] : testSpecification
258
+ return testFile?.moduleId || testFile?.filepath || (typeof testFile === 'string' ? testFile : undefined)
259
+ }
260
+
261
+ /**
262
+ * Returns the normalized suite path and absolute path for a Vitest test specification.
263
+ *
264
+ * @param {unknown} testSpecification
265
+ * @returns {{ testSuite: string, testSuiteAbsolutePath: string }|undefined}
266
+ */
267
+ function getTestSpecificationSuite (testSpecification) {
268
+ const testFilepath = getTestSpecificationFilepath(testSpecification)
269
+ if (!testFilepath) return
270
+
271
+ const testSuiteAbsolutePath = path.isAbsolute(testFilepath)
272
+ ? realpath(testFilepath)
273
+ : realpath(path.join(tiaRepositoryRoot, testFilepath))
274
+
275
+ return {
276
+ testSuite: getTestSuitePath(testSuiteAbsolutePath, tiaRepositoryRoot),
277
+ testSuiteAbsolutePath,
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Returns suites that Vitest selected for typechecking.
283
+ *
284
+ * @param {unknown[]} testSpecifications
285
+ * @returns {Set<string>}
286
+ */
287
+ function getTypecheckTestSuites (testSpecifications) {
288
+ const typecheckTestSuites = new Set()
289
+
290
+ for (const testSpecification of testSpecifications) {
291
+ if (getTestSpecificationPool(testSpecification) !== 'typescript') continue
292
+
293
+ const testSuite = getTestSpecificationSuite(testSpecification)?.testSuite
294
+ if (testSuite) {
295
+ typecheckTestSuites.add(testSuite)
296
+ }
297
+ }
298
+
299
+ return typecheckTestSuites
300
+ }
301
+
302
+ /**
303
+ * Removes suites selected by TIA and propagates suite metadata to Vitest workers.
304
+ *
305
+ * @param {object} ctx
306
+ * @param {unknown[]} testSpecifications
307
+ * @param {string} frameworkVersion
308
+ * @returns {unknown[]}
309
+ */
310
+ function applySuiteSkipping (ctx, testSpecifications, frameworkVersion) {
311
+ if (!Array.isArray(testSpecifications)) {
312
+ setProvidedContext(ctx, {
313
+ _ddIsCodeCoverageEnabled: isCodeCoverageEnabled,
314
+ }, 'Could not send TIA configuration to workers.')
315
+ return testSpecifications
316
+ }
317
+
318
+ if (testSpecifications.length > 0) {
319
+ hasSelectedSuites = true
320
+ }
321
+ if (!isSuitesSkippingEnabled) {
322
+ if (testSpecifications.length > 0) {
323
+ hasRunnableSuites = true
324
+ }
325
+ areAllSuitesSkipped = hasSelectedSuites && !hasRunnableSuites
326
+ setProvidedContext(ctx, {
327
+ _ddIsCodeCoverageEnabled: isCodeCoverageEnabled,
328
+ }, 'Could not send TIA configuration to workers.')
329
+ return testSpecifications
330
+ }
331
+
332
+ resetAppliedSuiteSkippingState()
333
+ const skippableSuiteSet = new Set(skippableSuites.map(testSuite => testSuite.replaceAll('\\', '/')))
334
+ const typecheckTestSuites = getTypecheckTestSuites(testSpecifications)
335
+ const currentSkippedSuites = []
336
+ const testSpecificationsToRun = []
337
+
338
+ for (const testSpecification of testSpecifications) {
339
+ const testSpecificationSuite = getTestSpecificationSuite(testSpecification)
340
+ if (!testSpecificationSuite) {
341
+ testSpecificationsToRun.push(testSpecification)
342
+ continue
343
+ }
344
+
345
+ const { testSuite, testSuiteAbsolutePath } = testSpecificationSuite
346
+ const shouldSkip = !typecheckTestSuites.has(testSuite) && skippableSuiteSet.has(testSuite)
347
+ const isUnskippable = isMarkedAsUnskippable({ path: testSuiteAbsolutePath })
348
+
349
+ if (isUnskippable) {
350
+ unskippableSuites[testSuite] = true
351
+ hasUnskippableSuites = true
352
+ if (shouldSkip) {
353
+ forcedToRunSuites[testSuite] = true
354
+ hasForcedToRunSuites = true
355
+ }
356
+ }
357
+
358
+ if (shouldSkip && !isUnskippable) {
359
+ skippedSuites.push(testSuite)
360
+ currentSkippedSuites.push(testSuite)
361
+ } else {
362
+ testSpecificationsToRun.push(testSpecification)
363
+ }
364
+ }
365
+
366
+ setProvidedContext(ctx, {
367
+ _ddIsCodeCoverageEnabled: isCodeCoverageEnabled,
368
+ _ddItrCorrelationId: itrCorrelationId,
369
+ _ddUnskippableSuites: unskippableSuites,
370
+ _ddForcedToRunSuites: forcedToRunSuites,
371
+ }, 'Could not send TIA configuration to workers.')
372
+
373
+ if (currentSkippedSuites.length) {
374
+ itrSkippedSuitesCh.publish({ skippedSuites: currentSkippedSuites, frameworkVersion })
375
+ }
376
+ if (testSpecificationsToRun.length > 0) {
377
+ hasRunnableSuites = true
378
+ }
379
+ areAllSuitesSkipped = hasSelectedSuites && !hasRunnableSuites
380
+ if (testSpecifications.length > 0 && testSpecificationsToRun.length === 0) {
381
+ const config = safeConfig(ctx)
382
+ if (config) {
383
+ config.passWithNoTests = true
384
+ }
385
+ }
386
+
387
+ return testSpecificationsToRun
201
388
  }
202
389
 
203
390
  /**
@@ -281,6 +468,10 @@ function getTestPropertiesByFilepath (
281
468
  for (const testFilepath of testFilepaths) {
282
469
  if (typeof testFilepath !== 'string') continue
283
470
 
471
+ const testSuiteAbsolutePath = path.isAbsolute(testFilepath)
472
+ ? testFilepath
473
+ : path.join(repositoryRoot, testFilepath)
474
+ const realTestFilepath = realpath(testSuiteAbsolutePath)
284
475
  const testSuite = getNormalizedTestSuitePath(testFilepath, repositoryRoot)
285
476
  const testProperties = { testSuite }
286
477
  const hasProperties = knownTestsBySuite !== undefined ||
@@ -299,6 +490,8 @@ function getTestPropertiesByFilepath (
299
490
 
300
491
  if (hasProperties) {
301
492
  testPropertiesByFilepath[testFilepath] = testProperties
493
+ testPropertiesByFilepath[testSuiteAbsolutePath] = testProperties
494
+ testPropertiesByFilepath[realTestFilepath] = testProperties
302
495
  }
303
496
  }
304
497
 
@@ -349,13 +542,14 @@ function resetLibraryConfig () {
349
542
  isFlakyTestRetriesEnabled = false
350
543
  flakyTestRetriesCount = 0
351
544
  isEarlyFlakeDetectionEnabled = false
352
- earlyFlakeDetectionNumRetries = 0
353
- earlyFlakeDetectionSlowTestRetries = {}
545
+ earlyFlakeDetectionRetryPolicy = EMPTY_EFD_RETRY_POLICY
354
546
  isEarlyFlakeDetectionFaulty = false
355
547
  isDiEnabled = false
356
548
  isKnownTestsEnabled = false
357
549
  isTestManagementTestsEnabled = false
358
550
  isImpactedTestsEnabled = false
551
+ isCodeCoverageEnabled = false
552
+ isSuitesSkippingEnabled = false
359
553
  testManagementAttemptToFixRetries = 0
360
554
  }
361
555
 
@@ -363,22 +557,22 @@ function applyLibraryConfig (libraryConfig) {
363
557
  isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
364
558
  flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
365
559
  isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
366
- earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
367
- earlyFlakeDetectionSlowTestRetries = libraryConfig.earlyFlakeDetectionSlowTestRetries ?? {}
560
+ earlyFlakeDetectionRetryPolicy = libraryConfig.earlyFlakeDetectionRetryPolicy ?? EMPTY_EFD_RETRY_POLICY
368
561
  isEarlyFlakeDetectionFaulty = false
369
562
  isDiEnabled = libraryConfig.isDiEnabled
370
563
  isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
371
564
  isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
372
565
  testManagementAttemptToFixRetries = libraryConfig.testManagementAttemptToFixRetries
373
566
  isImpactedTestsEnabled = libraryConfig.isImpactedTestsEnabled
567
+ isCodeCoverageEnabled = libraryConfig.isItrEnabled && libraryConfig.isCodeCoverageEnabled
568
+ isSuitesSkippingEnabled = libraryConfig.isItrEnabled && libraryConfig.isSuitesSkippingEnabled
374
569
  }
375
570
 
376
571
  function resetMainProcessProvidedContext (ctx) {
377
572
  setProvidedContext(ctx, {
378
573
  _ddIsDiEnabled: false,
379
574
  _ddIsEarlyFlakeDetectionEnabled: false,
380
- _ddEarlyFlakeDetectionNumRetries: 0,
381
- _ddEarlyFlakeDetectionSlowTestRetries: {},
575
+ _ddEarlyFlakeDetectionRetryPolicy: EMPTY_EFD_RETRY_POLICY,
382
576
  _ddIsFlakyTestRetriesEnabled: false,
383
577
  _ddFlakyTestRetriesCount: 0,
384
578
  _ddFlakyTestRetriesIncludesUnnamedProject: false,
@@ -388,6 +582,10 @@ function resetMainProcessProvidedContext (ctx) {
388
582
  _ddIsTestManagementTestsEnabled: false,
389
583
  _ddTestManagementAttemptToFixRetries: 0,
390
584
  _ddTestPropertiesByFilepath: {},
585
+ _ddIsCodeCoverageEnabled: false,
586
+ _ddItrCorrelationId: undefined,
587
+ _ddUnskippableSuites: {},
588
+ _ddForcedToRunSuites: {},
391
589
  }, 'Could not reset Test Optimization context for workers.')
392
590
  }
393
591
 
@@ -405,11 +603,22 @@ function mergeRequestErrorTags (requestResponse) {
405
603
  }
406
604
  }
407
605
 
408
- async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, shouldInstallNoWorkerInit) {
606
+ async function runMainProcessSetup (
607
+ ctx,
608
+ frameworkVersion,
609
+ testSpecifications,
610
+ shouldInstallNoWorkerInit,
611
+ shouldInstallBrowserReporter,
612
+ disableTestImpactAnalysis
613
+ ) {
409
614
  if (!testSessionFinishCh.hasSubscribers) {
410
615
  return
411
616
  }
412
617
 
618
+ resetSuiteSkippingRunState()
619
+ isVitestBrowserModeActive ||= shouldInstallBrowserReporter
620
+ isTestImpactAnalysisDisabled =
621
+ disableTestImpactAnalysis || shouldInstallNoWorkerInit || isVitestBrowserModeActive
413
622
  let repositoryRoot = process.cwd()
414
623
  let testSessionConfiguration
415
624
  let testFilepaths
@@ -435,7 +644,8 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
435
644
  requestErrorTags: receivedRequestErrorTags = {},
436
645
  } = await getChannelPromise(libraryConfigurationCh, {
437
646
  frameworkVersion,
438
- isVitestNoWorkerInitActive: shouldInstallNoWorkerInit,
647
+ disableTestImpactAnalysis: isTestImpactAnalysisDisabled,
648
+ isVitestNoWorkerInitActive: shouldInstallNoWorkerInit || isVitestBrowserModeActive,
439
649
  })
440
650
  requestErrorTags = receivedRequestErrorTags
441
651
  if (err) {
@@ -447,6 +657,8 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
447
657
  requestErrorTags = {}
448
658
  resetLibraryConfig()
449
659
  }
660
+ isSessionCodeCoverageEnabled ||= isCodeCoverageEnabled
661
+ isSessionSuitesSkippingEnabled ||= isSuitesSkippingEnabled
450
662
 
451
663
  resetMainProcessProvidedContext(ctx)
452
664
 
@@ -459,7 +671,11 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
459
671
  repositoryRoot: receivedRepositoryRoot,
460
672
  codeOwnersEntries,
461
673
  } = testSessionConfiguration
462
- repositoryRoot = receivedRepositoryRoot || repositoryRoot
674
+ repositoryRoot = realpath(receivedRepositoryRoot || repositoryRoot)
675
+ testSessionConfiguration = {
676
+ ...testSessionConfiguration,
677
+ repositoryRoot,
678
+ }
463
679
  if (!shouldInstallNoWorkerInit) {
464
680
  setProvidedContext(ctx, {
465
681
  _ddTestSessionId: testSessionId,
@@ -470,19 +686,33 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
470
686
  }, 'Could not send test session configuration to workers.')
471
687
  }
472
688
  }
689
+ tiaRepositoryRoot = realpath(repositoryRoot)
473
690
 
474
691
  const {
475
692
  knownTestsResponse,
693
+ skippableSuitesResponse,
476
694
  testManagementTestsResponse,
477
695
  } = await getTestOptimizationRequestResults({
478
696
  isKnownTestsEnabled,
697
+ isSuitesSkippingEnabled,
479
698
  isTestManagementTestsEnabled,
480
699
  getKnownTests: () => getChannelPromise(knownTestsCh),
700
+ getSkippableSuites: () => getChannelPromise(skippableSuitesCh),
481
701
  getTestManagementTests: () => getChannelPromise(testManagementTestsCh),
482
702
  })
483
703
  mergeRequestErrorTags(knownTestsResponse)
704
+ mergeRequestErrorTags(skippableSuitesResponse)
484
705
  mergeRequestErrorTags(testManagementTestsResponse)
485
706
 
707
+ if (isSuitesSkippingEnabled) {
708
+ const currentSkippableSuitesResponse = skippableSuitesResponse ||
709
+ await getChannelPromise(skippableSuitesCh)
710
+ if (!currentSkippableSuitesResponse?.err) {
711
+ skippableSuites = currentSkippableSuitesResponse.skippableSuites || []
712
+ itrCorrelationId = currentSkippableSuitesResponse.itrCorrelationId
713
+ }
714
+ }
715
+
486
716
  const flakyTestRetriesConfiguration = configureFlakyTestRetries(ctx, testSpecifications)
487
717
  if (flakyTestRetriesConfiguration) {
488
718
  setProvidedContext(ctx, {
@@ -519,9 +749,7 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
519
749
  setProvidedContext(ctx, {
520
750
  _ddIsKnownTestsEnabled: isKnownTestsEnabled,
521
751
  _ddIsEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionEnabled,
522
- _ddEarlyFlakeDetectionNumRetries:
523
- getConfiguredEfdRetryCount(earlyFlakeDetectionSlowTestRetries, earlyFlakeDetectionNumRetries),
524
- _ddEarlyFlakeDetectionSlowTestRetries: earlyFlakeDetectionSlowTestRetries,
752
+ _ddEarlyFlakeDetectionRetryPolicy: earlyFlakeDetectionRetryPolicy,
525
753
  }, 'Could not send known tests to workers so Early Flake Detection will not work.')
526
754
  }
527
755
  }
@@ -589,8 +817,11 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
589
817
  }
590
818
  }
591
819
 
592
- if (shouldInstallNoWorkerInit) {
593
- noWorkerInit.configure(ctx, frameworkVersion, testSpecifications, {
820
+ if (shouldInstallNoWorkerInit || shouldInstallBrowserReporter) {
821
+ const reporterTestSpecifications = shouldInstallNoWorkerInit
822
+ ? testSpecifications
823
+ : getBrowserTestSpecifications(testSpecifications)
824
+ noWorkerInit.configure(ctx, frameworkVersion, reporterTestSpecifications, {
594
825
  knownTests,
595
826
  knownTestsBySuite,
596
827
  modifiedFiles,
@@ -601,7 +832,7 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
601
832
  testPropertiesByFilepath: testPropertiesByFilepath || {},
602
833
  testSessionConfiguration,
603
834
  }, {
604
- getConfiguredEfdRetryCount,
835
+ shouldReportTestModule: shouldInstallBrowserReporter ? isBrowserTestModule : undefined,
605
836
  state: getNoWorkerInitState(),
606
837
  })
607
838
  }
@@ -614,8 +845,7 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
614
845
  function getNoWorkerInitState () {
615
846
  return {
616
847
  attemptToFixExecutions,
617
- earlyFlakeDetectionNumRetries,
618
- earlyFlakeDetectionSlowTestRetries,
848
+ earlyFlakeDetectionRetryPolicy,
619
849
  isEarlyFlakeDetectionEnabled,
620
850
  isEarlyFlakeDetectionFaulty,
621
851
  isFlakyTestRetriesEnabled,
@@ -626,20 +856,44 @@ function getNoWorkerInitState () {
626
856
  }
627
857
  }
628
858
 
629
- function ensureMainProcessSetup (ctx, frameworkVersion, testSpecifications, shouldDeactivateOnFallback = false) {
859
+ function ensureMainProcessSetup (
860
+ ctx,
861
+ frameworkVersion,
862
+ testSpecifications,
863
+ shouldDeactivateOnFallback = false,
864
+ forceDisableTestImpactAnalysis = false
865
+ ) {
630
866
  const shouldInstallNoWorkerInit = shouldUseNoWorkerInit(ctx, frameworkVersion, testSpecifications)
867
+ const shouldInstallBrowserReporter = shouldUseBrowserReporter(frameworkVersion, testSpecifications)
868
+ const shouldInstallMainReporter = shouldInstallNoWorkerInit || shouldInstallBrowserReporter
869
+ const disableTestImpactAnalysis =
870
+ forceDisableTestImpactAnalysis ||
871
+ safeConfig(ctx)?.watch === true ||
872
+ hasOnlyTypecheckTestSpecifications(testSpecifications)
631
873
  const specificationsKey = getTestSpecificationsKey(testSpecifications)
632
874
  let setupState = mainProcessSetupStates.get(ctx)
633
- if (shouldDeactivateOnFallback && setupState?.shouldInstallNoWorkerInit && !shouldInstallNoWorkerInit) {
875
+ if (shouldDeactivateOnFallback && setupState?.shouldInstallMainReporter && !shouldInstallMainReporter) {
634
876
  noWorkerInit.deactivate(ctx)
635
877
  }
636
878
  if (
637
879
  !setupState ||
638
880
  setupState.specificationsKey !== specificationsKey ||
639
- setupState.shouldInstallNoWorkerInit !== shouldInstallNoWorkerInit
881
+ setupState.shouldInstallNoWorkerInit !== shouldInstallNoWorkerInit ||
882
+ setupState.shouldInstallBrowserReporter !== shouldInstallBrowserReporter ||
883
+ setupState.disableTestImpactAnalysis !== disableTestImpactAnalysis
640
884
  ) {
641
885
  setupState = {
642
- setupPromise: runMainProcessSetup(ctx, frameworkVersion, testSpecifications, shouldInstallNoWorkerInit),
886
+ setupPromise: runMainProcessSetup(
887
+ ctx,
888
+ frameworkVersion,
889
+ testSpecifications,
890
+ shouldInstallNoWorkerInit,
891
+ shouldInstallBrowserReporter,
892
+ disableTestImpactAnalysis
893
+ ),
894
+ disableTestImpactAnalysis,
895
+ shouldInstallBrowserReporter,
896
+ shouldInstallMainReporter,
643
897
  shouldInstallNoWorkerInit,
644
898
  specificationsKey,
645
899
  }
@@ -655,6 +909,12 @@ function shouldUseNoWorkerInit (ctx, frameworkVersion, testSpecifications) {
655
909
  })
656
910
  }
657
911
 
912
+ function shouldUseBrowserReporter (frameworkVersion, testSpecifications) {
913
+ return noWorkerInit.isSupportedVersion(frameworkVersion) &&
914
+ Array.isArray(testSpecifications) &&
915
+ testSpecifications.some(isBrowserTestSpecification)
916
+ }
917
+
658
918
  function configureFlakyTestRetries (ctx, testSpecifications) {
659
919
  if (!isFlakyTestRetriesEnabled || flakyTestRetriesCount <= 0) return
660
920
 
@@ -796,7 +1056,11 @@ function safeWorkspaceProject (ctx) {
796
1056
 
797
1057
  function getSortWrapper (sort, frameworkVersion) {
798
1058
  return async function () {
799
- await ensureMainProcessSetup(this.ctx, frameworkVersion, arguments[0])
1059
+ if (!activeRunFilesContexts.has(this.ctx)) {
1060
+ const testSpecifications = arguments[0]
1061
+ await ensureMainProcessSetup(this.ctx, frameworkVersion, testSpecifications)
1062
+ arguments[0] = applySuiteSkipping(this.ctx, testSpecifications, frameworkVersion)
1063
+ }
800
1064
  return sort.apply(this, arguments)
801
1065
  }
802
1066
  }
@@ -820,18 +1084,30 @@ function getFinishWrapper (exitOrClose) {
820
1084
  }
821
1085
 
822
1086
  const flushPromise = getChannelPromise(testSessionFinishCh, {
823
- status: getSessionStatus(this.state),
1087
+ status: areAllSuitesSkipped ? 'skip' : getSessionStatus(this.state),
824
1088
  testCodeCoverageLinesTotal,
825
1089
  error,
826
1090
  isEarlyFlakeDetectionEnabled,
827
1091
  isEarlyFlakeDetectionFaulty,
828
1092
  isTestManagementTestsEnabled,
1093
+ isCodeCoverageEnabled: isSessionCodeCoverageEnabled,
1094
+ isSuitesSkippingEnabled: isSessionSuitesSkippingEnabled,
1095
+ isSuitesSkipped: skippedSuites.length > 0,
1096
+ numSkippedSuites: skippedSuites.length,
1097
+ hasUnskippableSuites,
1098
+ hasForcedToRunSuites,
829
1099
  requestErrorTags,
830
1100
  vitestPool,
831
- isVitestNoWorkerInitActive,
1101
+ isVitestNoWorkerInitActive: isVitestNoWorkerInitActive || isVitestBrowserModeActive,
832
1102
  })
833
1103
 
834
- logTestOptimizationSummary({ attemptToFixExecutions, newTestsWithDynamicNames })
1104
+ const shouldLogAllTestsSkippedMessage = areAllSuitesSkipped && !hasLoggedAllTestsSkippedMessage
1105
+ hasLoggedAllTestsSkippedMessage ||= shouldLogAllTestsSkippedMessage
1106
+ logTestOptimizationSummary({
1107
+ attemptToFixExecutions,
1108
+ newTestsWithDynamicNames,
1109
+ extraSections: shouldLogAllTestsSkippedMessage ? [TEST_IMPACT_ANALYSIS_ALL_TESTS_SKIPPED_MESSAGE] : [],
1110
+ })
835
1111
 
836
1112
  await flushPromise
837
1113
 
@@ -851,6 +1127,7 @@ function getCliOrStartVitestWrapper (frameworkVersion) {
851
1127
  return oldCliOrStartVitest.apply(this, args)
852
1128
  }
853
1129
  isSessionStarted = true
1130
+ resetSessionSuiteSkippingState()
854
1131
  testSessionStartCh.publish({ command: getTestCommand(), frameworkVersion })
855
1132
  return oldCliOrStartVitest.apply(this, args)
856
1133
  }
@@ -869,6 +1146,15 @@ function isVitestWorkerPool (pool) {
869
1146
  return isForkPool(pool) || isThreadPool(pool)
870
1147
  }
871
1148
 
1149
+ function isBrowserProject (project) {
1150
+ try {
1151
+ if (project?.isBrowserEnabled?.()) return true
1152
+ } catch {}
1153
+
1154
+ return safeConfig(project)?.browser?.enabled === true ||
1155
+ project?.serializedConfig?.browser?.enabled === true
1156
+ }
1157
+
872
1158
  function getTestSpecificationProject (testSpecification) {
873
1159
  if (Array.isArray(testSpecification)) {
874
1160
  return testSpecification[0]
@@ -890,6 +1176,38 @@ function getTestSpecificationPool (testSpecification) {
890
1176
  testSpecification?.pool
891
1177
  }
892
1178
 
1179
+ /**
1180
+ * Detect whether Vitest selected only TypeScript typecheck specifications.
1181
+ *
1182
+ * @param {unknown} testSpecifications
1183
+ * @returns {boolean}
1184
+ */
1185
+ function hasOnlyTypecheckTestSpecifications (testSpecifications) {
1186
+ if (!Array.isArray(testSpecifications) || testSpecifications.length === 0) return false
1187
+
1188
+ for (const testSpecification of testSpecifications) {
1189
+ if (getTestSpecificationPool(testSpecification) !== 'typescript') return false
1190
+ }
1191
+ return true
1192
+ }
1193
+
1194
+ function isBrowserTestSpecification (testSpecification) {
1195
+ return getTestSpecificationPool(testSpecification) === 'browser' ||
1196
+ isBrowserProject(getTestSpecificationProject(testSpecification))
1197
+ }
1198
+
1199
+ function getBrowserTestSpecifications (testSpecifications) {
1200
+ if (!Array.isArray(testSpecifications)) return testSpecifications
1201
+
1202
+ return testSpecifications.filter(isBrowserTestSpecification)
1203
+ }
1204
+
1205
+ function isBrowserTestModule (testModule) {
1206
+ return testModule?.task?.pool === 'browser' ||
1207
+ testModule?.pool === 'browser' ||
1208
+ isBrowserProject(testModule?.project)
1209
+ }
1210
+
893
1211
  function hasVitestWorkerPoolTestSpecification (testSpecifications) {
894
1212
  if (!Array.isArray(testSpecifications)) {
895
1213
  return false
@@ -923,14 +1241,26 @@ function markVitestWorkerEnv (ctx, testSpecifications, shouldSkipWorkerInit = fa
923
1241
  }
924
1242
 
925
1243
  function wrapVitestRunFiles (Vitest, frameworkVersion) {
926
- if (!Vitest?.prototype?.runFiles) {
1244
+ if (!Vitest?.prototype?.runFiles || runFilesWrappedPrototypes.has(Vitest.prototype)) {
927
1245
  return
928
1246
  }
1247
+ runFilesWrappedPrototypes.add(Vitest.prototype)
929
1248
 
930
1249
  shimmer.wrap(Vitest.prototype, 'runFiles', runFiles => async function (testSpecifications) {
1250
+ if (activeRunFilesContexts.has(this)) {
1251
+ return runFiles.apply(this, arguments)
1252
+ }
1253
+
931
1254
  const shouldSkipWorkerInit = await ensureMainProcessSetup(this, frameworkVersion, testSpecifications, true)
932
- markVitestWorkerEnv(this, testSpecifications, shouldSkipWorkerInit)
933
- return runFiles.apply(this, arguments)
1255
+ const testSpecificationsToRun = applySuiteSkipping(this, testSpecifications, frameworkVersion)
1256
+ arguments[0] = testSpecificationsToRun
1257
+ markVitestWorkerEnv(this, testSpecificationsToRun, shouldSkipWorkerInit)
1258
+ activeRunFilesContexts.add(this)
1259
+ try {
1260
+ return await runFiles.apply(this, arguments)
1261
+ } finally {
1262
+ activeRunFilesContexts.delete(this)
1263
+ }
934
1264
  })
935
1265
 
936
1266
  if (Vitest.prototype.collectTests) {
@@ -1139,13 +1469,34 @@ function reportTypecheckTest (task, testSuiteAbsolutePath, providedContext) {
1139
1469
  const isModified = testProperties.isModified === true
1140
1470
  const isSkippedByTestManagement = !isAttemptToFix && isDisabled
1141
1471
  const status = getTypecheckTaskStatus(task)
1472
+ const summaryStatus = isSkippedByTestManagement ? 'skip' : status
1473
+
1474
+ recordTestManagementExecution({
1475
+ testSuite: testProperties.testSuite,
1476
+ testName,
1477
+ status: summaryStatus,
1478
+ isAttemptToFix,
1479
+ isDisabled,
1480
+ isQuarantined,
1481
+ })
1482
+ if (isAttemptToFix) {
1483
+ recordAttemptToFixExecution(attemptToFixExecutions, {
1484
+ testSuite: testProperties.testSuite,
1485
+ testName,
1486
+ status: summaryStatus,
1487
+ isDisabled,
1488
+ isQuarantined,
1489
+ })
1490
+ }
1142
1491
 
1143
1492
  if (status === 'skip' || isSkippedByTestManagement) {
1144
1493
  testSkipCh.publish({
1145
1494
  testName,
1146
1495
  testSuiteAbsolutePath,
1147
1496
  isNew: testProperties.isNew,
1497
+ isAttemptToFix,
1148
1498
  isDisabled,
1499
+ isQuarantined,
1149
1500
  })
1150
1501
  updateTypecheckTaskResultForTestManagement(task, status, { isAttemptToFix, isDisabled, isQuarantined })
1151
1502
  return
@@ -1192,6 +1543,7 @@ async function reportTypecheckFile (file, sessionConfiguration, frameworkVersion
1192
1543
  testCommand: sessionConfiguration.testCommand,
1193
1544
  repositoryRoot: sessionConfiguration.repositoryRoot,
1194
1545
  codeOwnersEntries: sessionConfiguration.codeOwnersEntries,
1546
+ disableTestImpactAnalysis: isTestImpactAnalysisDisabled,
1195
1547
  }
1196
1548
  testSuiteStartCh.runStores(testSuiteCtx, () => {})
1197
1549
 
@@ -1217,8 +1569,18 @@ async function reportTypecheckResults (result, frameworkVersion, ctx, typechecke
1217
1569
  if (!testSuiteFinishCh.hasSubscribers) return
1218
1570
  if (!Array.isArray(result?.files)) return
1219
1571
 
1220
- if (ctx) {
1221
- await ensureMainProcessSetup(ctx, frameworkVersion, result.files)
1572
+ const setupState = ctx && mainProcessSetupStates.get(ctx)
1573
+ if (
1574
+ ctx &&
1575
+ (!setupState || setupState.shouldInstallMainReporter || setupState.disableTestImpactAnalysis)
1576
+ ) {
1577
+ await ensureMainProcessSetup(
1578
+ ctx,
1579
+ frameworkVersion,
1580
+ result.files,
1581
+ false,
1582
+ !setupState || setupState.disableTestImpactAnalysis
1583
+ )
1222
1584
  }
1223
1585
  const providedContext = getMainProcessProvidedContext(ctx)
1224
1586
  const sessionConfiguration = testSessionConfigurationCh.hasSubscribers
@@ -1409,11 +1771,21 @@ function handleWorkerReport (interprocessCode, data) {
1409
1771
  return true
1410
1772
  }
1411
1773
 
1774
+ if (interprocessCode === VITEST_WORKER_COVERAGE_PAYLOAD_CODE) {
1775
+ workerReportCoverageCh.publish(data)
1776
+ return true
1777
+ }
1778
+
1412
1779
  if (interprocessCode === VITEST_WORKER_LOGS_PAYLOAD_CODE) {
1413
1780
  workerReportLogsCh.publish(data)
1414
1781
  return true
1415
1782
  }
1416
1783
 
1784
+ if (interprocessCode === VITEST_WORKER_TELEMETRY_PAYLOAD_CODE) {
1785
+ workerReportTelemetryCh.publish(data)
1786
+ return true
1787
+ }
1788
+
1417
1789
  return false
1418
1790
  }
1419
1791
 
@@ -1477,9 +1849,9 @@ addHook({
1477
1849
  name: 'vitest',
1478
1850
  versions: ['>=1.6.0 <2.0.0'],
1479
1851
  filePattern: 'dist/vendor/index.*',
1480
- }, (vitestPackage) => {
1852
+ }, (vitestPackage, frameworkVersion) => {
1481
1853
  if (isReporterPackage(vitestPackage)) {
1482
- shimmer.wrap(vitestPackage.B.prototype, 'sort', getSortWrapper)
1854
+ shimmer.wrap(vitestPackage.B.prototype, 'sort', sort => getSortWrapper(sort, frameworkVersion))
1483
1855
  }
1484
1856
 
1485
1857
  return vitestPackage
@@ -1489,9 +1861,9 @@ addHook({
1489
1861
  name: 'vitest',
1490
1862
  versions: ['>=2.0.0 <2.0.5'],
1491
1863
  filePattern: 'dist/vendor/index.*',
1492
- }, (vitestPackage) => {
1864
+ }, (vitestPackage, frameworkVersion) => {
1493
1865
  if (isReporterPackageNew(vitestPackage)) {
1494
- shimmer.wrap(vitestPackage.e.prototype, 'sort', getSortWrapper)
1866
+ shimmer.wrap(vitestPackage.e.prototype, 'sort', sort => getSortWrapper(sort, frameworkVersion))
1495
1867
  }
1496
1868
 
1497
1869
  return vitestPackage
@@ -1501,9 +1873,9 @@ addHook({
1501
1873
  name: 'vitest',
1502
1874
  versions: ['>=2.0.5 <2.1.0'],
1503
1875
  filePattern: 'dist/chunks/index.*',
1504
- }, (vitestPackage) => {
1876
+ }, (vitestPackage, frameworkVersion) => {
1505
1877
  if (isReporterPackageNewest(vitestPackage)) {
1506
- shimmer.wrap(vitestPackage.h.prototype, 'sort', getSortWrapper)
1878
+ shimmer.wrap(vitestPackage.h.prototype, 'sort', sort => getSortWrapper(sort, frameworkVersion))
1507
1879
  }
1508
1880
 
1509
1881
  return vitestPackage
@@ -1525,8 +1897,12 @@ addHook({
1525
1897
  name: 'vitest',
1526
1898
  versions: ['>=2.1.0 <3.0.0'],
1527
1899
  filePattern: 'dist/chunks/RandomSequencer.*',
1528
- }, (randomSequencerPackage) => {
1529
- shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
1900
+ }, (randomSequencerPackage, frameworkVersion) => {
1901
+ shimmer.wrap(
1902
+ randomSequencerPackage.B.prototype,
1903
+ 'sort',
1904
+ sort => getSortWrapper(sort, frameworkVersion)
1905
+ )
1530
1906
  return randomSequencerPackage
1531
1907
  })
1532
1908
 
@@ -1534,10 +1910,14 @@ addHook({
1534
1910
  name: 'vitest',
1535
1911
  versions: ['>=3.0.9'],
1536
1912
  filePattern: 'dist/chunks/coverage.*',
1537
- }, (coveragePackage) => {
1913
+ }, (coveragePackage, frameworkVersion) => {
1538
1914
  const baseSequencer = getBaseSequencerExport(coveragePackage)
1539
1915
  if (baseSequencer) {
1540
- shimmer.wrap(baseSequencer.value.prototype, 'sort', getSortWrapper)
1916
+ shimmer.wrap(
1917
+ baseSequencer.value.prototype,
1918
+ 'sort',
1919
+ sort => getSortWrapper(sort, frameworkVersion)
1920
+ )
1541
1921
  }
1542
1922
  return coveragePackage
1543
1923
  })
@@ -1546,8 +1926,12 @@ addHook({
1546
1926
  name: 'vitest',
1547
1927
  versions: ['>=3.0.0 <3.0.9'],
1548
1928
  filePattern: 'dist/chunks/resolveConfig.*',
1549
- }, (resolveConfigPackage) => {
1550
- shimmer.wrap(resolveConfigPackage.B.prototype, 'sort', getSortWrapper)
1929
+ }, (resolveConfigPackage, frameworkVersion) => {
1930
+ shimmer.wrap(
1931
+ resolveConfigPackage.B.prototype,
1932
+ 'sort',
1933
+ sort => getSortWrapper(sort, frameworkVersion)
1934
+ )
1551
1935
  return resolveConfigPackage
1552
1936
  })
1553
1937