dd-trace 5.99.0 → 5.100.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/package.json +24 -5
- package/packages/datadog-instrumentations/src/cucumber.js +69 -5
- 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/jest.js +89 -63
- package/packages/datadog-instrumentations/src/mocha/main.js +18 -22
- package/packages/datadog-instrumentations/src/mocha/utils.js +114 -96
- package/packages/datadog-instrumentations/src/mocha/worker.js +2 -2
- 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 +3 -2
- package/packages/datadog-plugin-bullmq/src/producer.js +25 -11
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +32 -9
- package/packages/datadog-plugin-cypress/src/support.js +22 -21
- package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/utils.js +2 -2
- package/packages/datadog-plugin-grpc/src/client.js +1 -1
- package/packages/datadog-plugin-grpc/src/server.js +1 -1
- package/packages/datadog-plugin-memcached/src/index.js +1 -1
- 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/blocking.js +18 -6
- package/packages/dd-trace/src/appsec/graphql.js +1 -1
- package/packages/dd-trace/src/baggage.js +26 -13
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +1 -1
- package/packages/dd-trace/src/config/generated-config-types.d.ts +45 -69
- package/packages/dd-trace/src/config/index.js +13 -12
- package/packages/dd-trace/src/config/normalize-service.js +31 -0
- package/packages/dd-trace/src/config/supported-configurations.json +31 -76
- package/packages/dd-trace/src/debugger/config.js +1 -1
- package/packages/dd-trace/src/dogstatsd.js +5 -8
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +3 -3
- package/packages/dd-trace/src/exporter.js +1 -1
- package/packages/dd-trace/src/git_metadata_tagger.js +1 -1
- package/packages/dd-trace/src/heap_snapshots.js +4 -4
- package/packages/dd-trace/src/llmobs/constants/tags.js +3 -0
- package/packages/dd-trace/src/llmobs/sdk.js +21 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +14 -1
- package/packages/dd-trace/src/llmobs/writers/base.js +7 -1
- package/packages/dd-trace/src/llmobs/writers/spans.js +1 -1
- package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +2 -2
- package/packages/dd-trace/src/opentelemetry/context_manager.js +11 -8
- package/packages/dd-trace/src/opentelemetry/logs/index.js +5 -5
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +6 -6
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +170 -0
- package/packages/dd-trace/src/opentelemetry/span.js +14 -42
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +11 -36
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +44 -23
- package/packages/dd-trace/src/opentracing/propagation/tracestate.js +42 -12
- package/packages/dd-trace/src/opentracing/span.js +4 -3
- package/packages/dd-trace/src/plugin_manager.js +6 -6
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +119 -32
- package/packages/dd-trace/src/plugins/util/test.js +295 -29
- 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 +9 -9
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
- package/packages/dd-trace/src/span_processor.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +7 -5
- package/packages/dd-trace/src/tracer_metadata.js +1 -1
- package/vendor/dist/path-to-regexp/LICENSE +0 -21
- package/vendor/dist/path-to-regexp/index.js +0 -1
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -85,7 +85,6 @@
|
|
|
85
85
|
"node-gyp-build","https://github.com/prebuild/node-gyp-build","['MIT']","['Mathias Buus']"
|
|
86
86
|
"opentracing","https://github.com/opentracing/opentracing-javascript","['Apache-2.0']","['opentracing']"
|
|
87
87
|
"oxc-parser","https://github.com/oxc-project/oxc","['MIT']","['Boshen and oxc contributors']"
|
|
88
|
-
"path-to-regexp","https://github.com/pillarjs/path-to-regexp","['MIT']","['pillarjs']"
|
|
89
88
|
"pprof-format","https://github.com/DataDog/pprof-format","['MIT']","['Datadog Inc.']"
|
|
90
89
|
"protobufjs","https://github.com/protobufjs/protobuf.js","['BSD-3-Clause']","['Daniel Wirtz']"
|
|
91
90
|
"queue-tick","https://github.com/mafintosh/queue-tick","['MIT']","['Mathias Buus']"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.100.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"lint:fix": "node scripts/check_licenses.js && node scripts/check-no-coverage-artifacts.js && eslint . --concurrency=auto --max-warnings 0 --fix",
|
|
23
23
|
"lint:inspect": "npx @eslint/config-inspector@latest",
|
|
24
24
|
"lint:codeowners": "codeowners-audit",
|
|
25
|
-
"lint:codeowners:ci": "codeowners-audit --glob='**/*.spec.js'",
|
|
25
|
+
"lint:codeowners:ci": "codeowners-audit --glob='**/*.spec.js' --glob='benchmark/sirun/**'",
|
|
26
26
|
"release:proposal": "node scripts/release/proposal",
|
|
27
27
|
"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
|
|
28
28
|
"test": "echo '\nError: The root \"npm test\" command is intentionally disabled.\n\nInstead, run specific test suites:\n - npm run test:trace:core\n - npm run test:appsec\n - etc.\n\nOr run individual test files:\n npx mocha path/to/test.spec.js\n\nSee CONTRIBUTING.md (Testing section) for more details.\n' && exit 1",
|
|
@@ -66,23 +66,39 @@
|
|
|
66
66
|
"test:profiler": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 -- \"packages/dd-trace/test/profiling/**/*.spec.js\"",
|
|
67
67
|
"test:profiler:ci": "nyc --silent node init && nyc -- npm run test:profiler",
|
|
68
68
|
"test:integration": "mocha --timeout 60000 \"integration-tests/*.spec.js\"",
|
|
69
|
+
"test:integration:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/*.spec.js\"",
|
|
69
70
|
"test:integration:aiguard": "mocha --timeout 60000 \"integration-tests/aiguard/*.spec.js\"",
|
|
71
|
+
"test:integration:aiguard:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/aiguard/*.spec.js\"",
|
|
70
72
|
"test:integration:appsec": "mocha --timeout 60000 \"integration-tests/appsec/*.spec.js\"",
|
|
73
|
+
"test:integration:appsec:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/appsec/*.spec.js\"",
|
|
71
74
|
"test:integration:bun": "mocha --timeout 60000 \"integration-tests/bun/*.spec.js\"",
|
|
72
75
|
"test:integration:cucumber": "mocha --timeout 60000 \"integration-tests/cucumber/*.spec.js\"",
|
|
76
|
+
"test:integration:cucumber:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/cucumber/*.spec.js\"",
|
|
73
77
|
"test:integration:cypress": "mocha --timeout 60000 \"integration-tests/cypress/${SPEC:-cypress-*}.spec.js\"",
|
|
78
|
+
"test:integration:cypress:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/cypress/${SPEC:-cypress-*}.spec.js\"",
|
|
74
79
|
"test:integration:debugger": "mocha --timeout 60000 \"integration-tests/debugger/*.spec.js\"",
|
|
80
|
+
"test:integration:debugger:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/debugger/*.spec.js\"",
|
|
75
81
|
"test:integration:esbuild": "mocha --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
|
|
82
|
+
"test:integration:esbuild:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
|
|
76
83
|
"test:integration:webpack": "mocha --timeout 60000 \"integration-tests/webpack/*.spec.js\"",
|
|
77
84
|
"test:integration:openfeature": "mocha --timeout 60000 \"integration-tests/openfeature/*.spec.js\"",
|
|
85
|
+
"test:integration:openfeature:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/openfeature/*.spec.js\"",
|
|
78
86
|
"test:integration:jest": "mocha --timeout 60000 \"integration-tests/jest/*.spec.js\"",
|
|
87
|
+
"test:integration:jest:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/jest/*.spec.js\"",
|
|
79
88
|
"test:integration:mocha": "mocha --timeout 60000 \"integration-tests/mocha/*.spec.js\"",
|
|
89
|
+
"test:integration:mocha:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/mocha/*.spec.js\"",
|
|
80
90
|
"test:integration:playwright": "mocha --timeout 60000 \"integration-tests/playwright/${SPEC:-playwright-*}.spec.js\"",
|
|
91
|
+
"test:integration:playwright:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/playwright/${SPEC:-playwright-*}.spec.js\"",
|
|
81
92
|
"test:integration:selenium": "mocha --timeout 60000 \"integration-tests/selenium/*.spec.js\"",
|
|
93
|
+
"test:integration:selenium:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/selenium/*.spec.js\"",
|
|
82
94
|
"test:integration:vitest": "mocha --timeout 60000 \"integration-tests/vitest/*.spec.js\"",
|
|
95
|
+
"test:integration:vitest:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/vitest/*.spec.js\"",
|
|
83
96
|
"test:integration:testopt": "mocha --timeout 120000 \"integration-tests/ci-visibility/*.spec.js\"",
|
|
97
|
+
"test:integration:testopt:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 120000 \"integration-tests/ci-visibility/*.spec.js\"",
|
|
84
98
|
"test:integration:profiler": "mocha --timeout 180000 \"integration-tests/profiler/*.spec.js\"",
|
|
85
|
-
"test:integration:
|
|
99
|
+
"test:integration:profiler:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 180000 \"integration-tests/profiler/*.spec.js\"",
|
|
100
|
+
"test:integration:plugins": "yarn services && mocha \"packages/datadog-plugin-@(${PLUGINS})/test/integration-test/**/${SPEC:-*}*.spec.js\"",
|
|
101
|
+
"test:integration:plugins:coverage": "yarn services && node ./integration-tests/coverage/run-suite.js \"packages/datadog-plugin-@(${PLUGINS})/test/integration-test/**/${SPEC:-*}*.spec.js\"",
|
|
86
102
|
"test:unit:plugins": "mocha \"packages/datadog-instrumentations/test/@(${PLUGINS}).spec.js\" \"packages/datadog-plugin-@(${PLUGINS})/test/**/*.spec.js\" --exclude \"packages/datadog-plugin-@(${PLUGINS})/test/integration-test/**/*.spec.js\"",
|
|
87
103
|
"test:shimmer": "mocha \"packages/datadog-shimmer/test/**/*.spec.js\"",
|
|
88
104
|
"test:shimmer:ci": "nyc --silent node init && nyc -- npm run test:shimmer",
|
|
@@ -176,24 +192,27 @@
|
|
|
176
192
|
"bun": "1.3.13",
|
|
177
193
|
"codeowners-audit": "^2.9.0",
|
|
178
194
|
"eslint": "^9.39.2",
|
|
179
|
-
"eslint-plugin-cypress": "^6.
|
|
195
|
+
"eslint-plugin-cypress": "^6.4.0",
|
|
180
196
|
"eslint-plugin-import": "^2.32.0",
|
|
181
197
|
"eslint-plugin-jsdoc": "^62.9.0",
|
|
182
198
|
"eslint-plugin-mocha": "^11.2.0",
|
|
183
199
|
"eslint-plugin-n": "^17.23.2",
|
|
184
|
-
"eslint-plugin-promise": "^7.
|
|
200
|
+
"eslint-plugin-promise": "^7.3.0",
|
|
185
201
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
186
202
|
"express": "^5.1.0",
|
|
187
203
|
"glob": "^10.4.5",
|
|
188
204
|
"globals": "^17.2.0",
|
|
189
205
|
"graphql": "*",
|
|
190
206
|
"husky": "^9.1.7",
|
|
207
|
+
"istanbul-lib-report": "^3.0.0",
|
|
208
|
+
"istanbul-reports": "^3.0.2",
|
|
191
209
|
"jszip": "^3.10.1",
|
|
192
210
|
"mocha": "^11.6.0",
|
|
193
211
|
"mocha-junit-reporter": "^2.2.1",
|
|
194
212
|
"mocha-multi-reporters": "^1.5.1",
|
|
195
213
|
"multer": "^2.1.1",
|
|
196
214
|
"nock": "^13.5.6",
|
|
215
|
+
"node-preload": "^0.2.1",
|
|
197
216
|
"nyc": "^18.0.0",
|
|
198
217
|
"octokit": "^5.0.3",
|
|
199
218
|
"opentracing": ">=0.14.7",
|
|
@@ -12,6 +12,10 @@ const {
|
|
|
12
12
|
getTestSuitePath,
|
|
13
13
|
CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
|
|
14
14
|
getIsFaultyEarlyFlakeDetection,
|
|
15
|
+
recordAttemptToFixExecution,
|
|
16
|
+
collectAttemptToFixExecutionsFromTraces,
|
|
17
|
+
logAttemptToFixTestExecution,
|
|
18
|
+
logTestOptimizationSummary,
|
|
15
19
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
16
20
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
17
21
|
const { addHook, channel } = require('./helpers/instrument')
|
|
@@ -60,9 +64,12 @@ const atrStatusesByScenarioKey = new Map()
|
|
|
60
64
|
const numRetriesByPickleId = new Map()
|
|
61
65
|
const numAttemptToCtx = new Map()
|
|
62
66
|
const newTestsByTestFullname = new Map()
|
|
67
|
+
const attemptToFixTestsByTestFullname = new Map()
|
|
63
68
|
const modifiedTestsByPickleId = new Map()
|
|
64
69
|
// Pickle IDs for tests that are genuinely new (not in known tests list).
|
|
65
70
|
const newTestPickleIds = new Set()
|
|
71
|
+
const attemptToFixExecutions = new Map()
|
|
72
|
+
const loggedAttemptToFixTests = new Set()
|
|
66
73
|
|
|
67
74
|
let eventDataCollector = null
|
|
68
75
|
let pickleByFile = {}
|
|
@@ -154,6 +161,16 @@ function getTestStatusFromRetries (testStatuses) {
|
|
|
154
161
|
return 'pass'
|
|
155
162
|
}
|
|
156
163
|
|
|
164
|
+
function getTestStatusFromAttemptToFixExecutions (testStatuses) {
|
|
165
|
+
if (testStatuses.every(status => status === 'pass')) {
|
|
166
|
+
return 'pass'
|
|
167
|
+
}
|
|
168
|
+
if (testStatuses.every(status => status === 'skip')) {
|
|
169
|
+
return 'skip'
|
|
170
|
+
}
|
|
171
|
+
return 'fail'
|
|
172
|
+
}
|
|
173
|
+
|
|
157
174
|
function getErrorFromCucumberResult (cucumberResult) {
|
|
158
175
|
if (!cucumberResult.message) {
|
|
159
176
|
return
|
|
@@ -247,9 +264,8 @@ function getFinalStatus ({
|
|
|
247
264
|
}) {
|
|
248
265
|
// Note that intermediate executions DO NOT report a final status tag
|
|
249
266
|
|
|
250
|
-
// If the test is quarantined or disabled,
|
|
251
|
-
|
|
252
|
-
if (isQuarantined || isDisabled || status === 'skip') {
|
|
267
|
+
// If the test is quarantined or disabled, its final status is skip unless attempt-to-fix takes precedence.
|
|
268
|
+
if (status === 'skip' || (!isLastAttemptToFix && (isQuarantined || isDisabled))) {
|
|
253
269
|
return 'skip'
|
|
254
270
|
}
|
|
255
271
|
|
|
@@ -282,6 +298,7 @@ function wrapRun (pl, isLatestVersion, version) {
|
|
|
282
298
|
let numAttempt = 0
|
|
283
299
|
|
|
284
300
|
const testFileAbsolutePath = this.pickle.uri
|
|
301
|
+
const testSuitePath = getTestSuitePath(testFileAbsolutePath, process.cwd())
|
|
285
302
|
|
|
286
303
|
const testSourceLine = this.gherkinDocument?.feature?.location?.line
|
|
287
304
|
|
|
@@ -293,6 +310,9 @@ function wrapRun (pl, isLatestVersion, version) {
|
|
|
293
310
|
}
|
|
294
311
|
const ctx = testStartPayload
|
|
295
312
|
numAttemptToCtx.set(numAttempt, ctx)
|
|
313
|
+
if (isTestManagementTestsEnabled && getTestProperties(testSuitePath, this.pickle.name).attemptToFix) {
|
|
314
|
+
logAttemptToFixTestExecution(testSuitePath, this.pickle.name, loggedAttemptToFixTests)
|
|
315
|
+
}
|
|
296
316
|
testStartCh.runStores(ctx, () => {})
|
|
297
317
|
const promises = {}
|
|
298
318
|
try {
|
|
@@ -441,6 +461,16 @@ function wrapRun (pl, isLatestVersion, version) {
|
|
|
441
461
|
|
|
442
462
|
const error = getErrorFromCucumberResult(result)
|
|
443
463
|
|
|
464
|
+
if (isAttemptToFix) {
|
|
465
|
+
recordAttemptToFixExecution(attemptToFixExecutions, {
|
|
466
|
+
testSuite: testSuitePath,
|
|
467
|
+
testName: this.pickle.name,
|
|
468
|
+
status,
|
|
469
|
+
isDisabled,
|
|
470
|
+
isQuarantined,
|
|
471
|
+
})
|
|
472
|
+
}
|
|
473
|
+
|
|
444
474
|
if (promises.hitBreakpointPromise) {
|
|
445
475
|
await promises.hitBreakpointPromise
|
|
446
476
|
}
|
|
@@ -661,6 +691,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
661
691
|
}
|
|
662
692
|
|
|
663
693
|
atrStatusesByScenarioKey.clear()
|
|
694
|
+
attemptToFixTestsByTestFullname.clear()
|
|
664
695
|
sessionStartCh.publish({ command, frameworkVersion })
|
|
665
696
|
|
|
666
697
|
if (!errorSkippableRequest && skippedSuites.length) {
|
|
@@ -701,6 +732,8 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
701
732
|
isTestManagementTestsEnabled,
|
|
702
733
|
isParallel,
|
|
703
734
|
})
|
|
735
|
+
logTestOptimizationSummary({ attemptToFixExecutions })
|
|
736
|
+
loggedAttemptToFixTests.clear()
|
|
704
737
|
eventDataCollector = null
|
|
705
738
|
return success
|
|
706
739
|
}
|
|
@@ -811,6 +844,7 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
811
844
|
let testStatus = lastTestStatus
|
|
812
845
|
let shouldBePassedByEFD = false
|
|
813
846
|
let shouldBePassedByTestManagement = false
|
|
847
|
+
let shouldBeFailedByAttemptToFix = false
|
|
814
848
|
if ((isNew || isModified) && isEarlyFlakeDetectionEnabled) {
|
|
815
849
|
/**
|
|
816
850
|
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
@@ -827,7 +861,15 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
827
861
|
}
|
|
828
862
|
}
|
|
829
863
|
|
|
830
|
-
if (
|
|
864
|
+
if (isAttemptToFix && testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
865
|
+
testStatus = getTestStatusFromAttemptToFixExecutions(testStatuses)
|
|
866
|
+
if (testStatus === 'fail') {
|
|
867
|
+
this.success = false
|
|
868
|
+
shouldBeFailedByAttemptToFix = true
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
if (isTestManagementTestsEnabled && !isAttemptToFix && (isDisabled || isQuarantined)) {
|
|
831
873
|
this.success = true
|
|
832
874
|
shouldBePassedByTestManagement = true
|
|
833
875
|
}
|
|
@@ -863,10 +905,14 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
863
905
|
return shouldBePassedByEFD
|
|
864
906
|
}
|
|
865
907
|
|
|
866
|
-
if (isNewerCucumberVersion && isTestManagementTestsEnabled && (isQuarantined || isDisabled)) {
|
|
908
|
+
if (isNewerCucumberVersion && isTestManagementTestsEnabled && !isAttemptToFix && (isQuarantined || isDisabled)) {
|
|
867
909
|
return shouldBePassedByTestManagement
|
|
868
910
|
}
|
|
869
911
|
|
|
912
|
+
if (isNewerCucumberVersion && isAttemptToFix && shouldBeFailedByAttemptToFix) {
|
|
913
|
+
return false
|
|
914
|
+
}
|
|
915
|
+
|
|
870
916
|
return runTestCaseResult
|
|
871
917
|
}
|
|
872
918
|
}
|
|
@@ -882,6 +928,7 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
882
928
|
if (Array.isArray(message)) {
|
|
883
929
|
const [messageCode, payload] = message
|
|
884
930
|
if (messageCode === CUCUMBER_WORKER_TRACE_PAYLOAD_CODE) {
|
|
931
|
+
collectAttemptToFixExecutionsFromTraces(payload, attemptToFixExecutions)
|
|
885
932
|
workerReportTraceCh.publish(payload)
|
|
886
933
|
return
|
|
887
934
|
}
|
|
@@ -962,6 +1009,23 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
962
1009
|
// we only push to `finished` if the retries have finished
|
|
963
1010
|
finished.push(newTestFinalStatus)
|
|
964
1011
|
}
|
|
1012
|
+
} else if (
|
|
1013
|
+
isTestManagementTestsEnabled &&
|
|
1014
|
+
getTestProperties(getTestSuitePath(testFileAbsolutePath, process.cwd()), pickle.name).attemptToFix
|
|
1015
|
+
) {
|
|
1016
|
+
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
1017
|
+
let testStatuses = attemptToFixTestsByTestFullname.get(testFullname)
|
|
1018
|
+
if (testStatuses) {
|
|
1019
|
+
testStatuses.push(status)
|
|
1020
|
+
} else {
|
|
1021
|
+
testStatuses = [status]
|
|
1022
|
+
attemptToFixTestsByTestFullname.set(testFullname, testStatuses)
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
if (status === 'skip' || testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
1026
|
+
finished.push(getTestStatusFromAttemptToFixExecutions(testStatuses))
|
|
1027
|
+
attemptToFixTestsByTestFullname.delete(testFullname)
|
|
1028
|
+
}
|
|
965
1029
|
} else {
|
|
966
1030
|
// TODO: can we get error message?
|
|
967
1031
|
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const shimmer = require('../../datadog-shimmer')
|
|
4
4
|
const { createWrapRouterMethod } = require('./router')
|
|
5
5
|
const { addHook, channel, tracingChannel } = require('./helpers/instrument')
|
|
6
|
+
const { getCompileToRegexp } = require('./path-to-regexp')
|
|
6
7
|
const {
|
|
7
8
|
setRouterMountPath,
|
|
8
9
|
markAppMounted,
|
|
@@ -26,8 +27,6 @@ function wrapHandle (handle) {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
const wrapRouterMethod = createWrapRouterMethod('express')
|
|
30
|
-
|
|
31
30
|
const responseJsonChannel = channel('datadog:express:response:json:start')
|
|
32
31
|
|
|
33
32
|
function wrapResponseJson (json) {
|
|
@@ -163,6 +162,8 @@ addHook({ name: 'express', versions: ['>=4'], file: 'lib/express.js' }, express
|
|
|
163
162
|
// It would otherwise produce spans for router and express, and so duplicating them.
|
|
164
163
|
// We now fall back to router instrumentation
|
|
165
164
|
addHook({ name: 'express', versions: ['4'], file: 'lib/express.js' }, express => {
|
|
165
|
+
const wrapRouterMethod = createWrapRouterMethod('express', getCompileToRegexp())
|
|
166
|
+
|
|
166
167
|
shimmer.wrap(express.Router, 'use', wrapRouterMethod)
|
|
167
168
|
shimmer.wrap(express.Router, 'route', wrapRouterMethod)
|
|
168
169
|
|
|
@@ -118,6 +118,7 @@ module.exports = {
|
|
|
118
118
|
passport: () => require('../passport'),
|
|
119
119
|
'passport-http': () => require('../passport-http'),
|
|
120
120
|
'passport-local': () => require('../passport-local'),
|
|
121
|
+
'path-to-regexp': () => require('../path-to-regexp'),
|
|
121
122
|
pg: () => require('../pg'),
|
|
122
123
|
pino: () => require('../pino'),
|
|
123
124
|
'pino-pretty': () => require('../pino'),
|
|
@@ -14,9 +14,15 @@ const enterChannel = channel('apm:hono:middleware:enter')
|
|
|
14
14
|
const exitChannel = channel('apm:hono:middleware:exit')
|
|
15
15
|
const finishChannel = channel('apm:hono:middleware:finish')
|
|
16
16
|
|
|
17
|
+
// `app.request()` and non-node adapters call `app.fetch` without an `incoming`
|
|
18
|
+
// IncomingMessage; the APM `web` helpers depend on one, so the wrappers below
|
|
19
|
+
// skip publishing whenever it is missing.
|
|
17
20
|
function wrapFetch (fetch) {
|
|
18
21
|
return function (request, env, executionCtx) {
|
|
19
|
-
|
|
22
|
+
const req = env?.incoming
|
|
23
|
+
if (req) {
|
|
24
|
+
handleChannel.publish({ req })
|
|
25
|
+
}
|
|
20
26
|
return fetch.apply(this, arguments)
|
|
21
27
|
}
|
|
22
28
|
}
|
|
@@ -31,8 +37,10 @@ function wrapCompose (compose) {
|
|
|
31
37
|
|
|
32
38
|
const instrumentedOnError = (...args) => {
|
|
33
39
|
const [error, context] = args
|
|
34
|
-
const req = context.env
|
|
35
|
-
|
|
40
|
+
const req = context.env?.incoming
|
|
41
|
+
if (req) {
|
|
42
|
+
errorChannel.publish({ req, error })
|
|
43
|
+
}
|
|
36
44
|
return onError(...args)
|
|
37
45
|
}
|
|
38
46
|
|
|
@@ -62,7 +70,10 @@ function wrapMiddleware (middleware, route) {
|
|
|
62
70
|
middleware,
|
|
63
71
|
(middleware) =>
|
|
64
72
|
function (context, next) {
|
|
65
|
-
const req = context.env
|
|
73
|
+
const req = context.env?.incoming
|
|
74
|
+
if (!req) {
|
|
75
|
+
return middleware.apply(this, arguments)
|
|
76
|
+
}
|
|
66
77
|
routeChannel.publish({ req, route })
|
|
67
78
|
enterChannel.publish({ req, name, route })
|
|
68
79
|
if (typeof next === 'function') {
|
|
@@ -21,6 +21,9 @@ const {
|
|
|
21
21
|
isModifiedTest,
|
|
22
22
|
DYNAMIC_NAME_RE,
|
|
23
23
|
collectDynamicNamesFromTraces,
|
|
24
|
+
recordAttemptToFixExecution,
|
|
25
|
+
logAttemptToFixTestExecution,
|
|
26
|
+
logTestOptimizationSummary,
|
|
24
27
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
25
28
|
const {
|
|
26
29
|
SEED_SUFFIX_RE,
|
|
@@ -78,7 +81,7 @@ let knownTests = {}
|
|
|
78
81
|
let isCodeCoverageEnabled = false
|
|
79
82
|
let isCodeCoverageEnabledBecauseOfUs = false
|
|
80
83
|
let isSuitesSkippingEnabled = false
|
|
81
|
-
let
|
|
84
|
+
let DD_TEST_TIA_KEEP_COV_CONFIG = false
|
|
82
85
|
let isUserCodeCoverageEnabled = false
|
|
83
86
|
let isSuitesSkipped = false
|
|
84
87
|
let numSkippedSuites = 0
|
|
@@ -107,6 +110,7 @@ const wrappedWorkerChannels = new WeakMap()
|
|
|
107
110
|
// New tests whose names contain likely dynamic data (timestamps, UUIDs, etc.)
|
|
108
111
|
// Populated in-process for runInBand, and via worker-report:trace for parallel mode.
|
|
109
112
|
const newTestsWithDynamicNames = new Set()
|
|
113
|
+
const loggedAttemptToFixTests = new Set()
|
|
110
114
|
const testSuiteMockedFiles = new Map()
|
|
111
115
|
const testsToBeRetried = new Set()
|
|
112
116
|
// Per-test: how many EFD retries were determined after the first execution.
|
|
@@ -193,64 +197,88 @@ function getTestStats (testStatuses) {
|
|
|
193
197
|
}
|
|
194
198
|
|
|
195
199
|
/**
|
|
196
|
-
*
|
|
197
|
-
* @param {string[]} quarantineNames
|
|
198
|
-
* @param {number} totalCount
|
|
199
|
-
*/
|
|
200
|
-
/**
|
|
201
|
-
* Renders a truncated bullet list from an array of items.
|
|
200
|
+
* Formats the ignored-failure section for the Test Optimization summary.
|
|
202
201
|
*
|
|
203
|
-
* @param {
|
|
202
|
+
* @param {{ efdNames: string[], quarantineNames: string[], totalCount: number } | undefined} ignoredFailures
|
|
204
203
|
* @returns {string}
|
|
205
204
|
*/
|
|
206
|
-
function
|
|
205
|
+
function formatIgnoredFailuresSummary (ignoredFailures) {
|
|
206
|
+
if (!ignoredFailures) return ''
|
|
207
|
+
|
|
208
|
+
const items = []
|
|
209
|
+
|
|
210
|
+
for (const n of ignoredFailures.efdNames) {
|
|
211
|
+
items.push({ text: n, suffix: 'Early Flake Detection' })
|
|
212
|
+
}
|
|
213
|
+
for (const n of ignoredFailures.quarantineNames) {
|
|
214
|
+
items.push({ text: n, suffix: 'Quarantine' })
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (items.length === 0 || ignoredFailures.totalCount <= 0) return ''
|
|
218
|
+
|
|
207
219
|
const shown = items.slice(0, MAX_IGNORED_TEST_NAMES)
|
|
208
220
|
const more = items.length - shown.length
|
|
209
221
|
const moreSuffix = more > 0 ? `\n ... and ${more} more` : ''
|
|
210
|
-
|
|
222
|
+
const formattedItems = shown
|
|
223
|
+
.map(({ text, suffix }) => ` • ${text}${suffix ? ` (${suffix})` : ''}`)
|
|
224
|
+
.join('\n') + moreSuffix
|
|
225
|
+
|
|
226
|
+
return `${ignoredFailures.totalCount} test failure(s) were ignored. Exit code set to 0.\n\n${formattedItems}`
|
|
211
227
|
}
|
|
212
228
|
|
|
213
229
|
/**
|
|
214
|
-
* Logs a single "Datadog Test Optimization" summary at session end
|
|
215
|
-
* combining all relevant sections (ignored failures, dynamic names).
|
|
230
|
+
* Logs a single "Datadog Test Optimization" summary at session end.
|
|
216
231
|
*
|
|
217
232
|
* @param {{ efdNames: string[], quarantineNames: string[], totalCount: number } | undefined} ignoredFailures
|
|
218
233
|
*/
|
|
219
|
-
function logSessionSummary (ignoredFailures) {
|
|
220
|
-
|
|
234
|
+
function logSessionSummary (ignoredFailures, attemptToFixExecutions) {
|
|
235
|
+
logTestOptimizationSummary({
|
|
236
|
+
attemptToFixExecutions,
|
|
237
|
+
extraSections: [formatIgnoredFailuresSummary(ignoredFailures)],
|
|
238
|
+
newTestsWithDynamicNames,
|
|
239
|
+
})
|
|
240
|
+
loggedAttemptToFixTests.clear()
|
|
241
|
+
}
|
|
221
242
|
|
|
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
|
-
}
|
|
243
|
+
function getTestStatusFromJestResult (status) {
|
|
244
|
+
if (status === 'failed') return 'fail'
|
|
245
|
+
if (status === 'passed') return 'pass'
|
|
246
|
+
}
|
|
235
247
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
function getAttemptToFixExecutionsFromJestResults (result) {
|
|
249
|
+
const executions = new Map()
|
|
250
|
+
const rootDir = result.globalConfig?.rootDir || process.cwd()
|
|
251
|
+
|
|
252
|
+
for (const { testResults, testFilePath } of result.results.testResults) {
|
|
253
|
+
const testSuite = getTestSuitePath(testFilePath, rootDir)
|
|
254
|
+
const testManagementTestsForSuite = testManagementTests
|
|
255
|
+
?.jest
|
|
256
|
+
?.suites
|
|
257
|
+
?.[testSuite]
|
|
258
|
+
?.tests
|
|
259
|
+
if (!testManagementTestsForSuite) continue
|
|
260
|
+
|
|
261
|
+
for (const { fullName, status } of testResults) {
|
|
262
|
+
const testName = testSuiteAbsolutePathsWithFastCheck.has(testFilePath)
|
|
263
|
+
? fullName.replace(SEED_SUFFIX_RE, '')
|
|
264
|
+
: fullName
|
|
265
|
+
const testStatus = getTestStatusFromJestResult(status)
|
|
266
|
+
if (!testStatus) continue
|
|
267
|
+
|
|
268
|
+
const testManagementTest = testManagementTestsForSuite[testName]?.properties
|
|
269
|
+
if (!testManagementTest?.attempt_to_fix) continue
|
|
270
|
+
|
|
271
|
+
recordAttemptToFixExecution(executions, {
|
|
272
|
+
testSuite,
|
|
273
|
+
testName,
|
|
274
|
+
status: testStatus,
|
|
275
|
+
isDisabled: testManagementTest.disabled,
|
|
276
|
+
isQuarantined: testManagementTest.quarantined,
|
|
277
|
+
})
|
|
278
|
+
}
|
|
247
279
|
}
|
|
248
280
|
|
|
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`)
|
|
281
|
+
return executions
|
|
254
282
|
}
|
|
255
283
|
|
|
256
284
|
function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
@@ -556,6 +584,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
556
584
|
}
|
|
557
585
|
testContexts.set(event.test, ctx)
|
|
558
586
|
|
|
587
|
+
if (isAttemptToFix) {
|
|
588
|
+
logAttemptToFixTestExecution(this.testSuite, testName, loggedAttemptToFixTests)
|
|
589
|
+
}
|
|
590
|
+
|
|
559
591
|
testStartCh.runStores(ctx, () => {
|
|
560
592
|
let p = event.test.parent
|
|
561
593
|
const hooks = []
|
|
@@ -795,7 +827,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
795
827
|
// Only suppress on the final execution — not when ATR/EFD/ATF will retry the test.
|
|
796
828
|
if (!event.test?.[ATR_RETRY_SUPPRESSION_FLAG] && !willBeRetriedByFailedTestReplay) {
|
|
797
829
|
const quarantineCtx = testContexts.get(event.test)
|
|
798
|
-
if (quarantineCtx?.isQuarantined && event.test.errors?.length) {
|
|
830
|
+
if (quarantineCtx?.isQuarantined && !quarantineCtx.isAttemptToFix && event.test.errors?.length) {
|
|
799
831
|
quarantinedFailingTests.add(`${quarantineCtx.suite} › ${quarantineCtx.name}`)
|
|
800
832
|
event.test.errors = []
|
|
801
833
|
}
|
|
@@ -858,10 +890,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
858
890
|
}
|
|
859
891
|
if (event.name === 'run_finish') {
|
|
860
892
|
for (const [test, errors] of atrSuppressedErrors) {
|
|
861
|
-
// Do not restore errors for quarantined tests — they should stay suppressed
|
|
893
|
+
// Do not restore errors for non-ATF quarantined tests — they should stay suppressed
|
|
862
894
|
// so Jest doesn't see the failure (prevents --bail from stopping the run).
|
|
863
895
|
const ctx = testContexts.get(test)
|
|
864
|
-
if (ctx?.isQuarantined) {
|
|
896
|
+
if (ctx?.isQuarantined && !ctx.isAttemptToFix) {
|
|
865
897
|
const testName = getJestTestName(test, this.getShouldStripSeedFromTestName())
|
|
866
898
|
quarantinedFailingTests.add(`${ctx.suite} › ${testName}`)
|
|
867
899
|
} else {
|
|
@@ -984,7 +1016,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
984
1016
|
|
|
985
1017
|
// If the test is quarantined, regardless of its actual execution result,
|
|
986
1018
|
// the final status of its last execution should be reported as 'skip'.
|
|
987
|
-
if (
|
|
1019
|
+
if (!attemptToFixResult.isAttemptToFixEnabled &&
|
|
1020
|
+
this.isTestManagementTestsEnabled &&
|
|
988
1021
|
this.testManagementTestsForThisSuite?.quarantined?.includes(testName)) {
|
|
989
1022
|
return 'skip'
|
|
990
1023
|
}
|
|
@@ -1141,8 +1174,8 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1141
1174
|
if (!err) {
|
|
1142
1175
|
isCodeCoverageEnabled = libraryConfig.isCodeCoverageEnabled
|
|
1143
1176
|
isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
1144
|
-
|
|
1145
|
-
libraryConfig.
|
|
1177
|
+
DD_TEST_TIA_KEEP_COV_CONFIG =
|
|
1178
|
+
libraryConfig.DD_TEST_TIA_KEEP_COV_CONFIG ?? DD_TEST_TIA_KEEP_COV_CONFIG
|
|
1146
1179
|
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
1147
1180
|
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
1148
1181
|
earlyFlakeDetectionSlowTestRetries = libraryConfig.earlyFlakeDetectionSlowTestRetries ?? {}
|
|
@@ -1315,7 +1348,6 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1315
1348
|
}
|
|
1316
1349
|
|
|
1317
1350
|
let numFailedQuarantinedTests = 0
|
|
1318
|
-
let numFailedQuarantinedOrDisabledAttemptedToFixTests = 0
|
|
1319
1351
|
let numSuppressedQuarantinedTests = 0
|
|
1320
1352
|
if (isTestManagementTestsEnabled) {
|
|
1321
1353
|
const failedTests = result
|
|
@@ -1343,11 +1375,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1343
1375
|
?.tests
|
|
1344
1376
|
?.[testName]
|
|
1345
1377
|
?.properties
|
|
1346
|
-
|
|
1347
|
-
if (testManagementTest?.attempt_to_fix && (testManagementTest?.quarantined || testManagementTest?.disabled)) {
|
|
1348
|
-
numFailedQuarantinedOrDisabledAttemptedToFixTests++
|
|
1349
|
-
quarantineIgnoredNames.push(`${testSuite} › ${testName}`)
|
|
1350
|
-
} else if (testManagementTest?.quarantined) {
|
|
1378
|
+
if (testManagementTest?.quarantined && !testManagementTest?.attempt_to_fix) {
|
|
1351
1379
|
numFailedQuarantinedTests++
|
|
1352
1380
|
quarantineIgnoredNames.push(`${testSuite} › ${testName}`)
|
|
1353
1381
|
}
|
|
@@ -1365,13 +1393,11 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1365
1393
|
quarantinedFailingTests.clear()
|
|
1366
1394
|
|
|
1367
1395
|
// 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)
|
|
1396
|
+
// Attempt-to-fix tests ignore quarantine/disabled suppression and keep their framework result.
|
|
1371
1397
|
// Skip if EFD block already flipped (to avoid logging twice)
|
|
1372
1398
|
// Only use visible failures (from Jest results) for the flip check.
|
|
1373
1399
|
// Suppressed quarantine failures are not in numFailedTests.
|
|
1374
|
-
const visibleQuarantineFailures = numFailedQuarantinedTests
|
|
1400
|
+
const visibleQuarantineFailures = numFailedQuarantinedTests
|
|
1375
1401
|
if (
|
|
1376
1402
|
!result.results.success &&
|
|
1377
1403
|
!mustNotFlipSuccess &&
|
|
@@ -1406,7 +1432,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1406
1432
|
(isEarlyFlakeDetectionEnabled || isTestManagementTestsEnabled)
|
|
1407
1433
|
) {
|
|
1408
1434
|
const visibleIgnoredFailures =
|
|
1409
|
-
numEfdFailedTestsToIgnore + numFailedQuarantinedTests
|
|
1435
|
+
numEfdFailedTestsToIgnore + numFailedQuarantinedTests
|
|
1410
1436
|
if (
|
|
1411
1437
|
visibleIgnoredFailures !== 0 &&
|
|
1412
1438
|
result.results.numFailedTests === visibleIgnoredFailures
|
|
@@ -1474,7 +1500,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1474
1500
|
})
|
|
1475
1501
|
}
|
|
1476
1502
|
|
|
1477
|
-
logSessionSummary(ignoredFailuresSummary)
|
|
1503
|
+
logSessionSummary(ignoredFailuresSummary, getAttemptToFixExecutionsFromJestResults(result))
|
|
1478
1504
|
|
|
1479
1505
|
numSkippedSuites = 0
|
|
1480
1506
|
|
|
@@ -1495,7 +1521,7 @@ function coverageReporterWrapper (coverageReporter) {
|
|
|
1495
1521
|
*/
|
|
1496
1522
|
// `_addUntestedFiles` is an async function
|
|
1497
1523
|
shimmer.wrap(CoverageReporter.prototype, '_addUntestedFiles', addUntestedFiles => function () {
|
|
1498
|
-
if (
|
|
1524
|
+
if (DD_TEST_TIA_KEEP_COV_CONFIG) {
|
|
1499
1525
|
return addUntestedFiles.apply(this, arguments)
|
|
1500
1526
|
}
|
|
1501
1527
|
if (isCodeCoverageEnabledBecauseOfUs) {
|
|
@@ -1697,7 +1723,7 @@ function configureTestEnvironment (readConfigsResult) {
|
|
|
1697
1723
|
...readConfigsResult.globalConfig,
|
|
1698
1724
|
passWithNoTests: true,
|
|
1699
1725
|
}
|
|
1700
|
-
if (isCodeCoverageEnabledBecauseOfUs && !
|
|
1726
|
+
if (isCodeCoverageEnabledBecauseOfUs && !DD_TEST_TIA_KEEP_COV_CONFIG) {
|
|
1701
1727
|
globalConfig.coverageReporters = ['none']
|
|
1702
1728
|
readConfigsResult.configs = configs.map(config => ({
|
|
1703
1729
|
...config,
|