dd-trace 6.9.0 → 6.11.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/README.md +0 -17
- package/ci/vitest-no-worker-init-setup.mjs +112 -10
- package/index.d.ts +150 -3
- package/initialize.mjs +28 -17
- package/openfeature.js +2 -2
- package/package.json +14 -10
- package/packages/datadog-esbuild/index.js +0 -34
- package/packages/datadog-instrumentations/src/anthropic.js +210 -15
- package/packages/datadog-instrumentations/src/aws-sdk.js +9 -1
- package/packages/datadog-instrumentations/src/browser-bunyan.js +11 -0
- package/packages/datadog-instrumentations/src/bunyan.js +3 -16
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/cucumber.js +26 -11
- package/packages/datadog-instrumentations/src/cypress-config.js +182 -16
- package/packages/datadog-instrumentations/src/cypress-legacy-finalizers.js +30 -0
- package/packages/datadog-instrumentations/src/cypress.js +2 -0
- package/packages/datadog-instrumentations/src/fastify.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bunyan.js +22 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +634 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +81 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/jest.js +26 -18
- package/packages/datadog-instrumentations/src/mariadb.js +278 -21
- package/packages/datadog-instrumentations/src/mocha/main.js +540 -56
- package/packages/datadog-instrumentations/src/mocha/utils.js +132 -25
- package/packages/datadog-instrumentations/src/mysql.js +45 -15
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +116 -92
- package/packages/datadog-instrumentations/src/playwright-reporter.js +99 -0
- package/packages/datadog-instrumentations/src/playwright.js +149 -2
- package/packages/datadog-instrumentations/src/router.js +2 -0
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -4
- package/packages/datadog-instrumentations/src/vitest-main.js +180 -20
- package/packages/datadog-instrumentations/src/vitest-util.js +64 -5
- package/packages/datadog-instrumentations/src/vitest-worker.js +150 -25
- package/packages/datadog-instrumentations/src/webdriverio.js +31 -17
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +163 -44
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -13
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-browser-bunyan/src/index.js +9 -0
- package/packages/datadog-plugin-bunyan/src/index.js +5 -8
- package/packages/datadog-plugin-cucumber/src/index.js +11 -0
- package/packages/datadog-plugin-cypress/src/after-run.js +5 -1
- package/packages/datadog-plugin-cypress/src/after-spec.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +82 -30
- package/packages/datadog-plugin-cypress/src/finalization.js +76 -0
- package/packages/datadog-plugin-cypress/src/index.js +12 -6
- package/packages/datadog-plugin-cypress/src/plugin.js +16 -3
- package/packages/datadog-plugin-dd-trace-api/src/index.js +4 -0
- package/packages/datadog-plugin-electron/src/index.js +2 -0
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-jest/src/index.js +11 -4
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -2
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +606 -40
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-nats/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +1 -19
- package/packages/datadog-plugin-openai/src/tracing.js +41 -30
- package/packages/datadog-plugin-openai-agents/src/integration.js +279 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +1 -0
- package/packages/datadog-plugin-playwright/src/index.js +42 -13
- package/packages/datadog-plugin-vitest/src/index.js +14 -20
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/datadog-webpack/index.js +0 -11
- package/packages/dd-trace/index.js +0 -1
- package/packages/dd-trace/src/agent/info.js +6 -5
- package/packages/dd-trace/src/aiguard/client.js +100 -1
- package/packages/dd-trace/src/aiguard/errors.js +41 -0
- package/packages/dd-trace/src/aiguard/evaluation.js +357 -0
- package/packages/dd-trace/src/aiguard/integrations/anthropic.js +70 -0
- package/packages/dd-trace/src/aiguard/integrations/index.js +4 -0
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +423 -0
- package/packages/dd-trace/src/aiguard/messages/openai.js +1 -24
- package/packages/dd-trace/src/aiguard/messages/utils.js +28 -0
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +1 -11
- package/packages/dd-trace/src/aiguard/sdk.js +22 -278
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +13 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -12
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +1 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +27 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +21 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +164 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +365 -32
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +201 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -5
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +39 -0
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +6 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +7 -0
- package/packages/dd-trace/src/config/index.js +13 -2
- package/packages/dd-trace/src/config/major-overrides.js +7 -0
- package/packages/dd-trace/src/config/supported-configurations.json +24 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/index.js +2 -0
- package/packages/dd-trace/src/datastreams/manager.js +14 -3
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +16 -13
- package/packages/dd-trace/src/datastreams/size.js +5 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +49 -9
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +6 -4
- package/packages/dd-trace/src/exporters/common/writer.js +11 -6
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +163 -5
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +241 -87
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +280 -20
- package/packages/dd-trace/src/llmobs/experiments/index.js +58 -59
- package/packages/dd-trace/src/llmobs/experiments/noop.js +71 -3
- package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/util.js +41 -5
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +12 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -2
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/noop/proxy.js +3 -4
- package/packages/dd-trace/src/openfeature/flagging_provider.js +18 -2
- package/packages/dd-trace/src/openfeature/remote_config.js +1 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +7 -7
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +2 -1
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +67 -11
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +14 -3
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +25 -12
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +2 -5
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +96 -43
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/opentracing/tracer.js +5 -2
- package/packages/dd-trace/src/otel-thread-ctx.js +387 -0
- package/packages/dd-trace/src/plugin_manager.js +5 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +5 -65
- package/packages/dd-trace/src/plugins/util/test.js +93 -14
- package/packages/dd-trace/src/plugins/util/web.js +56 -2
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +37 -90
- package/packages/dd-trace/src/profiling/webspan-utils.js +45 -0
- package/packages/dd-trace/src/proxy.js +38 -29
- package/packages/dd-trace/src/ritm.js +9 -2
- package/packages/dd-trace/src/serverless.js +37 -0
- package/packages/dd-trace/src/span_format.js +1 -0
- package/packages/dd-trace/src/span_stats.js +30 -3
- package/packages/dd-trace/src/storage-channels.js +86 -0
- package/packages/dd-trace/src/tracer.js +9 -2
- package/packages/dd-trace/src/tracer_metadata.js +14 -1
- package/packages/dd-trace/src/web-tags-cache.js +132 -0
- package/vendor/dist/@datadog/openfeature-node-server/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +0 -65
- package/packages/datadog-webpack/src/optional-peer-loader.js +0 -17
- package/packages/dd-trace/src/feature-registry.js +0 -29
- package/packages/dd-trace/src/openfeature/register.js +0 -35
- package/packages/dd-trace/src/openfeature/require-provider.js +0 -18
|
@@ -10,7 +10,6 @@ const {
|
|
|
10
10
|
} = require('../helpers/channel')
|
|
11
11
|
const { addHook, channel } = require('../helpers/instrument')
|
|
12
12
|
const shimmer = require('../../../datadog-shimmer')
|
|
13
|
-
const { isMarkedAsUnskippable } = require('../../../datadog-plugin-jest/src/util')
|
|
14
13
|
const { EMPTY_EFD_RETRY_POLICY } = require('../../../dd-trace/src/ci-visibility/efd-retry-policy')
|
|
15
14
|
const { writeCoverageBackfillToCache } = require('../../../dd-trace/src/ci-visibility/test-optimization-cache')
|
|
16
15
|
const log = require('../../../dd-trace/src/log')
|
|
@@ -33,6 +32,7 @@ const {
|
|
|
33
32
|
TEST_IMPACT_ANALYSIS_ALL_TESTS_SKIPPED_MESSAGE,
|
|
34
33
|
getTestOptimizationRequestResults,
|
|
35
34
|
isModifiedTest,
|
|
35
|
+
isMarkedAsUnskippable,
|
|
36
36
|
} = require('../../../dd-trace/src/plugins/util/test')
|
|
37
37
|
|
|
38
38
|
const {
|
|
@@ -53,6 +53,7 @@ const {
|
|
|
53
53
|
testsQuarantined,
|
|
54
54
|
getTestFullName,
|
|
55
55
|
getRunTestsWrapper,
|
|
56
|
+
resetRunState,
|
|
56
57
|
newTestsWithDynamicNames,
|
|
57
58
|
attemptToFixExecutions,
|
|
58
59
|
loggedAttemptToFixTests,
|
|
@@ -63,7 +64,27 @@ require('./common')
|
|
|
63
64
|
|
|
64
65
|
const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
65
66
|
|
|
67
|
+
/**
|
|
68
|
+
* @typedef {{ replacement: Function, run: Function }} ReporterReplacement
|
|
69
|
+
* @typedef {{
|
|
70
|
+
* createFileRunner?: ReporterReplacement,
|
|
71
|
+
* hookRuns: Map<object, ReporterReplacement>,
|
|
72
|
+
* pendingTests: Map<object, { hadPending: boolean, pending: unknown }>,
|
|
73
|
+
* tests: Set<object>
|
|
74
|
+
* }} RunnerRecoveryState
|
|
75
|
+
*/
|
|
76
|
+
|
|
66
77
|
const patched = new WeakSet()
|
|
78
|
+
const runnerEndHandlers = new WeakMap()
|
|
79
|
+
const runnerHookMethods = new WeakMap()
|
|
80
|
+
const runnerTestEndHandlers = new WeakMap()
|
|
81
|
+
const runnerFailuresAdjusted = new WeakSet()
|
|
82
|
+
const runnerFrameworkErrors = new WeakMap()
|
|
83
|
+
const runnerStarted = new WeakSet()
|
|
84
|
+
const runnerRecoveryStates = new WeakMap()
|
|
85
|
+
const runnersWithPendingCoverageReset = new WeakSet()
|
|
86
|
+
const parallelRunners = new WeakSet()
|
|
87
|
+
const wrappedRunnerEmitPrototypes = new WeakSet()
|
|
67
88
|
let hasWarnedDeprecatedMochaVersion = false
|
|
68
89
|
|
|
69
90
|
const unskippableSuites = []
|
|
@@ -71,7 +92,7 @@ let suitesToSkip = []
|
|
|
71
92
|
let isSuitesSkipped = false
|
|
72
93
|
let areAllSuitesSkipped = false
|
|
73
94
|
let skippedSuites = []
|
|
74
|
-
let skippableSuitesCoverage
|
|
95
|
+
let skippableSuitesCoverage
|
|
75
96
|
let skippedSuitesCoverage = {}
|
|
76
97
|
let itrCorrelationId = ''
|
|
77
98
|
let isForcedToRun = false
|
|
@@ -182,12 +203,6 @@ function getFilteredSuites (originalSuites) {
|
|
|
182
203
|
}, { suitesToRun: [], skippedSuites: new Set(), suitesToSkipForRun })
|
|
183
204
|
}
|
|
184
205
|
|
|
185
|
-
function hasSkippableSuitesCoverage () {
|
|
186
|
-
return skippableSuitesCoverage &&
|
|
187
|
-
typeof skippableSuitesCoverage === 'object' &&
|
|
188
|
-
Object.keys(skippableSuitesCoverage).length > 0
|
|
189
|
-
}
|
|
190
|
-
|
|
191
206
|
function isTiaCoverageBackfillEnabled () {
|
|
192
207
|
return config.isItrEnabled && config.isCoverageReportUploadEnabled
|
|
193
208
|
}
|
|
@@ -218,7 +233,7 @@ function shouldReportCodeCoverageLinesPct (hasBackfilledCoverage) {
|
|
|
218
233
|
}
|
|
219
234
|
|
|
220
235
|
function getSkippedSuitesCoverageForRun () {
|
|
221
|
-
return isSuitesSkipped && isTiaCoverageBackfillEnabled() &&
|
|
236
|
+
return isSuitesSkipped && isTiaCoverageBackfillEnabled() && skippableSuitesCoverage !== undefined
|
|
222
237
|
? skippableSuitesCoverage
|
|
223
238
|
: {}
|
|
224
239
|
}
|
|
@@ -236,7 +251,7 @@ function resetSuiteSkippingRunState () {
|
|
|
236
251
|
isSuitesSkipped = false
|
|
237
252
|
areAllSuitesSkipped = false
|
|
238
253
|
skippedSuites = []
|
|
239
|
-
skippableSuitesCoverage =
|
|
254
|
+
skippableSuitesCoverage = undefined
|
|
240
255
|
skippedSuitesCoverage = {}
|
|
241
256
|
untestedCoverage = undefined
|
|
242
257
|
config.repositoryRoot = undefined
|
|
@@ -292,12 +307,12 @@ function getOnStartHandler (frameworkVersion) {
|
|
|
292
307
|
/**
|
|
293
308
|
* @param {boolean} isParallel
|
|
294
309
|
* @param {() => void} onDone
|
|
295
|
-
* @returns {() => void}
|
|
310
|
+
* @returns {(frameworkError?: unknown, onFrameworkErrorDone?: () => void) => void}
|
|
296
311
|
*/
|
|
297
312
|
function getOnEndHandler (isParallel, onDone) {
|
|
298
|
-
return function () {
|
|
313
|
+
return function (frameworkError, onFrameworkErrorDone) {
|
|
299
314
|
let status = 'pass'
|
|
300
|
-
let error
|
|
315
|
+
let error = frameworkError
|
|
301
316
|
if (this.stats) {
|
|
302
317
|
status = this.stats.failures === 0 ? 'pass' : 'fail'
|
|
303
318
|
if (this.stats.tests === 0) {
|
|
@@ -307,18 +322,9 @@ function getOnEndHandler (isParallel, onDone) {
|
|
|
307
322
|
status = 'fail'
|
|
308
323
|
}
|
|
309
324
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (status === 'fail') {
|
|
314
|
-
if (this.stats) {
|
|
315
|
-
status = this.stats.failures === 0 ? 'pass' : 'fail'
|
|
316
|
-
} else {
|
|
317
|
-
status = this.failures === 0 ? 'pass' : 'fail'
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (status === 'fail') {
|
|
325
|
+
if (arguments.length > 0) {
|
|
326
|
+
status = 'fail'
|
|
327
|
+
} else if (status === 'fail') {
|
|
322
328
|
error = new Error(`Failed tests: ${this.failures}.`)
|
|
323
329
|
}
|
|
324
330
|
|
|
@@ -363,7 +369,14 @@ function getOnEndHandler (isParallel, onDone) {
|
|
|
363
369
|
isEarlyFlakeDetectionFaulty: config.isEarlyFlakeDetectionFaulty,
|
|
364
370
|
isTestManagementEnabled: config.isTestManagementTestsEnabled,
|
|
365
371
|
isParallel,
|
|
366
|
-
|
|
372
|
+
isFrameworkError: arguments.length > 0,
|
|
373
|
+
}, () => {
|
|
374
|
+
try {
|
|
375
|
+
onDone()
|
|
376
|
+
} finally {
|
|
377
|
+
onFrameworkErrorDone?.()
|
|
378
|
+
}
|
|
379
|
+
})
|
|
367
380
|
|
|
368
381
|
logTestOptimizationSummary({
|
|
369
382
|
attemptToFixExecutions,
|
|
@@ -374,6 +387,448 @@ function getOnEndHandler (isParallel, onDone) {
|
|
|
374
387
|
}
|
|
375
388
|
}
|
|
376
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Applies Test Optimization failure suppression once per runner execution.
|
|
392
|
+
*
|
|
393
|
+
* @param {object} runner
|
|
394
|
+
* @returns {void}
|
|
395
|
+
*/
|
|
396
|
+
function adjustRunnerFailuresOnce (runner) {
|
|
397
|
+
if (runnerFailuresAdjusted.has(runner)) return
|
|
398
|
+
|
|
399
|
+
runnerFailuresAdjusted.add(runner)
|
|
400
|
+
adjustRunnerFailuresForTestOptimization(runner, config)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Returns the mutations that must be restored after reporter-error recovery.
|
|
405
|
+
*
|
|
406
|
+
* @param {object} runner
|
|
407
|
+
* @returns {RunnerRecoveryState}
|
|
408
|
+
*/
|
|
409
|
+
function getRunnerRecoveryState (runner) {
|
|
410
|
+
let state = runnerRecoveryStates.get(runner)
|
|
411
|
+
if (!state) {
|
|
412
|
+
state = {
|
|
413
|
+
hookRuns: new Map(),
|
|
414
|
+
pendingTests: new Map(),
|
|
415
|
+
tests: new Set(),
|
|
416
|
+
}
|
|
417
|
+
runnerRecoveryStates.set(runner, state)
|
|
418
|
+
}
|
|
419
|
+
return state
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Marks a test pending for the aborted run while retaining its reusable state.
|
|
424
|
+
*
|
|
425
|
+
* @param {object} runner
|
|
426
|
+
* @param {object} test
|
|
427
|
+
* @returns {void}
|
|
428
|
+
*/
|
|
429
|
+
function markTestPending (runner, test) {
|
|
430
|
+
const state = getRunnerRecoveryState(runner)
|
|
431
|
+
if (!state.pendingTests.has(test)) {
|
|
432
|
+
state.pendingTests.set(test, {
|
|
433
|
+
hadPending: Object.hasOwn(test, 'pending'),
|
|
434
|
+
pending: test.pending,
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
state.tests.add(test)
|
|
438
|
+
test.pending = true
|
|
439
|
+
test._ddReporterStartFailed = true
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Marks a completed test for immediate reporter-error finalization.
|
|
444
|
+
*
|
|
445
|
+
* @param {object} runner
|
|
446
|
+
* @param {object} test
|
|
447
|
+
* @returns {void}
|
|
448
|
+
*/
|
|
449
|
+
function markTestTerminal (runner, test) {
|
|
450
|
+
getRunnerRecoveryState(runner).tests.add(test)
|
|
451
|
+
test._ddReporterTerminalFailed = true
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Restores test and hook state changed only to abort the current run.
|
|
456
|
+
*
|
|
457
|
+
* @param {object} runner
|
|
458
|
+
* @returns {void}
|
|
459
|
+
*/
|
|
460
|
+
function restoreReporterMutations (runner) {
|
|
461
|
+
const state = runnerRecoveryStates.get(runner)
|
|
462
|
+
if (!state) return
|
|
463
|
+
|
|
464
|
+
runnerRecoveryStates.delete(runner)
|
|
465
|
+
for (const [test, { hadPending, pending }] of state.pendingTests) {
|
|
466
|
+
if (hadPending) test.pending = pending
|
|
467
|
+
else delete test.pending
|
|
468
|
+
}
|
|
469
|
+
for (const test of state.tests) {
|
|
470
|
+
delete test._ddTestFinishStarted
|
|
471
|
+
delete test._ddTestFinishPublished
|
|
472
|
+
delete test._ddIsFinalAttempt
|
|
473
|
+
delete test._ddHookFailed
|
|
474
|
+
delete test._ddReporterStartFailed
|
|
475
|
+
delete test._ddReporterTerminalFailed
|
|
476
|
+
}
|
|
477
|
+
for (const [hook, { replacement, run }] of state.hookRuns) {
|
|
478
|
+
if (hook.run === replacement) hook.run = run
|
|
479
|
+
}
|
|
480
|
+
if (state.createFileRunner && runner._createFileRunner === state.createFileRunner.replacement) {
|
|
481
|
+
runner._createFileRunner = state.createFileRunner.run
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Prevents Mocha from entering hooks or the test body after a test-start reporter error.
|
|
487
|
+
*
|
|
488
|
+
* @param {object} runner
|
|
489
|
+
* @param {object} test
|
|
490
|
+
* @returns {void}
|
|
491
|
+
*/
|
|
492
|
+
function stopCurrentTest (runner, test) {
|
|
493
|
+
const hookDown = runner.hookDown
|
|
494
|
+
const hookUp = runner.hookUp
|
|
495
|
+
|
|
496
|
+
markTestPending(runner, test)
|
|
497
|
+
runner.hookDown = function (name, onDone) {
|
|
498
|
+
runner.hookDown = hookDown
|
|
499
|
+
onDone()
|
|
500
|
+
}
|
|
501
|
+
runner.hookUp = function (name, onDone) {
|
|
502
|
+
runner.hookUp = hookUp
|
|
503
|
+
onDone()
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Prevents Mocha from entering a hook after its hook-start reporter event fails.
|
|
509
|
+
*
|
|
510
|
+
* @param {object} runner
|
|
511
|
+
* @param {object} hook
|
|
512
|
+
* @returns {void}
|
|
513
|
+
*/
|
|
514
|
+
function stopCurrentHook (runner, hook) {
|
|
515
|
+
const hookMethod = runner.hook
|
|
516
|
+
const hookDown = runner.hookDown
|
|
517
|
+
const hookUp = runner.hookUp
|
|
518
|
+
const run = hook.run
|
|
519
|
+
|
|
520
|
+
stopRemainingCurrentHooks(runner, hook)
|
|
521
|
+
runner.hook = function (name, onDone) {
|
|
522
|
+
runner.hook = hookMethod
|
|
523
|
+
onDone()
|
|
524
|
+
}
|
|
525
|
+
runner.hookDown = function (name, onDone) {
|
|
526
|
+
runner.hookDown = hookDown
|
|
527
|
+
onDone()
|
|
528
|
+
}
|
|
529
|
+
runner.hookUp = function (name, onDone) {
|
|
530
|
+
runner.hookUp = hookUp
|
|
531
|
+
onDone()
|
|
532
|
+
}
|
|
533
|
+
hook.run = function (onDone) {
|
|
534
|
+
hook.run = run
|
|
535
|
+
const test = hook.ctx?.currentTest
|
|
536
|
+
if (test) {
|
|
537
|
+
if (hook.parent?._afterEach?.includes(hook) || hook.parent?._afterAll?.includes(hook)) {
|
|
538
|
+
markTestTerminal(runner, test)
|
|
539
|
+
if (!test._ddTestFinishStarted) runnerTestEndHandlers.get(runner)?.(test)
|
|
540
|
+
} else {
|
|
541
|
+
markTestPending(runner, test)
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
onDone()
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Prevents Mocha from running after-each hooks after a terminal test reporter event fails.
|
|
550
|
+
*
|
|
551
|
+
* @param {object} runner
|
|
552
|
+
* @param {object} test
|
|
553
|
+
* @returns {void}
|
|
554
|
+
*/
|
|
555
|
+
function stopAfterEachHooks (runner, test) {
|
|
556
|
+
const hookUp = runner.hookUp
|
|
557
|
+
|
|
558
|
+
markTestTerminal(runner, test)
|
|
559
|
+
runner.hookUp = function (name, onDone) {
|
|
560
|
+
runner.hookUp = hookUp
|
|
561
|
+
onDone()
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Prevents Mocha from entering any subsequent user hooks after a reporter error.
|
|
567
|
+
*
|
|
568
|
+
* @param {object} runner
|
|
569
|
+
* @returns {void}
|
|
570
|
+
*/
|
|
571
|
+
function stopFutureHooks (runner) {
|
|
572
|
+
if (runnerHookMethods.has(runner)) return
|
|
573
|
+
|
|
574
|
+
runnerHookMethods.set(runner, runner.hook)
|
|
575
|
+
runner.hook = function (name, onDone) {
|
|
576
|
+
onDone()
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Restores the runner hook method after reporter-error finalization.
|
|
582
|
+
*
|
|
583
|
+
* @param {object} runner
|
|
584
|
+
* @returns {void}
|
|
585
|
+
*/
|
|
586
|
+
function restoreFutureHooks (runner) {
|
|
587
|
+
const hook = runnerHookMethods.get(runner)
|
|
588
|
+
if (!hook) return
|
|
589
|
+
|
|
590
|
+
runnerHookMethods.delete(runner)
|
|
591
|
+
runner.hook = hook
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Stops hooks remaining in the currently executing hook array.
|
|
596
|
+
*
|
|
597
|
+
* @param {object} runner
|
|
598
|
+
* @param {object} hook
|
|
599
|
+
* @returns {boolean} whether the completed hook was a before-each hook
|
|
600
|
+
*/
|
|
601
|
+
function stopRemainingCurrentHooks (runner, hook) {
|
|
602
|
+
const hookLists = [hook.parent?._beforeAll, hook.parent?._beforeEach, hook.parent?._afterEach, hook.parent?._afterAll]
|
|
603
|
+
|
|
604
|
+
for (const hooks of hookLists) {
|
|
605
|
+
const hookIndex = hooks?.indexOf(hook) ?? -1
|
|
606
|
+
if (hookIndex === -1) continue
|
|
607
|
+
|
|
608
|
+
for (let index = hookIndex + 1; index < hooks.length; index++) {
|
|
609
|
+
const remainingHook = hooks[index]
|
|
610
|
+
const run = remainingHook.run
|
|
611
|
+
const replacement = function (onDone) {
|
|
612
|
+
remainingHook.run = run
|
|
613
|
+
onDone()
|
|
614
|
+
}
|
|
615
|
+
getRunnerRecoveryState(runner).hookRuns.set(remainingHook, { replacement, run })
|
|
616
|
+
remainingHook.run = replacement
|
|
617
|
+
}
|
|
618
|
+
return hooks === hook.parent._beforeEach
|
|
619
|
+
}
|
|
620
|
+
return false
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Prevents a completed before-each hook from continuing into the test body.
|
|
625
|
+
*
|
|
626
|
+
* @param {object} runner
|
|
627
|
+
* @param {object} hook
|
|
628
|
+
* @returns {void}
|
|
629
|
+
*/
|
|
630
|
+
function stopAfterHookEnd (runner, hook) {
|
|
631
|
+
if (!stopRemainingCurrentHooks(runner, hook) || !runner.test) return
|
|
632
|
+
|
|
633
|
+
markTestPending(runner, runner.test)
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Prevents Mocha from entering the root suite after a run-start reporter error.
|
|
638
|
+
*
|
|
639
|
+
* @param {object} runner
|
|
640
|
+
* @returns {void}
|
|
641
|
+
*/
|
|
642
|
+
function stopRootSuite (runner) {
|
|
643
|
+
const runSuite = runner.runSuite
|
|
644
|
+
|
|
645
|
+
runner.runSuite = function (suite, onDone) {
|
|
646
|
+
runner.runSuite = runSuite
|
|
647
|
+
onDone()
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function skipParallelFile () {}
|
|
652
|
+
|
|
653
|
+
function createSkippedParallelFileRunner () {
|
|
654
|
+
return skipParallelFile
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Prevents a parallel run-start reporter error from scheduling test workers.
|
|
659
|
+
*
|
|
660
|
+
* @param {object} runner
|
|
661
|
+
* @returns {void}
|
|
662
|
+
*/
|
|
663
|
+
function stopParallelWorkers (runner) {
|
|
664
|
+
const state = getRunnerRecoveryState(runner)
|
|
665
|
+
if (state.createFileRunner) return
|
|
666
|
+
|
|
667
|
+
const run = runner._createFileRunner
|
|
668
|
+
const replacement = createSkippedParallelFileRunner
|
|
669
|
+
state.createFileRunner = { replacement, run }
|
|
670
|
+
runner._createFileRunner = replacement
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Resets suite coverage after every reporter has observed the completed suite.
|
|
675
|
+
*
|
|
676
|
+
* @param {object} runner
|
|
677
|
+
* @returns {void}
|
|
678
|
+
*/
|
|
679
|
+
function resetPendingSuiteCoverage (runner) {
|
|
680
|
+
if (!runnersWithPendingCoverageReset.delete(runner) || !global.__coverage__) return
|
|
681
|
+
|
|
682
|
+
resetCoverage(global.__coverage__)
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Reads a string Error property without invoking user code outside this boundary.
|
|
687
|
+
*
|
|
688
|
+
* @param {Error} error
|
|
689
|
+
* @param {'message' | 'name' | 'stack'} property
|
|
690
|
+
* @returns {string | undefined}
|
|
691
|
+
*/
|
|
692
|
+
function readErrorString (error, property) {
|
|
693
|
+
try {
|
|
694
|
+
const value = error[property]
|
|
695
|
+
if (typeof value === 'string') return value
|
|
696
|
+
} catch {
|
|
697
|
+
// Ignore user-defined accessors.
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Creates an Error for Test Optimization tags without coercing a user-thrown value.
|
|
703
|
+
*
|
|
704
|
+
* @param {unknown} frameworkError
|
|
705
|
+
* @returns {Error}
|
|
706
|
+
*/
|
|
707
|
+
function getFrameworkFinalizationError (frameworkError) {
|
|
708
|
+
if (typeof frameworkError === 'string') return new Error(frameworkError)
|
|
709
|
+
let isError = false
|
|
710
|
+
try {
|
|
711
|
+
isError = frameworkError instanceof Error
|
|
712
|
+
} catch {
|
|
713
|
+
// User-thrown proxies can fail the instanceof prototype lookup.
|
|
714
|
+
}
|
|
715
|
+
if (!isError) return new Error('Mocha reporter failed')
|
|
716
|
+
|
|
717
|
+
const message = readErrorString(frameworkError, 'message') || 'Mocha reporter failed'
|
|
718
|
+
const error = new Error(message)
|
|
719
|
+
const name = readErrorString(frameworkError, 'name')
|
|
720
|
+
const stack = readErrorString(frameworkError, 'stack')
|
|
721
|
+
if (name) error.name = name
|
|
722
|
+
if (stack) error.stack = stack
|
|
723
|
+
return error
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Defers reporter errors until Mocha can emit its remaining lifecycle events, then
|
|
728
|
+
* runs Datadog's end handler and propagates the original error after finalization.
|
|
729
|
+
*
|
|
730
|
+
* @param {Function} Runner
|
|
731
|
+
* @returns {void}
|
|
732
|
+
*/
|
|
733
|
+
function wrapRunnerEmit (Runner) {
|
|
734
|
+
if (wrappedRunnerEmitPrototypes.has(Runner.prototype)) return
|
|
735
|
+
|
|
736
|
+
wrappedRunnerEmitPrototypes.add(Runner.prototype)
|
|
737
|
+
shimmer.wrap(Runner.prototype, 'emit', emit => function (event) {
|
|
738
|
+
const endHandler = runnerEndHandlers.get(this)
|
|
739
|
+
if (!endHandler) return emit.apply(this, arguments)
|
|
740
|
+
|
|
741
|
+
if (event === 'start') runnerStarted.add(this)
|
|
742
|
+
|
|
743
|
+
if (!runnerStarted.has(this)) return emit.apply(this, arguments)
|
|
744
|
+
|
|
745
|
+
const hasPendingFrameworkError = runnerFrameworkErrors.has(this)
|
|
746
|
+
const pendingFrameworkError = runnerFrameworkErrors.get(this)
|
|
747
|
+
if (event !== 'end') {
|
|
748
|
+
try {
|
|
749
|
+
return emit.apply(this, arguments)
|
|
750
|
+
} catch (error) {
|
|
751
|
+
if (!hasPendingFrameworkError) {
|
|
752
|
+
runnerFrameworkErrors.set(this, error)
|
|
753
|
+
this.abort()
|
|
754
|
+
stopFutureHooks(this)
|
|
755
|
+
if (event === 'start') {
|
|
756
|
+
if (parallelRunners.has(this)) stopParallelWorkers(this)
|
|
757
|
+
else stopRootSuite(this)
|
|
758
|
+
} else if (event === 'test') stopCurrentTest(this, arguments[1])
|
|
759
|
+
else if (event === 'hook') stopCurrentHook(this, arguments[1])
|
|
760
|
+
else if (event === 'hook end') {
|
|
761
|
+
const hook = arguments[1]
|
|
762
|
+
stopAfterHookEnd(this, hook)
|
|
763
|
+
const test = hook.ctx?.currentTest
|
|
764
|
+
if (test && hook.parent?._afterEach?.includes(hook)) {
|
|
765
|
+
markTestTerminal(this, test)
|
|
766
|
+
if (!test._ddTestFinishStarted) runnerTestEndHandlers.get(this)?.(test)
|
|
767
|
+
}
|
|
768
|
+
} else if (event === 'pending' || event === 'pass' || event === 'fail' || event === 'retry' ||
|
|
769
|
+
event === 'test end') {
|
|
770
|
+
const test = arguments[1]
|
|
771
|
+
stopAfterEachHooks(this, test)
|
|
772
|
+
if (event === 'test end' && !test._ddTestFinishStarted) {
|
|
773
|
+
runnerTestEndHandlers.get(this)?.(test)
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return
|
|
778
|
+
} finally {
|
|
779
|
+
if (event === 'suite end') resetPendingSuiteCoverage(this)
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
runnerEndHandlers.delete(this)
|
|
784
|
+
restoreFutureHooks(this)
|
|
785
|
+
parallelRunners.delete(this)
|
|
786
|
+
runnerTestEndHandlers.delete(this)
|
|
787
|
+
runnerStarted.delete(this)
|
|
788
|
+
let result
|
|
789
|
+
let hasFrameworkError = hasPendingFrameworkError
|
|
790
|
+
let frameworkError = pendingFrameworkError
|
|
791
|
+
try {
|
|
792
|
+
result = emit.apply(this, arguments)
|
|
793
|
+
} catch (error) {
|
|
794
|
+
if (!hasFrameworkError) {
|
|
795
|
+
hasFrameworkError = true
|
|
796
|
+
frameworkError = error
|
|
797
|
+
runnerFrameworkErrors.set(this, error)
|
|
798
|
+
}
|
|
799
|
+
} finally {
|
|
800
|
+
restoreReporterMutations(this)
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
adjustRunnerFailuresOnce(this)
|
|
804
|
+
|
|
805
|
+
if (hasFrameworkError) {
|
|
806
|
+
const finalizationError = getFrameworkFinalizationError(frameworkError)
|
|
807
|
+
let hasPropagatedFrameworkError = false
|
|
808
|
+
const propagateFrameworkError = () => {
|
|
809
|
+
if (hasPropagatedFrameworkError) return
|
|
810
|
+
|
|
811
|
+
hasPropagatedFrameworkError = true
|
|
812
|
+
if (typeof this.uncaught === 'function') process.removeListener('uncaughtException', this.uncaught)
|
|
813
|
+
if (typeof this.unhandled === 'function') process.removeListener('unhandledRejection', this.unhandled)
|
|
814
|
+
process.nextTick(() => { throw frameworkError })
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
try {
|
|
818
|
+
endHandler.call(this, finalizationError, propagateFrameworkError)
|
|
819
|
+
} catch (finalizerError) {
|
|
820
|
+
log.error('Datadog Mocha finalizer failed after a reporter error', finalizerError)
|
|
821
|
+
propagateFrameworkError()
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
return result
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
endHandler.call(this)
|
|
828
|
+
return result
|
|
829
|
+
})
|
|
830
|
+
}
|
|
831
|
+
|
|
377
832
|
function applyKnownTestsResponse ({ err, knownTests }) {
|
|
378
833
|
if (err) {
|
|
379
834
|
config.knownTests = []
|
|
@@ -466,11 +921,11 @@ function getExecutionConfiguration (runner, isParallel, frameworkVersion, onFini
|
|
|
466
921
|
} = response || {}
|
|
467
922
|
if (!response || err) {
|
|
468
923
|
suitesToSkip = []
|
|
469
|
-
skippableSuitesCoverage =
|
|
924
|
+
skippableSuitesCoverage = undefined
|
|
470
925
|
} else {
|
|
471
926
|
suitesToSkip = skippableSuites
|
|
472
927
|
itrCorrelationId = responseItrCorrelationId
|
|
473
|
-
skippableSuitesCoverage = responseSkippableSuitesCoverage
|
|
928
|
+
skippableSuitesCoverage = responseSkippableSuitesCoverage
|
|
474
929
|
}
|
|
475
930
|
if (localSuites) {
|
|
476
931
|
suitesToSkip = getSuitesToSkipFromPaths(localSuites)
|
|
@@ -707,6 +1162,7 @@ addHook({
|
|
|
707
1162
|
if (patched.has(Runner)) return Runner
|
|
708
1163
|
|
|
709
1164
|
patched.add(Runner)
|
|
1165
|
+
wrapRunnerEmit(Runner)
|
|
710
1166
|
|
|
711
1167
|
shimmer.wrap(Runner.prototype, 'runTests', runTests => getRunTestsWrapper(runTests, config))
|
|
712
1168
|
|
|
@@ -716,7 +1172,16 @@ addHook({
|
|
|
716
1172
|
}
|
|
717
1173
|
|
|
718
1174
|
const { onRunDone, onFlushDone } = getRunCompletionCallbacks(args[0])
|
|
719
|
-
|
|
1175
|
+
resetRunState(this.suite)
|
|
1176
|
+
runnerFailuresAdjusted.delete(this)
|
|
1177
|
+
runnerFrameworkErrors.delete(this)
|
|
1178
|
+
runnerStarted.delete(this)
|
|
1179
|
+
args[0] = () => {
|
|
1180
|
+
adjustRunnerFailuresOnce(this)
|
|
1181
|
+
if (!this.failures && runnerFrameworkErrors.has(this)) this.failures = 1
|
|
1182
|
+
onRunDone(this.failures)
|
|
1183
|
+
runnerFrameworkErrors.delete(this)
|
|
1184
|
+
}
|
|
720
1185
|
|
|
721
1186
|
const { suitesByTestFile, numSuitesByTestFile } = getSuitesByTestFile(this.suite)
|
|
722
1187
|
// Root-level tests (direct children of root, no describe wrapper) keyed by file.
|
|
@@ -733,6 +1198,8 @@ addHook({
|
|
|
733
1198
|
let hasEnded = false
|
|
734
1199
|
let hasFinishedRun = false
|
|
735
1200
|
let endRunner
|
|
1201
|
+
let endError
|
|
1202
|
+
let onFrameworkErrorDone
|
|
736
1203
|
|
|
737
1204
|
function updateRootTestForFinalAttempt (test) {
|
|
738
1205
|
if (!test._retriedTest) return
|
|
@@ -750,7 +1217,8 @@ addHook({
|
|
|
750
1217
|
if (hasFinishedRun) return
|
|
751
1218
|
if (hasEnded && pendingRootFinalizations === 0) {
|
|
752
1219
|
hasFinishedRun = true
|
|
753
|
-
onEnd.call(endRunner)
|
|
1220
|
+
if (onFrameworkErrorDone) onEnd.call(endRunner, endError, onFrameworkErrorDone)
|
|
1221
|
+
else onEnd.call(endRunner)
|
|
754
1222
|
}
|
|
755
1223
|
}
|
|
756
1224
|
|
|
@@ -831,11 +1299,13 @@ addHook({
|
|
|
831
1299
|
|
|
832
1300
|
const onEnd = getOnEndHandler(false, onFlushDone)
|
|
833
1301
|
|
|
834
|
-
this.
|
|
1302
|
+
this.prependOnceListener('start', getOnStartHandler(frameworkVersion))
|
|
835
1303
|
|
|
836
|
-
|
|
1304
|
+
runnerEndHandlers.set(this, function (frameworkError, frameworkErrorDone) {
|
|
837
1305
|
hasEnded = true
|
|
838
1306
|
endRunner = this
|
|
1307
|
+
endError = frameworkError
|
|
1308
|
+
onFrameworkErrorDone = frameworkErrorDone
|
|
839
1309
|
finishRunIfReady()
|
|
840
1310
|
})
|
|
841
1311
|
|
|
@@ -845,7 +1315,10 @@ addHook({
|
|
|
845
1315
|
// instead of suiteA -> suiteB -> testA -> ... -> testB)
|
|
846
1316
|
// when the suite has tests that are in the top level
|
|
847
1317
|
// (no describe(...))
|
|
848
|
-
this.
|
|
1318
|
+
this.prependListener('test', getOnTestHandler(true))
|
|
1319
|
+
// Reporters are registered before Runner#run, so prepend this after the test handler
|
|
1320
|
+
// to start the suite first and preserve the test event if a reporter throws.
|
|
1321
|
+
this.prependListener('test', function (test) {
|
|
849
1322
|
const ctx = testFileToSuiteCtx.get(test.file)
|
|
850
1323
|
if (ctx?._pendingRootStart) {
|
|
851
1324
|
ctx._pendingRootStart = false
|
|
@@ -853,20 +1326,28 @@ addHook({
|
|
|
853
1326
|
}
|
|
854
1327
|
})
|
|
855
1328
|
|
|
856
|
-
this.
|
|
857
|
-
|
|
858
|
-
|
|
1329
|
+
// Reporters are registered before this run wrapper. Prepend terminal handlers
|
|
1330
|
+
// so a reporter error cannot strand a test span that Mocha already completed.
|
|
1331
|
+
const onTestEnd = getOnTestEndHandler(config, {
|
|
859
1332
|
onStart: incrementPendingRootFinalization,
|
|
860
1333
|
onFinish: function (test) {
|
|
861
1334
|
finishRootSuiteAfterFinalAttempt(test)
|
|
862
1335
|
decrementPendingRootFinalization(test)
|
|
863
1336
|
},
|
|
864
|
-
})
|
|
1337
|
+
})
|
|
1338
|
+
runnerTestEndHandlers.set(this, onTestEnd)
|
|
1339
|
+
this.prependListener('test end', onTestEnd)
|
|
865
1340
|
|
|
866
|
-
this.
|
|
1341
|
+
this.prependListener('retry', getOnTestRetryHandler(config))
|
|
867
1342
|
|
|
868
|
-
|
|
869
|
-
|
|
1343
|
+
this.prependListener('hook end', function (hook) {
|
|
1344
|
+
const test = hook.ctx?.currentTest
|
|
1345
|
+
if (!test) return
|
|
1346
|
+
finishRootSuiteAfterFinalAttempt(test)
|
|
1347
|
+
})
|
|
1348
|
+
|
|
1349
|
+
// If the hook passes, 'hook end' will be emitted. Otherwise, 'fail' will be emitted.
|
|
1350
|
+
this.prependListener('hook end', getOnHookEndHandler(config, {
|
|
870
1351
|
onStart: incrementPendingRootFinalization,
|
|
871
1352
|
onFinish: function (test) {
|
|
872
1353
|
finishRootSuiteAfterFinalAttempt(test)
|
|
@@ -874,24 +1355,17 @@ addHook({
|
|
|
874
1355
|
},
|
|
875
1356
|
}))
|
|
876
1357
|
|
|
877
|
-
this.
|
|
878
|
-
const test = hook.ctx?.currentTest
|
|
879
|
-
if (!test) return
|
|
880
|
-
finishRootSuiteAfterFinalAttempt(test)
|
|
881
|
-
})
|
|
882
|
-
|
|
883
|
-
this.on('fail', getOnFailHandler(true, config))
|
|
884
|
-
|
|
885
|
-
this.on('fail', function (testOrHook) {
|
|
1358
|
+
this.prependListener('fail', function (testOrHook) {
|
|
886
1359
|
if (testOrHook.type !== 'hook') return
|
|
887
1360
|
const test = testOrHook.ctx?.currentTest
|
|
888
1361
|
if (!test) return
|
|
889
1362
|
finishRootSuiteAfterFinalAttempt(test)
|
|
890
1363
|
})
|
|
1364
|
+
this.prependListener('fail', getOnFailHandler(true, config))
|
|
891
1365
|
|
|
892
|
-
this.
|
|
1366
|
+
this.prependListener('pending', getOnPendingHandler())
|
|
893
1367
|
|
|
894
|
-
this.
|
|
1368
|
+
this.prependListener('suite', function (suite) {
|
|
895
1369
|
if (suite.root || !suite.tests.length) {
|
|
896
1370
|
// This branch can be triggered when we have top level it(...) inside test files.
|
|
897
1371
|
// In that case, they all (even if they are from different files) are going to be
|
|
@@ -940,7 +1414,8 @@ addHook({
|
|
|
940
1414
|
}
|
|
941
1415
|
})
|
|
942
1416
|
|
|
943
|
-
|
|
1417
|
+
// Reporters are registered before Runner#run, so this must run first when one throws.
|
|
1418
|
+
this.prependListener('suite end', function (suite) {
|
|
944
1419
|
if (suite.root) {
|
|
945
1420
|
// Normal case: pure root-level files are finished by the 'test end' / 'hook end'
|
|
946
1421
|
// listeners via finishRootSuiteForFile. Two edge cases remain here:
|
|
@@ -1015,7 +1490,7 @@ addHook({
|
|
|
1015
1490
|
// We need to reset coverage to get a code coverage per suite
|
|
1016
1491
|
// Before that, we preserve the original coverage
|
|
1017
1492
|
mergeCoverage(global.__coverage__, originalCoverageMap)
|
|
1018
|
-
|
|
1493
|
+
runnersWithPendingCoverageReset.add(this)
|
|
1019
1494
|
}
|
|
1020
1495
|
|
|
1021
1496
|
const ctx = testFileToSuiteCtx.get(suite.file)
|
|
@@ -1121,10 +1596,19 @@ addHook({
|
|
|
1121
1596
|
}
|
|
1122
1597
|
|
|
1123
1598
|
const { onRunDone, onFlushDone } = getRunCompletionCallbacks(cb)
|
|
1124
|
-
|
|
1599
|
+
runnerFailuresAdjusted.delete(this)
|
|
1600
|
+
runnerFrameworkErrors.delete(this)
|
|
1601
|
+
runnerStarted.delete(this)
|
|
1602
|
+
parallelRunners.add(this)
|
|
1603
|
+
arguments[0] = () => {
|
|
1604
|
+
adjustRunnerFailuresOnce(this)
|
|
1605
|
+
if (!this.failures && runnerFrameworkErrors.has(this)) this.failures = 1
|
|
1606
|
+
onRunDone(this.failures)
|
|
1607
|
+
runnerFrameworkErrors.delete(this)
|
|
1608
|
+
}
|
|
1125
1609
|
|
|
1126
|
-
this.
|
|
1127
|
-
|
|
1610
|
+
this.prependOnceListener('start', getOnStartHandler(frameworkVersion))
|
|
1611
|
+
runnerEndHandlers.set(this, getOnEndHandler(true, onFlushDone))
|
|
1128
1612
|
|
|
1129
1613
|
// Populate unskippable suites before config is fetched (matches serial mode at Mocha.prototype.run)
|
|
1130
1614
|
for (const filePath of files) {
|