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.
- package/ci/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +14 -8
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +47 -37
- package/ci/test-optimization-validation/generated-test-contract.js +9 -7
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +301 -52
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/offline-output.js +6 -6
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +41 -21
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/safe-files.js +4 -4
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +60 -6
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +377 -84
- package/index.d.ts +175 -14
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +12 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-esbuild/src/utils.js +17 -2
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +85 -9
- package/packages/datadog-instrumentations/src/cucumber.js +131 -51
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +175 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +38 -7
- package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -3
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +986 -246
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +109 -51
- package/packages/datadog-instrumentations/src/mocha/utils.js +120 -32
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +44 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +441 -43
- package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/pg.js +180 -6
- package/packages/datadog-instrumentations/src/playwright.js +176 -81
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/rhea.js +1 -1
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +567 -65
- package/packages/datadog-instrumentations/src/vitest-main.js +438 -54
- package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
- package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
- package/packages/datadog-instrumentations/src/webdriverio.js +1090 -0
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aerospike/src/index.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
- package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
- package/packages/datadog-plugin-child_process/src/index.js +3 -3
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -11
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
- package/packages/datadog-plugin-graphql/src/execute.js +1 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +3 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +3 -21
- package/packages/datadog-plugin-jest/src/util.js +4 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +342 -6
- package/packages/datadog-plugin-next/src/index.js +57 -9
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-pg/src/index.js +65 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-prisma/src/index.js +5 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-undici/src/index.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +179 -18
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/datadog-webpack/index.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -1
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -15
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +25 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +2 -2
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/defaults.js +14 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +31 -5
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +13 -6
- package/packages/dd-trace/src/datastreams/encoding.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/url.js +3 -5
- package/packages/dd-trace/src/exporters/electron/index.js +4 -1
- package/packages/dd-trace/src/external-logger/src/index.js +1 -2
- package/packages/dd-trace/src/flare/index.js +2 -2
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/id.js +1 -1
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
- package/packages/dd-trace/src/llmobs/experiments/index.js +66 -19
- package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
- package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
- package/packages/dd-trace/src/llmobs/experiments/util.js +220 -0
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +152 -78
- package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
- package/packages/dd-trace/src/llmobs/tagger.js +1 -2
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/span_context.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +124 -23
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +13 -6
- package/packages/dd-trace/src/plugins/util/git.js +7 -5
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +3 -3
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/tags.js +2 -0
- package/packages/dd-trace/src/plugins/util/test.js +356 -86
- package/packages/dd-trace/src/plugins/util/url.js +5 -5
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +24 -2
- package/packages/dd-trace/src/priority_sampler.js +6 -3
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +10 -20
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/startup-log.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/packages/dd-trace/src/util.js +16 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -4,13 +4,15 @@ const path = require('node:path')
|
|
|
4
4
|
|
|
5
5
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
6
6
|
|
|
7
|
+
const { hasEfdRetries } = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
|
|
8
|
+
const { RUM_TEST_EXECUTION_ID_COOKIE_NAME } = require('../../dd-trace/src/ci-visibility/rum')
|
|
7
9
|
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
8
10
|
const log = require('../../dd-trace/src/log')
|
|
9
11
|
const {
|
|
10
12
|
DYNAMIC_NAME_RE,
|
|
11
|
-
EARLY_FLAKE_DETECTION_RETRY_THRESHOLDS,
|
|
12
13
|
getTestSuitePath,
|
|
13
14
|
logAttemptToFixTestExecution,
|
|
15
|
+
recordTestManagementExecution,
|
|
14
16
|
recordAttemptToFixExecution,
|
|
15
17
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
16
18
|
const {
|
|
@@ -29,9 +31,9 @@ const {
|
|
|
29
31
|
testSuiteStartCh,
|
|
30
32
|
} = require('./vitest-util')
|
|
31
33
|
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
34
|
+
// Main-process Vitest reporting used by no-worker-init and Browser Mode.
|
|
35
|
+
// Execution changes are applied by an instrumentation-less setup file in the test environment,
|
|
36
|
+
// while this module creates test spans from Vitest reporter events.
|
|
35
37
|
const mainProcessReporterStates = new WeakMap()
|
|
36
38
|
const loggedAttemptToFixTests = new Set()
|
|
37
39
|
|
|
@@ -53,16 +55,181 @@ const VITEST_NO_WORKER_INIT_SETUP_FILE = path.join(
|
|
|
53
55
|
'ci',
|
|
54
56
|
'vitest-no-worker-init-setup.mjs'
|
|
55
57
|
)
|
|
58
|
+
const VITEST_BROWSER_SETUP_FILE_PLUGIN = {
|
|
59
|
+
name: 'datadog:vitest-browser-setup-file',
|
|
60
|
+
config: configureVitestBrowserSetupFile,
|
|
61
|
+
configResolved: allowVitestBrowserSetupFile,
|
|
62
|
+
}
|
|
56
63
|
const VITEST_NO_WORKER_INIT_ISOLATE_WARNING =
|
|
57
64
|
`${VITEST_NO_WORKER_INIT_REQUEST_ENV} is ignored because Vitest isolate is disabled. ` +
|
|
58
65
|
'The lighter Vitest worker path only works when each test file runs in an isolated worker.'
|
|
59
66
|
const NODE_OPTIONS_QUOTE_RE = /[\s"\\]/
|
|
67
|
+
const VITEST_BROWSER_STACK_LOCATION_RE = /:\d+:\d+$/
|
|
68
|
+
const VITEST_BROWSER_URL_RE = /https?:\/\/[^\s)"'>\]]+/g
|
|
60
69
|
let hasWarnedDisabledIsolate = false
|
|
61
70
|
let hasWarnedUnsupportedVersion = false
|
|
62
71
|
let nodeOptionsBeforeNoWorkerInit
|
|
63
72
|
|
|
64
73
|
function noop () {}
|
|
65
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Removes Vite and Vitest runtime query parameters from browser error URLs.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} url
|
|
79
|
+
* @returns {string}
|
|
80
|
+
*/
|
|
81
|
+
function removeVitestBrowserUrlMetadata (url) {
|
|
82
|
+
const locationMatch = url.match(VITEST_BROWSER_STACK_LOCATION_RE)
|
|
83
|
+
const location = locationMatch?.[0] || ''
|
|
84
|
+
const urlWithoutLocation = location ? url.slice(0, -location.length) : url
|
|
85
|
+
const queryStart = urlWithoutLocation.indexOf('?')
|
|
86
|
+
if (queryStart === -1) return url
|
|
87
|
+
|
|
88
|
+
const fragmentStart = urlWithoutLocation.indexOf('#', queryStart)
|
|
89
|
+
const queryEnd = fragmentStart === -1 ? urlWithoutLocation.length : fragmentStart
|
|
90
|
+
const parameters = urlWithoutLocation.slice(queryStart + 1, queryEnd).split('&')
|
|
91
|
+
const keptParameters = []
|
|
92
|
+
let removedParameter = false
|
|
93
|
+
|
|
94
|
+
for (const parameter of parameters) {
|
|
95
|
+
const valueSeparator = parameter.indexOf('=')
|
|
96
|
+
const name = valueSeparator === -1 ? parameter : parameter.slice(0, valueSeparator)
|
|
97
|
+
if (name === 'import' || name === 'browserv') {
|
|
98
|
+
removedParameter = true
|
|
99
|
+
} else {
|
|
100
|
+
keptParameters.push(parameter)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!removedParameter) return url
|
|
105
|
+
|
|
106
|
+
const query = keptParameters.length ? `?${keptParameters.join('&')}` : ''
|
|
107
|
+
return urlWithoutLocation.slice(0, queryStart) + query + urlWithoutLocation.slice(queryEnd) + location
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Removes Vite and Vitest runtime URL metadata from browser error text.
|
|
112
|
+
*
|
|
113
|
+
* @param {string} value
|
|
114
|
+
* @returns {string}
|
|
115
|
+
*/
|
|
116
|
+
function normalizeVitestBrowserErrorText (value) {
|
|
117
|
+
return value.replaceAll(VITEST_BROWSER_URL_RE, removeVitestBrowserUrlMetadata)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Removes the ephemeral Vite server origin in addition to its runtime query parameters.
|
|
122
|
+
*
|
|
123
|
+
* @param {string} url
|
|
124
|
+
* @returns {string}
|
|
125
|
+
*/
|
|
126
|
+
function normalizeVitestBrowserStackUrl (url) {
|
|
127
|
+
const normalizedUrl = removeVitestBrowserUrlMetadata(url)
|
|
128
|
+
const protocolEnd = normalizedUrl.indexOf('://')
|
|
129
|
+
const pathStart = normalizedUrl.indexOf('/', protocolEnd + 3)
|
|
130
|
+
return pathStart === -1 ? normalizedUrl : normalizedUrl.slice(pathStart)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Normalizes browser URLs in a stack when Vitest does not provide parsed frames.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} value
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
function normalizeVitestBrowserStackText (value) {
|
|
140
|
+
return value.replaceAll(VITEST_BROWSER_URL_RE, normalizeVitestBrowserStackUrl)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Rebuilds an error stack from the source-mapped frames already parsed by Vitest.
|
|
145
|
+
*
|
|
146
|
+
* @param {{
|
|
147
|
+
* stack?: string,
|
|
148
|
+
* stacks?: Array<{ column: number, file: string, line: number, method?: string }>
|
|
149
|
+
* }} error
|
|
150
|
+
* @returns {string|undefined}
|
|
151
|
+
*/
|
|
152
|
+
function normalizeVitestBrowserErrorStack (error) {
|
|
153
|
+
if (typeof error.stack !== 'string') return error.stack
|
|
154
|
+
if (!Array.isArray(error.stacks)) {
|
|
155
|
+
return normalizeVitestBrowserStackText(error.stack)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const firstLineEnd = error.stack.indexOf('\n')
|
|
159
|
+
const stackLines = new Array(error.stacks.length + 1)
|
|
160
|
+
stackLines[0] = normalizeVitestBrowserErrorText(
|
|
161
|
+
firstLineEnd === -1 ? error.stack : error.stack.slice(0, firstLineEnd)
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
for (let index = 0; index < error.stacks.length; index++) {
|
|
165
|
+
const frame = error.stacks[index]
|
|
166
|
+
const location = `${frame.file}:${frame.line}:${frame.column}`
|
|
167
|
+
stackLines[index + 1] = frame.method
|
|
168
|
+
? ` at ${frame.method} (${location})`
|
|
169
|
+
: ` at ${location}`
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return stackLines.join('\n')
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Returns an error copy with browser-only URL metadata removed.
|
|
177
|
+
*
|
|
178
|
+
* @param {{
|
|
179
|
+
* message?: string,
|
|
180
|
+
* name?: string,
|
|
181
|
+
* stack?: string,
|
|
182
|
+
* stacks?: Array<{ column: number, file: string, line: number, method?: string }>
|
|
183
|
+
* }|undefined} error
|
|
184
|
+
* @returns {{
|
|
185
|
+
* message?: string,
|
|
186
|
+
* name?: string,
|
|
187
|
+
* stack?: string,
|
|
188
|
+
* stacks?: Array<{ column: number, file: string, line: number, method?: string }>
|
|
189
|
+
* }|undefined}
|
|
190
|
+
*/
|
|
191
|
+
function normalizeVitestBrowserError (error) {
|
|
192
|
+
if (!error) return error
|
|
193
|
+
|
|
194
|
+
const message = typeof error.message === 'string'
|
|
195
|
+
? normalizeVitestBrowserErrorText(error.message)
|
|
196
|
+
: error.message
|
|
197
|
+
const stack = normalizeVitestBrowserErrorStack(error)
|
|
198
|
+
if (message === error.message && stack === error.stack) return error
|
|
199
|
+
|
|
200
|
+
const normalizedError = { ...error }
|
|
201
|
+
if (error.name !== undefined) normalizedError.name = error.name
|
|
202
|
+
if (message !== undefined) normalizedError.message = message
|
|
203
|
+
if (stack !== undefined) normalizedError.stack = stack
|
|
204
|
+
return normalizedError
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Normalizes browser errors without mutating Vitest's task result.
|
|
209
|
+
*
|
|
210
|
+
* @param {Array<{
|
|
211
|
+
* message?: string,
|
|
212
|
+
* name?: string,
|
|
213
|
+
* stack?: string,
|
|
214
|
+
* stacks?: Array<{ column: number, file: string, line: number, method?: string }>
|
|
215
|
+
* }>|undefined} errors
|
|
216
|
+
* @returns {Array<{
|
|
217
|
+
* message?: string,
|
|
218
|
+
* name?: string,
|
|
219
|
+
* stack?: string,
|
|
220
|
+
* stacks?: Array<{ column: number, file: string, line: number, method?: string }>
|
|
221
|
+
* }>}
|
|
222
|
+
*/
|
|
223
|
+
function normalizeVitestBrowserErrors (errors) {
|
|
224
|
+
if (!errors?.length) return []
|
|
225
|
+
|
|
226
|
+
const normalizedErrors = new Array(errors.length)
|
|
227
|
+
for (let index = 0; index < errors.length; index++) {
|
|
228
|
+
normalizedErrors[index] = normalizeVitestBrowserError(errors[index])
|
|
229
|
+
}
|
|
230
|
+
return normalizedErrors
|
|
231
|
+
}
|
|
232
|
+
|
|
66
233
|
function isRequested () {
|
|
67
234
|
return getValueFromEnvSources(VITEST_NO_WORKER_INIT_REQUEST_ENV) === true
|
|
68
235
|
}
|
|
@@ -143,38 +310,51 @@ function isNoWorkerInitPool (pool, isVitestWorkerPool) {
|
|
|
143
310
|
return pool === undefined || isVitestWorkerPool(pool)
|
|
144
311
|
}
|
|
145
312
|
|
|
313
|
+
/**
|
|
314
|
+
* @param {object} state
|
|
315
|
+
* @returns {boolean}
|
|
316
|
+
*/
|
|
317
|
+
function isEarlyFlakeDetectionActive (state) {
|
|
318
|
+
return state.isEarlyFlakeDetectionEnabled &&
|
|
319
|
+
!state.isEarlyFlakeDetectionFaulty &&
|
|
320
|
+
hasEfdRetries(state.earlyFlakeDetectionRetryPolicy)
|
|
321
|
+
}
|
|
322
|
+
|
|
146
323
|
function configure (ctx, frameworkVersion, testSpecifications, setupData, options) {
|
|
147
|
-
const {
|
|
324
|
+
const { shouldReportTestModule, state } = options
|
|
148
325
|
addSetupFileToVitestConfigs(ctx, VITEST_NO_WORKER_INIT_SETUP_FILE, testSpecifications)
|
|
326
|
+
addVitestBrowserSetupFileAccess(testSpecifications)
|
|
149
327
|
|
|
150
328
|
const {
|
|
151
329
|
knownTestsBySuite,
|
|
152
330
|
modifiedFiles,
|
|
153
331
|
repositoryRoot,
|
|
154
332
|
testManagementTestsBySuite,
|
|
333
|
+
testPropertiesByFilepath,
|
|
155
334
|
testSessionConfiguration,
|
|
156
335
|
} = setupData
|
|
157
336
|
|
|
158
337
|
setProvidedContext(ctx, {
|
|
159
338
|
_ddVitestWorkerSetup: {
|
|
339
|
+
isActive: true,
|
|
160
340
|
attemptToFixRetries: state.testManagementAttemptToFixRetries,
|
|
161
341
|
attemptToFixTests: getSelectedTestManagementTests(testManagementTestsBySuite, 'isAttemptToFix'),
|
|
162
342
|
disabledTests: getSelectedTestManagementTests(testManagementTestsBySuite, 'isDisabled'),
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
),
|
|
167
|
-
earlyFlakeDetectionRetryThresholds: EARLY_FLAKE_DETECTION_RETRY_THRESHOLDS,
|
|
168
|
-
earlyFlakeDetectionSlowRetries: state.earlyFlakeDetectionSlowTestRetries,
|
|
169
|
-
isEarlyFlakeDetectionEnabled: state.isEarlyFlakeDetectionEnabled && !state.isEarlyFlakeDetectionFaulty,
|
|
343
|
+
earlyFlakeDetectionRetryPolicy: state.earlyFlakeDetectionRetryPolicy,
|
|
344
|
+
isEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionActive(state),
|
|
345
|
+
isRumCorrelationEnabled: !canRaceRumCorrelation(ctx, testSpecifications),
|
|
170
346
|
knownTests: knownTestsBySuite || {},
|
|
171
347
|
modifiedFiles: modifiedFiles || {},
|
|
172
348
|
quarantinedTests: getSelectedTestManagementTests(testManagementTestsBySuite, 'isQuarantined'),
|
|
173
349
|
repositoryRoot: repositoryRoot || process.cwd(),
|
|
350
|
+
rumTestExecutionIdCookieName: RUM_TEST_EXECUTION_ID_COOKIE_NAME,
|
|
351
|
+
testPropertiesByFilepath: testPropertiesByFilepath || {},
|
|
174
352
|
},
|
|
175
|
-
}, 'Could not send Vitest
|
|
353
|
+
}, 'Could not send Vitest setup context, so main-process execution changes will not work.')
|
|
176
354
|
|
|
177
|
-
installMainProcessReporter(ctx, frameworkVersion, testSessionConfiguration || {}, setupData, state
|
|
355
|
+
installMainProcessReporter(ctx, frameworkVersion, testSessionConfiguration || {}, setupData, state, {
|
|
356
|
+
shouldReportTestModule,
|
|
357
|
+
})
|
|
178
358
|
}
|
|
179
359
|
|
|
180
360
|
function deactivate (ctx) {
|
|
@@ -182,6 +362,11 @@ function deactivate (ctx) {
|
|
|
182
362
|
if (installedReporterState) {
|
|
183
363
|
installedReporterState.isActive = false
|
|
184
364
|
}
|
|
365
|
+
setProvidedContext(ctx, {
|
|
366
|
+
_ddVitestWorkerSetup: {
|
|
367
|
+
isActive: false,
|
|
368
|
+
},
|
|
369
|
+
}, 'Could not deactivate Vitest main-process execution changes.')
|
|
185
370
|
}
|
|
186
371
|
|
|
187
372
|
function configureWorkerEnv (workerEnv, shouldSkipWorkerInit = false) {
|
|
@@ -224,14 +409,75 @@ function addSetupFileToVitestConfigs (ctx, setupFile, testSpecifications) {
|
|
|
224
409
|
for (const config of configs) {
|
|
225
410
|
if (!config) continue
|
|
226
411
|
|
|
412
|
+
config.includeTaskLocation = true
|
|
227
413
|
if (config.setupFiles === undefined) {
|
|
228
414
|
config.setupFiles = []
|
|
229
415
|
} else if (typeof config.setupFiles === 'string') {
|
|
230
416
|
config.setupFiles = [config.setupFiles]
|
|
231
417
|
}
|
|
232
418
|
|
|
233
|
-
|
|
234
|
-
|
|
419
|
+
const setupFileIndex = config.setupFiles.indexOf(setupFile)
|
|
420
|
+
if (setupFileIndex !== 0) {
|
|
421
|
+
if (setupFileIndex > 0) {
|
|
422
|
+
config.setupFiles.splice(setupFileIndex, 1)
|
|
423
|
+
}
|
|
424
|
+
config.setupFiles.unshift(setupFile)
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Resolves the Vitest runner from the browser project's dependency tree.
|
|
431
|
+
*
|
|
432
|
+
* @param {{
|
|
433
|
+
* resolve?: { dedupe?: string[] }
|
|
434
|
+
* }} viteConfig
|
|
435
|
+
* @returns {void}
|
|
436
|
+
*/
|
|
437
|
+
function configureVitestBrowserSetupFile (viteConfig) {
|
|
438
|
+
viteConfig.resolve ||= {}
|
|
439
|
+
viteConfig.resolve.dedupe ||= []
|
|
440
|
+
|
|
441
|
+
if (!viteConfig.resolve.dedupe.includes('@vitest/runner')) {
|
|
442
|
+
viteConfig.resolve.dedupe.push('@vitest/runner')
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Allows Vite to serve the Datadog setup file after its default workspace detection has run.
|
|
448
|
+
*
|
|
449
|
+
* @param {{ server?: { fs?: { allow?: string[] } } }} viteConfig
|
|
450
|
+
* @returns {void}
|
|
451
|
+
*/
|
|
452
|
+
function allowVitestBrowserSetupFile (viteConfig) {
|
|
453
|
+
const allow = viteConfig.server?.fs?.allow
|
|
454
|
+
if (allow && !allow.includes(VITEST_NO_WORKER_INIT_SETUP_FILE)) {
|
|
455
|
+
allow.push(VITEST_NO_WORKER_INIT_SETUP_FILE)
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Installs the Vite access plugin on each parent project that owns a Browser Mode server.
|
|
461
|
+
*
|
|
462
|
+
* @param {object[]|undefined} testSpecifications
|
|
463
|
+
* @returns {void}
|
|
464
|
+
*/
|
|
465
|
+
function addVitestBrowserSetupFileAccess (testSpecifications) {
|
|
466
|
+
if (!Array.isArray(testSpecifications)) return
|
|
467
|
+
|
|
468
|
+
const configuredProjects = new Set()
|
|
469
|
+
for (const testSpecification of testSpecifications) {
|
|
470
|
+
const project = getTestSpecificationProject(testSpecification)
|
|
471
|
+
if (!isBrowserTestSpecification(testSpecification)) continue
|
|
472
|
+
|
|
473
|
+
const browserServerProject = project?._parent || project
|
|
474
|
+
if (!browserServerProject || configuredProjects.has(browserServerProject)) continue
|
|
475
|
+
|
|
476
|
+
configuredProjects.add(browserServerProject)
|
|
477
|
+
browserServerProject.options ||= {}
|
|
478
|
+
browserServerProject.options.plugins ||= []
|
|
479
|
+
if (!browserServerProject.options.plugins.includes(VITEST_BROWSER_SETUP_FILE_PLUGIN)) {
|
|
480
|
+
browserServerProject.options.plugins.push(VITEST_BROWSER_SETUP_FILE_PLUGIN)
|
|
235
481
|
}
|
|
236
482
|
}
|
|
237
483
|
}
|
|
@@ -279,12 +525,20 @@ function getSelectedTestManagementTests (testManagementTestsBySuite, propertyNam
|
|
|
279
525
|
return selectedTests
|
|
280
526
|
}
|
|
281
527
|
|
|
282
|
-
function installMainProcessReporter (
|
|
528
|
+
function installMainProcessReporter (
|
|
529
|
+
ctx,
|
|
530
|
+
frameworkVersion,
|
|
531
|
+
testSessionConfiguration,
|
|
532
|
+
testOptimizationData,
|
|
533
|
+
state,
|
|
534
|
+
options
|
|
535
|
+
) {
|
|
283
536
|
if (!ctx?.reporters) return
|
|
284
537
|
|
|
285
538
|
const reporterState = {
|
|
286
539
|
frameworkVersion,
|
|
287
540
|
isActive: true,
|
|
541
|
+
shouldReportTestModule: options.shouldReportTestModule,
|
|
288
542
|
state,
|
|
289
543
|
testSessionConfiguration,
|
|
290
544
|
testOptimizationData,
|
|
@@ -307,26 +561,26 @@ function createMainProcessReporter (reporterState) {
|
|
|
307
561
|
|
|
308
562
|
return {
|
|
309
563
|
onTestModuleStart (testModule) {
|
|
310
|
-
if (!
|
|
564
|
+
if (!shouldReport(testModule)) return
|
|
311
565
|
|
|
312
566
|
startTestSuite(testModule)
|
|
313
567
|
},
|
|
314
568
|
|
|
315
569
|
onTestModuleEnd (testModule) {
|
|
316
|
-
if (!
|
|
570
|
+
if (!shouldReport(testModule)) return
|
|
317
571
|
|
|
318
572
|
return reportTestModule(testModule)
|
|
319
573
|
},
|
|
320
574
|
|
|
321
575
|
onTestCaseResult (testCase) {
|
|
322
|
-
if (!
|
|
576
|
+
if (!shouldReport(testCase.module || testCase.task?.file)) return
|
|
323
577
|
|
|
324
578
|
const task = getTestCaseTask(testCase)
|
|
325
579
|
recordFinalTaskAttemptResult(task)
|
|
326
580
|
},
|
|
327
581
|
|
|
328
582
|
onTaskUpdate (packs, events) {
|
|
329
|
-
if (!
|
|
583
|
+
if (!isReporterActive()) return
|
|
330
584
|
if (!events) return
|
|
331
585
|
|
|
332
586
|
for (const event of events) {
|
|
@@ -336,23 +590,43 @@ function createMainProcessReporter (reporterState) {
|
|
|
336
590
|
}
|
|
337
591
|
},
|
|
338
592
|
|
|
593
|
+
onWatcherRerun () {
|
|
594
|
+
for (const testSuiteCtx of testSuiteContexts.values()) {
|
|
595
|
+
testSuiteFinishCh.publish({
|
|
596
|
+
status: 'skip',
|
|
597
|
+
deferFlush: true,
|
|
598
|
+
onDone: noop,
|
|
599
|
+
...testSuiteCtx.currentStore,
|
|
600
|
+
})
|
|
601
|
+
}
|
|
602
|
+
testSuiteContexts.clear()
|
|
603
|
+
finishedTestModules.clear()
|
|
604
|
+
taskAttemptStatuses.clear()
|
|
605
|
+
tasksWithRecordedFinalAttempt.clear()
|
|
606
|
+
},
|
|
607
|
+
|
|
339
608
|
onFinished (files) {
|
|
340
|
-
if (!
|
|
609
|
+
if (!isReporterActive()) return
|
|
341
610
|
if (!files) return
|
|
342
611
|
|
|
343
612
|
for (const file of files) {
|
|
344
613
|
const testModule = createTestModuleFromFile(file)
|
|
345
|
-
if (!finishedTestModules.has(file.id)) {
|
|
614
|
+
if (shouldReport(testModule) && !finishedTestModules.has(file.id)) {
|
|
346
615
|
reportTestModule(testModule)
|
|
347
616
|
}
|
|
348
617
|
}
|
|
349
618
|
},
|
|
350
619
|
}
|
|
351
620
|
|
|
352
|
-
function
|
|
621
|
+
function isReporterActive () {
|
|
353
622
|
return reporterState.isActive === true
|
|
354
623
|
}
|
|
355
624
|
|
|
625
|
+
function shouldReport (testModule) {
|
|
626
|
+
return isReporterActive() &&
|
|
627
|
+
(!reporterState.shouldReportTestModule || reporterState.shouldReportTestModule(testModule))
|
|
628
|
+
}
|
|
629
|
+
|
|
356
630
|
function recordTaskAttemptStatus (taskId, status, attemptCount) {
|
|
357
631
|
let statuses = taskAttemptStatuses.get(taskId)
|
|
358
632
|
if (!statuses) {
|
|
@@ -389,7 +663,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
389
663
|
let testSuiteError
|
|
390
664
|
|
|
391
665
|
for (const task of testTasks) {
|
|
392
|
-
const testReport = getTestReport(task, testSuiteCtx.currentStore)
|
|
666
|
+
const testReport = getTestReport(task, testSuiteCtx.currentStore, testSuiteCtx.browserEnvironment)
|
|
393
667
|
testReports.push(testReport)
|
|
394
668
|
|
|
395
669
|
for (const attempt of testReport.nonFinalAttempts) {
|
|
@@ -412,7 +686,9 @@ function createMainProcessReporter (reporterState) {
|
|
|
412
686
|
}
|
|
413
687
|
|
|
414
688
|
if (testSuiteError) {
|
|
415
|
-
testSuiteCtx.error =
|
|
689
|
+
testSuiteCtx.error = testSuiteCtx.browserEnvironment
|
|
690
|
+
? normalizeVitestBrowserError(testSuiteError)
|
|
691
|
+
: testSuiteError
|
|
416
692
|
testSuiteErrorCh.runStores(testSuiteCtx, () => {})
|
|
417
693
|
}
|
|
418
694
|
|
|
@@ -428,16 +704,22 @@ function createMainProcessReporter (reporterState) {
|
|
|
428
704
|
function startTestSuite (testModule) {
|
|
429
705
|
const { frameworkVersion, testSessionConfiguration } = reporterState
|
|
430
706
|
const testModuleId = getTestModuleId(testModule)
|
|
707
|
+
const browserEnvironment = getTestModuleBrowserEnvironment(testModule)
|
|
431
708
|
const testSuiteCtx = {
|
|
709
|
+
browserEnvironment,
|
|
710
|
+
browserDriver: browserEnvironment?.browserDriver,
|
|
711
|
+
browserName: browserEnvironment?.browserName,
|
|
712
|
+
browserProjectName: browserEnvironment?.browserProjectName,
|
|
432
713
|
testSuiteAbsolutePath: getTestModuleFilepath(testModule),
|
|
433
714
|
frameworkVersion,
|
|
434
715
|
testSessionId: testSessionConfiguration.testSessionId,
|
|
435
716
|
testModuleId: testSessionConfiguration.testModuleId,
|
|
436
717
|
testCommand: testSessionConfiguration.testCommand,
|
|
437
718
|
repositoryRoot: testSessionConfiguration.repositoryRoot,
|
|
438
|
-
codeOwnersEntries: testSessionConfiguration.codeOwnersEntries,
|
|
719
|
+
codeOwnersEntries: testSessionConfiguration.codeOwnersEntries ?? undefined,
|
|
439
720
|
requestErrorTags: reporterState.state.requestErrorTags,
|
|
440
721
|
isTestFrameworkWorker: true,
|
|
722
|
+
isBrowserMode: browserEnvironment !== undefined,
|
|
441
723
|
isVitestNoWorkerInitActive: true,
|
|
442
724
|
}
|
|
443
725
|
testSuiteStartCh.runStores(testSuiteCtx, () => {})
|
|
@@ -445,7 +727,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
445
727
|
return testSuiteCtx
|
|
446
728
|
}
|
|
447
729
|
|
|
448
|
-
function getTestReport (task, testSuiteStore) {
|
|
730
|
+
function getTestReport (task, testSuiteStore, browserEnvironment) {
|
|
449
731
|
const result = task.result
|
|
450
732
|
const testSuiteAbsolutePath = task.file?.filepath
|
|
451
733
|
const testName = getTestName(task)
|
|
@@ -459,6 +741,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
459
741
|
|
|
460
742
|
if (testProperties.isAttemptToFix && task.meta?.__ddTestOptAtfStatuses?.length) {
|
|
461
743
|
return getRepeatedTestReport(task, testName, testSuiteAbsolutePath, testProperties, status, {
|
|
744
|
+
browserEnvironment,
|
|
462
745
|
errorCounts: task.meta.__ddTestOptAtfErrorCounts,
|
|
463
746
|
finalStatus: getAttemptToFixFinalStatus,
|
|
464
747
|
state,
|
|
@@ -470,6 +753,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
470
753
|
|
|
471
754
|
if (testProperties.isEarlyFlakeDetection && task.meta?.__ddTestOptEfdStatuses?.length) {
|
|
472
755
|
return getRepeatedTestReport(task, testName, testSuiteAbsolutePath, testProperties, status, {
|
|
756
|
+
browserEnvironment,
|
|
473
757
|
errorCounts: task.meta.__ddTestOptEfdErrorCounts,
|
|
474
758
|
finalStatus: getEarlyFlakeDetectionFinalStatus,
|
|
475
759
|
state,
|
|
@@ -481,8 +765,9 @@ function createMainProcessReporter (reporterState) {
|
|
|
481
765
|
|
|
482
766
|
if (!testProperties.isAttemptToFix && task.meta?.__ddTestOptRepeatStatuses?.length) {
|
|
483
767
|
return getRepeatedTestReport(task, testName, testSuiteAbsolutePath, testProperties, status, {
|
|
768
|
+
browserEnvironment,
|
|
484
769
|
errorCounts: task.meta.__ddTestOptRepeatErrorCounts,
|
|
485
|
-
finalStatus: () => status,
|
|
770
|
+
finalStatus: () => getExternalFinalStatus(status, testProperties),
|
|
486
771
|
state,
|
|
487
772
|
statuses: task.meta.__ddTestOptRepeatStatuses,
|
|
488
773
|
testSuiteStore,
|
|
@@ -491,11 +776,18 @@ function createMainProcessReporter (reporterState) {
|
|
|
491
776
|
}
|
|
492
777
|
|
|
493
778
|
const attemptStatuses = taskAttemptStatuses.get(task.id)
|
|
494
|
-
|
|
779
|
+
const retryCount = task.result?.retryCount || 0
|
|
780
|
+
if (
|
|
781
|
+
!testProperties.isAttemptToFix &&
|
|
782
|
+
!testProperties.isEarlyFlakeDetection &&
|
|
783
|
+
(attemptStatuses?.length > 1 || retryCount > 0)
|
|
784
|
+
) {
|
|
495
785
|
return getRepeatedTestReport(task, testName, testSuiteAbsolutePath, testProperties, status, {
|
|
496
|
-
|
|
786
|
+
browserEnvironment,
|
|
787
|
+
errorCounts: task.meta?.__ddTestOptRetryErrorCounts,
|
|
788
|
+
finalStatus: () => getExternalFinalStatus(status, testProperties),
|
|
497
789
|
state,
|
|
498
|
-
statuses: attemptStatuses,
|
|
790
|
+
statuses: getRetriedTaskStatuses(attemptStatuses, retryCount, status),
|
|
499
791
|
testSuiteStore,
|
|
500
792
|
type: 'external',
|
|
501
793
|
})
|
|
@@ -503,6 +795,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
503
795
|
|
|
504
796
|
if (!testProperties.isAttemptToFix && task.result?.repeatCount > 0) {
|
|
505
797
|
return getRepeatedTestReport(task, testName, testSuiteAbsolutePath, testProperties, status, {
|
|
798
|
+
browserEnvironment,
|
|
506
799
|
finalStatus: () => status,
|
|
507
800
|
state,
|
|
508
801
|
statuses: getRepeatedTaskStatuses(task, status),
|
|
@@ -522,24 +815,14 @@ function createMainProcessReporter (reporterState) {
|
|
|
522
815
|
result.state = 'pass'
|
|
523
816
|
}
|
|
524
817
|
|
|
525
|
-
const errors =
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
if (status !== 'skip') {
|
|
530
|
-
for (let index = 0; index < errors.length; index++) {
|
|
531
|
-
if (index === finalErrorIndex) continue
|
|
532
|
-
nonFinalAttempts.push({
|
|
533
|
-
error: errors[index],
|
|
534
|
-
isRetry: index > 0,
|
|
535
|
-
status: 'fail',
|
|
536
|
-
})
|
|
537
|
-
}
|
|
538
|
-
}
|
|
818
|
+
const errors = browserEnvironment
|
|
819
|
+
? normalizeVitestBrowserErrors(result?.errors)
|
|
820
|
+
: result?.errors || []
|
|
539
821
|
|
|
540
822
|
return {
|
|
823
|
+
browserEnvironment,
|
|
541
824
|
errors,
|
|
542
|
-
nonFinalAttempts,
|
|
825
|
+
nonFinalAttempts: [],
|
|
543
826
|
state,
|
|
544
827
|
status,
|
|
545
828
|
task,
|
|
@@ -578,7 +861,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
578
861
|
return {
|
|
579
862
|
isAttemptToFix,
|
|
580
863
|
isDisabled: testManagementProperties.isDisabled,
|
|
581
|
-
isEarlyFlakeDetection: (isNew || isModified) && state
|
|
864
|
+
isEarlyFlakeDetection: (isNew || isModified) && isEarlyFlakeDetectionActive(state),
|
|
582
865
|
isFlakyTestRetries,
|
|
583
866
|
isQuarantined: testManagementProperties.isQuarantined,
|
|
584
867
|
isModified,
|
|
@@ -643,6 +926,7 @@ function createTaskFromReportedTask (reportedTask, file, suite) {
|
|
|
643
926
|
id: reportedTask.id,
|
|
644
927
|
type: reportedTask.type,
|
|
645
928
|
name: reportedTask.name || reportedTask.relativeModuleId || reportedTask.moduleId,
|
|
929
|
+
location: reportedTask.location,
|
|
646
930
|
mode: reportedTask.options?.mode,
|
|
647
931
|
meta: getReportedTaskMeta(reportedTask),
|
|
648
932
|
result: getReportedTaskResult(reportedTask),
|
|
@@ -731,8 +1015,10 @@ function getTestModuleProjectName (testModule) {
|
|
|
731
1015
|
|
|
732
1016
|
function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testProperties, status, options) {
|
|
733
1017
|
const result = task.result
|
|
734
|
-
const
|
|
735
|
-
const
|
|
1018
|
+
const { browserEnvironment, errorCounts, finalStatus, state, statuses, testSuiteStore, type } = options
|
|
1019
|
+
const errors = browserEnvironment
|
|
1020
|
+
? normalizeVitestBrowserErrors(result?.errors)
|
|
1021
|
+
: result?.errors || []
|
|
736
1022
|
const finalAttemptStatus = finalStatus(statuses)
|
|
737
1023
|
const hasFailure = finalAttemptStatus === 'fail'
|
|
738
1024
|
const attempts = []
|
|
@@ -757,7 +1043,9 @@ function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testPrope
|
|
|
757
1043
|
errorIndex++
|
|
758
1044
|
}
|
|
759
1045
|
const attempt = {
|
|
1046
|
+
index,
|
|
760
1047
|
attemptToFixFailed: type === 'attempt_to_fix' && isFinalAttempt && hasFailure,
|
|
1048
|
+
duration: task.meta?.__ddTestOptAttemptDurations?.[index],
|
|
761
1049
|
earlyFlakeAbortReason: type === 'early_flake_detection' && isFinalAttempt
|
|
762
1050
|
? task.meta?.__ddTestOptEfdAbortReason
|
|
763
1051
|
: undefined,
|
|
@@ -783,6 +1071,7 @@ function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testPrope
|
|
|
783
1071
|
}
|
|
784
1072
|
|
|
785
1073
|
return {
|
|
1074
|
+
browserEnvironment,
|
|
786
1075
|
errors,
|
|
787
1076
|
finalAttempt: attempts.at(-1),
|
|
788
1077
|
nonFinalAttempts: attempts.slice(0, -1),
|
|
@@ -841,6 +1130,17 @@ function getEarlyFlakeDetectionFinalStatus (statuses) {
|
|
|
841
1130
|
return statuses.includes('pass') ? 'pass' : 'fail'
|
|
842
1131
|
}
|
|
843
1132
|
|
|
1133
|
+
/**
|
|
1134
|
+
* Returns the final status for user-configured retries and repeats.
|
|
1135
|
+
*
|
|
1136
|
+
* @param {string} status
|
|
1137
|
+
* @param {{ isDisabled?: boolean, isQuarantined?: boolean }} testProperties
|
|
1138
|
+
* @returns {string}
|
|
1139
|
+
*/
|
|
1140
|
+
function getExternalFinalStatus (status, testProperties) {
|
|
1141
|
+
return testProperties.isDisabled || testProperties.isQuarantined ? 'skip' : status
|
|
1142
|
+
}
|
|
1143
|
+
|
|
844
1144
|
function getRepeatedTaskStatuses (task, status) {
|
|
845
1145
|
const repeatedStatuses = []
|
|
846
1146
|
const repeatCount = task.result?.repeatCount || 0
|
|
@@ -850,8 +1150,27 @@ function getRepeatedTaskStatuses (task, status) {
|
|
|
850
1150
|
return repeatedStatuses
|
|
851
1151
|
}
|
|
852
1152
|
|
|
1153
|
+
/**
|
|
1154
|
+
* Completes reporter retry events with Vitest's final retry count and status.
|
|
1155
|
+
*
|
|
1156
|
+
* @param {string[]} recordedStatuses
|
|
1157
|
+
* @param {number} retryCount
|
|
1158
|
+
* @param {string} finalStatus
|
|
1159
|
+
* @returns {string[]}
|
|
1160
|
+
*/
|
|
1161
|
+
function getRetriedTaskStatuses (recordedStatuses = [], retryCount, finalStatus) {
|
|
1162
|
+
const statuses = [...recordedStatuses]
|
|
1163
|
+
const attemptCount = Math.max(statuses.length, retryCount + 1)
|
|
1164
|
+
while (statuses.length < attemptCount - 1) {
|
|
1165
|
+
statuses.push('fail')
|
|
1166
|
+
}
|
|
1167
|
+
statuses[attemptCount - 1] = finalStatus
|
|
1168
|
+
return statuses
|
|
1169
|
+
}
|
|
1170
|
+
|
|
853
1171
|
function reportFinalTestAttempt (testReport) {
|
|
854
1172
|
const {
|
|
1173
|
+
browserEnvironment,
|
|
855
1174
|
errors,
|
|
856
1175
|
state,
|
|
857
1176
|
status,
|
|
@@ -863,13 +1182,40 @@ function reportFinalTestAttempt (testReport) {
|
|
|
863
1182
|
} = testReport
|
|
864
1183
|
|
|
865
1184
|
if (status === 'skip') {
|
|
1185
|
+
recordTestManagementExecution({
|
|
1186
|
+
testSuite: testProperties.testSuite,
|
|
1187
|
+
testName,
|
|
1188
|
+
status,
|
|
1189
|
+
isAttemptToFix: testProperties.isAttemptToFix,
|
|
1190
|
+
isDisabled: testProperties.isDisabled,
|
|
1191
|
+
isQuarantined: testProperties.isQuarantined,
|
|
1192
|
+
})
|
|
1193
|
+
if (testProperties.isAttemptToFix) {
|
|
1194
|
+
recordAttemptToFixExecution(state.attemptToFixExecutions, {
|
|
1195
|
+
testSuite: testProperties.testSuite,
|
|
1196
|
+
testName,
|
|
1197
|
+
status,
|
|
1198
|
+
isDisabled: testProperties.isDisabled,
|
|
1199
|
+
isQuarantined: testProperties.isQuarantined,
|
|
1200
|
+
})
|
|
1201
|
+
}
|
|
1202
|
+
const {
|
|
1203
|
+
isRumActive,
|
|
1204
|
+
testExecutionId,
|
|
1205
|
+
} = getRumCorrelation(task)
|
|
866
1206
|
testSkipCh.publish({
|
|
1207
|
+
...browserEnvironment,
|
|
867
1208
|
testName,
|
|
868
1209
|
testSuiteAbsolutePath,
|
|
869
1210
|
isNew: testProperties.isNew,
|
|
1211
|
+
isAttemptToFix: testProperties.isAttemptToFix,
|
|
870
1212
|
isDisabled: testProperties.isDisabled,
|
|
1213
|
+
isQuarantined: testProperties.isQuarantined,
|
|
1214
|
+
isRumActive,
|
|
871
1215
|
isTestFrameworkWorker: true,
|
|
872
1216
|
requestErrorTags: state.requestErrorTags,
|
|
1217
|
+
testStartLine: task.location?.line,
|
|
1218
|
+
testExecutionId,
|
|
873
1219
|
...testSuiteStore,
|
|
874
1220
|
})
|
|
875
1221
|
return
|
|
@@ -880,7 +1226,7 @@ function reportFinalTestAttempt (testReport) {
|
|
|
880
1226
|
const finalAttempt = testReport.finalAttempt
|
|
881
1227
|
|
|
882
1228
|
if (status === 'fail') {
|
|
883
|
-
const error =
|
|
1229
|
+
const error = finalAttempt?.error || errors[0]
|
|
884
1230
|
reportTestAttempt(testReport, finalAttempt || {
|
|
885
1231
|
error,
|
|
886
1232
|
finalStatus,
|
|
@@ -892,7 +1238,7 @@ function reportFinalTestAttempt (testReport) {
|
|
|
892
1238
|
true,
|
|
893
1239
|
true
|
|
894
1240
|
),
|
|
895
|
-
isRetry:
|
|
1241
|
+
isRetry: (result?.retryCount || 0) > 0 || (result?.repeatCount || 0) > 0,
|
|
896
1242
|
status: 'fail',
|
|
897
1243
|
})
|
|
898
1244
|
return finalStatus === 'skip' ? undefined : error
|
|
@@ -900,13 +1246,14 @@ function reportFinalTestAttempt (testReport) {
|
|
|
900
1246
|
|
|
901
1247
|
reportTestAttempt(testReport, finalAttempt || {
|
|
902
1248
|
finalStatus,
|
|
903
|
-
isRetry:
|
|
1249
|
+
isRetry: (result?.retryCount || 0) > 0 || (result?.repeatCount || 0) > 0,
|
|
904
1250
|
status: 'pass',
|
|
905
1251
|
})
|
|
906
1252
|
}
|
|
907
1253
|
|
|
908
1254
|
function reportTestAttempt (testReport, attempt) {
|
|
909
1255
|
const {
|
|
1256
|
+
browserEnvironment,
|
|
910
1257
|
state,
|
|
911
1258
|
task,
|
|
912
1259
|
testName,
|
|
@@ -916,7 +1263,27 @@ function reportTestAttempt (testReport, attempt) {
|
|
|
916
1263
|
} = testReport
|
|
917
1264
|
const result = task.result
|
|
918
1265
|
const status = attempt.status
|
|
1266
|
+
const {
|
|
1267
|
+
isRumActive,
|
|
1268
|
+
testExecutionId,
|
|
1269
|
+
} = getRumCorrelation(task, attempt.index)
|
|
1270
|
+
const attemptStartTimes = task.meta?.__ddTestOptAttemptStartTimes
|
|
1271
|
+
const attemptStartIndex = attempt.index ?? (attemptStartTimes?.length || 1) - 1
|
|
1272
|
+
const attemptStartTime = attemptStartTimes?.[attemptStartIndex]
|
|
1273
|
+
let duration
|
|
1274
|
+
if (status === 'pass') {
|
|
1275
|
+
if (
|
|
1276
|
+
attempt.duration !== undefined ||
|
|
1277
|
+
(!attempt.isRetry && isFinalTestAttempt(testReport, attempt) && result?.duration !== undefined)
|
|
1278
|
+
) {
|
|
1279
|
+
duration = attempt.duration ?? result.duration
|
|
1280
|
+
}
|
|
1281
|
+
} else {
|
|
1282
|
+
duration = attempt.duration ??
|
|
1283
|
+
(shouldUseTaskDurationForFailure(testReport, attempt) ? result?.duration : undefined)
|
|
1284
|
+
}
|
|
919
1285
|
const testCtx = {
|
|
1286
|
+
...browserEnvironment,
|
|
920
1287
|
currentStore: testSuiteStore,
|
|
921
1288
|
testName,
|
|
922
1289
|
testSuiteAbsolutePath,
|
|
@@ -931,9 +1298,23 @@ function reportTestAttempt (testReport, attempt) {
|
|
|
931
1298
|
isRetryReasonAttemptToFix: testProperties.isAttemptToFix && attempt.isRetry,
|
|
932
1299
|
isRetryReasonAtr: !testProperties.isAttemptToFix && !testProperties.isEarlyFlakeDetection &&
|
|
933
1300
|
testProperties.isFlakyTestRetries,
|
|
1301
|
+
isRumActive,
|
|
934
1302
|
isTestFrameworkWorker: true,
|
|
935
1303
|
requestErrorTags: state.requestErrorTags,
|
|
1304
|
+
startTime: Number.isFinite(attemptStartTime)
|
|
1305
|
+
? attemptStartTime
|
|
1306
|
+
: (Number.isFinite(duration) && duration >= 0 ? Date.now() - duration : undefined),
|
|
1307
|
+
testStartLine: task.location?.line,
|
|
1308
|
+
testExecutionId,
|
|
936
1309
|
}
|
|
1310
|
+
recordTestManagementExecution({
|
|
1311
|
+
testSuite: testProperties.testSuite,
|
|
1312
|
+
testName,
|
|
1313
|
+
status,
|
|
1314
|
+
isAttemptToFix: testProperties.isAttemptToFix,
|
|
1315
|
+
isDisabled: testProperties.isDisabled,
|
|
1316
|
+
isQuarantined: testProperties.isQuarantined,
|
|
1317
|
+
})
|
|
937
1318
|
if (testProperties.isAttemptToFix) {
|
|
938
1319
|
recordAttemptToFixExecution(state.attemptToFixExecutions, {
|
|
939
1320
|
testSuite: testProperties.testSuite,
|
|
@@ -954,13 +1335,8 @@ function reportTestAttempt (testReport, attempt) {
|
|
|
954
1335
|
testStartCh.runStores(testCtx, () => {})
|
|
955
1336
|
testCtx.status = status
|
|
956
1337
|
testCtx.task = task
|
|
957
|
-
if (
|
|
958
|
-
|
|
959
|
-
!attempt.isRetry &&
|
|
960
|
-
isFinalTestAttempt(testReport, attempt) &&
|
|
961
|
-
result?.duration !== undefined
|
|
962
|
-
) {
|
|
963
|
-
testCtx.duration = result.duration
|
|
1338
|
+
if (status === 'pass' && duration !== undefined) {
|
|
1339
|
+
testCtx.duration = duration
|
|
964
1340
|
}
|
|
965
1341
|
testFinishTimeCh.runStores(testCtx, () => {})
|
|
966
1342
|
|
|
@@ -975,7 +1351,7 @@ function reportTestAttempt (testReport, attempt) {
|
|
|
975
1351
|
}
|
|
976
1352
|
|
|
977
1353
|
testErrorCh.publish({
|
|
978
|
-
duration
|
|
1354
|
+
duration,
|
|
979
1355
|
error: attempt.error,
|
|
980
1356
|
earlyFlakeAbortReason: attempt.earlyFlakeAbortReason,
|
|
981
1357
|
finalStatus: attempt.finalStatus,
|
|
@@ -985,6 +1361,24 @@ function reportTestAttempt (testReport, attempt) {
|
|
|
985
1361
|
})
|
|
986
1362
|
}
|
|
987
1363
|
|
|
1364
|
+
/**
|
|
1365
|
+
* Returns the browser RUM correlation metadata for a test attempt.
|
|
1366
|
+
*
|
|
1367
|
+
* @param {object} task
|
|
1368
|
+
* @param {number|undefined} attemptIndex
|
|
1369
|
+
* @returns {{ isRumActive?: boolean, testExecutionId?: string }}
|
|
1370
|
+
*/
|
|
1371
|
+
function getRumCorrelation (task, attemptIndex) {
|
|
1372
|
+
const testExecutionIds = task.meta?.__ddTestOptRumTestExecutionIds
|
|
1373
|
+
if (!Array.isArray(testExecutionIds) || testExecutionIds.length === 0) return {}
|
|
1374
|
+
|
|
1375
|
+
attemptIndex ??= testExecutionIds.length - 1
|
|
1376
|
+
return {
|
|
1377
|
+
isRumActive: task.meta?.__ddTestOptRumActive?.[attemptIndex] === true,
|
|
1378
|
+
testExecutionId: testExecutionIds[attemptIndex],
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
988
1382
|
function isFinalTestAttempt (testReport, attempt) {
|
|
989
1383
|
return attempt.finalStatus !== undefined || testReport.finalAttempt === undefined
|
|
990
1384
|
}
|
|
@@ -1207,10 +1601,11 @@ function getTestSpecificationPool (testSpecification) {
|
|
|
1207
1601
|
const options = getTestSpecificationOptions(testSpecification)
|
|
1208
1602
|
const file = getTestSpecificationFile(testSpecification)
|
|
1209
1603
|
const project = getTestSpecificationProject(testSpecification)
|
|
1604
|
+
const projectConfig = safeConfig(project)
|
|
1210
1605
|
return options?.pool ||
|
|
1211
1606
|
file?.pool ||
|
|
1212
1607
|
testSpecification?.pool ||
|
|
1213
|
-
|
|
1608
|
+
projectConfig?.pool ||
|
|
1214
1609
|
project?.serializedConfig?.pool ||
|
|
1215
1610
|
project?.pool
|
|
1216
1611
|
}
|
|
@@ -1243,15 +1638,16 @@ function getTestSpecificationIsolate (testSpecification, pool) {
|
|
|
1243
1638
|
const options = getTestSpecificationOptions(testSpecification)
|
|
1244
1639
|
const file = getTestSpecificationFile(testSpecification)
|
|
1245
1640
|
const project = getTestSpecificationProject(testSpecification)
|
|
1641
|
+
const projectConfig = safeConfig(project)
|
|
1246
1642
|
return getPoolOptionsIsolate(options, pool) ??
|
|
1247
1643
|
getPoolOptionsIsolate(file, pool) ??
|
|
1248
|
-
getPoolOptionsIsolate(
|
|
1644
|
+
getPoolOptionsIsolate(projectConfig, pool) ??
|
|
1249
1645
|
getPoolOptionsIsolate(project?.serializedConfig, pool) ??
|
|
1250
1646
|
getPoolOptionsIsolate(project, pool) ??
|
|
1251
1647
|
getPoolOptionsIsolate(testSpecification, pool) ??
|
|
1252
1648
|
options?.isolate ??
|
|
1253
1649
|
file?.isolate ??
|
|
1254
|
-
|
|
1650
|
+
projectConfig?.isolate ??
|
|
1255
1651
|
project?.serializedConfig?.isolate ??
|
|
1256
1652
|
project?.isolate ??
|
|
1257
1653
|
testSpecification?.isolate
|
|
@@ -1263,7 +1659,7 @@ function getEffectiveTestSpecificationIsolate (testSpecification, pool, defaultI
|
|
|
1263
1659
|
}
|
|
1264
1660
|
|
|
1265
1661
|
function getProjectName (project) {
|
|
1266
|
-
return normalizeProjectName(project?.name || project?.
|
|
1662
|
+
return normalizeProjectName(project?.name || safeConfig(project)?.name || project?.test?.name)
|
|
1267
1663
|
}
|
|
1268
1664
|
|
|
1269
1665
|
function normalizeProjectName (name) {
|
|
@@ -1273,6 +1669,111 @@ function normalizeProjectName (name) {
|
|
|
1273
1669
|
return typeof label === 'string' ? label : undefined
|
|
1274
1670
|
}
|
|
1275
1671
|
|
|
1672
|
+
/**
|
|
1673
|
+
* Returns whether a Vitest specification runs in Browser Mode.
|
|
1674
|
+
*
|
|
1675
|
+
* @param {object} testSpecification
|
|
1676
|
+
* @returns {boolean}
|
|
1677
|
+
*/
|
|
1678
|
+
function isBrowserTestSpecification (testSpecification) {
|
|
1679
|
+
return getTestSpecificationPool(testSpecification) === 'browser' ||
|
|
1680
|
+
isBrowserProject(getTestSpecificationProject(testSpecification))
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
/**
|
|
1684
|
+
* Returns whether a Vitest project has Browser Mode enabled.
|
|
1685
|
+
*
|
|
1686
|
+
* @param {object|undefined} project
|
|
1687
|
+
* @returns {boolean}
|
|
1688
|
+
*/
|
|
1689
|
+
function isBrowserProject (project) {
|
|
1690
|
+
try {
|
|
1691
|
+
if (project?.isBrowserEnabled?.() === true) return true
|
|
1692
|
+
} catch {}
|
|
1693
|
+
return getProjectReportingConfig(project)?.browser?.enabled === true
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
/**
|
|
1697
|
+
* Returns whether Vitest can overlap tests or their setup and teardown.
|
|
1698
|
+
*
|
|
1699
|
+
* @param {object|undefined} config
|
|
1700
|
+
* @returns {boolean}
|
|
1701
|
+
*/
|
|
1702
|
+
function hasConcurrentTestExecution (config) {
|
|
1703
|
+
const sequence = config?.sequence
|
|
1704
|
+
return sequence?.concurrent === true ||
|
|
1705
|
+
sequence?.hooks === 'parallel' ||
|
|
1706
|
+
sequence?.setupFiles === 'parallel'
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/**
|
|
1710
|
+
* Returns whether Vitest can overlap browser execution that shares the RUM correlation cookie origin.
|
|
1711
|
+
*
|
|
1712
|
+
* @param {object} ctx
|
|
1713
|
+
* @param {object[]|undefined} testSpecifications
|
|
1714
|
+
* @returns {boolean}
|
|
1715
|
+
*/
|
|
1716
|
+
function canRaceRumCorrelation (ctx, testSpecifications) {
|
|
1717
|
+
if (!Array.isArray(testSpecifications)) {
|
|
1718
|
+
return hasConcurrentTestExecution(safeConfig(ctx))
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
let browserFileCount = 0
|
|
1722
|
+
let hasBrowserProject = false
|
|
1723
|
+
let project
|
|
1724
|
+
for (const testSpecification of testSpecifications) {
|
|
1725
|
+
const testProject = getTestSpecificationProject(testSpecification)
|
|
1726
|
+
if (!isBrowserTestSpecification(testSpecification)) continue
|
|
1727
|
+
|
|
1728
|
+
const config = getProjectReportingConfig(testProject) || safeConfig(ctx)
|
|
1729
|
+
if (hasConcurrentTestExecution(config)) return true
|
|
1730
|
+
|
|
1731
|
+
browserFileCount++
|
|
1732
|
+
if (hasBrowserProject && testProject !== project) return true
|
|
1733
|
+
project = testProject
|
|
1734
|
+
hasBrowserProject = true
|
|
1735
|
+
}
|
|
1736
|
+
if (browserFileCount < 2) return false
|
|
1737
|
+
|
|
1738
|
+
const config = getProjectReportingConfig(project) || safeConfig(ctx)
|
|
1739
|
+
const fileParallelism = config?.browser?.fileParallelism ?? config?.fileParallelism
|
|
1740
|
+
return fileParallelism !== false && config?.maxWorkers !== 1
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
function getTestModuleBrowserEnvironment (testModule) {
|
|
1744
|
+
const project = testModule?.project
|
|
1745
|
+
const config = getProjectReportingConfig(project)
|
|
1746
|
+
const isBrowserMode = testModule?.task?.pool === 'browser' ||
|
|
1747
|
+
testModule?.pool === 'browser' ||
|
|
1748
|
+
isBrowserProject(project)
|
|
1749
|
+
if (!isBrowserMode) return
|
|
1750
|
+
|
|
1751
|
+
const provider = config?.browser?.provider
|
|
1752
|
+
const browserDriver = typeof provider === 'string' ? provider : provider?.name
|
|
1753
|
+
|
|
1754
|
+
return {
|
|
1755
|
+
browserDriver,
|
|
1756
|
+
browserName: config?.browser?.name,
|
|
1757
|
+
browserProjectName: getTestModuleProjectName(testModule),
|
|
1758
|
+
isBrowserMode: true,
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
/**
|
|
1763
|
+
* Returns the runtime or serialized project configuration used for read-only reporting metadata.
|
|
1764
|
+
*
|
|
1765
|
+
* @param {object|undefined} project
|
|
1766
|
+
* @returns {object|undefined}
|
|
1767
|
+
*/
|
|
1768
|
+
function getProjectReportingConfig (project) {
|
|
1769
|
+
const config = safeConfig(project)
|
|
1770
|
+
if (config) return config
|
|
1771
|
+
|
|
1772
|
+
try {
|
|
1773
|
+
return project?.serializedConfig
|
|
1774
|
+
} catch {}
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1276
1777
|
function safeConfig (project) {
|
|
1277
1778
|
let config
|
|
1278
1779
|
try {
|
|
@@ -1293,5 +1794,6 @@ module.exports = {
|
|
|
1293
1794
|
configure,
|
|
1294
1795
|
deactivate,
|
|
1295
1796
|
configureWorkerEnv,
|
|
1797
|
+
isSupportedVersion,
|
|
1296
1798
|
shouldUse,
|
|
1297
1799
|
}
|