dd-trace 6.13.0 → 6.15.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 +3 -1
- package/ci/init.js +8 -3
- package/ci/test-optimization-validation/ci-package-scripts.js +2 -2
- package/ci/test-optimization-validation/ci-remediation.js +6 -6
- package/ci/test-optimization-validation/command-blocker.js +7 -5
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +1 -1
- package/ci/test-optimization-validation/framework-adapters/vitest.js +3 -3
- package/ci/test-optimization-validation/package-check.js +1 -1
- package/ci/test-optimization-validation/report-writer.js +7 -5
- package/ci/vitest-no-worker-init-runner-setup.mjs +8 -0
- package/ci/vitest-no-worker-init-setup.mjs +13 -13
- package/ci/vitest-no-worker-init-v5-setup.mjs +4 -0
- package/index.d.ts +8 -0
- package/package.json +13 -10
- package/packages/datadog-esbuild/index.js +3 -1
- package/packages/datadog-instrumentations/src/cypress-config.js +19 -17
- package/packages/datadog-instrumentations/src/fs.js +24 -20
- package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -2
- package/packages/datadog-instrumentations/src/graphql.js +16 -16
- package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +504 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +265 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +95 -30
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +0 -25
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +83 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +85 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/mercurius.js +30 -12
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +14 -5
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +251 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +11 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +562 -27
- package/packages/datadog-instrumentations/src/jest.js +166 -45
- package/packages/datadog-instrumentations/src/knex.js +76 -0
- package/packages/datadog-instrumentations/src/mariadb.js +6 -0
- package/packages/datadog-instrumentations/src/mocha/common.js +59 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +66 -20
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +98 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -8
- package/packages/datadog-instrumentations/src/net.js +14 -17
- package/packages/datadog-instrumentations/src/next.js +212 -62
- package/packages/datadog-instrumentations/src/openai.js +42 -40
- package/packages/datadog-instrumentations/src/pg.js +15 -0
- package/packages/datadog-instrumentations/src/playwright.js +113 -13
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +40 -0
- package/packages/datadog-instrumentations/src/sequelize.js +94 -2
- package/packages/datadog-instrumentations/src/undici.js +53 -4
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +37 -3
- package/packages/datadog-instrumentations/src/vitest-main.js +92 -9
- package/packages/datadog-instrumentations/src/vitest-worker.js +71 -14
- package/packages/datadog-instrumentations/src/webdriverio.js +965 -6
- package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
- package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
- package/packages/datadog-plugin-amqp10/src/util.js +2 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +16 -5
- package/packages/datadog-plugin-cassandra-driver/src/index.js +8 -3
- package/packages/datadog-plugin-cucumber/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +262 -48
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -1
- package/packages/datadog-plugin-graphql/src/execute.js +998 -196
- package/packages/datadog-plugin-graphql/src/index.js +27 -7
- package/packages/datadog-plugin-graphql/src/jit.js +136 -0
- package/packages/datadog-plugin-graphql/src/request.js +18 -27
- package/packages/datadog-plugin-graphql/src/resolve-error.js +108 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -2
- package/packages/datadog-plugin-graphql/src/tools/transforms.js +45 -3
- package/packages/datadog-plugin-graphql/src/utils.js +208 -120
- package/packages/datadog-plugin-graphql/src/validate.js +10 -23
- package/packages/datadog-plugin-jest/src/index.js +0 -6
- package/packages/datadog-plugin-langchain/src/tracing.js +7 -0
- package/packages/datadog-plugin-mocha/src/index.js +403 -75
- package/packages/datadog-plugin-mongodb-core/src/query.js +6 -0
- package/packages/datadog-plugin-mysql/src/index.js +41 -15
- package/packages/datadog-plugin-net/src/tcp.js +3 -1
- package/packages/datadog-plugin-next/src/index.js +63 -29
- package/packages/datadog-plugin-playwright/src/index.js +167 -27
- package/packages/datadog-plugin-undici/src/index.js +27 -41
- package/packages/datadog-plugin-vitest/src/index.js +6 -12
- package/packages/dd-trace/src/aiguard/evaluation.js +2 -1
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +8 -1
- package/packages/dd-trace/src/aiguard/messages/openai.js +8 -1
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +20 -6
- package/packages/dd-trace/src/appsec/api_security/index.js +23 -6
- package/packages/dd-trace/src/appsec/api_security/sampler.js +99 -40
- package/packages/dd-trace/src/appsec/graphql.js +6 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +8 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +3 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +531 -95
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/lambda.js +44 -26
- package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +32 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +8 -8
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +6 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +20 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +5 -173
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agents.js +54 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +394 -225
- package/packages/dd-trace/src/ci-visibility/exporters/limits.js +9 -0
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +323 -31
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +42 -0
- package/packages/dd-trace/src/ci-visibility/final-flush.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +57 -18
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +0 -3
- package/packages/dd-trace/src/ci-visibility/requests/request.js +11 -0
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +164 -71
- package/packages/dd-trace/src/ci-visibility/requests/video-request.js +180 -0
- package/packages/dd-trace/src/ci-visibility/telemetry.js +10 -7
- package/packages/dd-trace/src/ci-visibility/test-video.js +61 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
- package/packages/dd-trace/src/config/index.js +73 -13
- package/packages/dd-trace/src/config/parsers.js +11 -1
- package/packages/dd-trace/src/config/stable.js +3 -3
- package/packages/dd-trace/src/config/supported-configurations.json +22 -2
- package/packages/dd-trace/src/crashtracking/crashtracker.js +82 -18
- package/packages/dd-trace/src/debugger/config.js +12 -1
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/request-options.js +28 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -40
- package/packages/dd-trace/src/debugger/devtools_client/status.js +11 -6
- package/packages/dd-trace/src/debugger/devtools_client/tags.js +41 -0
- package/packages/dd-trace/src/debugger/index.js +23 -3
- package/packages/dd-trace/src/dogstatsd.js +510 -76
- package/packages/dd-trace/src/encode/0.4-cross-payload.js +170 -0
- package/packages/dd-trace/src/encode/0.4.js +5 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -8
- package/packages/dd-trace/src/evp_proxy/direct.js +3 -25
- package/packages/dd-trace/src/exporters/agent/index.js +2 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +24 -7
- package/packages/dd-trace/src/exporters/agentless/index.js +7 -9
- package/packages/dd-trace/src/exporters/agentless/writer.js +103 -119
- package/packages/dd-trace/src/exporters/common/agents.js +28 -6
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +191 -0
- package/packages/dd-trace/src/exporters/common/proxy.js +52 -0
- package/packages/dd-trace/src/exporters/common/request.js +42 -14
- package/packages/dd-trace/src/exporters/common/url.js +40 -1
- package/packages/dd-trace/src/exporters/common/writer.js +9 -7
- package/packages/dd-trace/src/flush.js +6 -3
- package/packages/dd-trace/src/id.js +14 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +2 -1
- package/packages/dd-trace/src/llmobs/index.js +32 -32
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +22 -71
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +23 -13
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +7 -0
- package/packages/dd-trace/src/llmobs/util.js +0 -33
- package/packages/dd-trace/src/llmobs/writers/base.js +49 -32
- package/packages/dd-trace/src/log/index.js +7 -1
- package/packages/dd-trace/src/{ci-visibility/log-submission → log-submission}/log-submission-plugin.js +48 -19
- package/packages/dd-trace/src/openfeature/writers/base.js +14 -12
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/index.js +5 -24
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +14 -4
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +15 -22
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +14 -4
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +10 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +5 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +19 -4
- package/packages/dd-trace/src/opentelemetry/resource-attributes.js +55 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +10 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +101 -20
- package/packages/dd-trace/src/payload-tagging/index.js +2 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +1 -6
- package/packages/dd-trace/src/plugins/tracing.js +12 -10
- package/packages/dd-trace/src/plugins/util/ci.js +3 -1
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +16 -15
- package/packages/dd-trace/src/plugins/util/test.js +83 -20
- package/packages/dd-trace/src/plugins/util/url.js +2 -2
- package/packages/dd-trace/src/plugins/util/web.js +4 -9
- package/packages/dd-trace/src/priority_sampler.js +4 -0
- package/packages/dd-trace/src/profiling/config.js +1 -0
- package/packages/dd-trace/src/profiling/oom.js +7 -2
- package/packages/dd-trace/src/profiling/profiler.js +23 -13
- package/packages/dd-trace/src/profiling/profilers/space.js +38 -11
- package/packages/dd-trace/src/profiling/webspan-utils.js +7 -4
- package/packages/dd-trace/src/proxy.js +75 -5
- package/packages/dd-trace/src/remote_config/index.js +319 -101
- package/packages/dd-trace/src/remote_config/scheduler.js +37 -12
- package/packages/dd-trace/src/runtime_metrics/client.js +37 -8
- package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +5 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -1
- package/packages/dd-trace/src/sampling_rule.js +39 -10
- package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +4 -8
- package/packages/dd-trace/src/serverless/vercel.js +53 -20
- package/packages/dd-trace/src/serverless.js +10 -3
- package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
- package/packages/dd-trace/src/span_processor.js +18 -3
- package/packages/dd-trace/src/span_stats.js +24 -28
- package/packages/dd-trace/src/startup-log.js +3 -2
- package/packages/dd-trace/src/telemetry/agentless-url.js +28 -0
- package/packages/dd-trace/src/telemetry/send-data.js +23 -20
- package/packages/dd-trace/src/telemetry/session-propagation.js +3 -2
- package/packages/dd-trace/src/tracer.js +4 -5
- package/packages/dd-trace/src/tracer_metadata.js +11 -3
- 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/packages/datadog-instrumentations/src/playwright-browser-scripts.js +0 -27
- package/packages/dd-trace/src/encode/agentless-json.js +0 -210
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { performance } = require('node:perf_hooks')
|
|
4
|
-
const dateNow = Date.now
|
|
5
4
|
const { fileURLToPath } = require('node:url')
|
|
6
5
|
|
|
7
6
|
const { channel } = require('dc-polyfill')
|
|
8
7
|
|
|
9
8
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
10
9
|
const { storage } = require('../../datadog-core')
|
|
10
|
+
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
11
11
|
const {
|
|
12
12
|
getEfdRetryCountForDuration,
|
|
13
13
|
hasEfdRetries,
|
|
14
14
|
} = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
|
|
15
|
+
const {
|
|
16
|
+
SCREENSHOT_UPLOAD_RESULT_ERROR,
|
|
17
|
+
SCREENSHOT_UPLOAD_RESULT_UPLOADED,
|
|
18
|
+
setScreenshotUploadTags,
|
|
19
|
+
} = require('../../dd-trace/src/ci-visibility/test-screenshot')
|
|
15
20
|
const log = require('../../dd-trace/src/log')
|
|
16
21
|
const {
|
|
22
|
+
requestWebdriverioScreenshotUpload,
|
|
17
23
|
sendWebdriverioWorkerMessage,
|
|
18
24
|
SUITE_FINISH,
|
|
25
|
+
WEBDRIVERIO_WORKER_ENV,
|
|
19
26
|
} = require('../../datadog-instrumentations/src/mocha/webdriverio-protocol')
|
|
20
27
|
|
|
21
28
|
const {
|
|
@@ -54,6 +61,10 @@ const {
|
|
|
54
61
|
getFailedTestReplayPromise,
|
|
55
62
|
getTestSuiteExecutionKey,
|
|
56
63
|
isModifiedTest,
|
|
64
|
+
setRumTestCorrelation,
|
|
65
|
+
TEST_BROWSER_NAME,
|
|
66
|
+
TEST_BROWSER_VERSION,
|
|
67
|
+
TEST_IS_RUM_ACTIVE,
|
|
57
68
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
58
69
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
59
70
|
const {
|
|
@@ -83,11 +94,16 @@ const jasmineSpecExecuteStartCh = 'tracing:orchestrion:jasmine-core:Spec_execute
|
|
|
83
94
|
const jasmineTestFunctionStartCh = 'tracing:orchestrion:@wdio/utils:testFrameworkFnWrapper:start'
|
|
84
95
|
const testFinishCh = channel('ci:mocha:test:finish')
|
|
85
96
|
const testRetryCh = channel('ci:mocha:test:retry')
|
|
97
|
+
const WEBDRIVERIO_FRAMEWORK = 'webdriverio'
|
|
86
98
|
const WEBDRIVERIO_JASMINE_ADAPTER = 'jasmine'
|
|
99
|
+
const WEBDRIVERIO_SCREENSHOT_CAPTURE_TIMEOUT_MS = 30_000
|
|
87
100
|
const workerFinishCh = channel('ci:mocha:worker:finish')
|
|
88
101
|
const WEBDRIVERIO_JASMINE_FAILED_EXPECTATION_COUNT = Symbol('webdriverioJasmineFailedExpectationCount')
|
|
89
102
|
const WEBDRIVERIO_JASMINE_FUNCTION_TYPE = Symbol('webdriverioJasmineFunctionType')
|
|
90
103
|
const WEBDRIVERIO_JASMINE_TEST = Symbol('webdriverioJasmineTest')
|
|
104
|
+
const isWebdriverioWorker = !!getEnvironmentVariable(WEBDRIVERIO_WORKER_ENV)
|
|
105
|
+
const PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])
|
|
106
|
+
const BASE64_RE = /^(?:[A-Za-z\d+/]{4})*(?:[A-Za-z\d+/]{2}==|[A-Za-z\d+/]{3}=)?$/
|
|
91
107
|
|
|
92
108
|
/**
|
|
93
109
|
* @typedef {object} WebdriverioJasmineResult
|
|
@@ -140,6 +156,63 @@ function getJasmineError (result) {
|
|
|
140
156
|
return error
|
|
141
157
|
}
|
|
142
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Applies WebdriverIO RUM correlation without replacing active-browser metadata with an inactive browser.
|
|
161
|
+
*
|
|
162
|
+
* @param {object} context
|
|
163
|
+
* @param {object|undefined} activeSpan
|
|
164
|
+
* @returns {object|undefined}
|
|
165
|
+
*/
|
|
166
|
+
function setWebdriverioRumTestCorrelation (context, activeSpan) {
|
|
167
|
+
const browserVersion = context.browserVersion
|
|
168
|
+
const correlationContext = {
|
|
169
|
+
isRumActive: context.isRumActive,
|
|
170
|
+
testExecutionId: context.testExecutionId,
|
|
171
|
+
}
|
|
172
|
+
const testSpan = setRumTestCorrelation(correlationContext, activeSpan)
|
|
173
|
+
context.testExecutionId = correlationContext.testExecutionId
|
|
174
|
+
if (!testSpan) return
|
|
175
|
+
|
|
176
|
+
const hasActiveRum = testSpan.context().getTag(TEST_IS_RUM_ACTIVE)
|
|
177
|
+
if (!context.isRumActive && hasActiveRum) return testSpan
|
|
178
|
+
if (context.browserName) testSpan.setTag(TEST_BROWSER_NAME, context.browserName)
|
|
179
|
+
if (browserVersion) testSpan.setTag(TEST_BROWSER_VERSION, browserVersion)
|
|
180
|
+
return testSpan
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Converts a screenshot capture failure into its upload result.
|
|
185
|
+
*
|
|
186
|
+
* @param {unknown} error
|
|
187
|
+
* @returns {string}
|
|
188
|
+
*/
|
|
189
|
+
function handleWebdriverioScreenshotError (error) {
|
|
190
|
+
log.error('Error capturing WebdriverIO failure screenshot: %s', error?.message || String(error))
|
|
191
|
+
return SCREENSHOT_UPLOAD_RESULT_ERROR
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Decodes and validates PNG screenshot data returned by WebdriverIO.
|
|
196
|
+
*
|
|
197
|
+
* @param {unknown} screenshot - Base64-encoded PNG data
|
|
198
|
+
* @returns {Buffer} Decoded PNG data
|
|
199
|
+
*/
|
|
200
|
+
function decodeWebdriverioScreenshot (screenshot) {
|
|
201
|
+
if (typeof screenshot !== 'string' || !BASE64_RE.test(screenshot)) {
|
|
202
|
+
throw new TypeError('WebdriverIO returned invalid Base64 screenshot data')
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const content = Buffer.from(screenshot, 'base64')
|
|
206
|
+
if (
|
|
207
|
+
content.toString('base64') !== screenshot ||
|
|
208
|
+
content.length < PNG_SIGNATURE.length ||
|
|
209
|
+
!content.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)
|
|
210
|
+
) {
|
|
211
|
+
throw new TypeError('WebdriverIO returned invalid PNG screenshot data')
|
|
212
|
+
}
|
|
213
|
+
return content
|
|
214
|
+
}
|
|
215
|
+
|
|
143
216
|
/**
|
|
144
217
|
* Resolves the spec file responsible for a run-level Jasmine failure.
|
|
145
218
|
*
|
|
@@ -174,14 +247,37 @@ class MochaPlugin extends CiPlugin {
|
|
|
174
247
|
|
|
175
248
|
this._testTitleToParams = {}
|
|
176
249
|
this.sourceRoot = process.cwd()
|
|
177
|
-
this.
|
|
178
|
-
this.
|
|
179
|
-
this.
|
|
180
|
-
|
|
181
|
-
this.addSub('ci:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
250
|
+
this._webdriverioScreenshotUploads = new WeakMap()
|
|
251
|
+
this._pendingWebdriverioScreenshotUploads = 0
|
|
252
|
+
this._webdriverioScreenshotUploadCallbacks = []
|
|
253
|
+
|
|
254
|
+
this.addSub('ci:webdriverio:screenshot:capabilities', (ctx) => {
|
|
255
|
+
ctx.enabled = Boolean(
|
|
256
|
+
this._tracerConfig.testOptimization?.DD_TEST_FAILURE_SCREENSHOTS_ENABLED &&
|
|
257
|
+
this.tracer._exporter?.canUploadTestScreenshots?.()
|
|
258
|
+
)
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
this.addSub('ci:webdriverio:screenshot:upload', ({
|
|
262
|
+
capturedAtMs,
|
|
263
|
+
idempotencyKey,
|
|
264
|
+
onDone,
|
|
265
|
+
screenshot,
|
|
266
|
+
traceId,
|
|
267
|
+
}) => {
|
|
268
|
+
const exporter = this.tracer?._exporter
|
|
269
|
+
if (!exporter?.canUploadTestScreenshots?.() || !exporter.uploadTestScreenshot) {
|
|
270
|
+
onDone(new Error('WebdriverIO screenshot upload is not supported by the active Test Optimization transport'))
|
|
271
|
+
return
|
|
272
|
+
}
|
|
273
|
+
let content
|
|
274
|
+
try {
|
|
275
|
+
content = decodeWebdriverioScreenshot(screenshot)
|
|
276
|
+
} catch (error) {
|
|
277
|
+
onDone(error)
|
|
278
|
+
return
|
|
279
|
+
}
|
|
280
|
+
exporter.uploadTestScreenshot({ content, traceId, idempotencyKey, capturedAtMs }, onDone)
|
|
185
281
|
})
|
|
186
282
|
|
|
187
283
|
this.addSub('ci:mocha:worker:configuration', ({
|
|
@@ -195,6 +291,18 @@ class MochaPlugin extends CiPlugin {
|
|
|
195
291
|
this.testFramework = testFramework
|
|
196
292
|
this.testFrameworkAdapter = testFrameworkAdapter
|
|
197
293
|
this._setRepositoryRoot(repositoryRoot)
|
|
294
|
+
if (
|
|
295
|
+
testFramework === WEBDRIVERIO_FRAMEWORK &&
|
|
296
|
+
this._tracerConfig.testOptimization.DD_TEST_FAILURE_SCREENSHOTS_ENABLED &&
|
|
297
|
+
!(isWebdriverioWorker
|
|
298
|
+
? libraryConfig.isTestFailureScreenshotsEnabled
|
|
299
|
+
: this.tracer._exporter?.canUploadTestScreenshots?.())
|
|
300
|
+
) {
|
|
301
|
+
log.warn(
|
|
302
|
+
'DD_TEST_FAILURE_SCREENSHOTS_ENABLED is true, but WebdriverIO screenshot upload is not supported by the %s',
|
|
303
|
+
'active Test Optimization transport.'
|
|
304
|
+
)
|
|
305
|
+
}
|
|
198
306
|
if (testFrameworkAdapter === WEBDRIVERIO_JASMINE_ADAPTER) {
|
|
199
307
|
this._webdriverioJasmineState = {
|
|
200
308
|
completedTestStatuses: new Map(),
|
|
@@ -210,6 +318,14 @@ class MochaPlugin extends CiPlugin {
|
|
|
210
318
|
}
|
|
211
319
|
})
|
|
212
320
|
|
|
321
|
+
this.addSub('ci:webdriverio:rum:page-navigate', (ctx) => {
|
|
322
|
+
if (this.testFramework !== 'webdriverio') return
|
|
323
|
+
ctx.isTestOptimizationRunner = true
|
|
324
|
+
|
|
325
|
+
const activeSpan = storage('legacy').getStore()?.span
|
|
326
|
+
setWebdriverioRumTestCorrelation(ctx, activeSpan)
|
|
327
|
+
})
|
|
328
|
+
|
|
213
329
|
this.addBind(jasmineTestFunctionStartCh, (ctx) => {
|
|
214
330
|
if (this.testFrameworkAdapter !== WEBDRIVERIO_JASMINE_ADAPTER) {
|
|
215
331
|
return storage('legacy').getStore()
|
|
@@ -232,7 +348,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
232
348
|
|
|
233
349
|
const functionType = currentStore[WEBDRIVERIO_JASMINE_FUNCTION_TYPE]
|
|
234
350
|
if (functionType === 'Test') {
|
|
235
|
-
ctx.retryCallback =
|
|
351
|
+
ctx.retryCallback = this.#retryWebdriverioJasmineTestWithRumCorrelation.bind(this, ctx, test)
|
|
236
352
|
}
|
|
237
353
|
const nextStore = {
|
|
238
354
|
...test.currentStore,
|
|
@@ -271,12 +387,11 @@ class MochaPlugin extends CiPlugin {
|
|
|
271
387
|
this.addSub(jasmineExecuteAsyncErrorCh, (ctx) => {
|
|
272
388
|
const currentStore = ctx.currentStore || storage('legacy').getStore()
|
|
273
389
|
const test = currentStore?.[WEBDRIVERIO_JASMINE_TEST]
|
|
274
|
-
if (
|
|
275
|
-
this.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
test.hasFinalHookFailure = true
|
|
390
|
+
if (this.testFrameworkAdapter === WEBDRIVERIO_JASMINE_ADAPTER && test) {
|
|
391
|
+
this.#startWebdriverioScreenshotUpload(test.span)
|
|
392
|
+
if (currentStore[WEBDRIVERIO_JASMINE_FUNCTION_TYPE] === 'Hook') {
|
|
393
|
+
test.hasFinalHookFailure = true
|
|
394
|
+
}
|
|
280
395
|
}
|
|
281
396
|
})
|
|
282
397
|
|
|
@@ -291,6 +406,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
291
406
|
this._webdriverioJasmineState.currentResult?.failedExpectations?.length > failedExpectationCount
|
|
292
407
|
) {
|
|
293
408
|
test.hasFinalHookFailure = true
|
|
409
|
+
this.#startWebdriverioScreenshotUpload(test.span)
|
|
294
410
|
}
|
|
295
411
|
})
|
|
296
412
|
|
|
@@ -482,19 +598,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
482
598
|
if (!testSuiteSpan.context().getTag(TEST_STATUS)) {
|
|
483
599
|
testSuiteSpan.setTag(TEST_STATUS, status)
|
|
484
600
|
}
|
|
485
|
-
|
|
486
|
-
if (exporter.deferTestSuiteSpan) {
|
|
487
|
-
exporter.deferTestSuiteSpan(testSuiteSpan)
|
|
488
|
-
testSuiteSpan.finish()
|
|
489
|
-
} else if (exporter.exportDeferredTestSuiteSpans) {
|
|
490
|
-
const finishTime = this._now()
|
|
491
|
-
this._pendingTestSuiteSpans.push({
|
|
492
|
-
span: testSuiteSpan,
|
|
493
|
-
finishTime,
|
|
494
|
-
})
|
|
495
|
-
} else {
|
|
496
|
-
testSuiteSpan.finish()
|
|
497
|
-
}
|
|
601
|
+
testSuiteSpan.finish()
|
|
498
602
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
499
603
|
}
|
|
500
604
|
})
|
|
@@ -544,8 +648,12 @@ class MochaPlugin extends CiPlugin {
|
|
|
544
648
|
})
|
|
545
649
|
|
|
546
650
|
this.addSub('ci:mocha:worker:finish', ({ onDone } = {}) => {
|
|
547
|
-
this.
|
|
548
|
-
this.
|
|
651
|
+
const flush = () => this.tracer._exporter.flush(onDone)
|
|
652
|
+
if (this._pendingWebdriverioScreenshotUploads === 0) {
|
|
653
|
+
flush()
|
|
654
|
+
return
|
|
655
|
+
}
|
|
656
|
+
this._webdriverioScreenshotUploadCallbacks.push(flush)
|
|
549
657
|
})
|
|
550
658
|
|
|
551
659
|
this.addSub('ci:mocha:test:finish', ({
|
|
@@ -562,6 +670,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
562
670
|
earlyFlakeAbortReason,
|
|
563
671
|
}) => {
|
|
564
672
|
if (span) {
|
|
673
|
+
const finishTime = span._getTime()
|
|
565
674
|
span.setTag(TEST_STATUS, status)
|
|
566
675
|
if (finalStatus) {
|
|
567
676
|
span.setTag(TEST_FINAL_STATUS, finalStatus)
|
|
@@ -590,20 +699,27 @@ class MochaPlugin extends CiPlugin {
|
|
|
590
699
|
span.setTag(TEST_RETRY_REASON, TEST_RETRY_REASON_TYPES.atf)
|
|
591
700
|
}
|
|
592
701
|
|
|
593
|
-
this.telemetry.ciVisEvent(
|
|
594
|
-
TELEMETRY_EVENT_FINISHED,
|
|
595
|
-
'test',
|
|
596
|
-
this.getTestTelemetryTags(span)
|
|
597
|
-
)
|
|
598
|
-
|
|
599
|
-
span.finish()
|
|
600
|
-
finishAllTraceSpans(span)
|
|
601
|
-
this.activeTestSpan = null
|
|
602
702
|
this.cancelDiBreakpointHitWait()
|
|
603
703
|
if (this.di && this.libraryConfig?.isDiEnabled && this.runningTestProbe && isLastRetry) {
|
|
604
704
|
this.removeDiProbe(this.runningTestProbe)
|
|
605
705
|
this.runningTestProbe = null
|
|
606
706
|
}
|
|
707
|
+
|
|
708
|
+
const finishSpan = () => {
|
|
709
|
+
this.telemetry.ciVisEvent(
|
|
710
|
+
TELEMETRY_EVENT_FINISHED,
|
|
711
|
+
'test',
|
|
712
|
+
this.getTestTelemetryTags(span)
|
|
713
|
+
)
|
|
714
|
+
span.finish(finishTime)
|
|
715
|
+
finishAllTraceSpans(span)
|
|
716
|
+
if (this.activeTestSpan === span) {
|
|
717
|
+
this.activeTestSpan = null
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
if (status !== 'fail' || !this.#startWebdriverioScreenshotUpload(span, finishSpan)) {
|
|
721
|
+
finishSpan()
|
|
722
|
+
}
|
|
607
723
|
}
|
|
608
724
|
})
|
|
609
725
|
|
|
@@ -633,6 +749,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
633
749
|
} else {
|
|
634
750
|
span.setTag(TEST_STATUS, 'fail')
|
|
635
751
|
span.setTag('error', err)
|
|
752
|
+
this.#startWebdriverioScreenshotUpload(span)
|
|
636
753
|
}
|
|
637
754
|
|
|
638
755
|
ctx.parentStore = ctx.currentStore
|
|
@@ -657,8 +774,9 @@ class MochaPlugin extends CiPlugin {
|
|
|
657
774
|
promises,
|
|
658
775
|
}) => {
|
|
659
776
|
if (span) {
|
|
777
|
+
const finishTime = span._getTime()
|
|
660
778
|
const finishSpan = () => {
|
|
661
|
-
span.finish()
|
|
779
|
+
span.finish(finishTime)
|
|
662
780
|
finishAllTraceSpans(span)
|
|
663
781
|
if (this.activeTestSpan === span) {
|
|
664
782
|
this.activeTestSpan = null
|
|
@@ -701,17 +819,42 @@ class MochaPlugin extends CiPlugin {
|
|
|
701
819
|
}
|
|
702
820
|
}
|
|
703
821
|
|
|
822
|
+
let finishWait
|
|
704
823
|
if (!isFirstFailure &&
|
|
705
824
|
willBeRetried &&
|
|
706
825
|
this.di &&
|
|
707
826
|
this.libraryConfig?.isDiEnabled &&
|
|
708
|
-
this.runningTestProbe
|
|
709
|
-
|
|
710
|
-
promises.finishTestPromise = this.waitForInFlightDiBreakpointHits().then(finishSpan, finishSpan)
|
|
711
|
-
return
|
|
827
|
+
this.runningTestProbe) {
|
|
828
|
+
finishWait = this.waitForInFlightDiBreakpointHits()
|
|
712
829
|
}
|
|
713
|
-
|
|
714
|
-
|
|
830
|
+
let screenshotFinished = false
|
|
831
|
+
let canFinishScreenshot = false
|
|
832
|
+
let replayFinished = !finishWait
|
|
833
|
+
let spanFinished = false
|
|
834
|
+
const finishWhenReady = () => {
|
|
835
|
+
if (!spanFinished && replayFinished && (screenshotStarted === false || screenshotFinished)) {
|
|
836
|
+
spanFinished = true
|
|
837
|
+
finishSpan()
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
const screenshotStarted = this.#startWebdriverioScreenshotUpload(span, () => {
|
|
841
|
+
screenshotFinished = true
|
|
842
|
+
if (canFinishScreenshot) {
|
|
843
|
+
finishWhenReady()
|
|
844
|
+
}
|
|
845
|
+
})
|
|
846
|
+
canFinishScreenshot = true
|
|
847
|
+
if (finishWait) {
|
|
848
|
+
const finishReplay = () => {
|
|
849
|
+
replayFinished = true
|
|
850
|
+
finishWhenReady()
|
|
851
|
+
}
|
|
852
|
+
const finishTestPromise = finishWait.then(finishReplay, finishReplay)
|
|
853
|
+
if (promises) {
|
|
854
|
+
promises.finishTestPromise = finishTestPromise
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
finishWhenReady()
|
|
715
858
|
}
|
|
716
859
|
})
|
|
717
860
|
|
|
@@ -755,7 +898,6 @@ class MochaPlugin extends CiPlugin {
|
|
|
755
898
|
this.testSessionSpan.setTag('error', error)
|
|
756
899
|
this.testModuleSpan.setTag('error', error)
|
|
757
900
|
if (isFrameworkError) {
|
|
758
|
-
this.tracer._exporter.setDeferredTestSuiteError?.(error)
|
|
759
901
|
for (const testSuiteSpan of this._testSuiteSpansByTestSuite.values()) {
|
|
760
902
|
testSuiteSpan.setTag(TEST_STATUS, 'fail')
|
|
761
903
|
testSuiteSpan.setTag('error', error)
|
|
@@ -763,8 +905,6 @@ class MochaPlugin extends CiPlugin {
|
|
|
763
905
|
}
|
|
764
906
|
}
|
|
765
907
|
|
|
766
|
-
this._finishPendingTestSuiteSpans()
|
|
767
|
-
|
|
768
908
|
if (isParallel) {
|
|
769
909
|
this.testSessionSpan.setTag(MOCHA_IS_PARALLEL, 'true')
|
|
770
910
|
}
|
|
@@ -802,7 +942,6 @@ class MochaPlugin extends CiPlugin {
|
|
|
802
942
|
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
|
|
803
943
|
}
|
|
804
944
|
|
|
805
|
-
this.tracer._exporter.exportDeferredTestSuiteSpans?.()
|
|
806
945
|
this.testModuleSpan.finish()
|
|
807
946
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
808
947
|
this.testSessionSpan.finish()
|
|
@@ -824,27 +963,6 @@ class MochaPlugin extends CiPlugin {
|
|
|
824
963
|
})
|
|
825
964
|
}
|
|
826
965
|
|
|
827
|
-
/**
|
|
828
|
-
* Returns the current time in the coordinate system used by spans.
|
|
829
|
-
*
|
|
830
|
-
* @returns {number}
|
|
831
|
-
*/
|
|
832
|
-
_now () {
|
|
833
|
-
return this._timeOrigin + performance.now() - this._perfOrigin
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Finishes suites retained for a later framework finalization event.
|
|
838
|
-
*
|
|
839
|
-
* @returns {void}
|
|
840
|
-
*/
|
|
841
|
-
_finishPendingTestSuiteSpans () {
|
|
842
|
-
for (const { span, finishTime } of this._pendingTestSuiteSpans) {
|
|
843
|
-
span.finish(finishTime)
|
|
844
|
-
}
|
|
845
|
-
this._pendingTestSuiteSpans = []
|
|
846
|
-
}
|
|
847
|
-
|
|
848
966
|
/**
|
|
849
967
|
* Starts a Jasmine test span around WebdriverIO's test-function wrapper.
|
|
850
968
|
*
|
|
@@ -1080,6 +1198,9 @@ class MochaPlugin extends CiPlugin {
|
|
|
1080
1198
|
}
|
|
1081
1199
|
|
|
1082
1200
|
const testStatus = getJasmineStatus(status)
|
|
1201
|
+
if (testStatus === 'fail') {
|
|
1202
|
+
this.#startWebdriverioScreenshotUpload(test.span)
|
|
1203
|
+
}
|
|
1083
1204
|
if (
|
|
1084
1205
|
testStatus !== 'skip' &&
|
|
1085
1206
|
test.isEarlyFlakeDetection &&
|
|
@@ -1177,6 +1298,25 @@ class MochaPlugin extends CiPlugin {
|
|
|
1177
1298
|
this.#startWebdriverioJasmineAttempt(test, test.currentStore)
|
|
1178
1299
|
}
|
|
1179
1300
|
|
|
1301
|
+
/**
|
|
1302
|
+
* Advances a native WebdriverIO retry without stopping its active RUM session.
|
|
1303
|
+
*
|
|
1304
|
+
* @param {object} context
|
|
1305
|
+
* @param {object} test
|
|
1306
|
+
* @param {Error|undefined} error
|
|
1307
|
+
* @returns {Promise<void>}
|
|
1308
|
+
*/
|
|
1309
|
+
async #retryWebdriverioJasmineTestWithRumCorrelation (context, test, error) {
|
|
1310
|
+
const correlationContext = await context.rumRetryCallback?.() || {}
|
|
1311
|
+
setWebdriverioRumTestCorrelation(correlationContext, test.span)
|
|
1312
|
+
|
|
1313
|
+
await this.#retryWebdriverioJasmineTest(test, error)
|
|
1314
|
+
|
|
1315
|
+
const testExecutionId = test.span.context().toTraceId()
|
|
1316
|
+
await context.rumRetryCallback?.(testExecutionId)
|
|
1317
|
+
setWebdriverioRumTestCorrelation(correlationContext, test.span)
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1180
1320
|
/**
|
|
1181
1321
|
* Finishes an intermediate native WebdriverIO retry and starts its next span.
|
|
1182
1322
|
*
|
|
@@ -1239,8 +1379,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
1239
1379
|
if (test._ddShouldWaitForHitProbe) {
|
|
1240
1380
|
delete test._ddShouldWaitForHitProbe
|
|
1241
1381
|
state.pendingTestFinishes++
|
|
1242
|
-
const
|
|
1243
|
-
this.#completeWebdriverioJasmineTest(test, result)
|
|
1382
|
+
const onTestFinished = () => {
|
|
1244
1383
|
state.pendingTestFinishes--
|
|
1245
1384
|
if (state.pendingTestFinishes === 0) {
|
|
1246
1385
|
const callbacks = state.pendingTestFinishCallbacks
|
|
@@ -1250,10 +1389,14 @@ class MochaPlugin extends CiPlugin {
|
|
|
1250
1389
|
}
|
|
1251
1390
|
}
|
|
1252
1391
|
}
|
|
1392
|
+
const finishTest = () => {
|
|
1393
|
+
const finishPromise = this.#completeWebdriverioJasmineTest(test, result)
|
|
1394
|
+
return finishPromise?.then(onTestFinished, onTestFinished) || onTestFinished()
|
|
1395
|
+
}
|
|
1253
1396
|
return this.waitForDiBreakpointHits().then(finishTest, finishTest)
|
|
1254
1397
|
}
|
|
1255
1398
|
|
|
1256
|
-
this.#completeWebdriverioJasmineTest(test, result)
|
|
1399
|
+
return this.#completeWebdriverioJasmineTest(test, result)
|
|
1257
1400
|
}
|
|
1258
1401
|
|
|
1259
1402
|
/**
|
|
@@ -1312,6 +1455,191 @@ class MochaPlugin extends CiPlugin {
|
|
|
1312
1455
|
}
|
|
1313
1456
|
}
|
|
1314
1457
|
|
|
1458
|
+
/**
|
|
1459
|
+
* Captures and uploads the current WebdriverIO browser state once for a failed test attempt.
|
|
1460
|
+
*
|
|
1461
|
+
* @param {object} span - Failed test span
|
|
1462
|
+
* @param {() => void} [onDone] - Called after the screenshot upload finishes
|
|
1463
|
+
* @returns {boolean} Whether a screenshot upload exists for the span
|
|
1464
|
+
*/
|
|
1465
|
+
#startWebdriverioScreenshotUpload (span, onDone) {
|
|
1466
|
+
if (
|
|
1467
|
+
!span ||
|
|
1468
|
+
this.testFramework !== WEBDRIVERIO_FRAMEWORK ||
|
|
1469
|
+
!this._tracerConfig.testOptimization?.DD_TEST_FAILURE_SCREENSHOTS_ENABLED
|
|
1470
|
+
) {
|
|
1471
|
+
return false
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
const previousUpload = this._webdriverioScreenshotUploads.get(span)
|
|
1475
|
+
if (previousUpload) {
|
|
1476
|
+
if (onDone) {
|
|
1477
|
+
if (previousUpload.finished) {
|
|
1478
|
+
onDone()
|
|
1479
|
+
} else {
|
|
1480
|
+
previousUpload.callbacks.push(onDone)
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
return true
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
const exporter = this.tracer?._exporter
|
|
1487
|
+
const canUpload = isWebdriverioWorker
|
|
1488
|
+
? this.libraryConfig?.isTestFailureScreenshotsEnabled
|
|
1489
|
+
: exporter?.canUploadTestScreenshots?.() && exporter.uploadTestScreenshot
|
|
1490
|
+
if (!canUpload) {
|
|
1491
|
+
return false
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
const browser = globalThis._wdioGlobals?.get?.('browser') || globalThis.browser
|
|
1495
|
+
const upload = {
|
|
1496
|
+
callbacks: onDone ? [onDone] : [],
|
|
1497
|
+
finished: false,
|
|
1498
|
+
}
|
|
1499
|
+
this._webdriverioScreenshotUploads.set(span, upload)
|
|
1500
|
+
this._pendingWebdriverioScreenshotUploads++
|
|
1501
|
+
const finishUpload = (result) => this.#finishWebdriverioScreenshotUpload(span, upload, result)
|
|
1502
|
+
let captureTimeout
|
|
1503
|
+
const failCapture = (error) => {
|
|
1504
|
+
if (upload.finished) return
|
|
1505
|
+
clearTimeout(captureTimeout)
|
|
1506
|
+
captureTimeout = undefined
|
|
1507
|
+
finishUpload(handleWebdriverioScreenshotError(error))
|
|
1508
|
+
}
|
|
1509
|
+
const uploadScreenshots = (content) => {
|
|
1510
|
+
if (upload.finished) return
|
|
1511
|
+
clearTimeout(captureTimeout)
|
|
1512
|
+
captureTimeout = undefined
|
|
1513
|
+
try {
|
|
1514
|
+
this.#uploadWebdriverioScreenshots(span, content, finishUpload)
|
|
1515
|
+
} catch (error) {
|
|
1516
|
+
failCapture(error)
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
captureTimeout = setTimeout(() => {
|
|
1520
|
+
failCapture(new Error(
|
|
1521
|
+
`WebdriverIO screenshot capture timed out after ${WEBDRIVERIO_SCREENSHOT_CAPTURE_TIMEOUT_MS}ms`
|
|
1522
|
+
))
|
|
1523
|
+
}, WEBDRIVERIO_SCREENSHOT_CAPTURE_TIMEOUT_MS)
|
|
1524
|
+
captureTimeout.unref?.()
|
|
1525
|
+
try {
|
|
1526
|
+
if (typeof browser?.takeScreenshot !== 'function') {
|
|
1527
|
+
throw new TypeError('browser.takeScreenshot is not available')
|
|
1528
|
+
}
|
|
1529
|
+
const screenshot = browser.takeScreenshot()
|
|
1530
|
+
if (typeof screenshot?.then === 'function') {
|
|
1531
|
+
screenshot.then(
|
|
1532
|
+
uploadScreenshots,
|
|
1533
|
+
failCapture
|
|
1534
|
+
)
|
|
1535
|
+
} else {
|
|
1536
|
+
uploadScreenshots(screenshot)
|
|
1537
|
+
}
|
|
1538
|
+
} catch (error) {
|
|
1539
|
+
failCapture(error)
|
|
1540
|
+
}
|
|
1541
|
+
return true
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
/**
|
|
1545
|
+
* Completes one WebdriverIO screenshot upload and its waiters.
|
|
1546
|
+
*
|
|
1547
|
+
* @param {object} span - Failed test span
|
|
1548
|
+
* @param {{callbacks: Array<() => void>, finished: boolean}} upload - Upload state
|
|
1549
|
+
* @param {string} result - Aggregate screenshot upload result
|
|
1550
|
+
* @returns {void}
|
|
1551
|
+
*/
|
|
1552
|
+
#finishWebdriverioScreenshotUpload (span, upload, result) {
|
|
1553
|
+
if (upload.finished) return
|
|
1554
|
+
|
|
1555
|
+
upload.finished = true
|
|
1556
|
+
setScreenshotUploadTags(span, result)
|
|
1557
|
+
const uploadCallbacks = upload.callbacks
|
|
1558
|
+
upload.callbacks = []
|
|
1559
|
+
|
|
1560
|
+
this._pendingWebdriverioScreenshotUploads--
|
|
1561
|
+
let workerCallbacks = []
|
|
1562
|
+
if (this._pendingWebdriverioScreenshotUploads === 0) {
|
|
1563
|
+
workerCallbacks = this._webdriverioScreenshotUploadCallbacks
|
|
1564
|
+
this._webdriverioScreenshotUploadCallbacks = []
|
|
1565
|
+
}
|
|
1566
|
+
for (const callback of uploadCallbacks) {
|
|
1567
|
+
callback()
|
|
1568
|
+
}
|
|
1569
|
+
for (const callback of workerCallbacks) {
|
|
1570
|
+
callback()
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
/**
|
|
1575
|
+
* Uploads the PNG data returned by WebdriverIO for one or more browser sessions.
|
|
1576
|
+
*
|
|
1577
|
+
* @param {object} span - Failed test span
|
|
1578
|
+
* @param {string|string[]} screenshots - Base64-encoded PNG data
|
|
1579
|
+
* @param {(result: string) => void} onDone - Aggregate upload completion callback
|
|
1580
|
+
* @returns {void}
|
|
1581
|
+
*/
|
|
1582
|
+
#uploadWebdriverioScreenshots (span, screenshots, onDone) {
|
|
1583
|
+
const screenshotList = Array.isArray(screenshots) ? screenshots : [screenshots]
|
|
1584
|
+
if (screenshotList.length === 0) {
|
|
1585
|
+
log.error('Error capturing WebdriverIO failure screenshot: WebdriverIO returned no screenshot data')
|
|
1586
|
+
onDone(SCREENSHOT_UPLOAD_RESULT_ERROR)
|
|
1587
|
+
return
|
|
1588
|
+
}
|
|
1589
|
+
const exporter = this.tracer?._exporter
|
|
1590
|
+
const traceId = span.context().toTraceId()
|
|
1591
|
+
const capturedAtMs = Date.now()
|
|
1592
|
+
let pendingUploads = screenshotList.length
|
|
1593
|
+
let hasUploadError = false
|
|
1594
|
+
const finishOne = (error) => {
|
|
1595
|
+
if (error) {
|
|
1596
|
+
hasUploadError = true
|
|
1597
|
+
log.error('Error uploading WebdriverIO failure screenshot: %s', error?.message || String(error))
|
|
1598
|
+
}
|
|
1599
|
+
if (--pendingUploads === 0) {
|
|
1600
|
+
onDone(hasUploadError ? SCREENSHOT_UPLOAD_RESULT_ERROR : SCREENSHOT_UPLOAD_RESULT_UPLOADED)
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
for (let index = 0; index < screenshotList.length; index++) {
|
|
1604
|
+
const screenshot = screenshotList[index]
|
|
1605
|
+
if (typeof screenshot !== 'string' || !screenshot) {
|
|
1606
|
+
finishOne(new TypeError('WebdriverIO returned invalid screenshot data'))
|
|
1607
|
+
continue
|
|
1608
|
+
}
|
|
1609
|
+
const options = {
|
|
1610
|
+
screenshot,
|
|
1611
|
+
traceId,
|
|
1612
|
+
idempotencyKey: `${traceId}:webdriverio-failure-${index}.png`,
|
|
1613
|
+
capturedAtMs,
|
|
1614
|
+
}
|
|
1615
|
+
if (isWebdriverioWorker) {
|
|
1616
|
+
try {
|
|
1617
|
+
requestWebdriverioScreenshotUpload(options, finishOne)
|
|
1618
|
+
} catch (error) {
|
|
1619
|
+
finishOne(error)
|
|
1620
|
+
}
|
|
1621
|
+
} else {
|
|
1622
|
+
let content
|
|
1623
|
+
try {
|
|
1624
|
+
content = decodeWebdriverioScreenshot(screenshot)
|
|
1625
|
+
} catch (error) {
|
|
1626
|
+
finishOne(error)
|
|
1627
|
+
continue
|
|
1628
|
+
}
|
|
1629
|
+
try {
|
|
1630
|
+
exporter.uploadTestScreenshot({
|
|
1631
|
+
content,
|
|
1632
|
+
traceId,
|
|
1633
|
+
idempotencyKey: options.idempotencyKey,
|
|
1634
|
+
capturedAtMs,
|
|
1635
|
+
}, finishOne)
|
|
1636
|
+
} catch (error) {
|
|
1637
|
+
finishOne(error)
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1315
1643
|
/**
|
|
1316
1644
|
* Reports Jasmine suite statuses and flushes worker traces before its run settles.
|
|
1317
1645
|
*
|
|
@@ -98,7 +98,13 @@ class MongodbCoreQueryPlugin extends DatabasePlugin {
|
|
|
98
98
|
const MAX_DEPTH = 10
|
|
99
99
|
const MAX_QUERY_LENGTH = 10_000
|
|
100
100
|
|
|
101
|
+
/** @param {{ q?: Record<string, unknown> }[] | { documents?: { q?: Record<string, unknown> }[] }} statements */
|
|
101
102
|
function extractQuery (statements) {
|
|
103
|
+
if (!Array.isArray(statements)) {
|
|
104
|
+
const { documents } = statements
|
|
105
|
+
statements = Array.isArray(documents) ? documents : []
|
|
106
|
+
}
|
|
107
|
+
|
|
102
108
|
if (statements.length === 1 && statements[0].q) return statements[0].q
|
|
103
109
|
|
|
104
110
|
const extractedQueries = []
|