dd-trace 6.11.0 → 6.12.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 +5 -0
- package/index.d.ts +20 -3
- package/package.json +18 -17
- package/packages/datadog-instrumentations/src/cucumber.js +4 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +5 -2
- package/packages/datadog-instrumentations/src/playwright-reporter.js +149 -1
- package/packages/datadog-instrumentations/src/playwright.js +33 -33
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +6 -8
- package/packages/datadog-plugin-playwright/src/index.js +4 -0
- package/packages/dd-trace/src/appsec/reporter.js +2 -0
- package/packages/dd-trace/src/appsec/telemetry/index.js +13 -0
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +16 -0
- package/packages/dd-trace/src/appsec/telemetry/waf.js +24 -0
- package/packages/dd-trace/src/carrier.js +107 -48
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +5 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +2 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +5 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +4 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -4
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +5 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -2
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +4 -2
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +4 -2
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +5 -5
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -10
- package/packages/dd-trace/src/debugger/index.js +4 -2
- package/packages/dd-trace/src/debugger/inspect-segment.js +154 -0
- package/packages/dd-trace/src/evp_proxy/constants.js +8 -0
- package/packages/dd-trace/src/evp_proxy/direct.js +64 -0
- package/packages/dd-trace/src/evp_proxy/discovery.js +133 -0
- package/packages/dd-trace/src/evp_proxy/path.js +22 -0
- package/packages/dd-trace/src/exporters/common/request.js +5 -2
- package/packages/dd-trace/src/llmobs/experiments/client.js +6 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +249 -11
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +23 -10
- package/packages/dd-trace/src/llmobs/experiments/index.js +18 -6
- package/packages/dd-trace/src/llmobs/experiments/noop.js +64 -4
- package/packages/dd-trace/src/llmobs/experiments/util.js +60 -4
- package/packages/dd-trace/src/openfeature/constants/constants.js +0 -18
- package/packages/dd-trace/src/openfeature/index.js +7 -4
- package/packages/dd-trace/src/openfeature/writers/base.js +153 -11
- package/packages/dd-trace/src/openfeature/writers/exposures.js +62 -14
- package/packages/dd-trace/src/openfeature/writers/util.js +97 -15
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -13
- package/packages/dd-trace/src/telemetry/metrics.js +62 -8
- package/packages/dd-trace/src/telemetry/send-data.js +1 -0
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/https-proxy-agent/LICENSE +22 -0
- package/vendor/dist/https-proxy-agent/index.js +4 -0
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/proxy-from-env/LICENSE +20 -0
- package/vendor/dist/proxy-from-env/index.js +1 -0
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -44,18 +44,21 @@
|
|
|
44
44
|
"@oxc-project/types","https://github.com/oxc-project/oxc","['MIT']","['Boshen and oxc contributors']"
|
|
45
45
|
"@tybys/wasm-util","https://github.com/toyobayashi/wasm-util","['MIT']","['toyobayashi']"
|
|
46
46
|
"@types/estree","https://github.com/DefinitelyTyped/DefinitelyTyped","['MIT']","['DefinitelyTyped']"
|
|
47
|
+
"agent-base","https://github.com/TooTallNate/proxy-agents","['MIT']","['Nathan Rajlich']"
|
|
47
48
|
"argparse","https://github.com/nodeca/argparse","['Python-2.0']","['nodeca']"
|
|
48
49
|
"astring","https://github.com/davidbonnet/astring","['MIT']","['David Bonnet']"
|
|
49
50
|
"cjs-module-lexer","https://github.com/nodejs/cjs-module-lexer","['MIT']","['Guy Bedford']"
|
|
50
51
|
"crypto-randomuuid","npm:crypto-randomuuid","['MIT']","['Stephen Belanger']"
|
|
51
52
|
"dc-polyfill","https://github.com/DataDog/dc-polyfill","['MIT']","['Thomas Hunter II']"
|
|
52
53
|
"dd-trace","https://github.com/DataDog/dd-trace-js","['(Apache-2.0 OR BSD-3-Clause)']","['Datadog Inc. <info@datadoghq.com>']"
|
|
54
|
+
"debug","https://github.com/debug-js/debug","['MIT']","['Josh Junon']"
|
|
53
55
|
"detect-newline","https://github.com/sindresorhus/detect-newline","['MIT']","['Sindre Sorhus']"
|
|
54
56
|
"es-module-lexer","https://github.com/guybedford/es-module-lexer","['MIT']","['Guy Bedford']"
|
|
55
57
|
"escape-string-regexp","https://github.com/sindresorhus/escape-string-regexp","['MIT']","['Sindre Sorhus']"
|
|
56
58
|
"esquery","https://github.com/estools/esquery","['BSD-3-Clause']","['Joel Feenstra']"
|
|
57
59
|
"estraverse","https://github.com/estools/estraverse","['BSD-2-Clause']","['estools']"
|
|
58
60
|
"fast-fifo","https://github.com/mafintosh/fast-fifo","['MIT']","['Mathias Buus']"
|
|
61
|
+
"https-proxy-agent","https://github.com/TooTallNate/proxy-agents","['MIT']","['Nathan Rajlich']"
|
|
59
62
|
"import-in-the-middle","https://github.com/nodejs/import-in-the-middle","['Apache-2.0']","['Bryan English']"
|
|
60
63
|
"istanbul-lib-coverage","https://github.com/istanbuljs/istanbuljs","['BSD-3-Clause']","['Krishnan Anantheswaran']"
|
|
61
64
|
"jest-docblock","https://github.com/jestjs/jest","['MIT']","['jestjs']"
|
|
@@ -68,6 +71,7 @@
|
|
|
68
71
|
"lru-cache","https://github.com/isaacs/node-lru-cache","['ISC']","['Isaac Z. Schlueter']"
|
|
69
72
|
"meriyah","https://github.com/meriyah/meriyah","['ISC']","['Kenny F.']"
|
|
70
73
|
"module-details-from-path","https://github.com/watson/module-details-from-path","['MIT']","['Thomas Watson']"
|
|
74
|
+
"ms","https://github.com/vercel/ms","['MIT']","['vercel']"
|
|
71
75
|
"mutexify","https://github.com/mafintosh/mutexify","['MIT']","['Mathias Buus']"
|
|
72
76
|
"node-addon-api","https://github.com/nodejs/node-addon-api","['MIT']","['nodejs']"
|
|
73
77
|
"node-gyp-build","https://github.com/prebuild/node-gyp-build","['MIT']","['Mathias Buus']"
|
|
@@ -75,6 +79,7 @@
|
|
|
75
79
|
"oxc-parser","https://github.com/oxc-project/oxc","['MIT']","['Boshen and oxc contributors']"
|
|
76
80
|
"pprof-format","https://github.com/DataDog/pprof-format","['MIT']","['Datadog Inc.']"
|
|
77
81
|
"protobufjs","https://github.com/protobufjs/protobuf.js","['BSD-3-Clause']","['Daniel Wirtz']"
|
|
82
|
+
"proxy-from-env","https://github.com/Rob--W/proxy-from-env","['MIT']","['Rob Wu']"
|
|
78
83
|
"queue-tick","https://github.com/mafintosh/queue-tick","['MIT']","['Mathias Buus']"
|
|
79
84
|
"retry","https://github.com/tim-kos/node-retry","['MIT']","['Tim Koschützki']"
|
|
80
85
|
"rfdc","https://github.com/davidmarkclements/rfdc","['MIT']","['David Mark Clements']"
|
package/index.d.ts
CHANGED
|
@@ -3804,7 +3804,8 @@ declare namespace tracer {
|
|
|
3804
3804
|
id?: string,
|
|
3805
3805
|
inputData: JSONType,
|
|
3806
3806
|
expectedOutput?: JSONType,
|
|
3807
|
-
metadata?: Record<string, JSONType
|
|
3807
|
+
metadata?: Record<string, JSONType>,
|
|
3808
|
+
tags?: string[]
|
|
3808
3809
|
}>
|
|
3809
3810
|
}
|
|
3810
3811
|
|
|
@@ -3837,6 +3838,8 @@ declare namespace tracer {
|
|
|
3837
3838
|
expectedRecordCount?: number
|
|
3838
3839
|
/** Maximum total time to wait, in ms. Default 30000. */
|
|
3839
3840
|
maxWaitMs?: number
|
|
3841
|
+
/** Filter records by these tags. */
|
|
3842
|
+
tags?: string[]
|
|
3840
3843
|
}
|
|
3841
3844
|
|
|
3842
3845
|
interface ExperimentResultRow {
|
|
@@ -3954,7 +3957,12 @@ declare namespace tracer {
|
|
|
3954
3957
|
}
|
|
3955
3958
|
|
|
3956
3959
|
interface Dataset {
|
|
3957
|
-
addRecord (
|
|
3960
|
+
addRecord (
|
|
3961
|
+
input: JSONType,
|
|
3962
|
+
expectedOutput?: JSONType,
|
|
3963
|
+
metadata?: Record<string, JSONType>,
|
|
3964
|
+
tags?: string[]
|
|
3965
|
+
): Dataset
|
|
3958
3966
|
/** Update fields on an existing dataset record. */
|
|
3959
3967
|
update (index: number, fields: {
|
|
3960
3968
|
input?: JSONType
|
|
@@ -3963,6 +3971,12 @@ declare namespace tracer {
|
|
|
3963
3971
|
}): Dataset
|
|
3964
3972
|
/** Delete an existing dataset record. */
|
|
3965
3973
|
delete (index: number): Dataset
|
|
3974
|
+
/** Add tags to a dataset record. */
|
|
3975
|
+
addTags (index: number, tags: string[]): Dataset
|
|
3976
|
+
/** Remove tags from a dataset record. */
|
|
3977
|
+
removeTags (index: number, tags: string[]): Dataset
|
|
3978
|
+
/** Replace all tags on a dataset record. */
|
|
3979
|
+
replaceTags (index: number, tags: string[]): Dataset
|
|
3966
3980
|
/** Creates the dataset remotely if needed and pushes any unpushed records. */
|
|
3967
3981
|
push (): Promise<DatasetPushResult>
|
|
3968
3982
|
name (): string
|
|
@@ -3975,8 +3989,11 @@ declare namespace tracer {
|
|
|
3975
3989
|
id: string | null,
|
|
3976
3990
|
input: JSONType,
|
|
3977
3991
|
expectedOutput: JSONType,
|
|
3978
|
-
metadata: Record<string, JSONType
|
|
3992
|
+
metadata: Record<string, JSONType>,
|
|
3993
|
+
tags: string[]
|
|
3979
3994
|
}>
|
|
3995
|
+
/** Return the tags used to filter this dataset. */
|
|
3996
|
+
filterTags (): string[]
|
|
3980
3997
|
/** Dashboard URL for the dataset, or null until pushed. */
|
|
3981
3998
|
url (): string | null
|
|
3982
3999
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.12.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -57,13 +57,14 @@
|
|
|
57
57
|
"test:core:ci": "node scripts/c8-ci.js test:core",
|
|
58
58
|
"test:code-origin": "mocha \"packages/datadog-code-origin/test/**/*.spec.js\"",
|
|
59
59
|
"test:code-origin:ci": "node scripts/c8-ci.js test:code-origin",
|
|
60
|
+
"test:evp_proxy": "mocha \"packages/dd-trace/test/evp_proxy/**/*.spec.js\"",
|
|
60
61
|
"test:lambda": "mocha \"packages/dd-trace/test/lambda/**/*.spec.js\"",
|
|
61
62
|
"test:lambda:ci": "node scripts/c8-ci.js test:lambda",
|
|
62
63
|
"test:llmobs:sdk": "mocha --exclude \"packages/dd-trace/test/llmobs/plugins/**/*.spec.js\" \"packages/dd-trace/test/llmobs/**/*.spec.js\"",
|
|
63
64
|
"test:llmobs:sdk:ci": "node scripts/c8-ci.js test:llmobs:sdk",
|
|
64
65
|
"test:llmobs:plugins": "mocha \"packages/dd-trace/test/llmobs/plugins/@(${PLUGINS})/*.spec.js\"",
|
|
65
66
|
"test:llmobs:plugins:ci": "yarn services && node scripts/c8-ci.js test:llmobs:plugins",
|
|
66
|
-
"test:openfeature": "mocha \"packages/dd-trace/test/openfeature/**/*.spec.js\"",
|
|
67
|
+
"test:openfeature": "mocha \"packages/dd-trace/test/evp_proxy/**/*.spec.js\" \"packages/dd-trace/test/openfeature/**/*.spec.js\"",
|
|
67
68
|
"test:openfeature:ci": "node scripts/c8-ci.js test:openfeature",
|
|
68
69
|
"test:plugins": "node --expose-gc ./node_modules/mocha/bin/mocha.js --fail-zero \"packages/datadog-plugin-@(${PLUGINS})/test/**/${SPEC:-*}*.spec.js\"",
|
|
69
70
|
"test:plugins:ci": "yarn services && node scripts/c8-ci.js test:plugins",
|
|
@@ -186,7 +187,7 @@
|
|
|
186
187
|
"@datadog/native-appsec": "11.0.1",
|
|
187
188
|
"@datadog/native-iast-taint-tracking": "4.2.0",
|
|
188
189
|
"@datadog/native-metrics": "3.1.2",
|
|
189
|
-
"@datadog/pprof": "5.18.
|
|
190
|
+
"@datadog/pprof": "5.18.1",
|
|
190
191
|
"@datadog/wasm-js-rewriter": "5.0.3",
|
|
191
192
|
"@opentelemetry/api": ">=1.0.0 <1.10.0",
|
|
192
193
|
"@opentelemetry/api-logs": "<1.0.0",
|
|
@@ -196,58 +197,58 @@
|
|
|
196
197
|
"@actions/core": "^3.0.1",
|
|
197
198
|
"@actions/github": "^9.1.1",
|
|
198
199
|
"@babel/helpers": "^8.0.0",
|
|
199
|
-
"@eslint/eslintrc": "^3.3.
|
|
200
|
+
"@eslint/eslintrc": "^3.3.6",
|
|
200
201
|
"@eslint/js": "^10.0.1",
|
|
201
202
|
"@eslint/plugin-kit": "^0.7.2",
|
|
202
203
|
"@datadog/openfeature-node-server": "2.1.0",
|
|
203
204
|
"@msgpack/msgpack": "^3.1.3",
|
|
204
|
-
"@openfeature/core": "^1.
|
|
205
|
-
"@openfeature/server-sdk": "~1.
|
|
205
|
+
"@openfeature/core": "^1.12.0",
|
|
206
|
+
"@openfeature/server-sdk": "~1.23.0",
|
|
206
207
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
207
208
|
"@types/mocha": "^10.0.10",
|
|
208
209
|
"@types/node": "^18.19.106",
|
|
209
210
|
"@types/sinon": "^22.0.0",
|
|
210
211
|
"@vercel/nft": "^1.10.2",
|
|
211
212
|
"@yarnpkg/lockfile": "^1.1.0",
|
|
212
|
-
"axios": "^1.
|
|
213
|
+
"axios": "^1.19.0",
|
|
213
214
|
"benchmark": "^2.1.4",
|
|
214
215
|
"body-parser": "^2.3.0",
|
|
215
216
|
"bun": "1.3.14",
|
|
216
217
|
"c8": "^12.0.0",
|
|
217
218
|
"codeowners-audit": "^2.9.0",
|
|
218
|
-
"eslint": "^10.
|
|
219
|
-
"eslint-plugin-cypress": "^
|
|
219
|
+
"eslint": "^10.8.1",
|
|
220
|
+
"eslint-plugin-cypress": "^7.0.0",
|
|
220
221
|
"eslint-plugin-import-x": "^4.16.2",
|
|
221
|
-
"eslint-plugin-jsdoc": "^
|
|
222
|
+
"eslint-plugin-jsdoc": "^64.2.0",
|
|
222
223
|
"eslint-plugin-mocha": "^11.3.0",
|
|
223
|
-
"eslint-plugin-n": "^18.
|
|
224
|
+
"eslint-plugin-n": "^18.3.0",
|
|
224
225
|
"eslint-plugin-promise": "^7.3.0",
|
|
225
226
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
226
227
|
"eslint-plugin-unicorn": "^73.0.0",
|
|
227
228
|
"express": "^5.1.0",
|
|
228
229
|
"glob": "^10.4.5",
|
|
229
|
-
"globals": "^17.
|
|
230
|
+
"globals": "^17.11.0",
|
|
230
231
|
"graphql": "*",
|
|
231
232
|
"husky": "^9.1.7",
|
|
232
233
|
"istanbul-lib-report": "^3.0.0",
|
|
233
234
|
"istanbul-reports": "^3.0.2",
|
|
234
235
|
"jsonc-parser": "^3.3.1",
|
|
235
236
|
"jszip": "^3.10.1",
|
|
236
|
-
"minimatch": "^10.2.
|
|
237
|
-
"mocha": "^11.
|
|
237
|
+
"minimatch": "^10.2.6",
|
|
238
|
+
"mocha": "^11.8.0",
|
|
238
239
|
"mocha-junit-reporter": "^2.2.1",
|
|
239
240
|
"mocha-multi-reporters": "^1.5.1",
|
|
240
241
|
"multer": "^2.2.0",
|
|
241
|
-
"nock": "^14.0.
|
|
242
|
+
"nock": "^14.0.17",
|
|
242
243
|
"node-preload": "^0.2.1",
|
|
243
244
|
"nyc": "^18.0.0",
|
|
244
245
|
"octokit": "^5.0.3",
|
|
245
|
-
"p-limit": "^7.
|
|
246
|
+
"p-limit": "^7.3.1",
|
|
246
247
|
"proxyquire": "^2.1.3",
|
|
247
248
|
"retry": "^0.13.1",
|
|
248
249
|
"semifies": "^1.0.0",
|
|
249
250
|
"semver": "^7.8.5",
|
|
250
|
-
"sinon": "^22.
|
|
251
|
+
"sinon": "^22.1.0",
|
|
251
252
|
"source-map-support": "^0.5.21",
|
|
252
253
|
"test-exclude": "^8.0.0",
|
|
253
254
|
"tiktoken": "^1.0.21",
|
|
@@ -1482,14 +1482,14 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
1482
1482
|
|
|
1483
1483
|
this.options.retry = originalRetry
|
|
1484
1484
|
|
|
1485
|
-
if (isNewerCucumberVersion && shouldRunEarlyFlakeDetection() && (isNew || isModified)) {
|
|
1486
|
-
return shouldBePassedByEFD
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
1485
|
if (isNewerCucumberVersion && isTestManagementTestsEnabled && !isAttemptToFix && (isQuarantined || isDisabled)) {
|
|
1490
1486
|
return shouldBePassedByTestManagement
|
|
1491
1487
|
}
|
|
1492
1488
|
|
|
1489
|
+
if (isNewerCucumberVersion && shouldRunEarlyFlakeDetection() && (isNew || isModified)) {
|
|
1490
|
+
return shouldBePassedByEFD
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
1493
|
if (isNewerCucumberVersion && isAttemptToFix && shouldBeFailedByAttemptToFix) {
|
|
1494
1494
|
return false
|
|
1495
1495
|
}
|
|
@@ -299,6 +299,9 @@ function retryTest (test, numRetries, tags, retryPolicy) {
|
|
|
299
299
|
clonedTest[tag] = true
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
|
+
if (clonedTest._ddIsQuarantined && !clonedTest._ddIsAttemptToFix) {
|
|
303
|
+
testsQuarantined.add(clonedTest)
|
|
304
|
+
}
|
|
302
305
|
}
|
|
303
306
|
}
|
|
304
307
|
|
|
@@ -1146,7 +1149,7 @@ function getRunTestsWrapper (runTests, config) {
|
|
|
1146
1149
|
retryTest(
|
|
1147
1150
|
test,
|
|
1148
1151
|
config.earlyFlakeDetectionRetryPolicy.schedulingRetryCount,
|
|
1149
|
-
['_ddIsModified', '_ddIsEfdRetry'],
|
|
1152
|
+
['_ddIsModified', '_ddIsEfdRetry', test._ddIsQuarantined && '_ddIsQuarantined'],
|
|
1150
1153
|
config.earlyFlakeDetectionRetryPolicy
|
|
1151
1154
|
)
|
|
1152
1155
|
}
|
|
@@ -1165,7 +1168,7 @@ function getRunTestsWrapper (runTests, config) {
|
|
|
1165
1168
|
retryTest(
|
|
1166
1169
|
test,
|
|
1167
1170
|
config.earlyFlakeDetectionRetryPolicy.schedulingRetryCount,
|
|
1168
|
-
['_ddIsNew', '_ddIsEfdRetry'],
|
|
1171
|
+
['_ddIsNew', '_ddIsEfdRetry', test._ddIsQuarantined && '_ddIsQuarantined'],
|
|
1169
1172
|
config.earlyFlakeDetectionRetryPolicy
|
|
1170
1173
|
)
|
|
1171
1174
|
}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
const { channel } = require('dc-polyfill')
|
|
4
4
|
|
|
5
5
|
const reporterErrorCh = channel('ci:playwright:reporter:error')
|
|
6
|
+
const reporterRunSummaryCh = channel('ci:playwright:reporter:run-summary')
|
|
7
|
+
const reporterSuiteHookErrorCh = channel('ci:playwright:reporter:suite-hook-error')
|
|
8
|
+
const suitesWithHookErrors = new Set()
|
|
6
9
|
const PLAYWRIGHT_REPORTER_ERROR_MESSAGE = 'Error in reporter'
|
|
7
10
|
const PLAYWRIGHT_REPORTER_ERROR_CALLER_RE =
|
|
8
11
|
/^\s*at wrapAsync .*?[\\/]playwright[\\/]lib[\\/]runner[\\/]index\.js:\d+:\d+\)?$/
|
|
@@ -27,7 +30,53 @@ function isPlaywrightReporterError (message) {
|
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Returns whether a finalized Playwright result contains a failed suite hook.
|
|
35
|
+
*
|
|
36
|
+
* @param {Array<object>} steps
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function hasFailedSuiteHook (steps) {
|
|
40
|
+
if (!steps) return false
|
|
41
|
+
|
|
42
|
+
for (const step of steps) {
|
|
43
|
+
if (step.error && (step.title === 'beforeAll hook' || step.title === 'afterAll hook')) return true
|
|
44
|
+
if (hasFailedSuiteHook(step.steps)) return true
|
|
45
|
+
}
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
class DatadogPlaywrightReporter {
|
|
50
|
+
/**
|
|
51
|
+
* Creates a reporter that observes the finalized Playwright result independently of user reporters.
|
|
52
|
+
*
|
|
53
|
+
* @param {object} [options]
|
|
54
|
+
* @param {boolean} [options.captureReporterErrors]
|
|
55
|
+
*/
|
|
56
|
+
constructor ({ captureReporterErrors = true } = {}) {
|
|
57
|
+
this.captureReporterErrors = captureReporterErrors
|
|
58
|
+
this.fatalErrorCount = 0
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Identifies this reporter as implementing Playwright's reporter v2 contract.
|
|
63
|
+
*
|
|
64
|
+
* @returns {'v2'}
|
|
65
|
+
*/
|
|
66
|
+
version () {
|
|
67
|
+
return 'v2'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
72
|
+
*
|
|
73
|
+
* @param {object} config
|
|
74
|
+
* @returns {void}
|
|
75
|
+
*/
|
|
76
|
+
onConfigure (config) {
|
|
77
|
+
this.failOnFlakyTests = config.failOnFlakyTests
|
|
78
|
+
}
|
|
79
|
+
|
|
31
80
|
/**
|
|
32
81
|
* Restores console error after Playwright completes the reporter lifecycle.
|
|
33
82
|
*
|
|
@@ -45,12 +94,96 @@ class DatadogPlaywrightReporter {
|
|
|
45
94
|
DatadogPlaywrightReporter.originalConsoleError = undefined
|
|
46
95
|
}
|
|
47
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Records the suite so finalized test outcomes can be counted in onEnd.
|
|
99
|
+
*
|
|
100
|
+
* @param {object} configOrSuite
|
|
101
|
+
* @param {object} [suite]
|
|
102
|
+
* @returns {void}
|
|
103
|
+
*/
|
|
104
|
+
onBegin (configOrSuite, suite) {
|
|
105
|
+
this.suite = suite || configOrSuite
|
|
106
|
+
if (suite) this.failOnFlakyTests = configOrSuite.failOnFlakyTests
|
|
107
|
+
suitesWithHookErrors.clear()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
112
|
+
*
|
|
113
|
+
* @returns {void}
|
|
114
|
+
*/
|
|
115
|
+
onTestBegin () {}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
119
|
+
*
|
|
120
|
+
* @returns {void}
|
|
121
|
+
*/
|
|
122
|
+
onStdOut () {}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
126
|
+
*
|
|
127
|
+
* @returns {void}
|
|
128
|
+
*/
|
|
129
|
+
onStdErr () {}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
133
|
+
*
|
|
134
|
+
* @returns {void}
|
|
135
|
+
*/
|
|
136
|
+
onTestEnd () {}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
140
|
+
*
|
|
141
|
+
* @returns {void}
|
|
142
|
+
*/
|
|
143
|
+
onStepBegin () {}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
147
|
+
*
|
|
148
|
+
* @returns {void}
|
|
149
|
+
*/
|
|
150
|
+
onStepEnd () {}
|
|
151
|
+
|
|
48
152
|
/**
|
|
49
153
|
* Marks the beginning of reporter finalization so later reporter errors can be identified.
|
|
50
154
|
*
|
|
51
155
|
* @returns {void}
|
|
52
156
|
*/
|
|
53
157
|
onEnd () {
|
|
158
|
+
let failureCount = this.fatalErrorCount
|
|
159
|
+
let quarantinedFailureCount = 0
|
|
160
|
+
let hasIncompleteTests = suitesWithHookErrors.size > 0
|
|
161
|
+
const tests = this.suite?.allTests?.()
|
|
162
|
+
if (tests) {
|
|
163
|
+
for (const test of tests) {
|
|
164
|
+
const outcome = test.outcome()
|
|
165
|
+
const finalResult = test.results.at(-1)
|
|
166
|
+
hasIncompleteTests ||= hasFailedSuiteHook(finalResult?.steps)
|
|
167
|
+
if (outcome === 'unexpected' || (outcome === 'flaky' && this.failOnFlakyTests)) {
|
|
168
|
+
failureCount += 1
|
|
169
|
+
const finalResultStatus = finalResult?.status
|
|
170
|
+
const hasFailed = finalResultStatus === 'failed' || finalResultStatus === 'timedOut'
|
|
171
|
+
if (outcome === 'unexpected' && hasFailed && test._ddIsQuarantined && !test._ddIsAttemptToFix) {
|
|
172
|
+
quarantinedFailureCount += 1
|
|
173
|
+
}
|
|
174
|
+
} else if (outcome === 'skipped' && !test._ddShouldSkipEfdRetry &&
|
|
175
|
+
(!test._ddIsDisabled || test._ddIsAttemptToFix)) {
|
|
176
|
+
const { results } = test
|
|
177
|
+
hasIncompleteTests ||= results.some(result => result.status === 'interrupted') ||
|
|
178
|
+
!results.length || test.expectedStatus !== 'skipped'
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
reporterRunSummaryCh.publish({ failureCount, quarantinedFailureCount, hasIncompleteTests })
|
|
183
|
+
suitesWithHookErrors.clear()
|
|
184
|
+
|
|
185
|
+
if (!this.captureReporterErrors) return
|
|
186
|
+
|
|
54
187
|
this.isFinalizing = true
|
|
55
188
|
// Playwright 1.60 and 1.61 only expose reporter errors through this exact console call.
|
|
56
189
|
// eslint-disable-next-line no-console
|
|
@@ -76,6 +209,13 @@ class DatadogPlaywrightReporter {
|
|
|
76
209
|
DatadogPlaywrightReporter.consoleError = consoleError
|
|
77
210
|
}
|
|
78
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Implements the reporter v2 lifecycle hook required by older Playwright versions.
|
|
214
|
+
*
|
|
215
|
+
* @returns {void}
|
|
216
|
+
*/
|
|
217
|
+
onExit () {}
|
|
218
|
+
|
|
79
219
|
/**
|
|
80
220
|
* Reports errors emitted by Playwright while later reporters are finalizing.
|
|
81
221
|
*
|
|
@@ -83,7 +223,11 @@ class DatadogPlaywrightReporter {
|
|
|
83
223
|
* @returns {void}
|
|
84
224
|
*/
|
|
85
225
|
onError (error) {
|
|
86
|
-
if (this.isFinalizing)
|
|
226
|
+
if (this.isFinalizing) {
|
|
227
|
+
reporterErrorCh.publish(error)
|
|
228
|
+
} else {
|
|
229
|
+
this.fatalErrorCount += 1
|
|
230
|
+
}
|
|
87
231
|
}
|
|
88
232
|
|
|
89
233
|
/**
|
|
@@ -96,4 +240,8 @@ class DatadogPlaywrightReporter {
|
|
|
96
240
|
}
|
|
97
241
|
}
|
|
98
242
|
|
|
243
|
+
reporterSuiteHookErrorCh.subscribe((testSuiteAbsolutePath) => {
|
|
244
|
+
suitesWithHookErrors.add(testSuiteAbsolutePath)
|
|
245
|
+
})
|
|
246
|
+
|
|
99
247
|
module.exports = DatadogPlaywrightReporter
|
|
@@ -46,6 +46,8 @@ const testSessionStartCh = channel('ci:playwright:session:start')
|
|
|
46
46
|
const testSessionConfigurationCh = channel('ci:playwright:session:configuration')
|
|
47
47
|
const testSessionFinishCh = channel('ci:playwright:session:finish')
|
|
48
48
|
const reporterErrorCh = channel('ci:playwright:reporter:error')
|
|
49
|
+
const reporterRunSummaryCh = channel('ci:playwright:reporter:run-summary')
|
|
50
|
+
const reporterSuiteHookErrorCh = channel('ci:playwright:reporter:suite-hook-error')
|
|
49
51
|
|
|
50
52
|
const libraryConfigurationCh = channel('ci:playwright:library-configuration')
|
|
51
53
|
const knownTestsCh = channel('ci:playwright:known-tests')
|
|
@@ -111,7 +113,7 @@ let testManagementAttemptToFixRetries = 0
|
|
|
111
113
|
let testManagementTests = {}
|
|
112
114
|
let isImpactedTestsEnabled = false
|
|
113
115
|
let modifiedFiles = {}
|
|
114
|
-
let
|
|
116
|
+
let playwrightRunSummary
|
|
115
117
|
let recordedTestOptimizationExecutions = new Set()
|
|
116
118
|
let testsReportedInGenerateSummary = new Set()
|
|
117
119
|
const newTestsWithDynamicNames = new Set()
|
|
@@ -785,6 +787,7 @@ function finishTestSuiteIfDone (testSuiteAbsolutePath, projects) {
|
|
|
785
787
|
testSourceLine: test.location.line,
|
|
786
788
|
browserName,
|
|
787
789
|
isNew: test._ddIsNew,
|
|
790
|
+
isAttemptToFix: test._ddIsAttemptToFix,
|
|
788
791
|
isDisabled: test._ddIsDisabled,
|
|
789
792
|
isModified: test._ddIsModified,
|
|
790
793
|
isQuarantined: test._ddIsQuarantined,
|
|
@@ -832,6 +835,7 @@ function testEndHandler ({
|
|
|
832
835
|
|
|
833
836
|
if (hookError) {
|
|
834
837
|
addErrorToTestSuite(testSuiteAbsolutePath, hookError)
|
|
838
|
+
reporterSuiteHookErrorCh.publish(testSuiteAbsolutePath)
|
|
835
839
|
}
|
|
836
840
|
return
|
|
837
841
|
}
|
|
@@ -917,9 +921,7 @@ function testEndHandler ({
|
|
|
917
921
|
|
|
918
922
|
// Check if all EFD retries failed
|
|
919
923
|
const efdRetryCount = getEfdRetryCountForTest(test)
|
|
920
|
-
if (efdRetryCount > 0 && testStatuses.length === efdRetryCount + 1 &&
|
|
921
|
-
(test._ddIsNew || test._ddIsModified) &&
|
|
922
|
-
isEarlyFlakeDetectionEnabled &&
|
|
924
|
+
if (isEfdManagedTest && efdRetryCount > 0 && testStatuses.length === efdRetryCount + 1 &&
|
|
923
925
|
testStatuses.every(status => status === 'fail')) {
|
|
924
926
|
test._ddHasFailedAllRetries = true
|
|
925
927
|
}
|
|
@@ -1259,6 +1261,7 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1259
1261
|
return async function (config) {
|
|
1260
1262
|
reporterError = undefined
|
|
1261
1263
|
hasReporterError = false
|
|
1264
|
+
playwrightRunSummary = undefined
|
|
1262
1265
|
let restoreReporterConsoleError
|
|
1263
1266
|
if (satisfies(playwrightVersion, '>=1.60.0') && config?.config) {
|
|
1264
1267
|
const DatadogPlaywrightReporter = require('./playwright-reporter')
|
|
@@ -1433,23 +1436,8 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1433
1436
|
const sessionStatus = runAllTestsReturn.status || runAllTestsReturn
|
|
1434
1437
|
|
|
1435
1438
|
if (isTestManagementTestsEnabled && sessionStatus === 'failed') {
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
for (const [fqn, testStatuses] of testsToTestStatuses) {
|
|
1440
|
-
// Only count as failed if the final status (after retries) is 'fail'
|
|
1441
|
-
const lastStatus = testStatuses.at(-1)
|
|
1442
|
-
if (lastStatus === 'fail') {
|
|
1443
|
-
totalFailedTestCount += 1
|
|
1444
|
-
if (quarantinedButNotAttemptToFixFqns.has(fqn)) {
|
|
1445
|
-
totalPureQuarantinedFailedTestCount += 1
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
|
-
const totalIgnorableFailures = totalPureQuarantinedFailedTestCount
|
|
1451
|
-
|
|
1452
|
-
if (totalFailedTestCount > 0 && totalFailedTestCount === totalIgnorableFailures) {
|
|
1439
|
+
const { failureCount, quarantinedFailureCount, hasIncompleteTests } = playwrightRunSummary || {}
|
|
1440
|
+
if (!hasIncompleteTests && quarantinedFailureCount > 0 && quarantinedFailureCount === failureCount) {
|
|
1453
1441
|
runAllTestsReturn = 'passed'
|
|
1454
1442
|
preventedToFail = true
|
|
1455
1443
|
}
|
|
@@ -1476,7 +1464,7 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1476
1464
|
|
|
1477
1465
|
startedSuites = []
|
|
1478
1466
|
remainingTestsByFile = {}
|
|
1479
|
-
|
|
1467
|
+
playwrightRunSummary = undefined
|
|
1480
1468
|
recordedTestOptimizationExecutions = new Set()
|
|
1481
1469
|
testsReportedInGenerateSummary = new Set()
|
|
1482
1470
|
efdManagedTestKeys.clear()
|
|
@@ -1507,6 +1495,8 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1507
1495
|
function reportersHook (reportersPackage) {
|
|
1508
1496
|
return shimmer.wrap(reportersPackage, 'createReporters', createReporters => async function () {
|
|
1509
1497
|
const reporters = await createReporters.apply(this, arguments)
|
|
1498
|
+
const DatadogPlaywrightReporter = require('./playwright-reporter')
|
|
1499
|
+
reporters.unshift(new DatadogPlaywrightReporter({ captureReporterErrors: false }))
|
|
1510
1500
|
for (const reporter of reporters) {
|
|
1511
1501
|
if (instrumentedPlaywrightReporters.has(reporter)) continue
|
|
1512
1502
|
|
|
@@ -1663,6 +1653,10 @@ reporterErrorCh.subscribe((error) => {
|
|
|
1663
1653
|
recordReporterError(error)
|
|
1664
1654
|
})
|
|
1665
1655
|
|
|
1656
|
+
reporterRunSummaryCh.subscribe((runSummary) => {
|
|
1657
|
+
playwrightRunSummary = runSummary
|
|
1658
|
+
})
|
|
1659
|
+
|
|
1666
1660
|
/**
|
|
1667
1661
|
* Records a reporter failure even when the reporter throws a falsy value.
|
|
1668
1662
|
*
|
|
@@ -1894,11 +1888,6 @@ function processRootSuite (createRootSuiteReturnValue) {
|
|
|
1894
1888
|
}
|
|
1895
1889
|
if (testProperties.quarantined) {
|
|
1896
1890
|
test._ddIsQuarantined = true
|
|
1897
|
-
if (!testProperties.attemptToFix) {
|
|
1898
|
-
// Do not skip quarantined tests, let them run and overwrite results post-run if they fail
|
|
1899
|
-
const testFqn = getTestFullyQualifiedName(test)
|
|
1900
|
-
quarantinedButNotAttemptToFixFqns.add(testFqn)
|
|
1901
|
-
}
|
|
1902
1891
|
}
|
|
1903
1892
|
if (testProperties.attemptToFix) {
|
|
1904
1893
|
test._ddIsAttemptToFix = true
|
|
@@ -1938,7 +1927,10 @@ function processRootSuite (createRootSuiteReturnValue) {
|
|
|
1938
1927
|
const fileSuitesWithImpactedTestsToProjects = new Map()
|
|
1939
1928
|
for (const impactedTest of impactedTests) {
|
|
1940
1929
|
impactedTest._ddIsModified = true
|
|
1941
|
-
if (shouldRunEarlyFlakeDetection() && impactedTest.expectedStatus !== 'skipped'
|
|
1930
|
+
if (shouldRunEarlyFlakeDetection() && impactedTest.expectedStatus !== 'skipped' &&
|
|
1931
|
+
!impactedTest._ddIsAttemptToFix) {
|
|
1932
|
+
// Prevent ATR or `--retries` from retrying tests that EFD manages.
|
|
1933
|
+
impactedTest.retries = 0
|
|
1942
1934
|
markEfdManagedTest(impactedTest)
|
|
1943
1935
|
const fileSuite = getSuiteType(impactedTest, 'file')
|
|
1944
1936
|
if (!fileSuitesWithImpactedTestsToProjects.has(fileSuite)) {
|
|
@@ -1946,14 +1938,15 @@ function processRootSuite (createRootSuiteReturnValue) {
|
|
|
1946
1938
|
}
|
|
1947
1939
|
}
|
|
1948
1940
|
}
|
|
1949
|
-
// If something
|
|
1941
|
+
// If something changes in the file, all tests in the file are impacted, except attempt-to-fix tests managed above.
|
|
1950
1942
|
applyRetriesToTests(
|
|
1951
1943
|
fileSuitesWithImpactedTestsToProjects,
|
|
1952
|
-
() =>
|
|
1944
|
+
(test) => !test._ddIsAttemptToFix,
|
|
1953
1945
|
[
|
|
1954
1946
|
'_ddIsModified',
|
|
1955
1947
|
'_ddIsEfdRetry',
|
|
1956
1948
|
(test) => (isKnownTestsEnabled && isNewTest(test) ? '_ddIsNew' : null),
|
|
1949
|
+
(test) => test._ddIsQuarantined && '_ddIsQuarantined',
|
|
1957
1950
|
],
|
|
1958
1951
|
earlyFlakeDetectionRetryPolicy.schedulingRetryCount,
|
|
1959
1952
|
(copiedTest, originalTest, retryIndex) => {
|
|
@@ -1981,7 +1974,8 @@ function processRootSuite (createRootSuiteReturnValue) {
|
|
|
1981
1974
|
const fileSuitesWithNewTestsToProjects = new Map()
|
|
1982
1975
|
for (const newTest of newTests) {
|
|
1983
1976
|
newTest._ddIsNew = true
|
|
1984
|
-
if (shouldRunEarlyFlakeDetection() && newTest.expectedStatus !== 'skipped' &&
|
|
1977
|
+
if (shouldRunEarlyFlakeDetection() && newTest.expectedStatus !== 'skipped' &&
|
|
1978
|
+
!newTest._ddIsModified && !newTest._ddIsAttemptToFix) {
|
|
1985
1979
|
// Prevent ATR or `--retries` from retrying tests that EFD manages.
|
|
1986
1980
|
newTest.retries = 0
|
|
1987
1981
|
markEfdManagedTest(newTest)
|
|
@@ -1994,8 +1988,12 @@ function processRootSuite (createRootSuiteReturnValue) {
|
|
|
1994
1988
|
|
|
1995
1989
|
applyRetriesToTests(
|
|
1996
1990
|
fileSuitesWithNewTestsToProjects,
|
|
1997
|
-
isNewTest,
|
|
1998
|
-
[
|
|
1991
|
+
(test) => !test._ddIsAttemptToFix && isNewTest(test),
|
|
1992
|
+
[
|
|
1993
|
+
'_ddIsNew',
|
|
1994
|
+
'_ddIsEfdRetry',
|
|
1995
|
+
(test) => test._ddIsQuarantined && '_ddIsQuarantined',
|
|
1996
|
+
],
|
|
1999
1997
|
earlyFlakeDetectionRetryPolicy.schedulingRetryCount,
|
|
2000
1998
|
(copiedTest, originalTest, retryIndex) => {
|
|
2001
1999
|
markEfdRetryTest(copiedTest, retryIndex, originalTest)
|
|
@@ -2447,6 +2445,7 @@ function generateSummaryWrapper (generateSummary) {
|
|
|
2447
2445
|
line: testSourceLine,
|
|
2448
2446
|
},
|
|
2449
2447
|
_ddIsNew: isNew,
|
|
2448
|
+
_ddIsAttemptToFix: isAttemptToFix,
|
|
2450
2449
|
_ddIsDisabled: isDisabled,
|
|
2451
2450
|
_ddIsModified: isModified,
|
|
2452
2451
|
_ddIsQuarantined: isQuarantined,
|
|
@@ -2461,6 +2460,7 @@ function generateSummaryWrapper (generateSummary) {
|
|
|
2461
2460
|
testSourceLine,
|
|
2462
2461
|
browserName,
|
|
2463
2462
|
isNew,
|
|
2463
|
+
isAttemptToFix,
|
|
2464
2464
|
isDisabled,
|
|
2465
2465
|
isModified,
|
|
2466
2466
|
isQuarantined,
|