dd-trace 5.41.1 → 5.42.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 +1 -0
- package/index.d.ts +8 -1
- package/package.json +6 -3
- package/packages/datadog-esbuild/index.js +3 -1
- package/packages/datadog-instrumentations/src/cucumber.js +37 -29
- package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +102 -0
- package/packages/datadog-instrumentations/src/{check_require_cache.js → helpers/check-require-cache.js} +2 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +4 -1
- package/packages/datadog-instrumentations/src/jest.js +72 -49
- package/packages/datadog-instrumentations/src/langchain.js +29 -10
- package/packages/datadog-instrumentations/src/mocha/main.js +53 -34
- package/packages/datadog-instrumentations/src/mocha/utils.js +34 -24
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -8
- package/packages/datadog-instrumentations/src/openai.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +37 -30
- package/packages/datadog-instrumentations/src/vitest.js +64 -29
- package/packages/datadog-plugin-cucumber/src/index.js +13 -4
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +41 -35
- package/packages/datadog-plugin-cypress/src/plugin.js +10 -0
- package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +195 -0
- package/packages/datadog-plugin-jest/src/index.js +18 -6
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +4 -1
- package/packages/datadog-plugin-mocha/src/index.js +13 -4
- package/packages/datadog-plugin-playwright/src/index.js +19 -5
- package/packages/datadog-plugin-vitest/src/index.js +41 -17
- package/packages/dd-trace/src/appsec/api_security_sampler.js +7 -3
- package/packages/dd-trace/src/appsec/blocking.js +23 -16
- package/packages/dd-trace/src/appsec/graphql.js +13 -6
- package/packages/dd-trace/src/appsec/rasp/utils.js +0 -1
- package/packages/dd-trace/src/appsec/reporter.js +35 -0
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -3
- package/packages/dd-trace/src/appsec/telemetry/index.js +5 -1
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +16 -1
- package/packages/dd-trace/src/appsec/telemetry/waf.js +16 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +43 -13
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +15 -14
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +1 -2
- package/packages/dd-trace/src/ci-visibility/telemetry.js +2 -1
- package/packages/dd-trace/src/ci-visibility/{quarantined-tests/get-quarantined-tests.js → test-management/get-test-management-tests.js} +5 -5
- package/packages/dd-trace/src/config.js +11 -1
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -2
- package/packages/dd-trace/src/lambda/runtime/patch.js +5 -3
- package/packages/dd-trace/src/lambda/runtime/ritm.js +13 -18
- package/packages/dd-trace/src/llmobs/plugins/openai.js +27 -2
- package/packages/dd-trace/src/opentracing/span.js +3 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +38 -10
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/git.js +7 -3
- package/packages/dd-trace/src/plugins/util/test.js +10 -0
- package/packages/dd-trace/src/plugins/util/web.js +5 -2
- package/packages/dd-trace/src/priority_sampler.js +116 -15
- package/packages/dd-trace/src/sampler.js +9 -0
- package/packages/dd-trace/src/standalone/product.js +6 -2
- package/packages/dd-trace/src/startup-log.js +2 -1
- package/packages/dd-trace/src/telemetry/metrics.js +0 -8
- package/packages/dd-trace/src/tracer.js +1 -1
- /package/packages/datadog-instrumentations/src/{utils/src → helpers}/extract-package-and-module-path.js +0 -0
|
@@ -43,7 +43,7 @@ const testErrCh = channel('ci:jest:test:err')
|
|
|
43
43
|
const skippableSuitesCh = channel('ci:jest:test-suite:skippable')
|
|
44
44
|
const libraryConfigurationCh = channel('ci:jest:library-configuration')
|
|
45
45
|
const knownTestsCh = channel('ci:jest:known-tests')
|
|
46
|
-
const
|
|
46
|
+
const testManagementTestsCh = channel('ci:jest:test-management-tests')
|
|
47
47
|
|
|
48
48
|
const itrSkippedSuitesCh = channel('ci:jest:itr:skipped-suites')
|
|
49
49
|
|
|
@@ -71,8 +71,8 @@ let earlyFlakeDetectionFaultyThreshold = 30
|
|
|
71
71
|
let isEarlyFlakeDetectionFaulty = false
|
|
72
72
|
let hasFilteredSkippableSuites = false
|
|
73
73
|
let isKnownTestsEnabled = false
|
|
74
|
-
let
|
|
75
|
-
let
|
|
74
|
+
let isTestManagementTestsEnabled = false
|
|
75
|
+
let testManagementTests = {}
|
|
76
76
|
|
|
77
77
|
const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
78
78
|
|
|
@@ -143,7 +143,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
143
143
|
this.flakyTestRetriesCount = this.testEnvironmentOptions._ddFlakyTestRetriesCount
|
|
144
144
|
this.isDiEnabled = this.testEnvironmentOptions._ddIsDiEnabled
|
|
145
145
|
this.isKnownTestsEnabled = this.testEnvironmentOptions._ddIsKnownTestsEnabled
|
|
146
|
-
this.
|
|
146
|
+
this.isTestManagementTestsEnabled = this.testEnvironmentOptions._ddIsTestManagementTestsEnabled
|
|
147
147
|
|
|
148
148
|
if (this.isKnownTestsEnabled) {
|
|
149
149
|
try {
|
|
@@ -166,15 +166,15 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
if (this.
|
|
169
|
+
if (this.isTestManagementTestsEnabled) {
|
|
170
170
|
try {
|
|
171
|
-
const
|
|
172
|
-
this.
|
|
173
|
-
? this.
|
|
174
|
-
: this.
|
|
171
|
+
const hasTestManagementTests = !!testManagementTests.jest
|
|
172
|
+
this.testManagementTestsForThisSuite = hasTestManagementTests
|
|
173
|
+
? this.getTestManagementTestsForSuite(testManagementTests.jest.suites?.[this.testSuite]?.tests)
|
|
174
|
+
: this.getTestManagementTestsForSuite(this.testEnvironmentOptions._ddTestManagementTests)
|
|
175
175
|
} catch (e) {
|
|
176
|
-
log.error('Error parsing
|
|
177
|
-
this.
|
|
176
|
+
log.error('Error parsing test management tests', e)
|
|
177
|
+
this.isTestManagementTestsEnabled = false
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
}
|
|
@@ -209,25 +209,38 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
209
209
|
return knownTestsForSuite
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
|
|
213
|
-
if (this.
|
|
214
|
-
return this.
|
|
212
|
+
getTestManagementTestsForSuite (testManagementTests) {
|
|
213
|
+
if (this.testManagementTestsForThisSuite) {
|
|
214
|
+
return this.testManagementTestsForThisSuite
|
|
215
215
|
}
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
// TODO - ADD ATTEMPT_TO_FIX tests
|
|
217
|
+
if (!testManagementTests) {
|
|
218
|
+
return {
|
|
219
|
+
disabled: [],
|
|
220
|
+
quarantined: []
|
|
221
|
+
}
|
|
218
222
|
}
|
|
219
|
-
let
|
|
220
|
-
// If jest is using workers,
|
|
223
|
+
let testManagementTestsForSuite = testManagementTests
|
|
224
|
+
// If jest is using workers, test management tests are serialized to json.
|
|
221
225
|
// If jest runs in band, they are not.
|
|
222
|
-
if (typeof
|
|
223
|
-
|
|
226
|
+
if (typeof testManagementTestsForSuite === 'string') {
|
|
227
|
+
testManagementTestsForSuite = JSON.parse(testManagementTestsForSuite)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const result = {
|
|
231
|
+
disabled: [],
|
|
232
|
+
quarantined: []
|
|
224
233
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
234
|
+
|
|
235
|
+
Object.entries(testManagementTestsForSuite).forEach(([testName, { properties }]) => {
|
|
236
|
+
if (properties?.disabled) {
|
|
237
|
+
result.disabled.push(testName)
|
|
238
|
+
} else if (properties?.quarantined) {
|
|
239
|
+
result.quarantined.push(testName)
|
|
228
240
|
}
|
|
229
|
-
|
|
230
|
-
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
return result
|
|
231
244
|
}
|
|
232
245
|
|
|
233
246
|
// Add the `add_test` event we don't have the test object yet, so
|
|
@@ -275,6 +288,13 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
275
288
|
retriedTestsToNumAttempts.set(originalTestName, numEfdRetry + 1)
|
|
276
289
|
}
|
|
277
290
|
}
|
|
291
|
+
|
|
292
|
+
if (this.isTestManagementTestsEnabled) {
|
|
293
|
+
const isDisabled = this.testManagementTestsForThisSuite?.disabled?.includes(testName)
|
|
294
|
+
if (isDisabled) {
|
|
295
|
+
event.test.mode = 'skip'
|
|
296
|
+
}
|
|
297
|
+
}
|
|
278
298
|
const isJestRetry = event.test?.invocations > 1
|
|
279
299
|
asyncResource.runInAsyncScope(() => {
|
|
280
300
|
testStartCh.publish({
|
|
@@ -341,9 +361,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
341
361
|
}
|
|
342
362
|
let isQuarantined = false
|
|
343
363
|
|
|
344
|
-
if (this.
|
|
364
|
+
if (this.isTestManagementTestsEnabled) {
|
|
345
365
|
const testName = getJestTestName(event.test)
|
|
346
|
-
isQuarantined = this.
|
|
366
|
+
isQuarantined = this.testManagementTestsForThisSuite?.quarantined?.includes(testName)
|
|
347
367
|
}
|
|
348
368
|
|
|
349
369
|
const promises = {}
|
|
@@ -391,12 +411,15 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
391
411
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
392
412
|
asyncResource.runInAsyncScope(() => {
|
|
393
413
|
testSkippedCh.publish({
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
414
|
+
test: {
|
|
415
|
+
name: getJestTestName(event.test),
|
|
416
|
+
suite: this.testSuite,
|
|
417
|
+
testSourceFile: this.testSourceFile,
|
|
418
|
+
displayName: this.displayName,
|
|
419
|
+
frameworkVersion: jestVersion,
|
|
420
|
+
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
|
|
421
|
+
},
|
|
422
|
+
isDisabled: this.testManagementTestsForThisSuite?.disabled?.includes(getJestTestName(event.test))
|
|
400
423
|
})
|
|
401
424
|
})
|
|
402
425
|
}
|
|
@@ -528,7 +551,7 @@ function cliWrapper (cli, jestVersion) {
|
|
|
528
551
|
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
529
552
|
earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
530
553
|
isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
531
|
-
|
|
554
|
+
isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
|
|
532
555
|
}
|
|
533
556
|
} catch (err) {
|
|
534
557
|
log.error('Jest library configuration error', err)
|
|
@@ -576,22 +599,22 @@ function cliWrapper (cli, jestVersion) {
|
|
|
576
599
|
}
|
|
577
600
|
}
|
|
578
601
|
|
|
579
|
-
if (
|
|
580
|
-
const
|
|
602
|
+
if (isTestManagementTestsEnabled) {
|
|
603
|
+
const testManagementTestsPromise = new Promise((resolve) => {
|
|
581
604
|
onDone = resolve
|
|
582
605
|
})
|
|
583
606
|
|
|
584
607
|
sessionAsyncResource.runInAsyncScope(() => {
|
|
585
|
-
|
|
608
|
+
testManagementTestsCh.publish({ onDone })
|
|
586
609
|
})
|
|
587
610
|
|
|
588
611
|
try {
|
|
589
|
-
const { err,
|
|
612
|
+
const { err, testManagementTests: receivedTestManagementTests } = await testManagementTestsPromise
|
|
590
613
|
if (!err) {
|
|
591
|
-
|
|
614
|
+
testManagementTests = receivedTestManagementTests
|
|
592
615
|
}
|
|
593
616
|
} catch (err) {
|
|
594
|
-
log.error('Jest
|
|
617
|
+
log.error('Jest test management tests error', err)
|
|
595
618
|
}
|
|
596
619
|
}
|
|
597
620
|
|
|
@@ -664,7 +687,7 @@ function cliWrapper (cli, jestVersion) {
|
|
|
664
687
|
error,
|
|
665
688
|
isEarlyFlakeDetectionEnabled,
|
|
666
689
|
isEarlyFlakeDetectionFaulty,
|
|
667
|
-
|
|
690
|
+
isTestManagementTestsEnabled,
|
|
668
691
|
onDone
|
|
669
692
|
})
|
|
670
693
|
})
|
|
@@ -698,7 +721,7 @@ function cliWrapper (cli, jestVersion) {
|
|
|
698
721
|
}
|
|
699
722
|
}
|
|
700
723
|
|
|
701
|
-
if (
|
|
724
|
+
if (isTestManagementTestsEnabled) {
|
|
702
725
|
const failedTests = result
|
|
703
726
|
.results
|
|
704
727
|
.testResults.flatMap(({ testResults, testFilePath: testSuiteAbsolutePath }) => (
|
|
@@ -710,7 +733,7 @@ function cliWrapper (cli, jestVersion) {
|
|
|
710
733
|
|
|
711
734
|
for (const { testName, testSuiteAbsolutePath } of failedTests) {
|
|
712
735
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, result.globalConfig.rootDir)
|
|
713
|
-
const isQuarantined =
|
|
736
|
+
const isQuarantined = testManagementTests
|
|
714
737
|
?.jest
|
|
715
738
|
?.suites
|
|
716
739
|
?.[testSuite]
|
|
@@ -922,8 +945,8 @@ addHook({
|
|
|
922
945
|
_ddFlakyTestRetriesCount,
|
|
923
946
|
_ddIsDiEnabled,
|
|
924
947
|
_ddIsKnownTestsEnabled,
|
|
925
|
-
|
|
926
|
-
|
|
948
|
+
_ddIsTestManagementTestsEnabled,
|
|
949
|
+
_ddTestManagementTests,
|
|
927
950
|
...restOfTestEnvironmentOptions
|
|
928
951
|
} = testEnvironmentOptions
|
|
929
952
|
|
|
@@ -1037,7 +1060,7 @@ addHook({
|
|
|
1037
1060
|
/*
|
|
1038
1061
|
* This hook does three things:
|
|
1039
1062
|
* - Pass known tests to the workers.
|
|
1040
|
-
* - Pass
|
|
1063
|
+
* - Pass test management tests to the workers.
|
|
1041
1064
|
* - Receive trace, coverage and logs payloads from the workers.
|
|
1042
1065
|
*/
|
|
1043
1066
|
addHook({
|
|
@@ -1047,7 +1070,7 @@ addHook({
|
|
|
1047
1070
|
}, (childProcessWorker) => {
|
|
1048
1071
|
const ChildProcessWorker = childProcessWorker.default
|
|
1049
1072
|
shimmer.wrap(ChildProcessWorker.prototype, 'send', send => function (request) {
|
|
1050
|
-
if (!isKnownTestsEnabled && !
|
|
1073
|
+
if (!isKnownTestsEnabled && !isTestManagementTestsEnabled) {
|
|
1051
1074
|
return send.apply(this, arguments)
|
|
1052
1075
|
}
|
|
1053
1076
|
const [type] = request
|
|
@@ -1068,14 +1091,14 @@ addHook({
|
|
|
1068
1091
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, globalConfig.rootDir || process.cwd())
|
|
1069
1092
|
const suiteKnownTests = knownTests?.jest?.[testSuite] || []
|
|
1070
1093
|
|
|
1071
|
-
const
|
|
1094
|
+
const suiteTestManagementTests = testManagementTests.jest?.suites?.[testSuite]?.tests || {}
|
|
1072
1095
|
|
|
1073
1096
|
args[0].config = {
|
|
1074
1097
|
...config,
|
|
1075
1098
|
testEnvironmentOptions: {
|
|
1076
1099
|
...config.testEnvironmentOptions,
|
|
1077
1100
|
_ddKnownTests: suiteKnownTests,
|
|
1078
|
-
|
|
1101
|
+
_ddTestManagementTests: suiteTestManagementTests
|
|
1079
1102
|
}
|
|
1080
1103
|
}
|
|
1081
1104
|
}
|
|
@@ -61,17 +61,36 @@ for (const extension of extensions) {
|
|
|
61
61
|
return exports
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
addHook({ name: '@langchain/
|
|
65
|
-
|
|
64
|
+
addHook({ name: '@langchain/core', file: `dist/embeddings.${extension}`, versions: ['>=0.1'] }, exports => {
|
|
65
|
+
// we cannot patch the prototype of the Embeddings class directly
|
|
66
|
+
// this is because the "abstract class Embeddings" is transpiled from TypeScript to not include abstract functions
|
|
67
|
+
// thus, we patch the exported class directly instead instead.
|
|
68
|
+
|
|
69
|
+
shimmer.wrap(exports, 'Embeddings', Embeddings => {
|
|
70
|
+
return class extends Embeddings {
|
|
71
|
+
constructor (...args) {
|
|
72
|
+
super(...args)
|
|
73
|
+
|
|
74
|
+
const namespace = ['langchain', 'embeddings']
|
|
75
|
+
|
|
76
|
+
// when originally implemented, we only wrapped OpenAI embeddings
|
|
77
|
+
// these embeddings had the resource name of `langchain.embeddings.openai.OpenAIEmbeddings`
|
|
78
|
+
// we need to make sure `openai` is appended to the resource name until a new tracer major version
|
|
79
|
+
if (this.constructor.name === 'OpenAIEmbeddings') {
|
|
80
|
+
namespace.push('openai')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
shimmer.wrap(this, 'embedQuery', embedQuery => wrapLangChainPromise(embedQuery, 'embedding', namespace))
|
|
84
|
+
shimmer.wrap(this, 'embedDocuments',
|
|
85
|
+
embedDocuments => wrapLangChainPromise(embedDocuments, 'embedding', namespace))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static [Symbol.hasInstance] (instance) {
|
|
89
|
+
return instance instanceof Embeddings
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
})
|
|
66
93
|
|
|
67
|
-
// OpenAI (and Embeddings in general) do not define an lc_namespace
|
|
68
|
-
const namespace = ['langchain', 'embeddings', 'openai']
|
|
69
|
-
shimmer.wrap(OpenAIEmbeddings.prototype, 'embedDocuments', embedDocuments =>
|
|
70
|
-
wrapLangChainPromise(embedDocuments, 'embedding', namespace)
|
|
71
|
-
)
|
|
72
|
-
shimmer.wrap(OpenAIEmbeddings.prototype, 'embedQuery', embedQuery =>
|
|
73
|
-
wrapLangChainPromise(embedQuery, 'embedding', namespace)
|
|
74
|
-
)
|
|
75
94
|
return exports
|
|
76
95
|
})
|
|
77
96
|
}
|
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
|
|
18
18
|
const {
|
|
19
19
|
isNewTest,
|
|
20
|
+
getTestProperties,
|
|
20
21
|
getSuitesByTestFile,
|
|
21
22
|
runnableWrapper,
|
|
22
23
|
getOnTestHandler,
|
|
@@ -62,7 +63,7 @@ const testSuiteCodeCoverageCh = channel('ci:mocha:test-suite:code-coverage')
|
|
|
62
63
|
const libraryConfigurationCh = channel('ci:mocha:library-configuration')
|
|
63
64
|
const knownTestsCh = channel('ci:mocha:known-tests')
|
|
64
65
|
const skippableSuitesCh = channel('ci:mocha:test-suite:skippable')
|
|
65
|
-
const
|
|
66
|
+
const testManagementTestsCh = channel('ci:mocha:test-management-tests')
|
|
66
67
|
const workerReportTraceCh = channel('ci:mocha:worker-report:trace')
|
|
67
68
|
const testSessionStartCh = channel('ci:mocha:session:start')
|
|
68
69
|
const testSessionFinishCh = channel('ci:mocha:session:finish')
|
|
@@ -76,7 +77,7 @@ function isTestFailed (test) {
|
|
|
76
77
|
return test.isFailed()
|
|
77
78
|
}
|
|
78
79
|
if (test.isPending) {
|
|
79
|
-
return !test.isPending() && test.state
|
|
80
|
+
return !test.isPending() && test.state === 'failed'
|
|
80
81
|
}
|
|
81
82
|
return false
|
|
82
83
|
}
|
|
@@ -138,7 +139,7 @@ function getOnEndHandler (isParallel) {
|
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
// We subtract the errors from quarantined tests from the total number of failures
|
|
141
|
-
if (config.
|
|
142
|
+
if (config.isTestManagementTestsEnabled) {
|
|
142
143
|
let numFailedQuarantinedTests = 0
|
|
143
144
|
for (const test of testsQuarantined) {
|
|
144
145
|
if (isTestFailed(test)) {
|
|
@@ -179,7 +180,7 @@ function getOnEndHandler (isParallel) {
|
|
|
179
180
|
error,
|
|
180
181
|
isEarlyFlakeDetectionEnabled: config.isEarlyFlakeDetectionEnabled,
|
|
181
182
|
isEarlyFlakeDetectionFaulty: config.isEarlyFlakeDetectionFaulty,
|
|
182
|
-
|
|
183
|
+
isTestManagementEnabled: config.isTestManagementTestsEnabled,
|
|
183
184
|
isParallel
|
|
184
185
|
})
|
|
185
186
|
})
|
|
@@ -188,12 +189,12 @@ function getOnEndHandler (isParallel) {
|
|
|
188
189
|
function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
189
190
|
const mochaRunAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
190
191
|
|
|
191
|
-
const
|
|
192
|
+
const onReceivedTestManagementTests = ({ err, testManagementTests: receivedTestManagementTests }) => {
|
|
192
193
|
if (err) {
|
|
193
|
-
config.
|
|
194
|
-
config.
|
|
194
|
+
config.testManagementTests = {}
|
|
195
|
+
config.isTestManagementTestsEnabled = false
|
|
195
196
|
} else {
|
|
196
|
-
config.
|
|
197
|
+
config.testManagementTests = receivedTestManagementTests
|
|
197
198
|
}
|
|
198
199
|
if (config.isSuitesSkippingEnabled) {
|
|
199
200
|
skippableSuitesCh.publish({
|
|
@@ -236,9 +237,9 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
|
236
237
|
} else {
|
|
237
238
|
config.knownTests = knownTests
|
|
238
239
|
}
|
|
239
|
-
if (config.
|
|
240
|
-
|
|
241
|
-
onDone: mochaRunAsyncResource.bind(
|
|
240
|
+
if (config.isTestManagementTestsEnabled) {
|
|
241
|
+
testManagementTestsCh.publish({
|
|
242
|
+
onDone: mochaRunAsyncResource.bind(onReceivedTestManagementTests)
|
|
242
243
|
})
|
|
243
244
|
} else if (config.isSuitesSkippingEnabled) {
|
|
244
245
|
skippableSuitesCh.publish({
|
|
@@ -258,19 +259,19 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
|
258
259
|
config.earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
259
260
|
config.earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
260
261
|
config.isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
261
|
-
|
|
262
|
+
config.isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
|
|
263
|
+
// ITR and auto test retries are not supported in parallel mode yet
|
|
262
264
|
config.isSuitesSkippingEnabled = !isParallel && libraryConfig.isSuitesSkippingEnabled
|
|
263
265
|
config.isFlakyTestRetriesEnabled = !isParallel && libraryConfig.isFlakyTestRetriesEnabled
|
|
264
266
|
config.flakyTestRetriesCount = !isParallel && libraryConfig.flakyTestRetriesCount
|
|
265
|
-
config.isQuarantinedTestsEnabled = !isParallel && libraryConfig.isQuarantinedTestsEnabled
|
|
266
267
|
|
|
267
268
|
if (config.isKnownTestsEnabled) {
|
|
268
269
|
knownTestsCh.publish({
|
|
269
270
|
onDone: mochaRunAsyncResource.bind(onReceivedKnownTests)
|
|
270
271
|
})
|
|
271
|
-
} else if (config.
|
|
272
|
-
|
|
273
|
-
onDone: mochaRunAsyncResource.bind(
|
|
272
|
+
} else if (config.isTestManagementTestsEnabled) {
|
|
273
|
+
testManagementTestsCh.publish({
|
|
274
|
+
onDone: mochaRunAsyncResource.bind(onReceivedTestManagementTests)
|
|
274
275
|
})
|
|
275
276
|
} else if (config.isSuitesSkippingEnabled) {
|
|
276
277
|
skippableSuitesCh.publish({
|
|
@@ -282,7 +283,8 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
|
282
283
|
}
|
|
283
284
|
|
|
284
285
|
libraryConfigurationCh.publish({
|
|
285
|
-
onDone: mochaRunAsyncResource.bind(onReceivedConfiguration)
|
|
286
|
+
onDone: mochaRunAsyncResource.bind(onReceivedConfiguration),
|
|
287
|
+
isParallel
|
|
286
288
|
})
|
|
287
289
|
}
|
|
288
290
|
|
|
@@ -613,41 +615,54 @@ addHook({
|
|
|
613
615
|
const { BufferedWorkerPool } = BufferedWorkerPoolPackage
|
|
614
616
|
|
|
615
617
|
shimmer.wrap(BufferedWorkerPool.prototype, 'run', run => async function (testSuiteAbsolutePath, workerArgs) {
|
|
616
|
-
if (!testStartCh.hasSubscribers || !config.isKnownTestsEnabled) {
|
|
618
|
+
if (!testStartCh.hasSubscribers || (!config.isKnownTestsEnabled && !config.isTestManagementTestsEnabled)) {
|
|
617
619
|
return run.apply(this, arguments)
|
|
618
620
|
}
|
|
619
621
|
|
|
620
622
|
const testPath = getTestSuitePath(testSuiteAbsolutePath, process.cwd())
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
+
|
|
624
|
+
const newWorkerArgs = { ...workerArgs }
|
|
625
|
+
|
|
626
|
+
if (config.isKnownTestsEnabled) {
|
|
627
|
+
const testSuiteKnownTests = config.knownTests.mocha?.[testPath] || []
|
|
628
|
+
newWorkerArgs._ddEfdNumRetries = config.earlyFlakeDetectionNumRetries
|
|
629
|
+
newWorkerArgs._ddIsEfdEnabled = config.isEarlyFlakeDetectionEnabled
|
|
630
|
+
newWorkerArgs._ddIsKnownTestsEnabled = true
|
|
631
|
+
newWorkerArgs._ddKnownTests = {
|
|
632
|
+
mocha: {
|
|
633
|
+
[testPath]: testSuiteKnownTests
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (config.isTestManagementTestsEnabled) {
|
|
638
|
+
const testSuiteTestManagementTests = config.testManagementTests?.mocha?.suites?.[testPath] || {}
|
|
639
|
+
newWorkerArgs._ddIsTestManagementTestsEnabled = true
|
|
640
|
+
newWorkerArgs._ddTestManagementTests = {
|
|
641
|
+
mocha: {
|
|
642
|
+
suites: {
|
|
643
|
+
[testPath]: testSuiteTestManagementTests
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
623
648
|
|
|
624
649
|
// We pass the known tests for the test file to the worker
|
|
625
650
|
const testFileResult = await run.apply(
|
|
626
651
|
this,
|
|
627
652
|
[
|
|
628
653
|
testSuiteAbsolutePath,
|
|
629
|
-
|
|
630
|
-
...workerArgs,
|
|
631
|
-
_ddEfdNumRetries: config.earlyFlakeDetectionNumRetries,
|
|
632
|
-
_ddIsEfdEnabled: config.isEarlyFlakeDetectionEnabled,
|
|
633
|
-
_ddIsQuarantinedEnabled: config.isQuarantinedTestsEnabled,
|
|
634
|
-
_ddQuarantinedTests: testSuiteQuarantinedTests,
|
|
635
|
-
_ddKnownTests: {
|
|
636
|
-
mocha: {
|
|
637
|
-
[testPath]: testSuiteKnownTests
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
654
|
+
newWorkerArgs
|
|
641
655
|
]
|
|
642
656
|
)
|
|
657
|
+
|
|
643
658
|
const tests = testFileResult
|
|
644
659
|
.events
|
|
645
660
|
.filter(event => event.eventName === 'test end')
|
|
646
661
|
.map(event => event.data)
|
|
647
662
|
|
|
648
|
-
// `newTests` is filled in the worker process, so we need to use the test results to fill it here too.
|
|
649
663
|
for (const test of tests) {
|
|
650
|
-
|
|
664
|
+
// `newTests` is filled in the worker process, so we need to use the test results to fill it here too.
|
|
665
|
+
if (config.isKnownTestsEnabled && isNewTest(test, config.knownTests)) {
|
|
651
666
|
const testFullName = getTestFullName(test)
|
|
652
667
|
const tests = newTests[testFullName]
|
|
653
668
|
|
|
@@ -657,6 +672,10 @@ addHook({
|
|
|
657
672
|
tests.push(test)
|
|
658
673
|
}
|
|
659
674
|
}
|
|
675
|
+
// `testsQuarantined` is filled in the worker process, so we need to use the test results to fill it here too.
|
|
676
|
+
if (config.isTestManagementTestsEnabled && getTestProperties(test, config.testManagementTests).isQuarantined) {
|
|
677
|
+
testsQuarantined.add(test)
|
|
678
|
+
}
|
|
660
679
|
}
|
|
661
680
|
return testFileResult
|
|
662
681
|
})
|
|
@@ -28,24 +28,26 @@ const wrappedFunctions = new WeakSet()
|
|
|
28
28
|
const newTests = {}
|
|
29
29
|
const testsQuarantined = new Set()
|
|
30
30
|
|
|
31
|
-
function
|
|
31
|
+
function getAfterEachHooks (testOrHook) {
|
|
32
|
+
const hooks = []
|
|
33
|
+
|
|
34
|
+
while (testOrHook.parent) {
|
|
35
|
+
if (testOrHook.parent._afterEach) {
|
|
36
|
+
hooks.push(...testOrHook.parent._afterEach)
|
|
37
|
+
}
|
|
38
|
+
testOrHook = testOrHook.parent
|
|
39
|
+
}
|
|
40
|
+
return hooks
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getTestProperties (test, testManagementTests) {
|
|
32
44
|
const testSuite = getTestSuitePath(test.file, process.cwd())
|
|
33
45
|
const testName = test.fullTitle()
|
|
34
46
|
|
|
35
|
-
const isQuarantined =
|
|
36
|
-
|
|
37
|
-
?.suites
|
|
38
|
-
?.[testSuite]
|
|
39
|
-
?.tests
|
|
40
|
-
?.[testName]
|
|
41
|
-
?.properties
|
|
42
|
-
?.quarantined) ?? false
|
|
43
|
-
|
|
44
|
-
if (isQuarantined) {
|
|
45
|
-
testsQuarantined.add(test)
|
|
46
|
-
}
|
|
47
|
+
const { disabled: isDisabled, quarantined: isQuarantined } =
|
|
48
|
+
testManagementTests?.mocha?.suites?.[testSuite]?.tests?.[testName]?.properties || {}
|
|
47
49
|
|
|
48
|
-
return isQuarantined
|
|
50
|
+
return { isDisabled, isQuarantined }
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
function isNewTest (test, knownTests) {
|
|
@@ -193,6 +195,7 @@ function getOnTestHandler (isMain) {
|
|
|
193
195
|
title,
|
|
194
196
|
_ddIsNew: isNew,
|
|
195
197
|
_ddIsEfdRetry: isEfdRetry,
|
|
198
|
+
_ddIsDisabled: isDisabled,
|
|
196
199
|
_ddIsQuarantined: isQuarantined
|
|
197
200
|
} = test
|
|
198
201
|
|
|
@@ -209,6 +212,7 @@ function getOnTestHandler (isMain) {
|
|
|
209
212
|
|
|
210
213
|
testInfo.isNew = isNew
|
|
211
214
|
testInfo.isEfdRetry = isEfdRetry
|
|
215
|
+
testInfo.isDisabled = isDisabled
|
|
212
216
|
testInfo.isQuarantined = isQuarantined
|
|
213
217
|
// We want to store the result of the new tests
|
|
214
218
|
if (isNew) {
|
|
@@ -220,6 +224,10 @@ function getOnTestHandler (isMain) {
|
|
|
220
224
|
}
|
|
221
225
|
}
|
|
222
226
|
|
|
227
|
+
if (isDisabled) {
|
|
228
|
+
test.pending = true
|
|
229
|
+
}
|
|
230
|
+
|
|
223
231
|
asyncResource.runInAsyncScope(() => {
|
|
224
232
|
testStartCh.publish(testInfo)
|
|
225
233
|
})
|
|
@@ -242,7 +250,7 @@ function getOnTestEndHandler () {
|
|
|
242
250
|
}
|
|
243
251
|
|
|
244
252
|
// if there are afterEach to be run, we don't finish the test yet
|
|
245
|
-
if (asyncResource && !test.
|
|
253
|
+
if (asyncResource && !getAfterEachHooks(test).length) {
|
|
246
254
|
asyncResource.runInAsyncScope(() => {
|
|
247
255
|
testFinishCh.publish({
|
|
248
256
|
status,
|
|
@@ -257,18 +265,15 @@ function getOnTestEndHandler () {
|
|
|
257
265
|
function getOnHookEndHandler () {
|
|
258
266
|
return function (hook) {
|
|
259
267
|
const test = hook.ctx.currentTest
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
return
|
|
264
|
-
}
|
|
265
|
-
const isLastAfterEach = hook.parent._afterEach.indexOf(hook) === hook.parent._afterEach.length - 1
|
|
268
|
+
const afterEachHooks = getAfterEachHooks(hook)
|
|
269
|
+
if (test && afterEachHooks.includes(hook)) { // only if it's an afterEach
|
|
270
|
+
const isLastAfterEach = afterEachHooks.indexOf(hook) === afterEachHooks.length - 1
|
|
266
271
|
if (isLastAfterEach) {
|
|
267
272
|
const status = getTestStatus(test)
|
|
268
273
|
const asyncResource = getTestAsyncResource(test)
|
|
269
274
|
if (asyncResource) {
|
|
270
275
|
asyncResource.runInAsyncScope(() => {
|
|
271
|
-
testFinishCh.publish({ status, hasBeenRetried: isMochaRetry(test), isLastRetry })
|
|
276
|
+
testFinishCh.publish({ status, hasBeenRetried: isMochaRetry(test), isLastRetry: getIsLastRetry(test) })
|
|
272
277
|
})
|
|
273
278
|
}
|
|
274
279
|
}
|
|
@@ -384,9 +389,13 @@ function getRunTestsWrapper (runTests, config) {
|
|
|
384
389
|
})
|
|
385
390
|
}
|
|
386
391
|
|
|
387
|
-
if (config.
|
|
392
|
+
if (config.isTestManagementTestsEnabled) {
|
|
388
393
|
suite.tests.forEach(test => {
|
|
389
|
-
|
|
394
|
+
const { isDisabled, isQuarantined } = getTestProperties(test, config.testManagementTests)
|
|
395
|
+
if (isDisabled) {
|
|
396
|
+
test._ddIsDisabled = true
|
|
397
|
+
} else if (isQuarantined) {
|
|
398
|
+
testsQuarantined.add(test)
|
|
390
399
|
test._ddIsQuarantined = true
|
|
391
400
|
}
|
|
392
401
|
})
|
|
@@ -398,6 +407,7 @@ function getRunTestsWrapper (runTests, config) {
|
|
|
398
407
|
|
|
399
408
|
module.exports = {
|
|
400
409
|
isNewTest,
|
|
410
|
+
getTestProperties,
|
|
401
411
|
retryTest,
|
|
402
412
|
getSuitesByTestFile,
|
|
403
413
|
isMochaRetry,
|
|
@@ -24,8 +24,7 @@ addHook({
|
|
|
24
24
|
file: 'lib/mocha.js'
|
|
25
25
|
}, (Mocha) => {
|
|
26
26
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
27
|
-
if (this.options.
|
|
28
|
-
// If there are known tests, it means isKnownTestsEnabled should be true
|
|
27
|
+
if (this.options._ddIsKnownTestsEnabled) {
|
|
29
28
|
config.isKnownTestsEnabled = true
|
|
30
29
|
config.isEarlyFlakeDetectionEnabled = this.options._ddIsEfdEnabled
|
|
31
30
|
config.knownTests = this.options._ddKnownTests
|
|
@@ -33,13 +32,13 @@ addHook({
|
|
|
33
32
|
delete this.options._ddIsEfdEnabled
|
|
34
33
|
delete this.options._ddKnownTests
|
|
35
34
|
delete this.options._ddEfdNumRetries
|
|
36
|
-
delete this.options.
|
|
35
|
+
delete this.options._ddIsKnownTestsEnabled
|
|
37
36
|
}
|
|
38
|
-
if (this.options.
|
|
39
|
-
config.
|
|
40
|
-
config.
|
|
41
|
-
delete this.options.
|
|
42
|
-
delete this.options.
|
|
37
|
+
if (this.options._ddIsTestManagementTestsEnabled) {
|
|
38
|
+
config.isTestManagementTestsEnabled = true
|
|
39
|
+
config.testManagementTests = this.options._ddTestManagementTests
|
|
40
|
+
delete this.options._ddIsTestManagementTestsEnabled
|
|
41
|
+
delete this.options._ddTestManagementTests
|
|
43
42
|
}
|
|
44
43
|
return run.apply(this, arguments)
|
|
45
44
|
})
|