dd-trace 5.90.0 → 5.92.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/index.d.ts +7 -0
- package/package.json +8 -7
- package/packages/datadog-instrumentations/src/child_process.js +14 -8
- package/packages/datadog-instrumentations/src/cucumber.js +18 -3
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +30 -0
- package/packages/datadog-instrumentations/src/jest.js +9 -2
- package/packages/datadog-instrumentations/src/langgraph.js +7 -0
- package/packages/datadog-instrumentations/src/mocha/main.js +32 -9
- package/packages/datadog-instrumentations/src/mocha/utils.js +0 -1
- package/packages/datadog-instrumentations/src/mocha/worker.js +2 -2
- package/packages/datadog-instrumentations/src/vitest.js +53 -24
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +1 -1
- package/packages/datadog-plugin-cypress/src/support.js +5 -7
- package/packages/datadog-plugin-graphql/src/execute.js +2 -2
- package/packages/datadog-plugin-graphql/src/resolve.js +22 -35
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-langgraph/src/index.js +24 -0
- package/packages/datadog-plugin-langgraph/src/stream.js +41 -0
- package/packages/dd-trace/src/config/defaults.js +3 -0
- package/packages/dd-trace/src/config/index.js +14 -1
- package/packages/dd-trace/src/config/supported-configurations.json +7 -0
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -0
- package/packages/dd-trace/src/dogstatsd.js +1 -0
- package/packages/dd-trace/src/encode/agentless-json.js +4 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +11 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +114 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -2
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/test.js +7 -10
- package/packages/dd-trace/src/priority_sampler.js +20 -2
- package/packages/dd-trace/src/process-tags/index.js +41 -34
- package/packages/dd-trace/src/profiling/profilers/wall.js +9 -1
- package/packages/dd-trace/src/proxy.js +4 -0
- package/packages/dd-trace/src/telemetry/send-data.js +5 -0
- package/packages/dd-trace/src/telemetry/session-propagation.js +78 -0
- package/packages/dd-trace/src/telemetry/telemetry.js +3 -0
package/index.d.ts
CHANGED
|
@@ -262,6 +262,7 @@ interface Plugins {
|
|
|
262
262
|
"knex": tracer.plugins.knex;
|
|
263
263
|
"koa": tracer.plugins.koa;
|
|
264
264
|
"langchain": tracer.plugins.langchain;
|
|
265
|
+
"langgraph": tracer.plugins.langgraph;
|
|
265
266
|
"mariadb": tracer.plugins.mariadb;
|
|
266
267
|
"memcached": tracer.plugins.memcached;
|
|
267
268
|
"microgateway-core": tracer.plugins.microgateway_core;
|
|
@@ -2579,6 +2580,12 @@ declare namespace tracer {
|
|
|
2579
2580
|
|
|
2580
2581
|
/**
|
|
2581
2582
|
* This plugin automatically instruments the
|
|
2583
|
+
* [langgraph](https://github.com/npmjs/package/langgraph) library.
|
|
2584
|
+
*/
|
|
2585
|
+
interface langgraph extends Instrumentation {}
|
|
2586
|
+
|
|
2587
|
+
/**
|
|
2588
|
+
* This plugin automatically instruments the
|
|
2582
2589
|
* [ldapjs](https://github.com/ldapjs/node-ldapjs/) module.
|
|
2583
2590
|
*/
|
|
2584
2591
|
interface ldapjs extends Instrumentation {}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.92.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"env": "bash ./plugin-env",
|
|
9
|
+
"prepare": "cd vendor && npm ci --include=dev",
|
|
9
10
|
"preinstall": "node scripts/preinstall.js",
|
|
10
11
|
"bench": "node benchmark/index.js",
|
|
11
12
|
"bench:e2e:test-optimization": "node benchmark/e2e-test-optimization/benchmark-run.js",
|
|
@@ -142,17 +143,17 @@
|
|
|
142
143
|
"@datadog/native-iast-taint-tracking": "4.1.0",
|
|
143
144
|
"@datadog/native-metrics": "3.1.1",
|
|
144
145
|
"@datadog/openfeature-node-server": "^1.1.0",
|
|
145
|
-
"@datadog/pprof": "5.
|
|
146
|
+
"@datadog/pprof": "5.14.0",
|
|
146
147
|
"@datadog/wasm-js-rewriter": "5.0.1",
|
|
147
148
|
"@opentelemetry/api": ">=1.0.0 <1.10.0",
|
|
148
149
|
"@opentelemetry/api-logs": "<1.0.0",
|
|
149
|
-
"oxc-parser": "^0.
|
|
150
|
+
"oxc-parser": "^0.118.0"
|
|
150
151
|
},
|
|
151
152
|
"devDependencies": {
|
|
152
153
|
"@actions/core": "^3.0.0",
|
|
153
154
|
"@actions/github": "^9.0.0",
|
|
154
155
|
"@babel/helpers": "^7.28.6",
|
|
155
|
-
"@eslint/eslintrc": "^3.3.
|
|
156
|
+
"@eslint/eslintrc": "^3.3.5",
|
|
156
157
|
"@eslint/js": "^9.39.2",
|
|
157
158
|
"@msgpack/msgpack": "^3.1.3",
|
|
158
159
|
"@openfeature/core": "^1.8.1",
|
|
@@ -165,11 +166,11 @@
|
|
|
165
166
|
"benchmark": "^2.1.4",
|
|
166
167
|
"body-parser": "^2.2.2",
|
|
167
168
|
"bun": "1.3.10",
|
|
168
|
-
"codeowners-audit": "^2.
|
|
169
|
+
"codeowners-audit": "^2.9.0",
|
|
169
170
|
"eslint": "^9.39.2",
|
|
170
|
-
"eslint-plugin-cypress": "^6.
|
|
171
|
+
"eslint-plugin-cypress": "^6.2.0",
|
|
171
172
|
"eslint-plugin-import": "^2.32.0",
|
|
172
|
-
"eslint-plugin-jsdoc": "^62.
|
|
173
|
+
"eslint-plugin-jsdoc": "^62.8.0",
|
|
173
174
|
"eslint-plugin-mocha": "^11.2.0",
|
|
174
175
|
"eslint-plugin-n": "^17.23.2",
|
|
175
176
|
"eslint-plugin-promise": "^7.2.1",
|
|
@@ -12,7 +12,7 @@ const {
|
|
|
12
12
|
const childProcessChannel = dc.tracingChannel('datadog:child_process:execution')
|
|
13
13
|
|
|
14
14
|
// ignored exec method because it calls to execFile directly
|
|
15
|
-
const execAsyncMethods = ['execFile', 'spawn']
|
|
15
|
+
const execAsyncMethods = ['execFile', 'spawn', 'fork']
|
|
16
16
|
|
|
17
17
|
const names = ['child_process', 'node:child_process']
|
|
18
18
|
|
|
@@ -97,8 +97,10 @@ function wrapChildProcessSyncMethod (returnError, shell = false) {
|
|
|
97
97
|
return childProcessMethod.apply(this, arguments)
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
const
|
|
100
|
+
const callArgs = [...arguments]
|
|
101
|
+
const childProcessInfo = normalizeArgs(callArgs, shell)
|
|
101
102
|
const context = createContextFromChildProcessInfo(childProcessInfo)
|
|
103
|
+
context.callArgs = callArgs
|
|
102
104
|
|
|
103
105
|
return childProcessChannel.start.runStores(context, () => {
|
|
104
106
|
try {
|
|
@@ -108,7 +110,7 @@ function wrapChildProcessSyncMethod (returnError, shell = false) {
|
|
|
108
110
|
return returnError(error, context)
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
const result = childProcessMethod.apply(this,
|
|
113
|
+
const result = childProcessMethod.apply(this, context.callArgs)
|
|
112
114
|
context.result = result
|
|
113
115
|
|
|
114
116
|
return result
|
|
@@ -131,9 +133,11 @@ function wrapChildProcessCustomPromisifyMethod (customPromisifyMethod, shell) {
|
|
|
131
133
|
return customPromisifyMethod.apply(this, arguments)
|
|
132
134
|
}
|
|
133
135
|
|
|
134
|
-
const
|
|
136
|
+
const callArgs = [...arguments]
|
|
137
|
+
const childProcessInfo = normalizeArgs(callArgs, shell)
|
|
135
138
|
|
|
136
139
|
const context = createContextFromChildProcessInfo(childProcessInfo)
|
|
140
|
+
context.callArgs = callArgs
|
|
137
141
|
|
|
138
142
|
const { start, end, asyncStart, asyncEnd, error } = childProcessChannel
|
|
139
143
|
start.publish(context)
|
|
@@ -143,7 +147,7 @@ function wrapChildProcessCustomPromisifyMethod (customPromisifyMethod, shell) {
|
|
|
143
147
|
result = Promise.reject(context.abortController.signal.reason || new Error('Aborted'))
|
|
144
148
|
} else {
|
|
145
149
|
try {
|
|
146
|
-
result = customPromisifyMethod.apply(this,
|
|
150
|
+
result = customPromisifyMethod.apply(this, context.callArgs)
|
|
147
151
|
} catch (error) {
|
|
148
152
|
context.error = error
|
|
149
153
|
error.publish(context)
|
|
@@ -181,9 +185,11 @@ function wrapChildProcessAsyncMethod (ChildProcess, shell = false) {
|
|
|
181
185
|
return childProcessMethod.apply(this, arguments)
|
|
182
186
|
}
|
|
183
187
|
|
|
184
|
-
const
|
|
188
|
+
const callArgs = [...arguments]
|
|
189
|
+
const childProcessInfo = normalizeArgs(callArgs, shell)
|
|
185
190
|
|
|
186
191
|
const context = createContextFromChildProcessInfo(childProcessInfo)
|
|
192
|
+
context.callArgs = callArgs
|
|
187
193
|
return childProcessChannel.start.runStores(context, () => {
|
|
188
194
|
let childProcess
|
|
189
195
|
if (context.abortController.signal.aborted) {
|
|
@@ -194,7 +200,7 @@ function wrapChildProcessAsyncMethod (ChildProcess, shell = false) {
|
|
|
194
200
|
const error = context.abortController.signal.reason || new Error('Aborted')
|
|
195
201
|
childProcess.emit('error', error)
|
|
196
202
|
|
|
197
|
-
const cb =
|
|
203
|
+
const cb = context.callArgs[context.callArgs.length - 1]
|
|
198
204
|
if (typeof cb === 'function') {
|
|
199
205
|
cb(error)
|
|
200
206
|
}
|
|
@@ -202,7 +208,7 @@ function wrapChildProcessAsyncMethod (ChildProcess, shell = false) {
|
|
|
202
208
|
childProcess.emit('close')
|
|
203
209
|
})
|
|
204
210
|
} else {
|
|
205
|
-
childProcess = childProcessMethod.apply(this,
|
|
211
|
+
childProcess = childProcessMethod.apply(this, context.callArgs)
|
|
206
212
|
}
|
|
207
213
|
|
|
208
214
|
if (childProcess) {
|
|
@@ -166,9 +166,9 @@ function getErrorFromCucumberResult (cucumberResult) {
|
|
|
166
166
|
return error
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
function getChannelPromise (channelToPublishTo,
|
|
169
|
+
function getChannelPromise (channelToPublishTo, frameworkVersion = null) {
|
|
170
170
|
return new Promise(resolve => {
|
|
171
|
-
channelToPublishTo.publish({ onDone: resolve,
|
|
171
|
+
channelToPublishTo.publish({ onDone: resolve, frameworkVersion })
|
|
172
172
|
})
|
|
173
173
|
}
|
|
174
174
|
|
|
@@ -505,7 +505,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
505
505
|
}
|
|
506
506
|
let errorSkippableRequest
|
|
507
507
|
|
|
508
|
-
const configurationResponse = await getChannelPromise(libraryConfigurationCh,
|
|
508
|
+
const configurationResponse = await getChannelPromise(libraryConfigurationCh, frameworkVersion)
|
|
509
509
|
|
|
510
510
|
isEarlyFlakeDetectionEnabled = configurationResponse.libraryConfig?.isEarlyFlakeDetectionEnabled
|
|
511
511
|
earlyFlakeDetectionNumRetries = configurationResponse.libraryConfig?.earlyFlakeDetectionNumRetries
|
|
@@ -681,6 +681,7 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
681
681
|
let isQuarantined = false
|
|
682
682
|
let isModified = false
|
|
683
683
|
|
|
684
|
+
const originalDryRun = this.options.dryRun
|
|
684
685
|
if (isTestManagementTestsEnabled) {
|
|
685
686
|
const testProperties = getTestProperties(testSuitePath, pickle.name)
|
|
686
687
|
isAttemptToFix = testProperties.attemptToFix
|
|
@@ -719,6 +720,9 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
719
720
|
// TODO: for >=11 we could use `runTestCaseResult` instead of accumulating results in `lastStatusByPickleId`
|
|
720
721
|
let runTestCaseResult = await runTestCaseFunction.apply(this, arguments)
|
|
721
722
|
|
|
723
|
+
// Restore dryRun so it doesn't affect subsequent tests in the same worker
|
|
724
|
+
this.options.dryRun = originalDryRun
|
|
725
|
+
|
|
722
726
|
const testStatuses = lastStatusByPickleId.get(pickle.id)
|
|
723
727
|
const lastTestStatus = testStatuses.at(-1)
|
|
724
728
|
|
|
@@ -1053,6 +1057,12 @@ addHook({
|
|
|
1053
1057
|
this.options.worldParameters._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
1054
1058
|
this.options.worldParameters._ddNumTestRetries = numTestRetries
|
|
1055
1059
|
|
|
1060
|
+
if (isTestManagementTestsEnabled) {
|
|
1061
|
+
this.options.worldParameters._ddIsTestManagementTestsEnabled = true
|
|
1062
|
+
this.options.worldParameters._ddTestManagementTests = testManagementTests
|
|
1063
|
+
this.options.worldParameters._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1056
1066
|
return startWorker.apply(this, arguments)
|
|
1057
1067
|
})
|
|
1058
1068
|
return adapterPackage
|
|
@@ -1090,6 +1100,11 @@ addHook({
|
|
|
1090
1100
|
}
|
|
1091
1101
|
isFlakyTestRetriesEnabled = !!this.options.worldParameters._ddIsFlakyTestRetriesEnabled
|
|
1092
1102
|
numTestRetries = this.options.worldParameters._ddNumTestRetries ?? 0
|
|
1103
|
+
isTestManagementTestsEnabled = !!this.options.worldParameters._ddIsTestManagementTestsEnabled
|
|
1104
|
+
if (isTestManagementTestsEnabled) {
|
|
1105
|
+
testManagementTests = this.options.worldParameters._ddTestManagementTests
|
|
1106
|
+
testManagementAttemptToFixRetries = this.options.worldParameters._ddTestManagementAttemptToFixRetries
|
|
1107
|
+
}
|
|
1093
1108
|
}
|
|
1094
1109
|
)
|
|
1095
1110
|
return workerPackage
|
|
@@ -277,7 +277,7 @@ function assertField (rootCtx, info, args) {
|
|
|
277
277
|
let field = fields[pathString]
|
|
278
278
|
|
|
279
279
|
if (!field) {
|
|
280
|
-
const fieldCtx = { info, rootCtx, args }
|
|
280
|
+
const fieldCtx = { info, rootCtx, args, path, pathString }
|
|
281
281
|
startResolveCh.publish(fieldCtx)
|
|
282
282
|
field = fields[pathString] = {
|
|
283
283
|
error: null,
|
|
@@ -4,6 +4,7 @@ module.exports = {
|
|
|
4
4
|
'@anthropic-ai/sdk': { esmFirst: true, fn: () => require('../anthropic') },
|
|
5
5
|
'@apollo/server': () => require('../apollo-server'),
|
|
6
6
|
'@apollo/gateway': () => require('../apollo'),
|
|
7
|
+
'@langchain/langgraph': { esmFirst: true, fn: () => require('../langgraph') },
|
|
7
8
|
'apollo-server-core': () => require('../apollo-server-core'),
|
|
8
9
|
'@aws-sdk/smithy-client': () => require('../aws-sdk'),
|
|
9
10
|
'@azure/event-hubs': () => require('../azure-event-hubs'),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = [
|
|
4
|
+
{
|
|
5
|
+
module: {
|
|
6
|
+
name: '@langchain/langgraph',
|
|
7
|
+
versionRange: '>=1.1.2',
|
|
8
|
+
filePath: 'dist/pregel/index.js',
|
|
9
|
+
},
|
|
10
|
+
functionQuery: {
|
|
11
|
+
methodName: 'stream',
|
|
12
|
+
className: 'Pregel',
|
|
13
|
+
kind: 'AsyncIterator',
|
|
14
|
+
},
|
|
15
|
+
channelName: 'Pregel_stream',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
module: {
|
|
19
|
+
name: '@langchain/langgraph',
|
|
20
|
+
versionRange: '>=1.1.2',
|
|
21
|
+
filePath: 'dist/pregel/index.cjs',
|
|
22
|
+
},
|
|
23
|
+
functionQuery: {
|
|
24
|
+
methodName: 'stream',
|
|
25
|
+
className: 'Pregel',
|
|
26
|
+
kind: 'AsyncIterator',
|
|
27
|
+
},
|
|
28
|
+
channelName: 'Pregel_stream',
|
|
29
|
+
},
|
|
30
|
+
]
|
|
@@ -702,11 +702,15 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
702
702
|
const mightHitBreakpoint = this.isDiEnabled && numTestExecutions >= 2
|
|
703
703
|
|
|
704
704
|
const ctx = testContexts.get(event.test)
|
|
705
|
+
if (!ctx) {
|
|
706
|
+
log.warn('"ci:jest:test_done": no context found for test "%s"', testName)
|
|
707
|
+
return
|
|
708
|
+
}
|
|
705
709
|
|
|
706
710
|
const finalStatus = this.getFinalStatus(testName,
|
|
707
711
|
status,
|
|
708
|
-
!!ctx
|
|
709
|
-
!!ctx
|
|
712
|
+
!!ctx.isNew,
|
|
713
|
+
!!ctx.isModified,
|
|
710
714
|
isEfdRetry,
|
|
711
715
|
isAttemptToFix,
|
|
712
716
|
numTestExecutions)
|
|
@@ -761,6 +765,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
761
765
|
efdDeterminedRetries.clear()
|
|
762
766
|
efdSlowAbortedTests.clear()
|
|
763
767
|
efdNewTestCandidates.clear()
|
|
768
|
+
retriedTestsToNumAttempts.clear()
|
|
769
|
+
attemptToFixRetriedTestsStatuses.clear()
|
|
770
|
+
testsToBeRetried.clear()
|
|
764
771
|
}
|
|
765
772
|
if (event.name === 'test_skip' || event.name === 'test_todo') {
|
|
766
773
|
const testName = getJestTestName(event.test, this.getShouldStripSeedFromTestName())
|
|
@@ -101,12 +101,12 @@ function getFilteredSuites (originalSuites) {
|
|
|
101
101
|
}, { suitesToRun: [], skippedSuites: new Set() })
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
function getOnStartHandler (
|
|
104
|
+
function getOnStartHandler (frameworkVersion) {
|
|
105
105
|
return function () {
|
|
106
106
|
const processArgv = process.argv.slice(2).join(' ')
|
|
107
107
|
const command = `mocha ${processArgv}`
|
|
108
108
|
testSessionStartCh.publish({ command, frameworkVersion })
|
|
109
|
-
if (
|
|
109
|
+
if (skippedSuites.length) {
|
|
110
110
|
itrSkippedSuitesCh.publish({ skippedSuites, frameworkVersion })
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -315,8 +315,7 @@ function getExecutionConfiguration (runner, isParallel, frameworkVersion, onFini
|
|
|
315
315
|
config.isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
|
|
316
316
|
config.testManagementAttemptToFixRetries = libraryConfig.testManagementAttemptToFixRetries
|
|
317
317
|
config.isImpactedTestsEnabled = libraryConfig.isImpactedTestsEnabled
|
|
318
|
-
|
|
319
|
-
config.isSuitesSkippingEnabled = !isParallel && libraryConfig.isSuitesSkippingEnabled
|
|
318
|
+
config.isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
320
319
|
config.isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
|
|
321
320
|
config.flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
|
|
322
321
|
|
|
@@ -452,7 +451,7 @@ addHook({
|
|
|
452
451
|
|
|
453
452
|
const { suitesByTestFile, numSuitesByTestFile } = getSuitesByTestFile(this.suite)
|
|
454
453
|
|
|
455
|
-
this.once('start', getOnStartHandler(
|
|
454
|
+
this.once('start', getOnStartHandler(frameworkVersion))
|
|
456
455
|
|
|
457
456
|
this.once('end', getOnEndHandler(false))
|
|
458
457
|
|
|
@@ -623,9 +622,16 @@ addHook({
|
|
|
623
622
|
return run.apply(this, arguments)
|
|
624
623
|
}
|
|
625
624
|
|
|
626
|
-
this.once('start', getOnStartHandler(
|
|
625
|
+
this.once('start', getOnStartHandler(frameworkVersion))
|
|
627
626
|
this.once('end', getOnEndHandler(true))
|
|
628
627
|
|
|
628
|
+
// Populate unskippable suites before config is fetched (matches serial mode at Mocha.prototype.run)
|
|
629
|
+
for (const filePath of files) {
|
|
630
|
+
if (isMarkedAsUnskippable({ path: filePath })) {
|
|
631
|
+
unskippableSuites.push(filePath)
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
629
635
|
getExecutionConfiguration(this, true, frameworkVersion, () => {
|
|
630
636
|
if (config.isKnownTestsEnabled) {
|
|
631
637
|
const testSuites = files.map(file => getTestSuitePath(file, process.cwd()))
|
|
@@ -640,7 +646,25 @@ addHook({
|
|
|
640
646
|
config.isEarlyFlakeDetectionFaulty = true
|
|
641
647
|
}
|
|
642
648
|
}
|
|
643
|
-
|
|
649
|
+
if (config.isSuitesSkippingEnabled && suitesToSkip.length) {
|
|
650
|
+
const filteredFiles = []
|
|
651
|
+
const skippedFiles = []
|
|
652
|
+
for (const file of files) {
|
|
653
|
+
const testPath = getTestSuitePath(file, process.cwd())
|
|
654
|
+
const shouldSkip = suitesToSkip.includes(testPath)
|
|
655
|
+
const isUnskippable = unskippableSuites.includes(file)
|
|
656
|
+
if (shouldSkip && !isUnskippable) {
|
|
657
|
+
skippedFiles.push(testPath)
|
|
658
|
+
} else {
|
|
659
|
+
filteredFiles.push(file)
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
isSuitesSkipped = skippedFiles.length > 0
|
|
663
|
+
skippedSuites = skippedFiles
|
|
664
|
+
run.apply(this, [cb, { files: filteredFiles }])
|
|
665
|
+
} else {
|
|
666
|
+
run.apply(this, arguments)
|
|
667
|
+
}
|
|
644
668
|
})
|
|
645
669
|
|
|
646
670
|
return this
|
|
@@ -694,8 +718,7 @@ addHook({
|
|
|
694
718
|
if (config.isTestManagementTestsEnabled) {
|
|
695
719
|
const testSuiteTestManagementTests = config.testManagementTests?.mocha?.suites?.[testPath] || {}
|
|
696
720
|
newWorkerArgs._ddIsTestManagementTestsEnabled = true
|
|
697
|
-
|
|
698
|
-
// newWorkerArgs._ddTestManagementAttemptToFixRetries = config.testManagementAttemptToFixRetries
|
|
721
|
+
newWorkerArgs._ddTestManagementAttemptToFixRetries = config.testManagementAttemptToFixRetries
|
|
699
722
|
newWorkerArgs._ddTestManagementTests = {
|
|
700
723
|
mocha: {
|
|
701
724
|
suites: {
|
|
@@ -140,7 +140,6 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
|
140
140
|
if (!testFinishCh.hasSubscribers) {
|
|
141
141
|
return run.apply(this, arguments)
|
|
142
142
|
}
|
|
143
|
-
// Flaky test retries does not work in parallel mode
|
|
144
143
|
if (libraryConfig?.isFlakyTestRetriesEnabled) {
|
|
145
144
|
this.retries(libraryConfig?.flakyTestRetriesCount)
|
|
146
145
|
}
|
|
@@ -43,10 +43,10 @@ addHook({
|
|
|
43
43
|
}
|
|
44
44
|
if (this.options._ddIsTestManagementTestsEnabled) {
|
|
45
45
|
config.isTestManagementTestsEnabled = true
|
|
46
|
-
|
|
47
|
-
// config.testManagementAttemptToFixRetries = this.options._ddTestManagementAttemptToFixRetries
|
|
46
|
+
config.testManagementAttemptToFixRetries = this.options._ddTestManagementAttemptToFixRetries
|
|
48
47
|
config.testManagementTests = this.options._ddTestManagementTests
|
|
49
48
|
delete this.options._ddIsTestManagementTestsEnabled
|
|
49
|
+
delete this.options._ddTestManagementAttemptToFixRetries
|
|
50
50
|
delete this.options._ddTestManagementTests
|
|
51
51
|
}
|
|
52
52
|
if (this.options._ddIsFlakyTestRetriesEnabled) {
|
|
@@ -146,8 +146,23 @@ function isReporterPackageNewest (vitestPackage) {
|
|
|
146
146
|
return vitestPackage.h?.name === 'BaseSequencer'
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Finds an export by its `.name` property in a minified vitest chunk.
|
|
151
|
+
* Minified export keys change across versions, so we search by function/class name.
|
|
152
|
+
* @param {object} pkg - The module exports object
|
|
153
|
+
* @param {string} name - The `.name` value to look for
|
|
154
|
+
* @returns {{ key: string, value: Function } | undefined}
|
|
155
|
+
*/
|
|
156
|
+
function findExportByName (pkg, name) {
|
|
157
|
+
for (const [key, value] of Object.entries(pkg)) {
|
|
158
|
+
if (value?.name === name) {
|
|
159
|
+
return { key, value }
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function getBaseSequencerExport (vitestPackage) {
|
|
165
|
+
return findExportByName(vitestPackage, 'BaseSequencer')
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
function getChannelPromise (channelToPublishTo, frameworkVersion) {
|
|
@@ -157,19 +172,19 @@ function getChannelPromise (channelToPublishTo, frameworkVersion) {
|
|
|
157
172
|
}
|
|
158
173
|
|
|
159
174
|
function isCliApiPackage (vitestPackage) {
|
|
160
|
-
return vitestPackage
|
|
175
|
+
return !!findExportByName(vitestPackage, 'startVitest')
|
|
161
176
|
}
|
|
162
177
|
|
|
163
|
-
function
|
|
164
|
-
return testPackage
|
|
178
|
+
function getTestRunnerExport (testPackage) {
|
|
179
|
+
return findExportByName(testPackage, 'VitestTestRunner') || findExportByName(testPackage, 'TestRunner')
|
|
165
180
|
}
|
|
166
181
|
|
|
167
|
-
function
|
|
168
|
-
return vitestPackage
|
|
182
|
+
function getForksPoolWorkerExport (vitestPackage) {
|
|
183
|
+
return findExportByName(vitestPackage, 'ForksPoolWorker')
|
|
169
184
|
}
|
|
170
185
|
|
|
171
|
-
function
|
|
172
|
-
return vitestPackage
|
|
186
|
+
function getThreadsPoolWorkerExport (vitestPackage) {
|
|
187
|
+
return findExportByName(vitestPackage, 'ThreadsPoolWorker')
|
|
173
188
|
}
|
|
174
189
|
|
|
175
190
|
function getSessionStatus (state) {
|
|
@@ -447,7 +462,11 @@ function getCliOrStartVitestWrapper (frameworkVersion) {
|
|
|
447
462
|
}
|
|
448
463
|
|
|
449
464
|
function getCreateCliWrapper (vitestPackage, frameworkVersion) {
|
|
450
|
-
|
|
465
|
+
const createCliExport = findExportByName(vitestPackage, 'createCLI')
|
|
466
|
+
if (!createCliExport) {
|
|
467
|
+
return vitestPackage
|
|
468
|
+
}
|
|
469
|
+
shimmer.wrap(vitestPackage, createCliExport.key, getCliOrStartVitestWrapper(frameworkVersion))
|
|
451
470
|
|
|
452
471
|
return vitestPackage
|
|
453
472
|
}
|
|
@@ -534,27 +553,30 @@ function getStartVitestWrapper (cliApiPackage, frameworkVersion) {
|
|
|
534
553
|
if (!isCliApiPackage(cliApiPackage)) {
|
|
535
554
|
return cliApiPackage
|
|
536
555
|
}
|
|
537
|
-
|
|
556
|
+
const startVitestExport = findExportByName(cliApiPackage, 'startVitest')
|
|
557
|
+
shimmer.wrap(cliApiPackage, startVitestExport.key, getCliOrStartVitestWrapper(frameworkVersion))
|
|
538
558
|
|
|
539
|
-
|
|
559
|
+
const forksPoolWorker = getForksPoolWorkerExport(cliApiPackage)
|
|
560
|
+
if (forksPoolWorker) {
|
|
540
561
|
// function is async
|
|
541
|
-
shimmer.wrap(
|
|
562
|
+
shimmer.wrap(forksPoolWorker.value.prototype, 'start', start => function () {
|
|
542
563
|
vitestPool = 'child_process'
|
|
543
564
|
this.env.DD_VITEST_WORKER = '1'
|
|
544
565
|
|
|
545
566
|
return start.apply(this, arguments)
|
|
546
567
|
})
|
|
547
|
-
shimmer.wrap(
|
|
568
|
+
shimmer.wrap(forksPoolWorker.value.prototype, 'on', getWrappedOn)
|
|
548
569
|
}
|
|
549
570
|
|
|
550
|
-
|
|
571
|
+
const threadsPoolWorker = getThreadsPoolWorkerExport(cliApiPackage)
|
|
572
|
+
if (threadsPoolWorker) {
|
|
551
573
|
// function is async
|
|
552
|
-
shimmer.wrap(
|
|
574
|
+
shimmer.wrap(threadsPoolWorker.value.prototype, 'start', start => function () {
|
|
553
575
|
vitestPool = 'worker_threads'
|
|
554
576
|
this.env.DD_VITEST_WORKER = '1'
|
|
555
577
|
return start.apply(this, arguments)
|
|
556
578
|
})
|
|
557
|
-
shimmer.wrap(
|
|
579
|
+
shimmer.wrap(threadsPoolWorker.value.prototype, 'on', getWrappedOn)
|
|
558
580
|
}
|
|
559
581
|
return cliApiPackage
|
|
560
582
|
}
|
|
@@ -747,7 +769,10 @@ function wrapVitestTestRunner (VitestTestRunner) {
|
|
|
747
769
|
}
|
|
748
770
|
|
|
749
771
|
const lastExecutionStatus = task.result.state
|
|
750
|
-
const
|
|
772
|
+
const isAtf = attemptToFixTasks.has(task)
|
|
773
|
+
const isQuarantinedOrDisabledAtf = isAtf && (quarantinedTasks.has(task) || disabledTasks.has(task))
|
|
774
|
+
const shouldTrackStatuses = isEarlyFlakeDetectionEnabled || isAtf
|
|
775
|
+
const shouldFlipStatus = isEarlyFlakeDetectionEnabled || isQuarantinedOrDisabledAtf
|
|
751
776
|
const statuses = taskToStatuses.get(task)
|
|
752
777
|
|
|
753
778
|
// These clauses handle task.repeats, whether EFD is enabled or not
|
|
@@ -765,8 +790,10 @@ function wrapVitestTestRunner (VitestTestRunner) {
|
|
|
765
790
|
} else {
|
|
766
791
|
testPassCh.publish({ task, ...ctx.currentStore })
|
|
767
792
|
}
|
|
768
|
-
if (
|
|
793
|
+
if (shouldTrackStatuses) {
|
|
769
794
|
statuses.push(lastExecutionStatus)
|
|
795
|
+
}
|
|
796
|
+
if (shouldFlipStatus) {
|
|
770
797
|
// If we don't "reset" the result.state to "pass", once a repetition fails,
|
|
771
798
|
// vitest will always consider the test as failed, so we can't read the actual status
|
|
772
799
|
// This means that we change vitest's behavior:
|
|
@@ -776,7 +803,7 @@ function wrapVitestTestRunner (VitestTestRunner) {
|
|
|
776
803
|
}
|
|
777
804
|
}
|
|
778
805
|
} else if (numRepetition === task.repeats) {
|
|
779
|
-
if (
|
|
806
|
+
if (shouldTrackStatuses) {
|
|
780
807
|
statuses.push(lastExecutionStatus)
|
|
781
808
|
}
|
|
782
809
|
|
|
@@ -864,11 +891,12 @@ addHook({
|
|
|
864
891
|
versions: ['>=4.0.0'],
|
|
865
892
|
filePattern: 'dist/chunks/test.*',
|
|
866
893
|
}, (testPackage) => {
|
|
867
|
-
|
|
894
|
+
const testRunner = getTestRunnerExport(testPackage)
|
|
895
|
+
if (!testRunner) {
|
|
868
896
|
return testPackage
|
|
869
897
|
}
|
|
870
898
|
|
|
871
|
-
wrapVitestTestRunner(
|
|
899
|
+
wrapVitestTestRunner(testRunner.value)
|
|
872
900
|
|
|
873
901
|
return testPackage
|
|
874
902
|
})
|
|
@@ -937,8 +965,9 @@ addHook({
|
|
|
937
965
|
versions: ['>=3.0.9'],
|
|
938
966
|
filePattern: 'dist/chunks/coverage.*',
|
|
939
967
|
}, (coveragePackage) => {
|
|
940
|
-
|
|
941
|
-
|
|
968
|
+
const baseSequencer = getBaseSequencerExport(coveragePackage)
|
|
969
|
+
if (baseSequencer) {
|
|
970
|
+
shimmer.wrap(baseSequencer.value.prototype, 'sort', getSortWrapper)
|
|
942
971
|
}
|
|
943
972
|
return coveragePackage
|
|
944
973
|
})
|
|
@@ -607,7 +607,7 @@ class CypressPlugin {
|
|
|
607
607
|
[TEST_SESSION_NAME]: testSessionName,
|
|
608
608
|
}
|
|
609
609
|
}
|
|
610
|
-
const libraryCapabilitiesTags = getLibraryCapabilitiesTags(this.constructor.id,
|
|
610
|
+
const libraryCapabilitiesTags = getLibraryCapabilitiesTags(this.constructor.id, this.frameworkVersion)
|
|
611
611
|
metadataTags.test = {
|
|
612
612
|
...metadataTags.test,
|
|
613
613
|
...libraryCapabilitiesTags,
|
|
@@ -61,18 +61,16 @@ Cypress.on('fail', (err, runnable) => {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const testName = runnable.fullTitle()
|
|
64
|
-
const { isQuarantined,
|
|
64
|
+
const { isQuarantined, isDisabled } = getTestProperties(testName)
|
|
65
65
|
|
|
66
|
-
//
|
|
67
|
-
// This
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
// Suppress failures for quarantined or disabled tests so they don't affect the exit code.
|
|
67
|
+
// This applies regardless of attempt-to-fix status: per spec, quarantined/disabled test
|
|
68
|
+
// results are always ignored.
|
|
69
|
+
if (isQuarantined || isDisabled) {
|
|
70
70
|
quarantinedTestErrors.set(testName, err)
|
|
71
|
-
// Don't re-throw - this prevents Cypress from marking the test as failed
|
|
72
71
|
return
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
// For all other tests (including attemptToFix), let the error propagate normally
|
|
76
74
|
throw err
|
|
77
75
|
})
|
|
78
76
|
|
|
@@ -58,8 +58,8 @@ function addVariableTags (config, span, variableValues) {
|
|
|
58
58
|
|
|
59
59
|
if (variableValues && config.variables) {
|
|
60
60
|
const variables = config.variables(variableValues)
|
|
61
|
-
for (const param
|
|
62
|
-
tags[`graphql.variables.${param}`] =
|
|
61
|
+
for (const [param, value] of Object.entries(variables)) {
|
|
62
|
+
tags[`graphql.variables.${param}`] = value
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|