dd-trace 6.4.0 → 6.6.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/README.electron.md +7 -0
- package/README.md +17 -0
- package/ci/diagnose.js +2100 -0
- package/ci/init.js +23 -2
- package/ci/runbook.md +198 -0
- package/ci/test-optimization-validation/approval-artifacts.js +143 -0
- package/ci/test-optimization-validation/approval.js +299 -0
- package/ci/test-optimization-validation/artifact-id.js +20 -0
- package/ci/test-optimization-validation/bounded-json.js +121 -0
- package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
- package/ci/test-optimization-validation/ci-discovery.js +181 -0
- package/ci/test-optimization-validation/ci-remediation.js +210 -0
- package/ci/test-optimization-validation/cli.js +903 -0
- package/ci/test-optimization-validation/command-blocker.js +81 -0
- package/ci/test-optimization-validation/command-output-policy.js +206 -0
- package/ci/test-optimization-validation/command-runner.js +707 -0
- package/ci/test-optimization-validation/command-suitability.js +471 -0
- package/ci/test-optimization-validation/executable-approval.js +48 -0
- package/ci/test-optimization-validation/executable.js +480 -0
- package/ci/test-optimization-validation/generated-file-policy.js +63 -0
- package/ci/test-optimization-validation/generated-files.js +351 -0
- package/ci/test-optimization-validation/generated-verifier.js +196 -0
- package/ci/test-optimization-validation/init-probe-preload.js +163 -0
- package/ci/test-optimization-validation/init-probe.js +246 -0
- package/ci/test-optimization-validation/late-initialization.js +63 -0
- package/ci/test-optimization-validation/local-command.js +163 -0
- package/ci/test-optimization-validation/manifest-loader.js +133 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
- package/ci/test-optimization-validation/manifest-schema.js +862 -0
- package/ci/test-optimization-validation/offline-fixtures.js +327 -0
- package/ci/test-optimization-validation/offline-output.js +406 -0
- package/ci/test-optimization-validation/payload-normalizer.js +72 -0
- package/ci/test-optimization-validation/plan-writer.js +1120 -0
- package/ci/test-optimization-validation/preflight-runner.js +114 -0
- package/ci/test-optimization-validation/redaction.js +331 -0
- package/ci/test-optimization-validation/report-writer.js +1508 -0
- package/ci/test-optimization-validation/safe-files.js +203 -0
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
- package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
- package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
- package/ci/test-optimization-validation/setup-runner.js +97 -0
- package/ci/test-optimization-validation/static-diagnosis.js +159 -0
- package/ci/test-optimization-validation/test-output.js +129 -0
- package/ci/test-optimization-validation-manifest.schema.json +1 -0
- package/ci/validate-test-optimization.js +3 -0
- package/ext/exporters.js +1 -0
- package/index.d.ts +121 -8
- package/init.js +18 -0
- package/initialize.mjs +1 -1
- package/loader-hook.mjs +28 -18
- package/openfeature.d.ts +1 -0
- package/openfeature.js +4 -0
- package/package.json +11 -8
- package/packages/datadog-instrumentations/src/ai.js +8 -2
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
- package/packages/datadog-instrumentations/src/cucumber.js +31 -19
- package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
- package/packages/datadog-instrumentations/src/fastify.js +7 -11
- package/packages/datadog-instrumentations/src/helpers/channel.js +74 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
- package/packages/datadog-instrumentations/src/jest.js +44 -17
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +79 -32
- package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
- package/packages/datadog-instrumentations/src/mongodb.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/mquery.js +2 -2
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +24 -0
- package/packages/datadog-instrumentations/src/nyc.js +0 -2
- package/packages/datadog-instrumentations/src/oracledb.js +2 -2
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/playwright.js +162 -46
- package/packages/datadog-instrumentations/src/process.js +3 -0
- package/packages/datadog-instrumentations/src/router.js +18 -8
- package/packages/datadog-instrumentations/src/selenium.js +52 -26
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +3 -3
- package/packages/datadog-instrumentations/src/vitest-main.js +14 -28
- package/packages/datadog-instrumentations/src/vitest-util.js +0 -7
- package/packages/datadog-instrumentations/src/vitest-worker.js +5 -8
- package/packages/datadog-instrumentations/src/ws.js +2 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
- package/packages/datadog-plugin-cucumber/src/index.js +3 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +19 -57
- package/packages/datadog-plugin-cypress/src/index.js +6 -1
- package/packages/datadog-plugin-cypress/src/support.js +92 -26
- package/packages/datadog-plugin-electron/src/ipc.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +87 -45
- package/packages/datadog-plugin-graphql/src/validate.js +2 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +2 -1
- package/packages/datadog-plugin-playwright/src/index.js +181 -65
- package/packages/datadog-plugin-router/src/index.js +11 -2
- package/packages/datadog-plugin-selenium/src/index.js +5 -36
- package/packages/datadog-plugin-vitest/src/index.js +5 -5
- package/packages/datadog-plugin-ws/src/close.js +2 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -1
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/datadog-plugin-ws/src/server.js +2 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
- package/packages/dd-trace/src/azure_metadata.js +2 -1
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +41 -3
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +7 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +1 -1
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
- package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +168 -8
- package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +16 -0
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +10 -0
- package/packages/dd-trace/src/config/supported-configurations.json +66 -0
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
- package/packages/dd-trace/src/exporters/common/request.js +59 -30
- package/packages/dd-trace/src/exporters/common/url.js +15 -1
- package/packages/dd-trace/src/feature-registry.js +10 -3
- package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
- package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
- package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
- package/packages/dd-trace/src/llmobs/noop.js +6 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
- package/packages/dd-trace/src/llmobs/sdk.js +17 -0
- package/packages/dd-trace/src/llmobs/tagger.js +68 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
- package/packages/dd-trace/src/llmobs/util.js +32 -0
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
- package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
- package/packages/dd-trace/src/openfeature/index.js +0 -2
- package/packages/dd-trace/src/openfeature/noop.js +1 -28
- package/packages/dd-trace/src/openfeature/register.js +16 -27
- package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
- package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
- package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
- package/packages/dd-trace/src/opentelemetry/span.js +5 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
- package/packages/dd-trace/src/plugins/util/git.js +3 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
- package/packages/dd-trace/src/plugins/util/test.js +56 -4
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +1 -0
- package/packages/dd-trace/src/proxy.js +84 -7
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/standalone/index.js +0 -14
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +26 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
|
@@ -419,7 +419,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
419
419
|
testSuiteFinishCh.publish({
|
|
420
420
|
status: getDatadogStatus(testSuiteResult),
|
|
421
421
|
deferFlush: true,
|
|
422
|
-
|
|
422
|
+
onDone: noop,
|
|
423
423
|
...testSuiteCtx.currentStore,
|
|
424
424
|
})
|
|
425
425
|
testSuiteContexts.delete(testModuleId)
|
|
@@ -784,7 +784,7 @@ function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testPrope
|
|
|
784
784
|
|
|
785
785
|
return {
|
|
786
786
|
errors,
|
|
787
|
-
finalAttempt: attempts
|
|
787
|
+
finalAttempt: attempts.at(-1),
|
|
788
788
|
nonFinalAttempts: attempts.slice(0, -1),
|
|
789
789
|
state,
|
|
790
790
|
status,
|
|
@@ -880,7 +880,7 @@ function reportFinalTestAttempt (testReport) {
|
|
|
880
880
|
const finalAttempt = testReport.finalAttempt
|
|
881
881
|
|
|
882
882
|
if (status === 'fail') {
|
|
883
|
-
const error = errors
|
|
883
|
+
const error = errors.at(-1) || errors[0]
|
|
884
884
|
reportTestAttempt(testReport, finalAttempt || {
|
|
885
885
|
error,
|
|
886
886
|
finalStatus,
|
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
getTestSuitePath,
|
|
17
17
|
isModifiedTest,
|
|
18
18
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
19
|
+
const { getChannelPromise } = require('./helpers/channel')
|
|
19
20
|
const { addHook } = require('./helpers/instrument')
|
|
20
21
|
const noWorkerInit = require('./vitest-main-no-worker-init')
|
|
21
22
|
const {
|
|
@@ -38,7 +39,6 @@ const {
|
|
|
38
39
|
workerReportLogsCh,
|
|
39
40
|
codeCoverageReportCh,
|
|
40
41
|
findExportByName,
|
|
41
|
-
getChannelPromise,
|
|
42
42
|
getTypeTasks,
|
|
43
43
|
getWorkspaceProject,
|
|
44
44
|
setProvidedContext,
|
|
@@ -433,7 +433,8 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
|
|
|
433
433
|
err,
|
|
434
434
|
libraryConfig,
|
|
435
435
|
requestErrorTags: receivedRequestErrorTags = {},
|
|
436
|
-
} = await getChannelPromise(libraryConfigurationCh,
|
|
436
|
+
} = await getChannelPromise(libraryConfigurationCh, {
|
|
437
|
+
frameworkVersion,
|
|
437
438
|
isVitestNoWorkerInitActive: shouldInstallNoWorkerInit,
|
|
438
439
|
})
|
|
439
440
|
requestErrorTags = receivedRequestErrorTags
|
|
@@ -450,7 +451,7 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
|
|
|
450
451
|
resetMainProcessProvidedContext(ctx)
|
|
451
452
|
|
|
452
453
|
if (testSessionConfigurationCh.hasSubscribers) {
|
|
453
|
-
testSessionConfiguration = await getChannelPromise(testSessionConfigurationCh, frameworkVersion)
|
|
454
|
+
testSessionConfiguration = await getChannelPromise(testSessionConfigurationCh, { frameworkVersion }) || {}
|
|
454
455
|
const {
|
|
455
456
|
testSessionId,
|
|
456
457
|
testModuleId,
|
|
@@ -494,7 +495,7 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
|
|
|
494
495
|
|
|
495
496
|
if (isKnownTestsEnabled) {
|
|
496
497
|
const currentKnownTestsResponse = knownTestsResponse || await getChannelPromise(knownTestsCh)
|
|
497
|
-
if (currentKnownTestsResponse.err) {
|
|
498
|
+
if (!currentKnownTestsResponse || currentKnownTestsResponse.err) {
|
|
498
499
|
isEarlyFlakeDetectionEnabled = false
|
|
499
500
|
} else {
|
|
500
501
|
knownTests = currentKnownTestsResponse.knownTests
|
|
@@ -538,12 +539,13 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
|
|
|
538
539
|
}
|
|
539
540
|
|
|
540
541
|
if (isTestManagementTestsEnabled) {
|
|
541
|
-
const
|
|
542
|
+
const testManagementResponse =
|
|
542
543
|
testManagementTestsResponse || await getChannelPromise(testManagementTestsCh)
|
|
543
|
-
if (err) {
|
|
544
|
+
if (!testManagementResponse || testManagementResponse.err) {
|
|
544
545
|
isTestManagementTestsEnabled = false
|
|
545
546
|
log.error('Could not get test management tests.')
|
|
546
547
|
} else {
|
|
548
|
+
const { testManagementTests: receivedTestManagementTests } = testManagementResponse
|
|
547
549
|
testManagementTests = receivedTestManagementTests
|
|
548
550
|
testManagementTestsBySuite = getTestManagementTestsBySuite(receivedTestManagementTests)
|
|
549
551
|
shouldSendTestProperties = true
|
|
@@ -558,8 +560,7 @@ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications, s
|
|
|
558
560
|
|
|
559
561
|
if (isImpactedTestsEnabled) {
|
|
560
562
|
const modifiedFilesResponse = await getChannelPromise(modifiedFilesCh)
|
|
561
|
-
|
|
562
|
-
if (err) {
|
|
563
|
+
if (!modifiedFilesResponse || modifiedFilesResponse.err) {
|
|
563
564
|
log.error('Could not get modified tests.')
|
|
564
565
|
} else {
|
|
565
566
|
modifiedFiles = modifiedFilesResponse.modifiedFiles
|
|
@@ -812,18 +813,13 @@ function getFinishWrapper (exitOrClose) {
|
|
|
812
813
|
return exitOrClose.apply(this, arguments)
|
|
813
814
|
}
|
|
814
815
|
|
|
815
|
-
let onFinish
|
|
816
|
-
|
|
817
|
-
const flushPromise = new Promise(resolve => {
|
|
818
|
-
onFinish = resolve
|
|
819
|
-
})
|
|
820
816
|
const failedSuites = this.state.getFailedFilepaths()
|
|
821
817
|
let error
|
|
822
818
|
if (failedSuites.length) {
|
|
823
819
|
error = new Error(`Test suites failed: ${failedSuites.length}.`)
|
|
824
820
|
}
|
|
825
821
|
|
|
826
|
-
testSessionFinishCh
|
|
822
|
+
const flushPromise = getChannelPromise(testSessionFinishCh, {
|
|
827
823
|
status: getSessionStatus(this.state),
|
|
828
824
|
testCodeCoverageLinesTotal,
|
|
829
825
|
error,
|
|
@@ -833,7 +829,6 @@ function getFinishWrapper (exitOrClose) {
|
|
|
833
829
|
requestErrorTags,
|
|
834
830
|
vitestPool,
|
|
835
831
|
isVitestNoWorkerInitActive,
|
|
836
|
-
onFinish,
|
|
837
832
|
})
|
|
838
833
|
|
|
839
834
|
logTestOptimizationSummary({ attemptToFixExecutions, newTestsWithDynamicNames })
|
|
@@ -842,9 +837,7 @@ function getFinishWrapper (exitOrClose) {
|
|
|
842
837
|
|
|
843
838
|
// If coverage was generated, publish coverage report channel for upload
|
|
844
839
|
if (coverageRootDir && codeCoverageReportCh.hasSubscribers) {
|
|
845
|
-
await
|
|
846
|
-
codeCoverageReportCh.publish({ rootDir: coverageRootDir, onDone: resolve })
|
|
847
|
-
})
|
|
840
|
+
await getChannelPromise(codeCoverageReportCh, { rootDir: coverageRootDir })
|
|
848
841
|
}
|
|
849
842
|
|
|
850
843
|
return exitOrClose.apply(this, arguments)
|
|
@@ -1213,16 +1206,11 @@ async function reportTypecheckFile (file, sessionConfiguration, frameworkVersion
|
|
|
1213
1206
|
testSuiteErrorCh.runStores(testSuiteCtx, () => {})
|
|
1214
1207
|
}
|
|
1215
1208
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
onFinish = resolve
|
|
1219
|
-
})
|
|
1220
|
-
testSuiteFinishCh.publish({
|
|
1209
|
+
await getChannelPromise(testSuiteFinishCh, {
|
|
1210
|
+
frameworkVersion,
|
|
1221
1211
|
status: getTypecheckTaskStatus(file),
|
|
1222
|
-
onFinish,
|
|
1223
1212
|
...testSuiteCtx.currentStore,
|
|
1224
1213
|
})
|
|
1225
|
-
await onFinishPromise
|
|
1226
1214
|
}
|
|
1227
1215
|
|
|
1228
1216
|
async function reportTypecheckResults (result, frameworkVersion, ctx, typechecker) {
|
|
@@ -1234,7 +1222,7 @@ async function reportTypecheckResults (result, frameworkVersion, ctx, typechecke
|
|
|
1234
1222
|
}
|
|
1235
1223
|
const providedContext = getMainProcessProvidedContext(ctx)
|
|
1236
1224
|
const sessionConfiguration = testSessionConfigurationCh.hasSubscribers
|
|
1237
|
-
? await getChannelPromise(testSessionConfigurationCh, frameworkVersion)
|
|
1225
|
+
? await getChannelPromise(testSessionConfigurationCh, { frameworkVersion }) || {}
|
|
1238
1226
|
: {}
|
|
1239
1227
|
|
|
1240
1228
|
await Promise.all(result.files.map(file => reportTypecheckFile(
|
|
@@ -1343,10 +1331,8 @@ function wrapTinyPoolRun (TinyPool) {
|
|
|
1343
1331
|
|
|
1344
1332
|
shimmer.wrap(TinyPool.prototype, 'run', run => async function () {
|
|
1345
1333
|
// We have to do this before and after because the threads list gets recycled, that is, the processes are re-created
|
|
1346
|
-
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1347
1334
|
this.threads.forEach(threadHandler)
|
|
1348
1335
|
const runResult = await run.apply(this, arguments)
|
|
1349
|
-
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1350
1336
|
this.threads.forEach(threadHandler)
|
|
1351
1337
|
return runResult
|
|
1352
1338
|
})
|
|
@@ -39,12 +39,6 @@ function findExportByName (pkg, name) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function getChannelPromise (channelToPublishTo, frameworkVersion, payload) {
|
|
43
|
-
return new Promise(resolve => {
|
|
44
|
-
channelToPublishTo.publish({ ...payload, onDone: resolve, frameworkVersion })
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
|
|
48
42
|
function getTestRunnerExport (testPackage) {
|
|
49
43
|
return findExportByName(testPackage, 'VitestTestRunner') || findExportByName(testPackage, 'TestRunner')
|
|
50
44
|
}
|
|
@@ -239,7 +233,6 @@ module.exports = {
|
|
|
239
233
|
workerReportLogsCh,
|
|
240
234
|
codeCoverageReportCh,
|
|
241
235
|
findExportByName,
|
|
242
|
-
getChannelPromise,
|
|
243
236
|
getTestRunnerExport,
|
|
244
237
|
getTypeTasks,
|
|
245
238
|
getTestName,
|
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
recordAttemptToFixExecution,
|
|
10
10
|
logAttemptToFixTestExecution,
|
|
11
11
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
12
|
+
const { getChannelPromise } = require('./helpers/channel')
|
|
12
13
|
const { addHook } = require('./helpers/instrument')
|
|
13
14
|
const {
|
|
14
15
|
testStartCh,
|
|
@@ -661,11 +662,6 @@ addHook({
|
|
|
661
662
|
testSuiteStartCh.runStores(testSuiteCtx, () => {})
|
|
662
663
|
const startTestsResponse = await startTests.apply(this, arguments)
|
|
663
664
|
|
|
664
|
-
let onFinish = null
|
|
665
|
-
const onFinishPromise = new Promise(resolve => {
|
|
666
|
-
onFinish = resolve
|
|
667
|
-
})
|
|
668
|
-
|
|
669
665
|
const testTasks = getTypeTasks(startTestsResponse[0].tasks)
|
|
670
666
|
const testEventPromises = []
|
|
671
667
|
|
|
@@ -811,9 +807,10 @@ addHook({
|
|
|
811
807
|
testSuiteErrorCh.runStores(testSuiteCtx, () => {})
|
|
812
808
|
}
|
|
813
809
|
|
|
814
|
-
testSuiteFinishCh
|
|
815
|
-
|
|
816
|
-
|
|
810
|
+
await getChannelPromise(testSuiteFinishCh, {
|
|
811
|
+
status: testSuiteResult.state,
|
|
812
|
+
...testSuiteCtx.currentStore,
|
|
813
|
+
})
|
|
817
814
|
|
|
818
815
|
return startTestsResponse
|
|
819
816
|
})
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { tracingChannel } = /** @type {import('node:diagnostics_channel')} */ (require('dc-polyfill'))
|
|
4
4
|
|
|
5
5
|
const shimmer = require('../../datadog-shimmer')
|
|
6
|
+
const { getSegment } = require('../../dd-trace/src/util')
|
|
6
7
|
const {
|
|
7
8
|
addHook,
|
|
8
9
|
channel,
|
|
@@ -106,7 +107,7 @@ function createWrapEmit (emit) {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
const ctx = { req }
|
|
109
|
-
ctx.req.resStatus = headers[0]
|
|
110
|
+
ctx.req.resStatus = getSegment(headers[0], ' ', 1)
|
|
110
111
|
|
|
111
112
|
emitCh.runStores(ctx, () => {
|
|
112
113
|
try {
|
|
@@ -94,7 +94,7 @@ class RunInChildContextPlugin extends BaseContextPlugin {
|
|
|
94
94
|
static retryable = false
|
|
95
95
|
|
|
96
96
|
bindStart (ctx) {
|
|
97
|
-
if (SUPPRESSED_CHILD_CONTEXT_SUBTYPES.has(
|
|
97
|
+
if (SUPPRESSED_CHILD_CONTEXT_SUBTYPES.has(getRunInChildContextSubtype(ctx))) {
|
|
98
98
|
// Pass the active store through unchanged so any nested spans
|
|
99
99
|
// remain parented to the surrounding map/parallel span
|
|
100
100
|
ctx.suppressed = true
|
|
@@ -105,7 +105,7 @@ class RunInChildContextPlugin extends BaseContextPlugin {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// runInChildContext has two overloads: `(name, fn, options)` and `(fn, options)`.
|
|
108
|
-
function
|
|
108
|
+
function getRunInChildContextSubtype (ctx) {
|
|
109
109
|
const args = ctx.arguments || []
|
|
110
110
|
const opts = typeof args[0] === 'function' ? args[1] : args[2]
|
|
111
111
|
return opts?.subType
|
|
@@ -16,7 +16,8 @@ const REPLAYED_STATUSES = new Set(['SUCCEEDED', 'FAILED'])
|
|
|
16
16
|
* @returns {{ stepId: string | undefined, stepData: object | undefined }}
|
|
17
17
|
*/
|
|
18
18
|
function getStepDataForNext (ctxImpl) {
|
|
19
|
-
|
|
19
|
+
// @aws/durable-execution-sdk-js@2.2.0 renames .getNextStepId() to .peekStepId()
|
|
20
|
+
const stepId = ctxImpl?.peekStepId?.() ?? ctxImpl?.getNextStepId?.()
|
|
20
21
|
const stepData = stepId ? ctxImpl?._executionContext?.getStepData?.(stepId) : undefined
|
|
21
22
|
return { stepId, stepData }
|
|
22
23
|
}
|
|
@@ -120,8 +120,8 @@ const extractQueueMetadata = queueURL => {
|
|
|
120
120
|
|
|
121
121
|
if (parts.length < minParts) return null
|
|
122
122
|
|
|
123
|
-
const accountId = parts
|
|
124
|
-
const queueName = parts
|
|
123
|
+
const accountId = parts.at(-2)
|
|
124
|
+
const queueName = parts.at(-1)
|
|
125
125
|
const host = hasScheme ? parts[1] : parts[0]
|
|
126
126
|
|
|
127
127
|
let region = 'us-east-1' // Default region if not found in URL
|
|
@@ -72,6 +72,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
72
72
|
isEarlyFlakeDetectionFaulty,
|
|
73
73
|
isTestManagementTestsEnabled,
|
|
74
74
|
isParallel,
|
|
75
|
+
onDone,
|
|
75
76
|
}) => {
|
|
76
77
|
this._exportPendingWorkerTraces()
|
|
77
78
|
const {
|
|
@@ -127,7 +128,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
127
128
|
})
|
|
128
129
|
|
|
129
130
|
this.libraryConfig = null
|
|
130
|
-
this.tracer._exporter.flush()
|
|
131
|
+
this.tracer._exporter.flush(onDone)
|
|
131
132
|
})
|
|
132
133
|
|
|
133
134
|
this.addSub('ci:cucumber:test-suite:start', ({
|
|
@@ -438,7 +439,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
438
439
|
const isModified = isModifiedTest(
|
|
439
440
|
testScenarioPath,
|
|
440
441
|
scenario.location.line,
|
|
441
|
-
scenario.steps
|
|
442
|
+
scenario.steps.at(-1).location.line,
|
|
442
443
|
modifiedFiles,
|
|
443
444
|
'cucumber'
|
|
444
445
|
)
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
// Capture real timers at module load, before any test can install fake timers.
|
|
4
4
|
const { performance } = require('perf_hooks')
|
|
5
|
-
const { statSync } = require('node:fs')
|
|
6
5
|
const { basename } = require('node:path')
|
|
7
6
|
const dateNow = Date.now
|
|
8
7
|
|
|
9
8
|
const { createCoverageMap } = require('../../../vendor/dist/istanbul-lib-coverage')
|
|
10
9
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
10
|
+
const { RUM_TEST_EXECUTION_ID_COOKIE_NAME } = require('../../dd-trace/src/ci-visibility/rum')
|
|
11
11
|
const {
|
|
12
12
|
TEST_STATUS,
|
|
13
|
-
|
|
13
|
+
setRumTestTags,
|
|
14
14
|
TEST_CODE_OWNERS,
|
|
15
15
|
getTestEnvironmentMetadata,
|
|
16
16
|
getTestLevelsMetadataTags,
|
|
@@ -79,14 +79,19 @@ const {
|
|
|
79
79
|
getMaxEfdRetryCount,
|
|
80
80
|
getPullRequestBaseBranch,
|
|
81
81
|
TEST_FINAL_STATUS,
|
|
82
|
-
TEST_FAILURE_SCREENSHOT_UPLOADED,
|
|
83
|
-
TEST_FAILURE_SCREENSHOT_UPLOAD_ERROR,
|
|
84
82
|
getTestOptimizationRequestResults,
|
|
85
83
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
86
84
|
const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
|
|
87
85
|
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
88
86
|
const { RESOURCE_NAME } = require('../../../ext/tags')
|
|
89
87
|
const getConfig = require('../../dd-trace/src/config')
|
|
88
|
+
const {
|
|
89
|
+
SCREENSHOT_UPLOAD_RESULT_ERROR,
|
|
90
|
+
SCREENSHOT_UPLOAD_RESULT_UPLOADED,
|
|
91
|
+
getScreenshotCapturedAtMs,
|
|
92
|
+
getScreenshotUploadResult,
|
|
93
|
+
setScreenshotUploadTags,
|
|
94
|
+
} = require('../../dd-trace/src/ci-visibility/test-screenshot')
|
|
90
95
|
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
|
|
91
96
|
const log = require('../../dd-trace/src/log')
|
|
92
97
|
|
|
@@ -141,8 +146,6 @@ const CYPRESS_STATUS_TO_TEST_STATUS = {
|
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
const SCREENSHOT_ATTEMPT_RE = /\(attempt \d+\)/
|
|
144
|
-
const SCREENSHOT_UPLOAD_RESULT_UPLOADED = 'uploaded'
|
|
145
|
-
const SCREENSHOT_UPLOAD_RESULT_ERROR = 'error'
|
|
146
149
|
|
|
147
150
|
function getScreenshotFilePath (screenshot) {
|
|
148
151
|
return typeof screenshot === 'string' ? screenshot : screenshot?.path
|
|
@@ -155,31 +158,6 @@ function isFailureScreenshotByMetadata (screenshot, screenshotFilePath) {
|
|
|
155
158
|
return screenshotFilePath.includes('(failed)')
|
|
156
159
|
}
|
|
157
160
|
|
|
158
|
-
/**
|
|
159
|
-
* Resolves a screenshot's capture time (epoch ms) for the media upload. Cypress
|
|
160
|
-
* screenshot objects carry an ISO `takenAt`; falls back to the file's mtime, then
|
|
161
|
-
* to the current time. Stamped once here and reused on retry via the idempotency
|
|
162
|
-
* key, so the stored object is overwritten rather than duplicated.
|
|
163
|
-
*
|
|
164
|
-
* @param {object|string} screenshot - Cypress screenshot object or path
|
|
165
|
-
* @param {string} filePath - Resolved screenshot file path
|
|
166
|
-
* @returns {number} Capture time in epoch milliseconds
|
|
167
|
-
*/
|
|
168
|
-
function getScreenshotCapturedAtMs (screenshot, filePath) {
|
|
169
|
-
const takenAt = screenshot !== null && typeof screenshot === 'object' ? screenshot.takenAt : undefined
|
|
170
|
-
if (takenAt) {
|
|
171
|
-
const parsedMs = new Date(takenAt).getTime()
|
|
172
|
-
if (Number.isInteger(parsedMs) && parsedMs > 0) {
|
|
173
|
-
return parsedMs
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
try {
|
|
177
|
-
return Math.floor(statSync(filePath).mtimeMs)
|
|
178
|
-
} catch {
|
|
179
|
-
return dateNow()
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
161
|
function isFailureScreenshotForUpload (screenshot) {
|
|
184
162
|
const screenshotFilePath = getScreenshotFilePath(screenshot)
|
|
185
163
|
if (!screenshotFilePath) {
|
|
@@ -240,27 +218,6 @@ function getTestScreenshots (cypressTest, attemptIndex, specScreenshots) {
|
|
|
240
218
|
return specScreenshots.filter(screenshot => isScreenshotForTestAttempt(screenshot, titleParts, attemptIndex))
|
|
241
219
|
}
|
|
242
220
|
|
|
243
|
-
function getScreenshotUploadResult (uploadResults) {
|
|
244
|
-
let hasUploaded = false
|
|
245
|
-
for (const uploadResult of uploadResults) {
|
|
246
|
-
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_ERROR) {
|
|
247
|
-
return SCREENSHOT_UPLOAD_RESULT_ERROR
|
|
248
|
-
}
|
|
249
|
-
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_UPLOADED) {
|
|
250
|
-
hasUploaded = true
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return hasUploaded ? SCREENSHOT_UPLOAD_RESULT_UPLOADED : undefined
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function setScreenshotUploadTags (testSpan, uploadResult) {
|
|
257
|
-
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_ERROR) {
|
|
258
|
-
testSpan.setTag(TEST_FAILURE_SCREENSHOT_UPLOAD_ERROR, 'true')
|
|
259
|
-
} else if (uploadResult === SCREENSHOT_UPLOAD_RESULT_UPLOADED) {
|
|
260
|
-
testSpan.setTag(TEST_FAILURE_SCREENSHOT_UPLOADED, 'true')
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
221
|
function getSessionStatus (summary) {
|
|
265
222
|
if (summary.totalFailed !== undefined && summary.totalFailed > 0) {
|
|
266
223
|
return 'fail'
|
|
@@ -901,6 +858,12 @@ class CypressPlugin {
|
|
|
901
858
|
if (isFlakyTestRetriesEnabled && this.isTestIsolationEnabled) {
|
|
902
859
|
this.isFlakyTestRetriesEnabled = true
|
|
903
860
|
this.flakyTestRetriesCount = flakyTestRetriesCount ?? 0
|
|
861
|
+
if (typeof this.cypressConfig.retries === 'number') {
|
|
862
|
+
this.cypressConfig.retries = {
|
|
863
|
+
openMode: this.cypressConfig.retries,
|
|
864
|
+
runMode: this.cypressConfig.retries,
|
|
865
|
+
}
|
|
866
|
+
}
|
|
904
867
|
this.cypressConfig.retries.runMode = this.flakyTestRetriesCount
|
|
905
868
|
} else {
|
|
906
869
|
this.flakyTestRetriesCount = 0
|
|
@@ -1444,13 +1407,13 @@ class CypressPlugin {
|
|
|
1444
1407
|
// and create a skipped test span for each of them
|
|
1445
1408
|
for (const { title } of cypressTests) {
|
|
1446
1409
|
const cypressTestName = title.join(' ')
|
|
1447
|
-
const isTestFinished = finishedTests.
|
|
1410
|
+
const isTestFinished = finishedTests.some(({ testName }) => cypressTestName === testName)
|
|
1448
1411
|
|
|
1449
1412
|
if (isTestFinished) {
|
|
1450
1413
|
continue
|
|
1451
1414
|
}
|
|
1452
1415
|
|
|
1453
|
-
const isSkippedByItr = this.testsToSkip.
|
|
1416
|
+
const isSkippedByItr = this.testsToSkip.some(test =>
|
|
1454
1417
|
cypressTestName === test.name && spec.relative === test.suite
|
|
1455
1418
|
)
|
|
1456
1419
|
const testSourceFile = spec.absolute && this.repositoryRoot
|
|
@@ -1721,6 +1684,7 @@ class CypressPlugin {
|
|
|
1721
1684
|
repositoryRoot: this.repositoryRoot,
|
|
1722
1685
|
isTestIsolationEnabled: this.isTestIsolationEnabled,
|
|
1723
1686
|
rumFlushWaitMillis: this.rumFlushWaitMillis,
|
|
1687
|
+
rumTestExecutionIdCookieName: RUM_TEST_EXECUTION_ID_COOKIE_NAME,
|
|
1724
1688
|
}
|
|
1725
1689
|
|
|
1726
1690
|
this.testSuiteSpan ||= this.getTestSuiteSpan({ testSuite, testSuiteAbsolutePath })
|
|
@@ -1847,9 +1811,7 @@ class CypressPlugin {
|
|
|
1847
1811
|
if (error) {
|
|
1848
1812
|
this.activeTestSpan.setTag('error', error)
|
|
1849
1813
|
}
|
|
1850
|
-
|
|
1851
|
-
this.activeTestSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
1852
|
-
}
|
|
1814
|
+
setRumTestTags(this.activeTestSpan, isRUMActive)
|
|
1853
1815
|
// Source-line resolution strategy:
|
|
1854
1816
|
// 1. If plain JS and no source map, trust invocationDetails.line directly.
|
|
1855
1817
|
// 2. Otherwise, try invocationDetails.stack line mapped through source map.
|
|
@@ -80,7 +80,12 @@ class CypressPlugin extends Plugin {
|
|
|
80
80
|
// Already initialized by manual plugin call — just chain user handlers.
|
|
81
81
|
// Pass the plugin's afterScreenshot so chaining a user handler doesn't drop the upload
|
|
82
82
|
// (the chained registration replaces the one plugin.js set, so it must include it).
|
|
83
|
-
|
|
83
|
+
if (userAfterSpecHandlers.length > 0) {
|
|
84
|
+
on('after:spec', (spec, results) => userAfterSpecHandlers.reduce(
|
|
85
|
+
(chain, handler) => chain.then(() => handler(spec, results)),
|
|
86
|
+
Promise.resolve()
|
|
87
|
+
))
|
|
88
|
+
}
|
|
84
89
|
registerAfterScreenshot(datadogAfterScreenshotHandler)
|
|
85
90
|
registerAfterRunWithCleanup()
|
|
86
91
|
payload.registered = true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id'
|
|
4
3
|
let rumFlushWaitMillis = 500
|
|
4
|
+
let rumTestExecutionIdCookieName
|
|
5
5
|
|
|
6
6
|
let isEarlyFlakeDetectionEnabled = false
|
|
7
7
|
let isKnownTestsEnabled = false
|
|
@@ -129,6 +129,89 @@ function runBeforeEachTask (test) {
|
|
|
129
129
|
})
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* @param {string} message
|
|
134
|
+
* @param {unknown} error
|
|
135
|
+
* @returns {false}
|
|
136
|
+
*/
|
|
137
|
+
function logRumCorrelationCookieError (message, error) {
|
|
138
|
+
try {
|
|
139
|
+
Cypress.log({
|
|
140
|
+
name: 'dd-trace',
|
|
141
|
+
message,
|
|
142
|
+
consoleProps: () => ({ Error: error }),
|
|
143
|
+
})
|
|
144
|
+
} catch (loggingError) {
|
|
145
|
+
// eslint-disable-next-line no-console
|
|
146
|
+
console.error(message, error, loggingError)
|
|
147
|
+
}
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param {unknown} error
|
|
153
|
+
* @returns {false}
|
|
154
|
+
*/
|
|
155
|
+
function handleRumCorrelationCookieError (error) {
|
|
156
|
+
return logRumCorrelationCookieError('Could not set the RUM correlation cookie', error)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {unknown} error
|
|
161
|
+
* @returns {false}
|
|
162
|
+
*/
|
|
163
|
+
function handleRumCorrelationCookieCleanupError (error) {
|
|
164
|
+
return logRumCorrelationCookieError('Could not clear the previous RUM correlation cookie', error)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @param {string} traceId
|
|
169
|
+
* @returns {Promise<boolean>}
|
|
170
|
+
*/
|
|
171
|
+
function setRumCorrelationCookie (traceId) {
|
|
172
|
+
if (typeof cy.now !== 'function') {
|
|
173
|
+
return Cypress.Promise.resolve(handleRumCorrelationCookieError(new Error('Cypress cy.now is not available')))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let clearCookiePromise = Cypress.Promise.resolve()
|
|
177
|
+
if (!isTestIsolationEnabled) {
|
|
178
|
+
clearCookiePromise = Cypress.Promise.try(() => {
|
|
179
|
+
return cy.now('clearCookie', rumTestExecutionIdCookieName, { log: false })
|
|
180
|
+
}).then(undefined, handleRumCorrelationCookieCleanupError)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return clearCookiePromise.then(() => {
|
|
184
|
+
return Cypress.Promise.try(() => {
|
|
185
|
+
return cy.now('setCookie', rumTestExecutionIdCookieName, traceId, { log: false })
|
|
186
|
+
})
|
|
187
|
+
}).then(() => true, handleRumCorrelationCookieError)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @param {boolean} isCookieSet
|
|
192
|
+
* @returns {void}
|
|
193
|
+
*/
|
|
194
|
+
function restartRumSession (isCookieSet) {
|
|
195
|
+
if (!isCookieSet || isTestIsolationEnabled || !originalWindow) {
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const rum = safeGetRum(originalWindow)
|
|
200
|
+
if (rum) {
|
|
201
|
+
try {
|
|
202
|
+
const evt = new originalWindow.MouseEvent('click', { bubbles: true, cancelable: true })
|
|
203
|
+
// The browser-sdk addEventListener wrapper filters out untrusted synthetic events
|
|
204
|
+
// unless __ddIsTrusted is set. Set it so the click triggers expandOrRenewSession().
|
|
205
|
+
// See: https://github.com/DataDog/browser-sdk/blob/v6.27.1/packages/core/src/browser/addEventListener.ts#L119
|
|
206
|
+
Object.defineProperty(evt, '__ddIsTrusted', { value: true })
|
|
207
|
+
originalWindow.dispatchEvent(evt)
|
|
208
|
+
} catch {}
|
|
209
|
+
if (rum.startView) {
|
|
210
|
+
rum.startView()
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
132
215
|
// Catch test failures for quarantined tests and suppress them
|
|
133
216
|
// By not re-throwing the error, Cypress marks the test as passed
|
|
134
217
|
// This allows quarantined tests to run but not affect the exit code
|
|
@@ -150,6 +233,8 @@ Cypress.on('fail', (err, runnable) => {
|
|
|
150
233
|
// If command:end fired for all commands (none in-flight) but the last command
|
|
151
234
|
// has no error, it means command:end fired before the error was attached to it.
|
|
152
235
|
if (!hadInFlightCommands && currentTestCommands.length > 0) {
|
|
236
|
+
// We have to support very old cypress versions in v5
|
|
237
|
+
// eslint-disable-next-line unicorn/prefer-at
|
|
153
238
|
const lastCommand = currentTestCommands[currentTestCommands.length - 1]
|
|
154
239
|
if (!lastCommand.error) {
|
|
155
240
|
lastCommand.error = { message: err.message, stack: err.stack, name: err.name }
|
|
@@ -316,36 +401,16 @@ beforeEach(function () {
|
|
|
316
401
|
if (shouldDiscard) {
|
|
317
402
|
this.currentTest._ddShouldDiscard = true
|
|
318
403
|
}
|
|
404
|
+
let rumCookiePromise
|
|
319
405
|
if (traceId) {
|
|
320
|
-
|
|
321
|
-
// When testIsolation:false, the page is not reset between tests, so the RUM session
|
|
322
|
-
// stopped in afterEach must be explicitly restarted so events in this test are
|
|
323
|
-
// associated with the new testExecutionId.
|
|
324
|
-
//
|
|
325
|
-
// After stopSession(), the RUM SDK creates a new session upon a user interaction
|
|
326
|
-
// (click, scroll, keydown, or touchstart). We dispatch a synthetic click on the window
|
|
327
|
-
// to trigger session renewal, then call startView() to establish a view boundary.
|
|
328
|
-
if (!isTestIsolationEnabled && originalWindow) {
|
|
329
|
-
const rum = safeGetRum(originalWindow)
|
|
330
|
-
if (rum) {
|
|
331
|
-
try {
|
|
332
|
-
const evt = new originalWindow.MouseEvent('click', { bubbles: true, cancelable: true })
|
|
333
|
-
// The browser-sdk addEventListener wrapper filters out untrusted synthetic events
|
|
334
|
-
// unless __ddIsTrusted is set. Set it so the click triggers expandOrRenewSession().
|
|
335
|
-
// See: https://github.com/DataDog/browser-sdk/blob/v6.27.1/packages/core/src/browser/addEventListener.ts#L119
|
|
336
|
-
Object.defineProperty(evt, '__ddIsTrusted', { value: true })
|
|
337
|
-
originalWindow.dispatchEvent(evt)
|
|
338
|
-
} catch {}
|
|
339
|
-
if (rum.startView) {
|
|
340
|
-
rum.startView()
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
})
|
|
406
|
+
rumCookiePromise = setRumCorrelationCookie(traceId)
|
|
345
407
|
}
|
|
346
408
|
if (shouldSkip) {
|
|
347
409
|
this.skip()
|
|
348
410
|
}
|
|
411
|
+
if (rumCookiePromise) {
|
|
412
|
+
return rumCookiePromise.then(restartRumSession)
|
|
413
|
+
}
|
|
349
414
|
}).then(() => {
|
|
350
415
|
// Clear any commands accumulated during DD-owned setup (e.g. setCookie, RUM restart)
|
|
351
416
|
// so they are not reported as user test steps.
|
|
@@ -370,6 +435,7 @@ before(function () {
|
|
|
370
435
|
isImpactedTestsEnabled = suiteConfig.isImpactedTestsEnabled
|
|
371
436
|
isModifiedTest = suiteConfig.isModifiedTest
|
|
372
437
|
isTestIsolationEnabled = suiteConfig.isTestIsolationEnabled
|
|
438
|
+
rumTestExecutionIdCookieName = suiteConfig.rumTestExecutionIdCookieName
|
|
373
439
|
if (Number.isFinite(suiteConfig.rumFlushWaitMillis)) {
|
|
374
440
|
rumFlushWaitMillis = suiteConfig.rumFlushWaitMillis
|
|
375
441
|
}
|
|
@@ -46,7 +46,7 @@ class ElectronRendererReceivePlugin extends ConsumerPlugin {
|
|
|
46
46
|
|
|
47
47
|
if (channel?.startsWith('datadog:')) return
|
|
48
48
|
|
|
49
|
-
const childOf = this._tracer.extract('text_map', args
|
|
49
|
+
const childOf = this._tracer.extract('text_map', args.at(-1))
|
|
50
50
|
|
|
51
51
|
if (childOf) {
|
|
52
52
|
args.pop()
|