dd-trace 6.13.0 → 6.14.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/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 +13 -0
- 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 +25 -20
- 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 +25 -15
- 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 +109 -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/sql-sensitive-analyzer.js +11 -36
- 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/upload-test-screenshot.js +164 -71
- package/packages/dd-trace/src/ci-visibility/requests/video-request.js +176 -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 +20 -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 +33 -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 +27 -23
- 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 +100 -118
- 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/request.js +31 -11
- 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_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 +93 -18
- 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/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 +36 -9
- 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_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 +18 -16
- 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
|
@@ -18,6 +18,8 @@ const {
|
|
|
18
18
|
getEfdRetryCountForDuration,
|
|
19
19
|
hasEfdRetries,
|
|
20
20
|
} = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
|
|
21
|
+
const { FINAL_FLUSH_FALLBACK_DELAY, FINAL_FLUSH_TIMEOUT } =
|
|
22
|
+
require('../../dd-trace/src/ci-visibility/final-flush')
|
|
21
23
|
const {
|
|
22
24
|
getCoveredFilesFromCoverage,
|
|
23
25
|
JEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
@@ -95,10 +97,10 @@ const itrSkippedSuitesCh = channel('ci:jest:itr:skipped-suites')
|
|
|
95
97
|
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/types.ts#L37
|
|
96
98
|
const CHILD_MESSAGE_CALL = 1
|
|
97
99
|
|
|
98
|
-
// Maximum time we'll wait for the tracer to flush
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
const FLUSH_TIMEOUT =
|
|
100
|
+
// Maximum time we'll wait for the tracer to flush.
|
|
101
|
+
// Let the exporter enforce its hard deadline and invoke its completion callback
|
|
102
|
+
// before Jest's --forceExit fallback takes over.
|
|
103
|
+
const FLUSH_TIMEOUT = FINAL_FLUSH_TIMEOUT + FINAL_FLUSH_FALLBACK_DELAY + 5000
|
|
102
104
|
const JEST_SESSION_STATE = Symbol.for('dd-trace:jest:session')
|
|
103
105
|
const JEST_BAIL_REPORTER_PATH = require.resolve('./jest/bail-reporter')
|
|
104
106
|
const DD_JEST_HANDLE_TEST_EVENT_WRAPPED = Symbol('dd-trace:jest:handle-test-event-wrapped')
|
|
@@ -342,16 +344,17 @@ function getTestStats (testStatuses) {
|
|
|
342
344
|
function formatIgnoredFailuresSummary (ignoredFailures) {
|
|
343
345
|
if (!ignoredFailures?.efdFailureCount) return ''
|
|
344
346
|
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
if (items.length === 0) return ''
|
|
348
|
-
|
|
349
|
-
const shown = items.slice(0, MAX_IGNORED_TEST_NAMES)
|
|
350
|
-
const more = items.length - shown.length
|
|
347
|
+
const shown = ignoredFailures.efdNames.slice(0, MAX_IGNORED_TEST_NAMES)
|
|
348
|
+
const more = ignoredFailures.efdNames.length - shown.length
|
|
351
349
|
const moreSuffix = more > 0 ? `\n ... and ${more} more` : ''
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
350
|
+
let formattedItems = ''
|
|
351
|
+
let isFirstItem = true
|
|
352
|
+
for (const text of shown) {
|
|
353
|
+
if (!isFirstItem) formattedItems += '\n'
|
|
354
|
+
formattedItems += ` • ${text} (Early Flake Detection)`
|
|
355
|
+
isFirstItem = false
|
|
356
|
+
}
|
|
357
|
+
formattedItems += moreSuffix
|
|
355
358
|
|
|
356
359
|
return `${ignoredFailures.efdFailureCount} test failure(s) were ignored. Exit code set to 0.\n\n${formattedItems}`
|
|
357
360
|
}
|
|
@@ -764,7 +767,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
764
767
|
}
|
|
765
768
|
return test.call(this, testName, testFn, ...callArgs)
|
|
766
769
|
}
|
|
767
|
-
const
|
|
770
|
+
const boundTest = bind(eachTest)
|
|
771
|
+
const eachBind = boundTest.apply(this, eachArgs)
|
|
768
772
|
return eachBind.apply(this, testArgs)
|
|
769
773
|
}
|
|
770
774
|
}
|
|
@@ -877,7 +881,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
877
881
|
}
|
|
878
882
|
return concurrentTest.call(this, testName, testFn, ...callArgs)
|
|
879
883
|
}
|
|
880
|
-
const
|
|
884
|
+
const boundTest = bind(concurrentEachTest, false, needsEachError)
|
|
885
|
+
const eachBind = boundTest.apply(this, eachArgs)
|
|
881
886
|
return eachBind.apply(this, testArgs)
|
|
882
887
|
}
|
|
883
888
|
}
|
|
@@ -926,10 +931,12 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
926
931
|
|
|
927
932
|
let jestEach
|
|
928
933
|
try {
|
|
929
|
-
|
|
934
|
+
const requireFromPath = createRequire(path.join(this.rootDir, 'package.json'))
|
|
935
|
+
jestEach = requireFromPath('jest-each')
|
|
930
936
|
} catch {
|
|
931
937
|
try {
|
|
932
|
-
|
|
938
|
+
const requireFromPath = createRequire(path.join(process.cwd(), 'package.json'))
|
|
939
|
+
jestEach = requireFromPath('jest-each')
|
|
933
940
|
} catch {
|
|
934
941
|
jestEach = undefined
|
|
935
942
|
}
|
|
@@ -3067,9 +3074,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
3067
3074
|
result = await runCLI.apply(this, arguments)
|
|
3068
3075
|
} catch (error) {
|
|
3069
3076
|
try {
|
|
3070
|
-
await waitForTestSessionFinish(getTestSessionFinishPayload('fail', error
|
|
3071
|
-
isTestSessionFinalizationError: true,
|
|
3072
|
-
}))
|
|
3077
|
+
await waitForTestSessionFinish(getTestSessionFinishPayload('fail', error))
|
|
3073
3078
|
} catch (finalizationError) {
|
|
3074
3079
|
log.error('Jest test session finalization error: %s', finalizationError)
|
|
3075
3080
|
}
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
const shimmer = require('../../datadog-shimmer')
|
|
4
4
|
const { addHook, channel } = require('./helpers/instrument')
|
|
5
5
|
const { wrapThen } = require('./helpers/promise')
|
|
6
|
+
const {
|
|
7
|
+
wrapPoolRelease,
|
|
8
|
+
wrapPromisePoolAcquire,
|
|
9
|
+
wrapPromisePoolQueryMethod,
|
|
10
|
+
} = require('./helpers/pool-acquire')
|
|
6
11
|
|
|
7
12
|
const startRawQueryCh = channel('datadog:knex:raw:start')
|
|
8
13
|
const rawQuerySubscribes = channel('datadog:knex:raw:subscribes')
|
|
@@ -32,6 +37,14 @@ addHook({
|
|
|
32
37
|
versions: ['>=2'],
|
|
33
38
|
file: 'lib/knex-builder/Knex.js',
|
|
34
39
|
}, Knex => {
|
|
40
|
+
shimmer.wrap(Knex.Client.prototype, 'acquireConnection', acquireConnection => wrapPromisePoolAcquire(
|
|
41
|
+
acquireConnection,
|
|
42
|
+
resolveKnexDriver,
|
|
43
|
+
resolveKnexConfig,
|
|
44
|
+
knexHasIdleConnection
|
|
45
|
+
))
|
|
46
|
+
shimmer.wrap(Knex.Client.prototype, 'releaseConnection', wrapPoolRelease)
|
|
47
|
+
|
|
35
48
|
shimmer.wrap(Knex.Client.prototype, 'raw', raw => function (...args) {
|
|
36
49
|
if (!startRawQueryCh.hasSubscribers) {
|
|
37
50
|
return raw.apply(this, args)
|
|
@@ -77,6 +90,34 @@ addHook({
|
|
|
77
90
|
return Knex
|
|
78
91
|
})
|
|
79
92
|
|
|
93
|
+
addHook({
|
|
94
|
+
name: 'knex',
|
|
95
|
+
versions: ['>=2'],
|
|
96
|
+
file: 'lib/execution/runner.js',
|
|
97
|
+
}, Runner => {
|
|
98
|
+
shimmer.wrap(Runner.prototype, 'ensureConnection', ensureConnection => wrapPromisePoolQueryMethod(
|
|
99
|
+
ensureConnection,
|
|
100
|
+
runner => runner.connection || runner.builder?._connection ? undefined : runner.client,
|
|
101
|
+
runner => resolveKnexDriver(runner.client)
|
|
102
|
+
))
|
|
103
|
+
|
|
104
|
+
return Runner
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
addHook({
|
|
108
|
+
name: 'knex',
|
|
109
|
+
versions: ['>=2'],
|
|
110
|
+
file: 'lib/execution/transaction.js',
|
|
111
|
+
}, Transaction => {
|
|
112
|
+
shimmer.wrap(Transaction.prototype, 'acquireConnection', acquireConnection => wrapPromisePoolQueryMethod(
|
|
113
|
+
acquireConnection,
|
|
114
|
+
(transaction, args) => args[0]?.connection ? undefined : transaction.client,
|
|
115
|
+
transaction => resolveKnexDriver(transaction.client)
|
|
116
|
+
))
|
|
117
|
+
|
|
118
|
+
return Transaction
|
|
119
|
+
})
|
|
120
|
+
|
|
80
121
|
function wrapCallbackWithFinish (callback, finish, context) {
|
|
81
122
|
if (typeof callback !== 'function') return callback
|
|
82
123
|
|
|
@@ -84,3 +125,38 @@ function wrapCallbackWithFinish (callback, finish, context) {
|
|
|
84
125
|
finish(context, () => callback.apply(this, args))
|
|
85
126
|
})
|
|
86
127
|
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {{ pool?: { numFree?: () => number, numPendingAcquires?: () => number } }} client
|
|
131
|
+
* @returns {boolean}
|
|
132
|
+
*/
|
|
133
|
+
function knexHasIdleConnection (client) {
|
|
134
|
+
const pool = client.pool
|
|
135
|
+
if (typeof pool?.numFree !== 'function') return false
|
|
136
|
+
return pool.numFree() > pool.numPendingAcquires()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {{ driverName?: string }|undefined} client
|
|
141
|
+
* @returns {'mysql'|'mysql2'|'pg'|undefined}
|
|
142
|
+
*/
|
|
143
|
+
function resolveKnexDriver (client) {
|
|
144
|
+
switch (client?.driverName) {
|
|
145
|
+
case 'mysql':
|
|
146
|
+
return 'mysql'
|
|
147
|
+
case 'mysql2':
|
|
148
|
+
return 'mysql2'
|
|
149
|
+
case 'pg':
|
|
150
|
+
case 'cockroachdb':
|
|
151
|
+
case 'pg-redshift':
|
|
152
|
+
return 'pg'
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @param {{ connectionSettings?: Record<string, unknown> }} client
|
|
158
|
+
* @returns {Record<string, unknown>}
|
|
159
|
+
*/
|
|
160
|
+
function resolveKnexConfig (client) {
|
|
161
|
+
return client.connectionSettings ?? {}
|
|
162
|
+
}
|
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
runOutsidePoolQueryAcquire,
|
|
12
12
|
runPoolAcquireError,
|
|
13
13
|
runWithPoolWait,
|
|
14
|
+
setPromisePoolConnectionConfig,
|
|
14
15
|
takePoolWaitTime,
|
|
15
16
|
wrapPoolQueryMethod,
|
|
16
17
|
} = require('./helpers/pool-acquire')
|
|
@@ -97,6 +98,8 @@ function createWrapQuery (options) {
|
|
|
97
98
|
if (!startCh.hasSubscribers) return query.apply(this, arguments)
|
|
98
99
|
|
|
99
100
|
const ctx = { sql, conf: options }
|
|
101
|
+
const poolWaitTime = takePoolWaitTime(this)
|
|
102
|
+
if (poolWaitTime !== undefined) ctx.poolWaitTime = poolWaitTime
|
|
100
103
|
|
|
101
104
|
return startCh.runStores(ctx, query, this, ...arguments)
|
|
102
105
|
.then(result => {
|
|
@@ -146,8 +149,11 @@ function createWrapQueryCallback (options) {
|
|
|
146
149
|
function wrapConnection (promiseMethod, Connection) {
|
|
147
150
|
return function (options) {
|
|
148
151
|
Connection.apply(this, arguments)
|
|
152
|
+
setPromisePoolConnectionConfig(this, options)
|
|
149
153
|
|
|
154
|
+
const query = this[promiseMethod]
|
|
150
155
|
shimmer.wrap(this, promiseMethod, createWrapQuery(options))
|
|
156
|
+
if (this.query === query) this.query = this[promiseMethod]
|
|
151
157
|
shimmer.wrap(this, '_queryCallback', createWrapQueryCallback(options))
|
|
152
158
|
}
|
|
153
159
|
}
|
|
@@ -11,6 +11,60 @@ const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
|
11
11
|
const parameterizedTestCh = channel('ci:mocha:test:parameterize')
|
|
12
12
|
const patched = new WeakSet()
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Registers every Mocha package view that can expose the constructor.
|
|
16
|
+
*
|
|
17
|
+
* @param {string[]} versions
|
|
18
|
+
* @param {(Mocha: Function, frameworkVersion: string) => Function} wrapMochaRun
|
|
19
|
+
* @returns {void}
|
|
20
|
+
*/
|
|
21
|
+
function addMochaRunHooks (versions, wrapMochaRun) {
|
|
22
|
+
const patchedMochaConstructors = new WeakSet()
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Function} Mocha
|
|
26
|
+
* @param {string} frameworkVersion
|
|
27
|
+
* @returns {Function}
|
|
28
|
+
*/
|
|
29
|
+
function wrapMochaOnce (Mocha, frameworkVersion) {
|
|
30
|
+
if (patchedMochaConstructors.has(Mocha)) return Mocha
|
|
31
|
+
patchedMochaConstructors.add(Mocha)
|
|
32
|
+
return wrapMochaRun(Mocha, frameworkVersion)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {object|Function} MochaPackage
|
|
37
|
+
* @param {string} frameworkVersion
|
|
38
|
+
* @returns {object|Function}
|
|
39
|
+
*/
|
|
40
|
+
function wrapMochaPackage (MochaPackage, frameworkVersion) {
|
|
41
|
+
wrapMochaOnce(MochaPackage.default ?? MochaPackage, frameworkVersion)
|
|
42
|
+
return MochaPackage
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
addHook({
|
|
46
|
+
name: 'mocha',
|
|
47
|
+
versions,
|
|
48
|
+
filePattern: String.raw`lib/mocha\.(?:c?js)$`,
|
|
49
|
+
}, wrapMochaOnce)
|
|
50
|
+
|
|
51
|
+
// Mocha 12's ESM package root can load lib/mocha.cjs before the CJS hook observes it. ESM imports report the
|
|
52
|
+
// package root while synchronous require reports index.js, so hook both views. Keeping the namespace intact makes
|
|
53
|
+
// the ESM hook skip its separate default-export callback, and wrapMochaOnce deduplicates loaders exposing both.
|
|
54
|
+
addHook({
|
|
55
|
+
name: 'mocha',
|
|
56
|
+
versions: ['>=12.0.0'],
|
|
57
|
+
patchDefault: false,
|
|
58
|
+
}, wrapMochaPackage)
|
|
59
|
+
|
|
60
|
+
addHook({
|
|
61
|
+
name: 'mocha',
|
|
62
|
+
versions: ['>=12.0.0'],
|
|
63
|
+
file: 'index.js',
|
|
64
|
+
patchDefault: false,
|
|
65
|
+
}, wrapMochaPackage)
|
|
66
|
+
}
|
|
67
|
+
|
|
14
68
|
// mocha-each support
|
|
15
69
|
addHook({
|
|
16
70
|
name: 'mocha-each',
|
|
@@ -38,7 +92,8 @@ addHook({
|
|
|
38
92
|
name: 'mocha',
|
|
39
93
|
versions: [MINIMUM_MOCHA_VERSION],
|
|
40
94
|
file: 'lib/suite.js',
|
|
41
|
-
}, (
|
|
95
|
+
}, (SuitePackage) => {
|
|
96
|
+
const Suite = SuitePackage.Suite ?? SuitePackage
|
|
42
97
|
shimmer.wrap(Suite.prototype, 'addTest', addTest => function (test) {
|
|
43
98
|
const callSites = getCallSites()
|
|
44
99
|
const testCallSite = callSites.find(site => site.getFileName() === test.file)
|
|
@@ -47,5 +102,7 @@ addHook({
|
|
|
47
102
|
}
|
|
48
103
|
return addTest.apply(this, arguments)
|
|
49
104
|
})
|
|
50
|
-
return
|
|
105
|
+
return SuitePackage
|
|
51
106
|
})
|
|
107
|
+
|
|
108
|
+
module.exports = { addMochaRunHooks }
|
|
@@ -35,6 +35,7 @@ const {
|
|
|
35
35
|
isMarkedAsUnskippable,
|
|
36
36
|
} = require('../../../dd-trace/src/plugins/util/test')
|
|
37
37
|
|
|
38
|
+
const { addMochaRunHooks } = require('./common')
|
|
38
39
|
const {
|
|
39
40
|
isNewTest,
|
|
40
41
|
getTestProperties,
|
|
@@ -60,8 +61,6 @@ const {
|
|
|
60
61
|
adjustRunnerFailuresForTestOptimization,
|
|
61
62
|
} = require('./utils')
|
|
62
63
|
|
|
63
|
-
require('./common')
|
|
64
|
-
|
|
65
64
|
const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
66
65
|
|
|
67
66
|
/**
|
|
@@ -536,7 +535,10 @@ function stopCurrentHook (runner, hook) {
|
|
|
536
535
|
if (test) {
|
|
537
536
|
if (hook.parent?._afterEach?.includes(hook) || hook.parent?._afterAll?.includes(hook)) {
|
|
538
537
|
markTestTerminal(runner, test)
|
|
539
|
-
if (!test._ddTestFinishStarted)
|
|
538
|
+
if (!test._ddTestFinishStarted) {
|
|
539
|
+
const onTestEnd = runnerTestEndHandlers.get(runner)
|
|
540
|
+
onTestEnd?.(test)
|
|
541
|
+
}
|
|
540
542
|
} else {
|
|
541
543
|
markTestPending(runner, test)
|
|
542
544
|
}
|
|
@@ -763,14 +765,18 @@ function wrapRunnerEmit (Runner) {
|
|
|
763
765
|
const test = hook.ctx?.currentTest
|
|
764
766
|
if (test && hook.parent?._afterEach?.includes(hook)) {
|
|
765
767
|
markTestTerminal(this, test)
|
|
766
|
-
if (!test._ddTestFinishStarted)
|
|
768
|
+
if (!test._ddTestFinishStarted) {
|
|
769
|
+
const onTestEnd = runnerTestEndHandlers.get(this)
|
|
770
|
+
onTestEnd?.(test)
|
|
771
|
+
}
|
|
767
772
|
}
|
|
768
773
|
} else if (event === 'pending' || event === 'pass' || event === 'fail' || event === 'retry' ||
|
|
769
774
|
event === 'test end') {
|
|
770
775
|
const test = arguments[1]
|
|
771
776
|
stopAfterEachHooks(this, test)
|
|
772
777
|
if (event === 'test end' && !test._ddTestFinishStarted) {
|
|
773
|
-
runnerTestEndHandlers.get(this)
|
|
778
|
+
const onTestEnd = runnerTestEndHandlers.get(this)
|
|
779
|
+
onTestEnd?.(test)
|
|
774
780
|
}
|
|
775
781
|
}
|
|
776
782
|
}
|
|
@@ -1063,13 +1069,15 @@ function getExecutionConfiguration (runner, isParallel, frameworkVersion, onFini
|
|
|
1063
1069
|
// In this hook we delay the execution with options.delay to grab library configuration,
|
|
1064
1070
|
// skippable and known tests.
|
|
1065
1071
|
// It is called but skipped in parallel mode.
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1072
|
+
/**
|
|
1073
|
+
* @param {Function} Mocha
|
|
1074
|
+
* @param {string} frameworkVersion
|
|
1075
|
+
* @returns {Function}
|
|
1076
|
+
*/
|
|
1077
|
+
function wrapMochaRun (Mocha, frameworkVersion) {
|
|
1071
1078
|
warnDeprecatedMochaVersion(frameworkVersion)
|
|
1072
1079
|
|
|
1080
|
+
// Shimmer is required because run must return its Runner while execution is paused and resumed after configuration.
|
|
1073
1081
|
shimmer.wrap(Mocha.prototype, 'run', run => function (...args) {
|
|
1074
1082
|
// Workers do not need to request any data, just run the tests
|
|
1075
1083
|
if (!testFinishCh.hasSubscribers || getEnvironmentVariable('MOCHA_WORKER_ID') || this.options.parallel) {
|
|
@@ -1121,12 +1129,14 @@ addHook({
|
|
|
1121
1129
|
return runner
|
|
1122
1130
|
})
|
|
1123
1131
|
return Mocha
|
|
1124
|
-
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
addMochaRunHooks([MINIMUM_MOCHA_VERSION], wrapMochaRun)
|
|
1125
1135
|
|
|
1126
1136
|
addHook({
|
|
1127
1137
|
name: 'mocha',
|
|
1128
1138
|
versions: [MINIMUM_MOCHA_VERSION],
|
|
1129
|
-
|
|
1139
|
+
filePattern: String.raw`lib/cli/run-helpers\.(?:c?js)$`,
|
|
1130
1140
|
}, (run) => {
|
|
1131
1141
|
// `runMocha` is an async function
|
|
1132
1142
|
shimmer.wrap(run, 'runMocha', runMocha => function (...args) {
|
|
@@ -1157,7 +1167,7 @@ addHook({
|
|
|
1157
1167
|
addHook({
|
|
1158
1168
|
name: 'mocha',
|
|
1159
1169
|
versions: [MINIMUM_MOCHA_VERSION],
|
|
1160
|
-
|
|
1170
|
+
filePattern: String.raw`lib/runner\.(?:c?js)$`,
|
|
1161
1171
|
}, function (Runner, frameworkVersion) {
|
|
1162
1172
|
if (patched.has(Runner)) return Runner
|
|
1163
1173
|
|
|
@@ -1588,7 +1598,7 @@ addHook({
|
|
|
1588
1598
|
addHook({
|
|
1589
1599
|
name: 'mocha',
|
|
1590
1600
|
versions: ['>=8.0.0'],
|
|
1591
|
-
|
|
1601
|
+
filePattern: String.raw`lib/nodejs/parallel-buffered-runner\.(?:c?js)$`,
|
|
1592
1602
|
}, (ParallelBufferedRunner, frameworkVersion) => {
|
|
1593
1603
|
shimmer.wrap(ParallelBufferedRunner.prototype, 'run', run => function (cb, { files, options = {} }) {
|
|
1594
1604
|
if (!testFinishCh.hasSubscribers) {
|
|
@@ -1667,7 +1677,7 @@ addHook({
|
|
|
1667
1677
|
addHook({
|
|
1668
1678
|
name: 'mocha',
|
|
1669
1679
|
versions: ['>=8.0.0'],
|
|
1670
|
-
|
|
1680
|
+
filePattern: String.raw`lib/nodejs/buffered-worker-pool\.(?:c?js)$`,
|
|
1671
1681
|
}, (BufferedWorkerPoolPackage, frameworkVersion) => {
|
|
1672
1682
|
const { BufferedWorkerPool } = BufferedWorkerPoolPackage
|
|
1673
1683
|
|
|
@@ -507,7 +507,8 @@ function inheritDatadogPropertiesFromRetriedTest (test) {
|
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
510
|
-
|
|
510
|
+
const Runnable = RunnablePackage.Runnable ?? RunnablePackage
|
|
511
|
+
shimmer.wrap(Runnable.prototype, 'run', run => function (...args) {
|
|
511
512
|
if (!testFinishCh.hasSubscribers) {
|
|
512
513
|
return run.apply(this, args)
|
|
513
514
|
}
|
|
@@ -6,6 +6,11 @@ const {
|
|
|
6
6
|
WEBDRIVERIO_WORKER_EVENT,
|
|
7
7
|
WEBDRIVERIO_WORKER_ORIGIN,
|
|
8
8
|
} = require('../../../dd-trace/src/ci-visibility/exporters/test-worker/webdriverio')
|
|
9
|
+
const { FINAL_FLUSH_TIMEOUT } = require('../../../dd-trace/src/ci-visibility/final-flush')
|
|
10
|
+
|
|
11
|
+
const SCREENSHOT_UPLOAD = 'dd:test-optimization:webdriverio:screenshot:upload'
|
|
12
|
+
const SCREENSHOT_UPLOAD_RESPONSE = 'dd:test-optimization:webdriverio:screenshot:upload:response'
|
|
13
|
+
const SCREENSHOT_UPLOAD_TIMEOUT_MS = FINAL_FLUSH_TIMEOUT + 5000
|
|
9
14
|
|
|
10
15
|
/**
|
|
11
16
|
* Sends a message over WebdriverIO's worker IPC envelope.
|
|
@@ -30,10 +35,103 @@ function sendWebdriverioWorkerMessage (message, onError, onDone) {
|
|
|
30
35
|
})
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
let screenshotUploadRequestId = 0
|
|
39
|
+
const screenshotUploadRequests = new Map()
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Removes shared screenshot response listeners when there are no pending requests.
|
|
43
|
+
*
|
|
44
|
+
* @returns {void}
|
|
45
|
+
*/
|
|
46
|
+
function removeScreenshotUploadListeners () {
|
|
47
|
+
if (screenshotUploadRequests.size !== 0) return
|
|
48
|
+
|
|
49
|
+
process.off('message', onScreenshotUploadResponse)
|
|
50
|
+
process.off('disconnect', onScreenshotUploadDisconnect)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Completes one pending screenshot upload request.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} requestId
|
|
57
|
+
* @param {Error} [error]
|
|
58
|
+
* @returns {void}
|
|
59
|
+
*/
|
|
60
|
+
function finishScreenshotUploadRequest (requestId, error) {
|
|
61
|
+
const request = screenshotUploadRequests.get(requestId)
|
|
62
|
+
if (!request) return
|
|
63
|
+
|
|
64
|
+
screenshotUploadRequests.delete(requestId)
|
|
65
|
+
clearTimeout(request.timeout)
|
|
66
|
+
removeScreenshotUploadListeners()
|
|
67
|
+
request.onDone(error)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Dispatches one coordinator screenshot response to its pending request.
|
|
72
|
+
*
|
|
73
|
+
* @param {object} message
|
|
74
|
+
* @returns {void}
|
|
75
|
+
*/
|
|
76
|
+
function onScreenshotUploadResponse (message) {
|
|
77
|
+
if (message?.name !== SCREENSHOT_UPLOAD_RESPONSE) return
|
|
78
|
+
|
|
79
|
+
const { error: errorMessage, requestId } = message.content || {}
|
|
80
|
+
if (!requestId) return
|
|
81
|
+
|
|
82
|
+
finishScreenshotUploadRequest(requestId, errorMessage ? new Error(errorMessage) : undefined)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Fails every pending screenshot upload after coordinator disconnect.
|
|
87
|
+
*
|
|
88
|
+
* @returns {void}
|
|
89
|
+
*/
|
|
90
|
+
function onScreenshotUploadDisconnect () {
|
|
91
|
+
for (const requestId of screenshotUploadRequests.keys()) {
|
|
92
|
+
finishScreenshotUploadRequest(
|
|
93
|
+
requestId,
|
|
94
|
+
new Error('WebdriverIO coordinator disconnected during screenshot upload')
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Requests one screenshot upload from the WebdriverIO coordinator.
|
|
101
|
+
*
|
|
102
|
+
* @param {object} content - Screenshot upload metadata
|
|
103
|
+
* @param {(error?: Error) => void} onDone - Upload completion callback
|
|
104
|
+
* @returns {void}
|
|
105
|
+
*/
|
|
106
|
+
function requestWebdriverioScreenshotUpload (content, onDone) {
|
|
107
|
+
const requestId = `${process.pid}-${++screenshotUploadRequestId}`
|
|
108
|
+
const timeout = setTimeout(() => {
|
|
109
|
+
finishScreenshotUploadRequest(requestId, new Error('WebdriverIO screenshot upload timed out'))
|
|
110
|
+
}, SCREENSHOT_UPLOAD_TIMEOUT_MS)
|
|
111
|
+
timeout.unref?.()
|
|
112
|
+
if (screenshotUploadRequests.size === 0) {
|
|
113
|
+
process.on('message', onScreenshotUploadResponse)
|
|
114
|
+
process.once('disconnect', onScreenshotUploadDisconnect)
|
|
115
|
+
}
|
|
116
|
+
screenshotUploadRequests.set(requestId, { onDone, timeout })
|
|
117
|
+
sendWebdriverioWorkerMessage({
|
|
118
|
+
origin: 'datadog',
|
|
119
|
+
name: SCREENSHOT_UPLOAD,
|
|
120
|
+
content: { ...content, requestId },
|
|
121
|
+
}, error => finishScreenshotUploadRequest(
|
|
122
|
+
requestId,
|
|
123
|
+
error || new Error('WebdriverIO screenshot upload IPC failed')
|
|
124
|
+
))
|
|
125
|
+
}
|
|
126
|
+
|
|
33
127
|
module.exports = {
|
|
34
128
|
CONFIGURATION_REQUEST: 'dd:test-optimization:webdriverio:configuration:request',
|
|
35
129
|
CONFIGURATION_RESPONSE: 'dd:test-optimization:webdriverio:configuration:response',
|
|
36
130
|
createWebdriverioWorkerMessage,
|
|
131
|
+
requestWebdriverioScreenshotUpload,
|
|
132
|
+
SCREENSHOT_UPLOAD,
|
|
133
|
+
SCREENSHOT_UPLOAD_RESPONSE,
|
|
134
|
+
SCREENSHOT_UPLOAD_TIMEOUT_MS,
|
|
37
135
|
sendWebdriverioWorkerMessage,
|
|
38
136
|
SUITE_FINISH: 'dd:test-optimization:webdriverio:test-suite:finish',
|
|
39
137
|
WORKER_READY: 'dd:test-optimization:webdriverio:worker:ready',
|
|
@@ -7,6 +7,7 @@ const { getEnvironmentVariable } = require('../../../dd-trace/src/config/helper'
|
|
|
7
7
|
const log = require('../../../dd-trace/src/log')
|
|
8
8
|
const { DD_MAJOR } = require('../../../../version')
|
|
9
9
|
|
|
10
|
+
const { addMochaRunHooks } = require('./common')
|
|
10
11
|
const {
|
|
11
12
|
runnableWrapper,
|
|
12
13
|
getOnTestHandler,
|
|
@@ -29,7 +30,6 @@ const {
|
|
|
29
30
|
WEBDRIVERIO_WORKER_ENV,
|
|
30
31
|
WORKER_READY,
|
|
31
32
|
} = require('./webdriverio-protocol')
|
|
32
|
-
require('./common')
|
|
33
33
|
|
|
34
34
|
const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
35
35
|
|
|
@@ -360,13 +360,15 @@ function isFailedTestReplayEnabled () {
|
|
|
360
360
|
return config.isTestDynamicInstrumentationEnabled && config.isDiEnabled
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
363
|
+
/**
|
|
364
|
+
* @param {Function} Mocha
|
|
365
|
+
* @param {string} frameworkVersion
|
|
366
|
+
* @returns {Function}
|
|
367
|
+
*/
|
|
368
|
+
function wrapMochaRun (Mocha, frameworkVersion) {
|
|
368
369
|
reportWebdriverioWorkerReady(frameworkVersion)
|
|
369
370
|
|
|
371
|
+
// Shimmer is required because run must return its Runner while execution is paused and resumed after configuration.
|
|
370
372
|
shimmer.wrap(Mocha.prototype, 'run', run => function (...args) {
|
|
371
373
|
applyMochaOptions(this.options)
|
|
372
374
|
if (!isWebdriverioWorker || !workerFinishCh.hasSubscribers) {
|
|
@@ -438,13 +440,15 @@ addHook({
|
|
|
438
440
|
})
|
|
439
441
|
|
|
440
442
|
return Mocha
|
|
441
|
-
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
addMochaRunHooks(['>=8.0.0'], wrapMochaRun)
|
|
442
446
|
|
|
443
447
|
// Runner is also hooked in mocha/main.js, but in here we only generate test events.
|
|
444
448
|
addHook({
|
|
445
449
|
name: 'mocha',
|
|
446
450
|
versions: [MINIMUM_MOCHA_VERSION],
|
|
447
|
-
|
|
451
|
+
filePattern: String.raw`lib/runner\.(?:c?js)$`,
|
|
448
452
|
}, function (Runner) {
|
|
449
453
|
shimmer.wrap(Runner.prototype, 'runTests', runTests => getRunTestsWrapper(runTests, config))
|
|
450
454
|
|
|
@@ -27,8 +27,6 @@ addHook({ name: 'net' }, (net) => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const options = getOptions(args)
|
|
30
|
-
const lastIndex = args.length - 1
|
|
31
|
-
const callback = args[lastIndex]
|
|
32
30
|
|
|
33
31
|
if (!options) return connect.apply(this, args)
|
|
34
32
|
|
|
@@ -38,42 +36,39 @@ addHook({ name: 'net' }, (net) => {
|
|
|
38
36
|
const errorCh = protocol === 'ipc' ? errorICPCh : errorTCPCh
|
|
39
37
|
const ctx = { options }
|
|
40
38
|
|
|
41
|
-
if (typeof callback === 'function') {
|
|
42
|
-
args[lastIndex] = function (...args) {
|
|
43
|
-
return finishCh.runStores(ctx, callback, this, ...args)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
39
|
return startCh.runStores(ctx, () => {
|
|
48
|
-
setupListeners(this, protocol, ctx, finishCh, errorCh)
|
|
40
|
+
const cleanup = setupListeners(this, protocol, ctx, finishCh, errorCh)
|
|
49
41
|
|
|
50
|
-
const
|
|
42
|
+
const originalEmit = this.emit
|
|
51
43
|
let pendingReadyEvents = 2
|
|
52
44
|
// Named `emit`/arity-1 mirrors the socket method so the per-socket wrap
|
|
53
45
|
// skips its name/length rewrite.
|
|
54
|
-
this.emit = shimmer.wrapFunction(
|
|
46
|
+
this.emit = shimmer.wrapFunction(originalEmit, wrappedEmit => function emit (eventName) {
|
|
55
47
|
switch (eventName) {
|
|
56
48
|
case 'ready':
|
|
57
49
|
case 'connect':
|
|
58
50
|
if (--pendingReadyEvents === 0) this.emit = originalEmit
|
|
59
51
|
return readyCh.runStores(ctx, () => {
|
|
60
|
-
return Reflect.apply(
|
|
52
|
+
return Reflect.apply(wrappedEmit, this, arguments)
|
|
61
53
|
})
|
|
62
54
|
case 'error':
|
|
63
55
|
case 'close':
|
|
64
56
|
this.emit = originalEmit
|
|
65
|
-
return Reflect.apply(
|
|
57
|
+
return Reflect.apply(wrappedEmit, this, arguments)
|
|
66
58
|
default:
|
|
67
|
-
return Reflect.apply(
|
|
59
|
+
return Reflect.apply(wrappedEmit, this, arguments)
|
|
68
60
|
}
|
|
69
61
|
})
|
|
70
62
|
|
|
71
63
|
try {
|
|
72
64
|
return connect.apply(this, args)
|
|
73
|
-
} catch (
|
|
74
|
-
|
|
65
|
+
} catch (error) {
|
|
66
|
+
cleanup()
|
|
67
|
+
this.emit = originalEmit
|
|
68
|
+
errorCh.publish(error)
|
|
69
|
+
finishCh.runStores(ctx, () => {})
|
|
75
70
|
|
|
76
|
-
throw
|
|
71
|
+
throw error
|
|
77
72
|
}
|
|
78
73
|
})
|
|
79
74
|
})
|
|
@@ -142,4 +137,6 @@ function setupListeners (socket, protocol, ctx, finishCh, errorCh) {
|
|
|
142
137
|
for (const event of events) {
|
|
143
138
|
socket.once(event, wrapListener)
|
|
144
139
|
}
|
|
140
|
+
|
|
141
|
+
return cleanupOtherListeners
|
|
145
142
|
}
|