dd-trace 5.99.1 → 5.101.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/LICENSE-3rdparty.csv +0 -1
- package/index.d.ts +14 -0
- package/package.json +8 -8
- package/packages/datadog-instrumentations/src/cucumber.js +69 -5
- package/packages/datadog-instrumentations/src/cypress.js +5 -3
- package/packages/datadog-instrumentations/src/express.js +3 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/hono.js +15 -4
- package/packages/datadog-instrumentations/src/http/client.js +20 -3
- package/packages/datadog-instrumentations/src/jest.js +146 -90
- package/packages/datadog-instrumentations/src/mocha/common.js +4 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +43 -26
- package/packages/datadog-instrumentations/src/mocha/utils.js +114 -96
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -4
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +11 -6
- package/packages/datadog-instrumentations/src/path-to-regexp.js +44 -0
- package/packages/datadog-instrumentations/src/playwright.js +108 -18
- package/packages/datadog-instrumentations/src/router.js +53 -33
- package/packages/datadog-instrumentations/src/vitest.js +76 -30
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -1
- package/packages/datadog-plugin-bullmq/src/consumer.js +5 -4
- package/packages/datadog-plugin-bullmq/src/producer.js +37 -29
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +49 -9
- package/packages/datadog-plugin-cypress/src/plugin.js +5 -14
- package/packages/datadog-plugin-cypress/src/support.js +22 -21
- package/packages/datadog-plugin-grpc/src/client.js +1 -1
- package/packages/datadog-plugin-grpc/src/server.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -9
- package/packages/datadog-plugin-kafkajs/src/producer.js +2 -8
- package/packages/datadog-plugin-mongodb-core/src/index.js +2 -3
- package/packages/datadog-plugin-playwright/src/index.js +6 -0
- package/packages/datadog-plugin-router/src/index.js +13 -0
- package/packages/dd-trace/index.js +4 -3
- package/packages/dd-trace/src/aiguard/sdk.js +2 -2
- package/packages/dd-trace/src/appsec/reporter.js +4 -1
- package/packages/dd-trace/src/baggage.js +10 -0
- package/packages/dd-trace/src/ci-visibility/lage.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/request.js +11 -33
- package/packages/dd-trace/src/config/config-types.d.ts +0 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +17 -41
- package/packages/dd-trace/src/config/index.js +7 -60
- package/packages/dd-trace/src/config/normalize-service.js +31 -0
- package/packages/dd-trace/src/config/supported-configurations.json +15 -32
- package/packages/dd-trace/src/datastreams/checkpointer.js +4 -10
- package/packages/dd-trace/src/datastreams/encoding.js +39 -28
- package/packages/dd-trace/src/datastreams/pathway.js +29 -26
- package/packages/dd-trace/src/datastreams/processor.js +17 -15
- package/packages/dd-trace/src/datastreams/size.js +6 -2
- package/packages/dd-trace/src/debugger/config.js +6 -3
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -5
- package/packages/dd-trace/src/debugger/devtools_client/send.js +2 -1
- package/packages/dd-trace/src/dogstatsd.js +10 -7
- package/packages/dd-trace/src/encode/0.4.js +3 -3
- package/packages/dd-trace/src/encode/0.5.js +2 -2
- package/packages/dd-trace/src/encode/agentless-json.js +2 -2
- package/packages/dd-trace/src/encode/tags-processors.js +2 -27
- package/packages/dd-trace/src/exporters/common/request.js +22 -11
- package/packages/dd-trace/src/exporters/common/retry.js +104 -0
- package/packages/dd-trace/src/git_metadata.js +66 -0
- package/packages/dd-trace/src/git_metadata_tagger.js +13 -5
- package/packages/dd-trace/src/heap_snapshots.js +4 -4
- package/packages/dd-trace/src/id.js +15 -26
- package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +27 -16
- package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +3 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +30 -13
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +20 -50
- package/packages/dd-trace/src/llmobs/sdk.js +5 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +28 -2
- package/packages/dd-trace/src/llmobs/tagger.js +42 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +29 -0
- package/packages/dd-trace/src/llmobs/util.js +80 -5
- package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +2 -2
- package/packages/dd-trace/src/opentelemetry/active-span-proxy.js +42 -0
- package/packages/dd-trace/src/opentelemetry/bridge-span-base.js +106 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +22 -10
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +308 -0
- package/packages/dd-trace/src/opentelemetry/span.js +42 -108
- package/packages/dd-trace/src/opentelemetry/tracer.js +11 -36
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +95 -36
- package/packages/dd-trace/src/opentracing/propagation/tracestate.js +98 -32
- package/packages/dd-trace/src/opentracing/span.js +58 -49
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +119 -32
- package/packages/dd-trace/src/plugins/util/test.js +293 -27
- package/packages/dd-trace/src/priority_sampler.js +6 -4
- package/packages/dd-trace/src/profiling/config.js +5 -4
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +2 -2
- package/packages/dd-trace/src/propagation-hash/index.js +1 -1
- package/packages/dd-trace/src/proxy.js +3 -3
- package/packages/dd-trace/src/remote_config/index.js +5 -3
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
- package/packages/dd-trace/src/span_format.js +52 -5
- package/packages/dd-trace/src/span_processor.js +1 -5
- package/packages/dd-trace/src/spanleak.js +0 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +7 -5
- package/packages/dd-trace/src/tracer_metadata.js +1 -1
- package/packages/dd-trace/src/util.js +17 -0
- package/vendor/dist/path-to-regexp/LICENSE +0 -21
- package/vendor/dist/path-to-regexp/index.js +0 -1
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
const realSetTimeout = setTimeout
|
|
5
5
|
|
|
6
6
|
const path = require('path')
|
|
7
|
+
const satisfies = require('../../../vendor/dist/semifies')
|
|
8
|
+
const { DD_MAJOR } = require('../../../version')
|
|
7
9
|
const shimmer = require('../../datadog-shimmer')
|
|
8
10
|
const log = require('../../dd-trace/src/log')
|
|
9
11
|
const {
|
|
@@ -21,6 +23,9 @@ const {
|
|
|
21
23
|
isModifiedTest,
|
|
22
24
|
DYNAMIC_NAME_RE,
|
|
23
25
|
collectDynamicNamesFromTraces,
|
|
26
|
+
recordAttemptToFixExecution,
|
|
27
|
+
logAttemptToFixTestExecution,
|
|
28
|
+
logTestOptimizationSummary,
|
|
24
29
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
25
30
|
const {
|
|
26
31
|
SEED_SUFFIX_RE,
|
|
@@ -107,6 +112,7 @@ const wrappedWorkerChannels = new WeakMap()
|
|
|
107
112
|
// New tests whose names contain likely dynamic data (timestamps, UUIDs, etc.)
|
|
108
113
|
// Populated in-process for runInBand, and via worker-report:trace for parallel mode.
|
|
109
114
|
const newTestsWithDynamicNames = new Set()
|
|
115
|
+
const loggedAttemptToFixTests = new Set()
|
|
110
116
|
const testSuiteMockedFiles = new Map()
|
|
111
117
|
const testsToBeRetried = new Set()
|
|
112
118
|
// Per-test: how many EFD retries were determined after the first execution.
|
|
@@ -122,7 +128,13 @@ const testSuiteJestObjects = new Map()
|
|
|
122
128
|
|
|
123
129
|
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
|
|
124
130
|
const ATR_RETRY_SUPPRESSION_FLAG = '_ddDisableAtrRetry'
|
|
131
|
+
const MINIMUM_JEST_VERSION = DD_MAJOR >= 6 ? '>=28.0.0' : '>=24.8.0'
|
|
132
|
+
const MINIMUM_JEST_VERSION_BEFORE_30 = DD_MAJOR >= 6 ? '>=28.0.0 <30.0.0' : '>=24.8.0 <30.0.0'
|
|
133
|
+
const MINIMUM_JEST_WORKER_VERSION_BEFORE_30 = DD_MAJOR >= 6 ? '>=28.0.0 <30.0.0' : '>=24.9.0 <30.0.0'
|
|
134
|
+
const MINIMUM_JEST_CONFIG_ASYNC_VERSION = DD_MAJOR >= 6 ? '>=28.0.0' : '>=25.1.0'
|
|
135
|
+
const MINIMUM_JEST_TEST_SCHEDULER_VERSION = DD_MAJOR >= 6 ? '>=28.0.0' : '>=27.0.0'
|
|
125
136
|
const atrSuppressedErrors = new Map()
|
|
137
|
+
let hasWarnedDeprecatedJestVersion = false
|
|
126
138
|
|
|
127
139
|
// Track quarantined tests whose errors were suppressed, keyed by "suite › testName"
|
|
128
140
|
const quarantinedFailingTests = new Set()
|
|
@@ -173,6 +185,20 @@ function formatJestError (errors) {
|
|
|
173
185
|
return error
|
|
174
186
|
}
|
|
175
187
|
|
|
188
|
+
function warnDeprecatedJestVersion (frameworkVersion) {
|
|
189
|
+
if (DD_MAJOR >= 6 || hasWarnedDeprecatedJestVersion || !frameworkVersion ||
|
|
190
|
+
!satisfies(frameworkVersion, '<28.0.0')) {
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
hasWarnedDeprecatedJestVersion = true
|
|
195
|
+
// eslint-disable-next-line no-console
|
|
196
|
+
console.warn(
|
|
197
|
+
'dd-trace support for Jest<28.0.0 is deprecated and will be removed in dd-trace v6. ' +
|
|
198
|
+
'Please upgrade Jest to >=28.0.0.'
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
176
202
|
function getTestEnvironmentOptions (config) {
|
|
177
203
|
if (config.projectConfig && config.projectConfig.testEnvironmentOptions) { // newer versions
|
|
178
204
|
return config.projectConfig.testEnvironmentOptions
|
|
@@ -193,64 +219,88 @@ function getTestStats (testStatuses) {
|
|
|
193
219
|
}
|
|
194
220
|
|
|
195
221
|
/**
|
|
196
|
-
*
|
|
197
|
-
* @param {string[]} quarantineNames
|
|
198
|
-
* @param {number} totalCount
|
|
199
|
-
*/
|
|
200
|
-
/**
|
|
201
|
-
* Renders a truncated bullet list from an array of items.
|
|
222
|
+
* Formats the ignored-failure section for the Test Optimization summary.
|
|
202
223
|
*
|
|
203
|
-
* @param {
|
|
224
|
+
* @param {{ efdNames: string[], quarantineNames: string[], totalCount: number } | undefined} ignoredFailures
|
|
204
225
|
* @returns {string}
|
|
205
226
|
*/
|
|
206
|
-
function
|
|
227
|
+
function formatIgnoredFailuresSummary (ignoredFailures) {
|
|
228
|
+
if (!ignoredFailures) return ''
|
|
229
|
+
|
|
230
|
+
const items = []
|
|
231
|
+
|
|
232
|
+
for (const n of ignoredFailures.efdNames) {
|
|
233
|
+
items.push({ text: n, suffix: 'Early Flake Detection' })
|
|
234
|
+
}
|
|
235
|
+
for (const n of ignoredFailures.quarantineNames) {
|
|
236
|
+
items.push({ text: n, suffix: 'Quarantine' })
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (items.length === 0 || ignoredFailures.totalCount <= 0) return ''
|
|
240
|
+
|
|
207
241
|
const shown = items.slice(0, MAX_IGNORED_TEST_NAMES)
|
|
208
242
|
const more = items.length - shown.length
|
|
209
243
|
const moreSuffix = more > 0 ? `\n ... and ${more} more` : ''
|
|
210
|
-
|
|
244
|
+
const formattedItems = shown
|
|
245
|
+
.map(({ text, suffix }) => ` • ${text}${suffix ? ` (${suffix})` : ''}`)
|
|
246
|
+
.join('\n') + moreSuffix
|
|
247
|
+
|
|
248
|
+
return `${ignoredFailures.totalCount} test failure(s) were ignored. Exit code set to 0.\n\n${formattedItems}`
|
|
211
249
|
}
|
|
212
250
|
|
|
213
251
|
/**
|
|
214
|
-
* Logs a single "Datadog Test Optimization" summary at session end
|
|
215
|
-
* combining all relevant sections (ignored failures, dynamic names).
|
|
252
|
+
* Logs a single "Datadog Test Optimization" summary at session end.
|
|
216
253
|
*
|
|
217
254
|
* @param {{ efdNames: string[], quarantineNames: string[], totalCount: number } | undefined} ignoredFailures
|
|
218
255
|
*/
|
|
219
|
-
function logSessionSummary (ignoredFailures) {
|
|
220
|
-
|
|
256
|
+
function logSessionSummary (ignoredFailures, attemptToFixExecutions) {
|
|
257
|
+
logTestOptimizationSummary({
|
|
258
|
+
attemptToFixExecutions,
|
|
259
|
+
extraSections: [formatIgnoredFailuresSummary(ignoredFailures)],
|
|
260
|
+
newTestsWithDynamicNames,
|
|
261
|
+
})
|
|
262
|
+
loggedAttemptToFixTests.clear()
|
|
263
|
+
}
|
|
221
264
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
for (const n of ignoredFailures.quarantineNames) {
|
|
228
|
-
items.push({ text: n, suffix: 'Quarantine' })
|
|
229
|
-
}
|
|
230
|
-
sections.push(
|
|
231
|
-
`${ignoredFailures.totalCount} test failure(s) were ignored. Exit code set to 0.\n\n` +
|
|
232
|
-
formatList(items)
|
|
233
|
-
)
|
|
234
|
-
}
|
|
265
|
+
function getTestStatusFromJestResult (status) {
|
|
266
|
+
if (status === 'failed') return 'fail'
|
|
267
|
+
if (status === 'passed') return 'pass'
|
|
268
|
+
}
|
|
235
269
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
270
|
+
function getAttemptToFixExecutionsFromJestResults (result) {
|
|
271
|
+
const executions = new Map()
|
|
272
|
+
const rootDir = result.globalConfig?.rootDir || process.cwd()
|
|
273
|
+
|
|
274
|
+
for (const { testResults, testFilePath } of result.results.testResults) {
|
|
275
|
+
const testSuite = getTestSuitePath(testFilePath, rootDir)
|
|
276
|
+
const testManagementTestsForSuite = testManagementTests
|
|
277
|
+
?.jest
|
|
278
|
+
?.suites
|
|
279
|
+
?.[testSuite]
|
|
280
|
+
?.tests
|
|
281
|
+
if (!testManagementTestsForSuite) continue
|
|
282
|
+
|
|
283
|
+
for (const { fullName, status } of testResults) {
|
|
284
|
+
const testName = testSuiteAbsolutePathsWithFastCheck.has(testFilePath)
|
|
285
|
+
? fullName.replace(SEED_SUFFIX_RE, '')
|
|
286
|
+
: fullName
|
|
287
|
+
const testStatus = getTestStatusFromJestResult(status)
|
|
288
|
+
if (!testStatus) continue
|
|
289
|
+
|
|
290
|
+
const testManagementTest = testManagementTestsForSuite[testName]?.properties
|
|
291
|
+
if (!testManagementTest?.attempt_to_fix) continue
|
|
292
|
+
|
|
293
|
+
recordAttemptToFixExecution(executions, {
|
|
294
|
+
testSuite,
|
|
295
|
+
testName,
|
|
296
|
+
status: testStatus,
|
|
297
|
+
isDisabled: testManagementTest.disabled,
|
|
298
|
+
isQuarantined: testManagementTest.quarantined,
|
|
299
|
+
})
|
|
300
|
+
}
|
|
247
301
|
}
|
|
248
302
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const line = '-'.repeat(50)
|
|
252
|
-
// eslint-disable-next-line no-console -- Intentional user-facing session summary
|
|
253
|
-
console.warn(`\n${line}\nDatadog Test Optimization\n${line}\n${sections.join('\n\n')}\n`)
|
|
303
|
+
return executions
|
|
254
304
|
}
|
|
255
305
|
|
|
256
306
|
function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
@@ -556,6 +606,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
556
606
|
}
|
|
557
607
|
testContexts.set(event.test, ctx)
|
|
558
608
|
|
|
609
|
+
if (isAttemptToFix) {
|
|
610
|
+
logAttemptToFixTestExecution(this.testSuite, testName, loggedAttemptToFixTests)
|
|
611
|
+
}
|
|
612
|
+
|
|
559
613
|
testStartCh.runStores(ctx, () => {
|
|
560
614
|
let p = event.test.parent
|
|
561
615
|
const hooks = []
|
|
@@ -795,7 +849,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
795
849
|
// Only suppress on the final execution — not when ATR/EFD/ATF will retry the test.
|
|
796
850
|
if (!event.test?.[ATR_RETRY_SUPPRESSION_FLAG] && !willBeRetriedByFailedTestReplay) {
|
|
797
851
|
const quarantineCtx = testContexts.get(event.test)
|
|
798
|
-
if (quarantineCtx?.isQuarantined && event.test.errors?.length) {
|
|
852
|
+
if (quarantineCtx?.isQuarantined && !quarantineCtx.isAttemptToFix && event.test.errors?.length) {
|
|
799
853
|
quarantinedFailingTests.add(`${quarantineCtx.suite} › ${quarantineCtx.name}`)
|
|
800
854
|
event.test.errors = []
|
|
801
855
|
}
|
|
@@ -858,10 +912,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
858
912
|
}
|
|
859
913
|
if (event.name === 'run_finish') {
|
|
860
914
|
for (const [test, errors] of atrSuppressedErrors) {
|
|
861
|
-
// Do not restore errors for quarantined tests — they should stay suppressed
|
|
915
|
+
// Do not restore errors for non-ATF quarantined tests — they should stay suppressed
|
|
862
916
|
// so Jest doesn't see the failure (prevents --bail from stopping the run).
|
|
863
917
|
const ctx = testContexts.get(test)
|
|
864
|
-
if (ctx?.isQuarantined) {
|
|
918
|
+
if (ctx?.isQuarantined && !ctx.isAttemptToFix) {
|
|
865
919
|
const testName = getJestTestName(test, this.getShouldStripSeedFromTestName())
|
|
866
920
|
quarantinedFailingTests.add(`${ctx.suite} › ${testName}`)
|
|
867
921
|
} else {
|
|
@@ -984,7 +1038,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
984
1038
|
|
|
985
1039
|
// If the test is quarantined, regardless of its actual execution result,
|
|
986
1040
|
// the final status of its last execution should be reported as 'skip'.
|
|
987
|
-
if (
|
|
1041
|
+
if (!attemptToFixResult.isAttemptToFixEnabled &&
|
|
1042
|
+
this.isTestManagementTestsEnabled &&
|
|
988
1043
|
this.testManagementTestsForThisSuite?.quarantined?.includes(testName)) {
|
|
989
1044
|
return 'skip'
|
|
990
1045
|
}
|
|
@@ -1040,12 +1095,12 @@ function applySuiteSkipping (originalTests, rootDir, frameworkVersion) {
|
|
|
1040
1095
|
|
|
1041
1096
|
addHook({
|
|
1042
1097
|
name: 'jest-environment-node',
|
|
1043
|
-
versions: [
|
|
1098
|
+
versions: [MINIMUM_JEST_VERSION],
|
|
1044
1099
|
}, getTestEnvironment)
|
|
1045
1100
|
|
|
1046
1101
|
addHook({
|
|
1047
1102
|
name: 'jest-environment-jsdom',
|
|
1048
|
-
versions: [
|
|
1103
|
+
versions: [MINIMUM_JEST_VERSION],
|
|
1049
1104
|
}, getTestEnvironment)
|
|
1050
1105
|
|
|
1051
1106
|
addHook({
|
|
@@ -1117,6 +1172,8 @@ function searchSourceWrapper (searchSourcePackage, frameworkVersion) {
|
|
|
1117
1172
|
|
|
1118
1173
|
function getCliWrapper (isNewJestVersion) {
|
|
1119
1174
|
return function cliWrapper (cli, jestVersion) {
|
|
1175
|
+
warnDeprecatedJestVersion(jestVersion)
|
|
1176
|
+
|
|
1120
1177
|
if (isNewJestVersion) {
|
|
1121
1178
|
cli = shimmer.wrap(
|
|
1122
1179
|
cli,
|
|
@@ -1315,7 +1372,6 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1315
1372
|
}
|
|
1316
1373
|
|
|
1317
1374
|
let numFailedQuarantinedTests = 0
|
|
1318
|
-
let numFailedQuarantinedOrDisabledAttemptedToFixTests = 0
|
|
1319
1375
|
let numSuppressedQuarantinedTests = 0
|
|
1320
1376
|
if (isTestManagementTestsEnabled) {
|
|
1321
1377
|
const failedTests = result
|
|
@@ -1343,11 +1399,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1343
1399
|
?.tests
|
|
1344
1400
|
?.[testName]
|
|
1345
1401
|
?.properties
|
|
1346
|
-
|
|
1347
|
-
if (testManagementTest?.attempt_to_fix && (testManagementTest?.quarantined || testManagementTest?.disabled)) {
|
|
1348
|
-
numFailedQuarantinedOrDisabledAttemptedToFixTests++
|
|
1349
|
-
quarantineIgnoredNames.push(`${testSuite} › ${testName}`)
|
|
1350
|
-
} else if (testManagementTest?.quarantined) {
|
|
1402
|
+
if (testManagementTest?.quarantined && !testManagementTest?.attempt_to_fix) {
|
|
1351
1403
|
numFailedQuarantinedTests++
|
|
1352
1404
|
quarantineIgnoredNames.push(`${testSuite} › ${testName}`)
|
|
1353
1405
|
}
|
|
@@ -1365,13 +1417,11 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1365
1417
|
quarantinedFailingTests.clear()
|
|
1366
1418
|
|
|
1367
1419
|
// If every test that failed was quarantined, we'll consider the suite passed
|
|
1368
|
-
//
|
|
1369
|
-
// it's considered quarantined both if it's disabled and if it's quarantined
|
|
1370
|
-
// (it'll run but its status is ignored)
|
|
1420
|
+
// Attempt-to-fix tests ignore quarantine/disabled suppression and keep their framework result.
|
|
1371
1421
|
// Skip if EFD block already flipped (to avoid logging twice)
|
|
1372
1422
|
// Only use visible failures (from Jest results) for the flip check.
|
|
1373
1423
|
// Suppressed quarantine failures are not in numFailedTests.
|
|
1374
|
-
const visibleQuarantineFailures = numFailedQuarantinedTests
|
|
1424
|
+
const visibleQuarantineFailures = numFailedQuarantinedTests
|
|
1375
1425
|
if (
|
|
1376
1426
|
!result.results.success &&
|
|
1377
1427
|
!mustNotFlipSuccess &&
|
|
@@ -1406,7 +1456,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1406
1456
|
(isEarlyFlakeDetectionEnabled || isTestManagementTestsEnabled)
|
|
1407
1457
|
) {
|
|
1408
1458
|
const visibleIgnoredFailures =
|
|
1409
|
-
numEfdFailedTestsToIgnore + numFailedQuarantinedTests
|
|
1459
|
+
numEfdFailedTestsToIgnore + numFailedQuarantinedTests
|
|
1410
1460
|
if (
|
|
1411
1461
|
visibleIgnoredFailures !== 0 &&
|
|
1412
1462
|
result.results.numFailedTests === visibleIgnoredFailures
|
|
@@ -1474,7 +1524,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1474
1524
|
})
|
|
1475
1525
|
}
|
|
1476
1526
|
|
|
1477
|
-
logSessionSummary(ignoredFailuresSummary)
|
|
1527
|
+
logSessionSummary(ignoredFailuresSummary, getAttemptToFixExecutionsFromJestResults(result))
|
|
1478
1528
|
|
|
1479
1529
|
numSkippedSuites = 0
|
|
1480
1530
|
|
|
@@ -1510,7 +1560,7 @@ function coverageReporterWrapper (coverageReporter) {
|
|
|
1510
1560
|
addHook({
|
|
1511
1561
|
name: '@jest/core',
|
|
1512
1562
|
file: 'build/TestScheduler.js',
|
|
1513
|
-
versions: [
|
|
1563
|
+
versions: [MINIMUM_JEST_TEST_SCHEDULER_VERSION],
|
|
1514
1564
|
}, (testSchedulerPackage, frameworkVersion) => {
|
|
1515
1565
|
const oldCreateTestScheduler = testSchedulerPackage.createTestScheduler
|
|
1516
1566
|
const newCreateTestScheduler = async function () {
|
|
@@ -1526,17 +1576,19 @@ addHook({
|
|
|
1526
1576
|
return testSchedulerPackage
|
|
1527
1577
|
})
|
|
1528
1578
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1579
|
+
if (DD_MAJOR < 6) {
|
|
1580
|
+
addHook({
|
|
1581
|
+
name: '@jest/core',
|
|
1582
|
+
file: 'build/TestScheduler.js',
|
|
1583
|
+
versions: ['>=24.8.0 <27.0.0'],
|
|
1584
|
+
}, (testSchedulerPackage, frameworkVersion) => {
|
|
1585
|
+
shimmer.wrap(
|
|
1586
|
+
testSchedulerPackage.default.prototype,
|
|
1587
|
+
'scheduleTests', scheduleTests => getWrappedScheduleTests(scheduleTests, frameworkVersion)
|
|
1588
|
+
)
|
|
1589
|
+
return testSchedulerPackage
|
|
1590
|
+
})
|
|
1591
|
+
}
|
|
1540
1592
|
|
|
1541
1593
|
addHook({
|
|
1542
1594
|
name: '@jest/test-sequencer',
|
|
@@ -1556,16 +1608,18 @@ addHook({
|
|
|
1556
1608
|
return sequencerPackage
|
|
1557
1609
|
})
|
|
1558
1610
|
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1611
|
+
if (DD_MAJOR < 6) {
|
|
1612
|
+
addHook({
|
|
1613
|
+
name: '@jest/reporters',
|
|
1614
|
+
file: 'build/coverage_reporter.js',
|
|
1615
|
+
versions: ['>=24.8.0 <26.6.2'],
|
|
1616
|
+
}, coverageReporterWrapper)
|
|
1617
|
+
}
|
|
1564
1618
|
|
|
1565
1619
|
addHook({
|
|
1566
1620
|
name: '@jest/reporters',
|
|
1567
1621
|
file: 'build/CoverageReporter.js',
|
|
1568
|
-
versions: ['>=26.6.2'],
|
|
1622
|
+
versions: [DD_MAJOR >= 6 ? '>=28.0.0' : '>=26.6.2'],
|
|
1569
1623
|
}, coverageReporterWrapper)
|
|
1570
1624
|
|
|
1571
1625
|
addHook({
|
|
@@ -1578,7 +1632,7 @@ addHook({
|
|
|
1578
1632
|
addHook({
|
|
1579
1633
|
name: '@jest/core',
|
|
1580
1634
|
file: 'build/cli/index.js',
|
|
1581
|
-
versions: [
|
|
1635
|
+
versions: [MINIMUM_JEST_VERSION_BEFORE_30],
|
|
1582
1636
|
}, getCliWrapper(false))
|
|
1583
1637
|
|
|
1584
1638
|
addHook({
|
|
@@ -1665,7 +1719,7 @@ addHook({
|
|
|
1665
1719
|
addHook({
|
|
1666
1720
|
name: 'jest-circus',
|
|
1667
1721
|
file: 'build/legacy-code-todo-rewrite/jestAdapter.js',
|
|
1668
|
-
versions: [
|
|
1722
|
+
versions: [MINIMUM_JEST_VERSION],
|
|
1669
1723
|
}, jestAdapterWrapper)
|
|
1670
1724
|
|
|
1671
1725
|
function configureTestEnvironment (readConfigsResult) {
|
|
@@ -1802,7 +1856,7 @@ function wrapCreateScriptTransformer (createScriptTransformer) {
|
|
|
1802
1856
|
|
|
1803
1857
|
addHook({
|
|
1804
1858
|
name: '@jest/transform',
|
|
1805
|
-
versions: [
|
|
1859
|
+
versions: [MINIMUM_JEST_VERSION_BEFORE_30],
|
|
1806
1860
|
file: 'build/ScriptTransformer.js',
|
|
1807
1861
|
}, transformPackage => {
|
|
1808
1862
|
transformPackage.createScriptTransformer = wrapCreateScriptTransformer(transformPackage.createScriptTransformer)
|
|
@@ -1822,20 +1876,22 @@ addHook({
|
|
|
1822
1876
|
*/
|
|
1823
1877
|
addHook({
|
|
1824
1878
|
name: '@jest/core',
|
|
1825
|
-
versions: [
|
|
1879
|
+
versions: [MINIMUM_JEST_VERSION_BEFORE_30],
|
|
1826
1880
|
file: 'build/SearchSource.js',
|
|
1827
1881
|
}, searchSourceWrapper)
|
|
1828
1882
|
|
|
1829
1883
|
// from 25.1.0 on, readConfigs becomes async
|
|
1830
1884
|
addHook({
|
|
1831
1885
|
name: 'jest-config',
|
|
1832
|
-
versions: [
|
|
1886
|
+
versions: [MINIMUM_JEST_CONFIG_ASYNC_VERSION],
|
|
1833
1887
|
}, jestConfigAsyncWrapper)
|
|
1834
1888
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1889
|
+
if (DD_MAJOR < 6) {
|
|
1890
|
+
addHook({
|
|
1891
|
+
name: 'jest-config',
|
|
1892
|
+
versions: ['24.8.0 - 24.9.0'],
|
|
1893
|
+
}, jestConfigSyncWrapper)
|
|
1894
|
+
}
|
|
1839
1895
|
|
|
1840
1896
|
const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
|
|
1841
1897
|
'selenium-webdriver',
|
|
@@ -1850,7 +1906,7 @@ const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
|
|
|
1850
1906
|
|
|
1851
1907
|
addHook({
|
|
1852
1908
|
name: 'jest-runtime',
|
|
1853
|
-
versions: [
|
|
1909
|
+
versions: [MINIMUM_JEST_VERSION],
|
|
1854
1910
|
}, (runtimePackage) => {
|
|
1855
1911
|
const Runtime = runtimePackage.default ?? runtimePackage
|
|
1856
1912
|
|
|
@@ -2051,7 +2107,7 @@ function enqueueWrapper (enqueue) {
|
|
|
2051
2107
|
*/
|
|
2052
2108
|
addHook({
|
|
2053
2109
|
name: 'jest-worker',
|
|
2054
|
-
versions: [
|
|
2110
|
+
versions: [MINIMUM_JEST_WORKER_VERSION_BEFORE_30],
|
|
2055
2111
|
file: 'build/workers/ChildProcessWorker.js',
|
|
2056
2112
|
}, (childProcessWorker) => {
|
|
2057
2113
|
const ChildProcessWorker = childProcessWorker.default
|
|
@@ -2066,7 +2122,7 @@ addHook({
|
|
|
2066
2122
|
|
|
2067
2123
|
addHook({
|
|
2068
2124
|
name: 'jest-worker',
|
|
2069
|
-
versions: [
|
|
2125
|
+
versions: [MINIMUM_JEST_WORKER_VERSION_BEFORE_30],
|
|
2070
2126
|
file: 'build/workers/NodeThreadsWorker.js',
|
|
2071
2127
|
}, (nodeThreadsWorker) => {
|
|
2072
2128
|
const ExperimentalWorker = nodeThreadsWorker.default
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
const { addHook, channel } = require('../helpers/instrument')
|
|
4
4
|
const shimmer = require('../../../datadog-shimmer')
|
|
5
5
|
const { getCallSites } = require('../../../dd-trace/src/plugins/util/stacktrace')
|
|
6
|
+
const { DD_MAJOR } = require('../../../../version')
|
|
6
7
|
const { testToStartLine } = require('./utils')
|
|
7
8
|
|
|
9
|
+
const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
10
|
+
|
|
8
11
|
const parameterizedTestCh = channel('ci:mocha:test:parameterize')
|
|
9
12
|
const patched = new WeakSet()
|
|
10
13
|
|
|
@@ -33,7 +36,7 @@ addHook({
|
|
|
33
36
|
// support for start line
|
|
34
37
|
addHook({
|
|
35
38
|
name: 'mocha',
|
|
36
|
-
versions: [
|
|
39
|
+
versions: [MINIMUM_MOCHA_VERSION],
|
|
37
40
|
file: 'lib/suite.js',
|
|
38
41
|
}, (Suite) => {
|
|
39
42
|
shimmer.wrap(Suite.prototype, 'addTest', addTest => function (test) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { createCoverageMap } = require('../../../../vendor/dist/istanbul-lib-coverage')
|
|
4
|
+
const satisfies = require('../../../../vendor/dist/semifies')
|
|
5
|
+
const { DD_MAJOR } = require('../../../../version')
|
|
4
6
|
const { addHook, channel } = require('../helpers/instrument')
|
|
5
7
|
const shimmer = require('../../../datadog-shimmer')
|
|
6
8
|
const { isMarkedAsUnskippable } = require('../../../datadog-plugin-jest/src/util')
|
|
@@ -14,8 +16,8 @@ const {
|
|
|
14
16
|
mergeCoverage,
|
|
15
17
|
resetCoverage,
|
|
16
18
|
getIsFaultyEarlyFlakeDetection,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
collectTestOptimizationSummariesFromTraces,
|
|
20
|
+
logTestOptimizationSummary,
|
|
19
21
|
} = require('../../../dd-trace/src/plugins/util/test')
|
|
20
22
|
|
|
21
23
|
const {
|
|
@@ -34,14 +36,17 @@ const {
|
|
|
34
36
|
testsQuarantined,
|
|
35
37
|
getTestFullName,
|
|
36
38
|
getRunTestsWrapper,
|
|
37
|
-
testsAttemptToFix,
|
|
38
|
-
testsStatuses,
|
|
39
39
|
newTestsWithDynamicNames,
|
|
40
|
+
attemptToFixExecutions,
|
|
41
|
+
loggedAttemptToFixTests,
|
|
40
42
|
} = require('./utils')
|
|
41
43
|
|
|
42
44
|
require('./common')
|
|
43
45
|
|
|
46
|
+
const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
47
|
+
|
|
44
48
|
const patched = new WeakSet()
|
|
49
|
+
let hasWarnedDeprecatedMochaVersion = false
|
|
45
50
|
|
|
46
51
|
const unskippableSuites = []
|
|
47
52
|
let suitesToSkip = []
|
|
@@ -79,6 +84,20 @@ const itrSkippedSuitesCh = channel('ci:mocha:itr:skipped-suites')
|
|
|
79
84
|
|
|
80
85
|
const getCodeCoverageCh = channel('ci:nyc:get-coverage')
|
|
81
86
|
|
|
87
|
+
function warnDeprecatedMochaVersion (frameworkVersion) {
|
|
88
|
+
if (DD_MAJOR >= 6 || hasWarnedDeprecatedMochaVersion || !frameworkVersion ||
|
|
89
|
+
!satisfies(frameworkVersion, '<8.0.0')) {
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
hasWarnedDeprecatedMochaVersion = true
|
|
94
|
+
// eslint-disable-next-line no-console
|
|
95
|
+
console.warn(
|
|
96
|
+
'dd-trace support for Mocha<8.0.0 is deprecated and will be removed in dd-trace v6. ' +
|
|
97
|
+
'Please upgrade Mocha to >=8.0.0.'
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
82
101
|
// Tests from workers do not come with `isFailed` method
|
|
83
102
|
function isTestFailed (test) {
|
|
84
103
|
if (test.isFailed) {
|
|
@@ -146,26 +165,17 @@ function getOnEndHandler (isParallel) {
|
|
|
146
165
|
}
|
|
147
166
|
}
|
|
148
167
|
|
|
149
|
-
// We
|
|
150
|
-
//
|
|
168
|
+
// We subtract the errors from quarantined tests from the total number of failures.
|
|
169
|
+
// Attempt-to-fix tests ignore quarantine/disabled suppression and keep their framework result.
|
|
151
170
|
if (config.isTestManagementTestsEnabled) {
|
|
152
171
|
let numFailedQuarantinedTests = 0
|
|
153
|
-
let numFailedRetriedQuarantinedOrDisabledTests = 0
|
|
154
|
-
for (const test of testsAttemptToFix) {
|
|
155
|
-
const testName = getTestFullName(test)
|
|
156
|
-
const testProperties = getTestProperties(test, config.testManagementTests)
|
|
157
|
-
if (isTestFailed(test) && (testProperties.isQuarantined || testProperties.isDisabled)) {
|
|
158
|
-
const numFailedTests = testsStatuses.get(testName).filter(status => status === 'fail').length
|
|
159
|
-
numFailedRetriedQuarantinedOrDisabledTests += numFailedTests
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
172
|
for (const test of testsQuarantined) {
|
|
163
173
|
if (isTestFailed(test)) {
|
|
164
174
|
numFailedQuarantinedTests++
|
|
165
175
|
}
|
|
166
176
|
}
|
|
167
|
-
this.stats.failures -= numFailedQuarantinedTests
|
|
168
|
-
this.failures -= numFailedQuarantinedTests
|
|
177
|
+
this.stats.failures -= numFailedQuarantinedTests
|
|
178
|
+
this.failures -= numFailedQuarantinedTests
|
|
169
179
|
}
|
|
170
180
|
|
|
171
181
|
// Recompute status after EFD and quarantine adjustments have reduced failure counts
|
|
@@ -211,7 +221,8 @@ function getOnEndHandler (isParallel) {
|
|
|
211
221
|
isParallel,
|
|
212
222
|
})
|
|
213
223
|
|
|
214
|
-
|
|
224
|
+
logTestOptimizationSummary({ attemptToFixExecutions, newTestsWithDynamicNames })
|
|
225
|
+
loggedAttemptToFixTests.clear()
|
|
215
226
|
}
|
|
216
227
|
}
|
|
217
228
|
|
|
@@ -353,9 +364,11 @@ function getExecutionConfiguration (runner, isParallel, frameworkVersion, onFini
|
|
|
353
364
|
// It is called but skipped in parallel mode.
|
|
354
365
|
addHook({
|
|
355
366
|
name: 'mocha',
|
|
356
|
-
versions: [
|
|
367
|
+
versions: [MINIMUM_MOCHA_VERSION],
|
|
357
368
|
file: 'lib/mocha.js',
|
|
358
369
|
}, (Mocha, frameworkVersion) => {
|
|
370
|
+
warnDeprecatedMochaVersion(frameworkVersion)
|
|
371
|
+
|
|
359
372
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
360
373
|
// Workers do not need to request any data, just run the tests
|
|
361
374
|
if (!testFinishCh.hasSubscribers || getEnvironmentVariable('MOCHA_WORKER_ID') || this.options.parallel) {
|
|
@@ -409,7 +422,7 @@ addHook({
|
|
|
409
422
|
|
|
410
423
|
addHook({
|
|
411
424
|
name: 'mocha',
|
|
412
|
-
versions: [
|
|
425
|
+
versions: [MINIMUM_MOCHA_VERSION],
|
|
413
426
|
file: 'lib/cli/run-helpers.js',
|
|
414
427
|
}, (run) => {
|
|
415
428
|
// `runMocha` is an async function
|
|
@@ -440,7 +453,7 @@ addHook({
|
|
|
440
453
|
// This hook is used to generate session, module, suite and test events
|
|
441
454
|
addHook({
|
|
442
455
|
name: 'mocha',
|
|
443
|
-
versions: [
|
|
456
|
+
versions: [MINIMUM_MOCHA_VERSION],
|
|
444
457
|
file: 'lib/runner.js',
|
|
445
458
|
}, function (Runner, frameworkVersion) {
|
|
446
459
|
if (patched.has(Runner)) return Runner
|
|
@@ -467,9 +480,9 @@ addHook({
|
|
|
467
480
|
this.on('retry', getOnTestRetryHandler(config))
|
|
468
481
|
|
|
469
482
|
// If the hook passes, 'hook end' will be emitted. Otherwise, 'fail' will be emitted
|
|
470
|
-
this.on('hook end', getOnHookEndHandler())
|
|
483
|
+
this.on('hook end', getOnHookEndHandler(config))
|
|
471
484
|
|
|
472
|
-
this.on('fail', getOnFailHandler(true))
|
|
485
|
+
this.on('fail', getOnFailHandler(true, config))
|
|
473
486
|
|
|
474
487
|
this.on('pending', getOnPendingHandler())
|
|
475
488
|
|
|
@@ -549,7 +562,7 @@ addHook({
|
|
|
549
562
|
// Used to set the correct async resource to the test.
|
|
550
563
|
addHook({
|
|
551
564
|
name: 'mocha',
|
|
552
|
-
versions: [
|
|
565
|
+
versions: [MINIMUM_MOCHA_VERSION],
|
|
553
566
|
file: 'lib/runnable.js',
|
|
554
567
|
}, (runnablePackage) => runnableWrapper(runnablePackage, config))
|
|
555
568
|
|
|
@@ -557,7 +570,10 @@ function onMessage (message) {
|
|
|
557
570
|
if (Array.isArray(message)) {
|
|
558
571
|
const [messageCode, payload] = message
|
|
559
572
|
if (messageCode === MOCHA_WORKER_TRACE_PAYLOAD_CODE) {
|
|
560
|
-
|
|
573
|
+
collectTestOptimizationSummariesFromTraces(payload, {
|
|
574
|
+
newTestsWithDynamicNames,
|
|
575
|
+
attemptToFixExecutions,
|
|
576
|
+
})
|
|
561
577
|
workerReportTraceCh.publish(payload)
|
|
562
578
|
}
|
|
563
579
|
}
|
|
@@ -771,7 +787,8 @@ addHook({
|
|
|
771
787
|
}
|
|
772
788
|
}
|
|
773
789
|
// `testsQuarantined` is filled in the worker process, so we need to use the test results to fill it here too.
|
|
774
|
-
|
|
790
|
+
const testProperties = getTestProperties(test, config.testManagementTests)
|
|
791
|
+
if (config.isTestManagementTestsEnabled && testProperties.isQuarantined && !testProperties.isAttemptToFix) {
|
|
775
792
|
testsQuarantined.add(test)
|
|
776
793
|
}
|
|
777
794
|
}
|