dd-trace 5.54.0 → 5.56.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 +1 -0
- package/ci/cypress/plugin.js +8 -0
- package/ci/cypress/polyfills.js +23 -0
- package/ci/init.js +8 -7
- package/initialize.mjs +2 -2
- package/package.json +10 -9
- package/packages/datadog-code-origin/index.js +22 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +3 -3
- package/packages/datadog-core/src/utils/src/set.js +8 -10
- package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -6
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +2 -3
- package/packages/datadog-instrumentations/src/cookie-parser.js +1 -1
- package/packages/datadog-instrumentations/src/couchbase.js +3 -6
- package/packages/datadog-instrumentations/src/cucumber.js +21 -28
- package/packages/datadog-instrumentations/src/dns.js +4 -4
- package/packages/datadog-instrumentations/src/elasticsearch.js +9 -10
- package/packages/datadog-instrumentations/src/fastify.js +7 -9
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +14 -16
- package/packages/datadog-instrumentations/src/hapi.js +10 -11
- package/packages/datadog-instrumentations/src/helpers/fetch.js +4 -5
- package/packages/datadog-instrumentations/src/helpers/hook.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +6 -5
- package/packages/datadog-instrumentations/src/jest.js +421 -376
- package/packages/datadog-instrumentations/src/koa.js +2 -3
- package/packages/datadog-instrumentations/src/mariadb.js +11 -4
- package/packages/datadog-instrumentations/src/mocha/main.js +79 -75
- package/packages/datadog-instrumentations/src/mocha.js +3 -1
- package/packages/datadog-instrumentations/src/mysql.js +11 -2
- package/packages/datadog-instrumentations/src/nyc.js +2 -1
- package/packages/datadog-instrumentations/src/openai.js +2 -2
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -3
- package/packages/datadog-instrumentations/src/pg.js +2 -3
- package/packages/datadog-instrumentations/src/playwright.js +19 -22
- package/packages/datadog-instrumentations/src/protobufjs.js +3 -4
- package/packages/datadog-instrumentations/src/redis.js +1 -1
- package/packages/datadog-instrumentations/src/restify.js +9 -13
- package/packages/datadog-instrumentations/src/router.js +12 -11
- package/packages/datadog-instrumentations/src/tedious.js +1 -2
- package/packages/datadog-instrumentations/src/vitest.js +15 -29
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +12 -12
- package/packages/datadog-plugin-aws-sdk/src/base.js +12 -8
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +12 -20
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -5
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -10
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -4
- package/packages/datadog-plugin-cucumber/src/index.js +3 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -1
- package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -1
- package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +1 -1
- package/packages/datadog-plugin-graphql/src/index.js +3 -2
- package/packages/datadog-plugin-graphql/src/resolve.js +17 -10
- package/packages/datadog-plugin-http/src/client.js +5 -6
- package/packages/datadog-plugin-http2/src/client.js +7 -8
- package/packages/datadog-plugin-jest/src/index.js +3 -2
- package/packages/datadog-plugin-mocha/src/index.js +6 -1
- package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
- package/packages/datadog-plugin-mysql/src/index.js +11 -0
- package/packages/datadog-plugin-next/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/tracing.js +2 -4
- package/packages/datadog-plugin-oracledb/src/index.js +2 -1
- package/packages/datadog-plugin-playwright/src/index.js +3 -2
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +8 -9
- package/packages/datadog-plugin-redis/src/index.js +1 -3
- package/packages/datadog-plugin-vitest/src/index.js +5 -4
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +1 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +12 -13
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +44 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +10 -11
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +0 -4
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +0 -1
- package/packages/dd-trace/src/appsec/index.js +16 -5
- package/packages/dd-trace/src/appsec/reporter.js +11 -11
- package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -3
- package/packages/dd-trace/src/appsec/telemetry/index.js +31 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -2
- package/packages/dd-trace/src/azure_metadata.js +8 -3
- package/packages/dd-trace/src/baggage.js +2 -2
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +8 -7
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +4 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +7 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -3
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -1
- package/packages/dd-trace/src/config-helper.js +89 -0
- package/packages/dd-trace/src/config.js +120 -115
- package/packages/dd-trace/src/config_stable.js +7 -4
- package/packages/dd-trace/src/datastreams/fnv.js +1 -1
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +6 -6
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -3
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/status.js +5 -1
- package/packages/dd-trace/src/debugger/index.js +1 -0
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +5 -2
- package/packages/dd-trace/src/encode/0.5.js +3 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -5
- package/packages/dd-trace/src/exporter.js +2 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +3 -1
- package/packages/dd-trace/src/exporters/common/docker.js +3 -2
- package/packages/dd-trace/src/exporters/common/request.js +4 -1
- package/packages/dd-trace/src/exporters/common/util.js +3 -1
- package/packages/dd-trace/src/id.js +3 -3
- package/packages/dd-trace/src/index.js +4 -3
- package/packages/dd-trace/src/lambda/handler.js +2 -1
- package/packages/dd-trace/src/lambda/index.js +2 -1
- package/packages/dd-trace/src/lambda/runtime/patch.js +3 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/index.js +21 -5
- package/packages/dd-trace/src/llmobs/noop.js +18 -20
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +11 -13
- package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -2
- package/packages/dd-trace/src/llmobs/sdk.js +2 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +19 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
- package/packages/dd-trace/src/log/index.js +5 -4
- package/packages/dd-trace/src/log/writer.js +1 -2
- package/packages/dd-trace/src/msgpack/encoder.js +3 -3
- package/packages/dd-trace/src/noop/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +4 -5
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -42
- package/packages/dd-trace/src/opentracing/span.js +7 -6
- package/packages/dd-trace/src/payload-tagging/config/index.js +17 -21
- package/packages/dd-trace/src/plugin_manager.js +4 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +25 -1
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +7 -7
- package/packages/dd-trace/src/plugins/util/git.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +8 -1
- package/packages/dd-trace/src/plugins/util/test.js +4 -3
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -1
- package/packages/dd-trace/src/plugins/util/web.js +3 -4
- package/packages/dd-trace/src/priority_sampler.js +46 -35
- package/packages/dd-trace/src/profiling/config.js +12 -32
- package/packages/dd-trace/src/profiling/exporter_cli.js +20 -20
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -1
- package/packages/dd-trace/src/profiling/index.js +2 -1
- package/packages/dd-trace/src/profiling/profiler.js +7 -4
- package/packages/dd-trace/src/profiling/profilers/events.js +10 -2
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +3 -1
- package/packages/dd-trace/src/profiling/tagger.js +22 -12
- package/packages/dd-trace/src/proxy.js +2 -1
- package/packages/dd-trace/src/ritm.js +4 -4
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -2
- package/packages/dd-trace/src/sampler.js +10 -2
- package/packages/dd-trace/src/serverless.js +11 -4
- package/packages/dd-trace/src/span_processor.js +2 -1
- package/packages/dd-trace/src/standalone/tracesource.js +1 -2
- package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +1 -2
- package/packages/dd-trace/src/startup-log.js +5 -17
- package/packages/dd-trace/src/supported-configurations.json +440 -0
- package/packages/dd-trace/src/telemetry/dependencies.js +62 -57
- package/packages/dd-trace/src/telemetry/send-data.js +7 -6
- package/packages/dd-trace/src/telemetry/telemetry.js +16 -26
- package/packages/dd-trace/src/tracer.js +3 -7
- package/packages/dd-trace/src/util.js +0 -5
- package/packages/datadog-core/src/utils/src/get.js +0 -11
- package/packages/datadog-core/src/utils/src/has.js +0 -14
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +0 -120
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +0 -20
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { addHook, channel
|
|
3
|
+
const { addHook, channel } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
5
|
const log = require('../../dd-trace/src/log')
|
|
6
6
|
const {
|
|
@@ -83,14 +83,13 @@ let testManagementAttemptToFixRetries = 0
|
|
|
83
83
|
let isImpactedTestsEnabled = false
|
|
84
84
|
let modifiedTests = {}
|
|
85
85
|
|
|
86
|
-
const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
87
|
-
|
|
88
86
|
const testContexts = new WeakMap()
|
|
89
87
|
const originalTestFns = new WeakMap()
|
|
90
88
|
const originalHookFns = new WeakMap()
|
|
91
89
|
const retriedTestsToNumAttempts = new Map()
|
|
92
90
|
const newTestsTestStatuses = new Map()
|
|
93
91
|
const attemptToFixRetriedTestsStatuses = new Map()
|
|
92
|
+
const wrappedWorkers = new WeakSet()
|
|
94
93
|
|
|
95
94
|
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
|
|
96
95
|
|
|
@@ -427,6 +426,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
427
426
|
if (event.name === 'add_test') {
|
|
428
427
|
const originalTestName = this.getTestNameFromAddTestEvent(event, state)
|
|
429
428
|
|
|
429
|
+
if (event.failing) {
|
|
430
|
+
return
|
|
431
|
+
}
|
|
432
|
+
|
|
430
433
|
const isSkipped = event.mode === 'todo' || event.mode === 'skip'
|
|
431
434
|
if (this.isTestManagementTestsEnabled) {
|
|
432
435
|
const isAttemptToFix = this.testManagementTestsForThisSuite?.attemptToFix?.includes(originalTestName)
|
|
@@ -581,22 +584,30 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
581
584
|
}
|
|
582
585
|
}
|
|
583
586
|
if (event.name === 'test_skip' || event.name === 'test_todo') {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
},
|
|
595
|
-
isDisabled: this.testManagementTestsForThisSuite?.disabled?.includes(getJestTestName(event.test))
|
|
596
|
-
})
|
|
587
|
+
testSkippedCh.publish({
|
|
588
|
+
test: {
|
|
589
|
+
name: getJestTestName(event.test),
|
|
590
|
+
suite: this.testSuite,
|
|
591
|
+
testSourceFile: this.testSourceFile,
|
|
592
|
+
displayName: this.displayName,
|
|
593
|
+
frameworkVersion: jestVersion,
|
|
594
|
+
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
|
|
595
|
+
},
|
|
596
|
+
isDisabled: this.testManagementTestsForThisSuite?.disabled?.includes(getJestTestName(event.test))
|
|
597
597
|
})
|
|
598
598
|
}
|
|
599
599
|
}
|
|
600
|
+
|
|
601
|
+
teardown () {
|
|
602
|
+
if (this._globalProxy?.propertyToValue) {
|
|
603
|
+
for (const [key] of this._globalProxy.propertyToValue) {
|
|
604
|
+
if (typeof key === 'string' && key.startsWith('_dd')) {
|
|
605
|
+
this._globalProxy.propertyToValue.delete(key)
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return super.teardown()
|
|
610
|
+
}
|
|
600
611
|
}
|
|
601
612
|
}
|
|
602
613
|
|
|
@@ -652,219 +663,210 @@ function getWrappedScheduleTests (scheduleTests, frameworkVersion) {
|
|
|
652
663
|
}
|
|
653
664
|
}
|
|
654
665
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
file: 'build/TestScheduler.js',
|
|
658
|
-
versions: ['>=27.0.0']
|
|
659
|
-
}, (testSchedulerPackage, frameworkVersion) => {
|
|
660
|
-
const oldCreateTestScheduler = testSchedulerPackage.createTestScheduler
|
|
661
|
-
const newCreateTestScheduler = async function () {
|
|
662
|
-
if (!isSuitesSkippingEnabled || hasFilteredSkippableSuites) {
|
|
663
|
-
return oldCreateTestScheduler.apply(this, arguments)
|
|
664
|
-
}
|
|
665
|
-
// If suite skipping is enabled and has not filtered skippable suites yet, we'll attempt to do it
|
|
666
|
-
const scheduler = await oldCreateTestScheduler.apply(this, arguments)
|
|
667
|
-
shimmer.wrap(scheduler, 'scheduleTests', scheduleTests => getWrappedScheduleTests(scheduleTests, frameworkVersion))
|
|
668
|
-
return scheduler
|
|
669
|
-
}
|
|
670
|
-
testSchedulerPackage.createTestScheduler = newCreateTestScheduler
|
|
671
|
-
return testSchedulerPackage
|
|
672
|
-
})
|
|
666
|
+
function searchSourceWrapper (searchSourcePackage, frameworkVersion) {
|
|
667
|
+
const SearchSource = searchSourcePackage.default ?? searchSourcePackage
|
|
673
668
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
versions: ['>=24.8.0 <27.0.0']
|
|
678
|
-
}, (testSchedulerPackage, frameworkVersion) => {
|
|
679
|
-
shimmer.wrap(
|
|
680
|
-
testSchedulerPackage.default.prototype,
|
|
681
|
-
'scheduleTests', scheduleTests => getWrappedScheduleTests(scheduleTests, frameworkVersion)
|
|
682
|
-
)
|
|
683
|
-
return testSchedulerPackage
|
|
684
|
-
})
|
|
669
|
+
shimmer.wrap(SearchSource.prototype, 'getTestPaths', getTestPaths => async function () {
|
|
670
|
+
const testPaths = await getTestPaths.apply(this, arguments)
|
|
671
|
+
const [{ rootDir, shard }] = arguments
|
|
685
672
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
673
|
+
if (isKnownTestsEnabled) {
|
|
674
|
+
const projectSuites = testPaths.tests.map(test => getTestSuitePath(test.path, test.context.config.rootDir))
|
|
675
|
+
const isFaulty =
|
|
676
|
+
getIsFaultyEarlyFlakeDetection(projectSuites, knownTests?.jest || {}, earlyFlakeDetectionFaultyThreshold)
|
|
677
|
+
if (isFaulty) {
|
|
678
|
+
log.error('Early flake detection is disabled because the number of new suites is too high.')
|
|
679
|
+
isEarlyFlakeDetectionEnabled = false
|
|
680
|
+
isKnownTestsEnabled = false
|
|
681
|
+
const testEnvironmentOptions = testPaths.tests[0]?.context?.config?.testEnvironmentOptions
|
|
682
|
+
// Project config is shared among all tests, so we can modify it here
|
|
683
|
+
if (testEnvironmentOptions) {
|
|
684
|
+
testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled = false
|
|
685
|
+
testEnvironmentOptions._ddIsKnownTestsEnabled = false
|
|
686
|
+
}
|
|
687
|
+
isEarlyFlakeDetectionFaulty = true
|
|
688
|
+
}
|
|
689
|
+
}
|
|
692
690
|
|
|
693
|
-
if (
|
|
694
|
-
|
|
691
|
+
if (shard?.shardCount > 1 || !isSuitesSkippingEnabled || !skippableSuites.length) {
|
|
692
|
+
// If the user is using jest sharding, we want to apply the filtering of tests in the shard process.
|
|
693
|
+
// The reason for this is the following:
|
|
694
|
+
// The tests for different shards are likely being run in different CI jobs so
|
|
695
|
+
// the requests to the skippable endpoint might be done at different times and their responses might be different.
|
|
696
|
+
// If the skippable endpoint is returning different suites and we filter the list of tests here,
|
|
697
|
+
// the base list of tests that is used for sharding might be different,
|
|
698
|
+
// causing the shards to potentially run the same suite.
|
|
699
|
+
return testPaths
|
|
695
700
|
}
|
|
696
|
-
const
|
|
697
|
-
const rootDir = test?.context?.config?.rootDir
|
|
701
|
+
const { tests } = testPaths
|
|
698
702
|
|
|
699
|
-
|
|
703
|
+
const suitesToRun = applySuiteSkipping(tests, rootDir, frameworkVersion)
|
|
704
|
+
return { ...testPaths, tests: suitesToRun }
|
|
700
705
|
})
|
|
701
|
-
return sequencerPackage
|
|
702
|
-
})
|
|
703
706
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
707
|
+
return searchSourcePackage
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function getCliWrapper (isNewJestVersion) {
|
|
711
|
+
return function cliWrapper (cli, jestVersion) {
|
|
712
|
+
if (isNewJestVersion) {
|
|
713
|
+
cli = shimmer.wrap(
|
|
714
|
+
cli,
|
|
715
|
+
'SearchSource',
|
|
716
|
+
searchSource => searchSourceWrapper(searchSource, jestVersion),
|
|
717
|
+
{ replaceGetter: true }
|
|
718
|
+
)
|
|
712
719
|
}
|
|
720
|
+
return shimmer.wrap(cli, 'runCLI', runCLI => async function () {
|
|
721
|
+
let onDone
|
|
722
|
+
const configurationPromise = new Promise((resolve) => {
|
|
723
|
+
onDone = resolve
|
|
724
|
+
})
|
|
725
|
+
if (!libraryConfigurationCh.hasSubscribers) {
|
|
726
|
+
return runCLI.apply(this, arguments)
|
|
727
|
+
}
|
|
713
728
|
|
|
714
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
715
729
|
libraryConfigurationCh.publish({ onDone })
|
|
716
|
-
})
|
|
717
730
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
731
|
+
try {
|
|
732
|
+
const { err, libraryConfig } = await configurationPromise
|
|
733
|
+
if (!err) {
|
|
734
|
+
isCodeCoverageEnabled = libraryConfig.isCodeCoverageEnabled
|
|
735
|
+
isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
736
|
+
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
737
|
+
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
738
|
+
earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
739
|
+
isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
740
|
+
isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
|
|
741
|
+
testManagementAttemptToFixRetries = libraryConfig.testManagementAttemptToFixRetries
|
|
742
|
+
isImpactedTestsEnabled = libraryConfig.isImpactedTestsEnabled
|
|
743
|
+
}
|
|
744
|
+
} catch (err) {
|
|
745
|
+
log.error('Jest library configuration error', err)
|
|
730
746
|
}
|
|
731
|
-
} catch (err) {
|
|
732
|
-
log.error('Jest library configuration error', err)
|
|
733
|
-
}
|
|
734
747
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
748
|
+
if (isKnownTestsEnabled) {
|
|
749
|
+
const knownTestsPromise = new Promise((resolve) => {
|
|
750
|
+
onDone = resolve
|
|
751
|
+
})
|
|
739
752
|
|
|
740
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
741
753
|
knownTestsCh.publish({ onDone })
|
|
742
|
-
})
|
|
743
754
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
755
|
+
try {
|
|
756
|
+
const { err, knownTests: receivedKnownTests } = await knownTestsPromise
|
|
757
|
+
if (err) {
|
|
758
|
+
// We disable EFD if there has been an error in the known tests request
|
|
759
|
+
isEarlyFlakeDetectionEnabled = false
|
|
760
|
+
isKnownTestsEnabled = false
|
|
761
|
+
} else {
|
|
762
|
+
knownTests = receivedKnownTests
|
|
763
|
+
}
|
|
764
|
+
} catch (err) {
|
|
765
|
+
log.error('Jest known tests error', err)
|
|
752
766
|
}
|
|
753
|
-
} catch (err) {
|
|
754
|
-
log.error('Jest known tests error', err)
|
|
755
767
|
}
|
|
756
|
-
}
|
|
757
768
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
769
|
+
if (isSuitesSkippingEnabled) {
|
|
770
|
+
const skippableSuitesPromise = new Promise((resolve) => {
|
|
771
|
+
onDone = resolve
|
|
772
|
+
})
|
|
762
773
|
|
|
763
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
764
774
|
skippableSuitesCh.publish({ onDone })
|
|
765
|
-
})
|
|
766
775
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
776
|
+
try {
|
|
777
|
+
const { err, skippableSuites: receivedSkippableSuites } = await skippableSuitesPromise
|
|
778
|
+
if (!err) {
|
|
779
|
+
skippableSuites = receivedSkippableSuites
|
|
780
|
+
}
|
|
781
|
+
} catch (err) {
|
|
782
|
+
log.error('Jest test-suite skippable error', err)
|
|
771
783
|
}
|
|
772
|
-
} catch (err) {
|
|
773
|
-
log.error('Jest test-suite skippable error', err)
|
|
774
784
|
}
|
|
775
|
-
}
|
|
776
785
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
786
|
+
if (isTestManagementTestsEnabled) {
|
|
787
|
+
const testManagementTestsPromise = new Promise((resolve) => {
|
|
788
|
+
onDone = resolve
|
|
789
|
+
})
|
|
781
790
|
|
|
782
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
783
791
|
testManagementTestsCh.publish({ onDone })
|
|
784
|
-
})
|
|
785
792
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
793
|
+
try {
|
|
794
|
+
const { err, testManagementTests: receivedTestManagementTests } = await testManagementTestsPromise
|
|
795
|
+
if (!err) {
|
|
796
|
+
testManagementTests = receivedTestManagementTests
|
|
797
|
+
}
|
|
798
|
+
} catch (err) {
|
|
799
|
+
log.error('Jest test management tests error', err)
|
|
790
800
|
}
|
|
791
|
-
} catch (err) {
|
|
792
|
-
log.error('Jest test management tests error', err)
|
|
793
801
|
}
|
|
794
|
-
}
|
|
795
802
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
803
|
+
if (isImpactedTestsEnabled) {
|
|
804
|
+
const impactedTestsPromise = new Promise((resolve) => {
|
|
805
|
+
onDone = resolve
|
|
806
|
+
})
|
|
800
807
|
|
|
801
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
802
808
|
impactedTestsCh.publish({ onDone })
|
|
803
|
-
})
|
|
804
809
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
810
|
+
try {
|
|
811
|
+
const { err, modifiedTests: receivedModifiedTests } = await impactedTestsPromise
|
|
812
|
+
if (!err) {
|
|
813
|
+
modifiedTests = receivedModifiedTests
|
|
814
|
+
}
|
|
815
|
+
} catch (err) {
|
|
816
|
+
log.error('Jest impacted tests error', err)
|
|
809
817
|
}
|
|
810
|
-
} catch (err) {
|
|
811
|
-
log.error('Jest impacted tests error', err)
|
|
812
818
|
}
|
|
813
|
-
}
|
|
814
819
|
|
|
815
|
-
|
|
816
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
820
|
+
const processArgv = process.argv.slice(2).join(' ')
|
|
817
821
|
testSessionStartCh.publish({ command: `jest ${processArgv}`, frameworkVersion: jestVersion })
|
|
818
|
-
})
|
|
819
822
|
|
|
820
|
-
|
|
823
|
+
const result = await runCLI.apply(this, arguments)
|
|
821
824
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
825
|
+
const {
|
|
826
|
+
results: {
|
|
827
|
+
success,
|
|
828
|
+
coverageMap,
|
|
829
|
+
numFailedTestSuites,
|
|
830
|
+
numFailedTests,
|
|
831
|
+
numTotalTests,
|
|
832
|
+
numTotalTestSuites
|
|
833
|
+
}
|
|
834
|
+
} = result
|
|
832
835
|
|
|
833
|
-
|
|
836
|
+
let testCodeCoverageLinesTotal
|
|
834
837
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
838
|
+
if (isUserCodeCoverageEnabled) {
|
|
839
|
+
try {
|
|
840
|
+
const { pct, total } = coverageMap.getCoverageSummary().lines
|
|
841
|
+
testCodeCoverageLinesTotal = total === 0 ? 0 : pct
|
|
842
|
+
} catch {
|
|
843
|
+
// ignore errors
|
|
844
|
+
}
|
|
841
845
|
}
|
|
842
|
-
|
|
843
|
-
let status, error
|
|
846
|
+
let status, error
|
|
844
847
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
}
|
|
851
|
-
let timeoutId
|
|
852
|
-
|
|
853
|
-
// Pass the resolve callback to defer it to DC listener
|
|
854
|
-
const flushPromise = new Promise((resolve) => {
|
|
855
|
-
onDone = () => {
|
|
856
|
-
clearTimeout(timeoutId)
|
|
857
|
-
resolve()
|
|
848
|
+
if (success) {
|
|
849
|
+
status = numTotalTests === 0 && numTotalTestSuites === 0 ? 'skip' : 'pass'
|
|
850
|
+
} else {
|
|
851
|
+
status = 'fail'
|
|
852
|
+
error = new Error(`Failed test suites: ${numFailedTestSuites}. Failed tests: ${numFailedTests}`)
|
|
858
853
|
}
|
|
859
|
-
|
|
854
|
+
let timeoutId
|
|
860
855
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
856
|
+
// Pass the resolve callback to defer it to DC listener
|
|
857
|
+
const flushPromise = new Promise((resolve) => {
|
|
858
|
+
onDone = () => {
|
|
859
|
+
clearTimeout(timeoutId)
|
|
860
|
+
resolve()
|
|
861
|
+
}
|
|
862
|
+
})
|
|
863
|
+
|
|
864
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
865
|
+
timeoutId = setTimeout(() => {
|
|
866
|
+
resolve('timeout')
|
|
867
|
+
}, FLUSH_TIMEOUT).unref()
|
|
868
|
+
})
|
|
866
869
|
|
|
867
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
868
870
|
testSessionFinishCh.publish({
|
|
869
871
|
status,
|
|
870
872
|
isSuitesSkipped,
|
|
@@ -880,84 +882,86 @@ function cliWrapper (cli, jestVersion) {
|
|
|
880
882
|
isTestManagementTestsEnabled,
|
|
881
883
|
onDone
|
|
882
884
|
})
|
|
883
|
-
})
|
|
884
|
-
const waitingResult = await Promise.race([flushPromise, timeoutPromise])
|
|
885
885
|
|
|
886
|
-
|
|
887
|
-
log.error('Timeout waiting for the tracer to flush')
|
|
888
|
-
}
|
|
886
|
+
const waitingResult = await Promise.race([flushPromise, timeoutPromise])
|
|
889
887
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
/**
|
|
893
|
-
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
894
|
-
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
|
|
895
|
-
* - If just a single attempt passes, we will prevent the test process from failing.
|
|
896
|
-
* The rationale behind is the following: you may still be able to block your CI pipeline by gating
|
|
897
|
-
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
|
|
898
|
-
*/
|
|
899
|
-
|
|
900
|
-
if (isEarlyFlakeDetectionEnabled) {
|
|
901
|
-
let numFailedTestsToIgnore = 0
|
|
902
|
-
for (const testStatuses of newTestsTestStatuses.values()) {
|
|
903
|
-
const { pass, fail } = getTestStats(testStatuses)
|
|
904
|
-
if (pass > 0) { // as long as one passes, we'll consider the test passed
|
|
905
|
-
numFailedTestsToIgnore += fail
|
|
906
|
-
}
|
|
888
|
+
if (waitingResult === 'timeout') {
|
|
889
|
+
log.error('Timeout waiting for the tracer to flush')
|
|
907
890
|
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
891
|
+
|
|
892
|
+
numSkippedSuites = 0
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
896
|
+
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
|
|
897
|
+
* - If just a single attempt passes, we will prevent the test process from failing.
|
|
898
|
+
* The rationale behind is the following: you may still be able to block your CI pipeline by gating
|
|
899
|
+
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
|
|
900
|
+
*/
|
|
901
|
+
|
|
902
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
903
|
+
let numFailedTestsToIgnore = 0
|
|
904
|
+
for (const testStatuses of newTestsTestStatuses.values()) {
|
|
905
|
+
const { pass, fail } = getTestStats(testStatuses)
|
|
906
|
+
if (pass > 0) { // as long as one passes, we'll consider the test passed
|
|
907
|
+
numFailedTestsToIgnore += fail
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
// If every test that failed was an EFD retry, we'll consider the suite passed
|
|
911
|
+
if (numFailedTestsToIgnore !== 0 && result.results.numFailedTests === numFailedTestsToIgnore) {
|
|
912
|
+
result.results.success = true
|
|
913
|
+
}
|
|
911
914
|
}
|
|
912
|
-
}
|
|
913
915
|
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
916
|
+
if (isTestManagementTestsEnabled) {
|
|
917
|
+
const failedTests = result
|
|
918
|
+
.results
|
|
919
|
+
.testResults.flatMap(({ testResults, testFilePath: testSuiteAbsolutePath }) => (
|
|
920
|
+
testResults.map(({ fullName: testName, status }) => (
|
|
921
|
+
{ testName, testSuiteAbsolutePath, status }
|
|
922
|
+
))
|
|
920
923
|
))
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
924
|
+
.filter(({ status }) => status === 'failed')
|
|
925
|
+
|
|
926
|
+
let numFailedQuarantinedTests = 0
|
|
927
|
+
let numFailedQuarantinedOrDisabledAttemptedToFixTests = 0
|
|
928
|
+
|
|
929
|
+
for (const { testName, testSuiteAbsolutePath } of failedTests) {
|
|
930
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, result.globalConfig.rootDir)
|
|
931
|
+
const originalName = removeAttemptToFixStringFromTestName(testName)
|
|
932
|
+
const testManagementTest = testManagementTests
|
|
933
|
+
?.jest
|
|
934
|
+
?.suites
|
|
935
|
+
?.[testSuite]
|
|
936
|
+
?.tests
|
|
937
|
+
?.[originalName]
|
|
938
|
+
?.properties
|
|
939
|
+
// This uses `attempt_to_fix` because this is always the main process and it's not formatted in camelCase
|
|
940
|
+
if (testManagementTest?.attempt_to_fix && (testManagementTest?.quarantined || testManagementTest?.disabled)) {
|
|
941
|
+
numFailedQuarantinedOrDisabledAttemptedToFixTests++
|
|
942
|
+
} else if (testManagementTest?.quarantined) {
|
|
943
|
+
numFailedQuarantinedTests++
|
|
944
|
+
}
|
|
942
945
|
}
|
|
943
|
-
}
|
|
944
946
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
(
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
947
|
+
// If every test that failed was quarantined, we'll consider the suite passed
|
|
948
|
+
// Note that if a test is attempted to fix,
|
|
949
|
+
// it's considered quarantined both if it's disabled and if it's quarantined
|
|
950
|
+
// (it'll run but its status is ignored)
|
|
951
|
+
if (
|
|
952
|
+
(numFailedQuarantinedOrDisabledAttemptedToFixTests !== 0 || numFailedQuarantinedTests !== 0) &&
|
|
953
|
+
result.results.numFailedTests ===
|
|
954
|
+
numFailedQuarantinedTests + numFailedQuarantinedOrDisabledAttemptedToFixTests
|
|
955
|
+
) {
|
|
956
|
+
result.results.success = true
|
|
957
|
+
}
|
|
954
958
|
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
return result
|
|
958
|
-
})
|
|
959
959
|
|
|
960
|
-
|
|
960
|
+
return result
|
|
961
|
+
}, {
|
|
962
|
+
replaceGetter: true
|
|
963
|
+
})
|
|
964
|
+
}
|
|
961
965
|
}
|
|
962
966
|
|
|
963
967
|
function coverageReporterWrapper (coverageReporter) {
|
|
@@ -981,6 +985,55 @@ function coverageReporterWrapper (coverageReporter) {
|
|
|
981
985
|
return coverageReporter
|
|
982
986
|
}
|
|
983
987
|
|
|
988
|
+
addHook({
|
|
989
|
+
name: '@jest/core',
|
|
990
|
+
file: 'build/TestScheduler.js',
|
|
991
|
+
versions: ['>=27.0.0']
|
|
992
|
+
}, (testSchedulerPackage, frameworkVersion) => {
|
|
993
|
+
const oldCreateTestScheduler = testSchedulerPackage.createTestScheduler
|
|
994
|
+
const newCreateTestScheduler = async function () {
|
|
995
|
+
if (!isSuitesSkippingEnabled || hasFilteredSkippableSuites) {
|
|
996
|
+
return oldCreateTestScheduler.apply(this, arguments)
|
|
997
|
+
}
|
|
998
|
+
// If suite skipping is enabled and has not filtered skippable suites yet, we'll attempt to do it
|
|
999
|
+
const scheduler = await oldCreateTestScheduler.apply(this, arguments)
|
|
1000
|
+
shimmer.wrap(scheduler, 'scheduleTests', scheduleTests => getWrappedScheduleTests(scheduleTests, frameworkVersion))
|
|
1001
|
+
return scheduler
|
|
1002
|
+
}
|
|
1003
|
+
testSchedulerPackage.createTestScheduler = newCreateTestScheduler
|
|
1004
|
+
return testSchedulerPackage
|
|
1005
|
+
})
|
|
1006
|
+
|
|
1007
|
+
addHook({
|
|
1008
|
+
name: '@jest/core',
|
|
1009
|
+
file: 'build/TestScheduler.js',
|
|
1010
|
+
versions: ['>=24.8.0 <27.0.0']
|
|
1011
|
+
}, (testSchedulerPackage, frameworkVersion) => {
|
|
1012
|
+
shimmer.wrap(
|
|
1013
|
+
testSchedulerPackage.default.prototype,
|
|
1014
|
+
'scheduleTests', scheduleTests => getWrappedScheduleTests(scheduleTests, frameworkVersion)
|
|
1015
|
+
)
|
|
1016
|
+
return testSchedulerPackage
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1019
|
+
addHook({
|
|
1020
|
+
name: '@jest/test-sequencer',
|
|
1021
|
+
versions: ['>=28']
|
|
1022
|
+
}, (sequencerPackage, frameworkVersion) => {
|
|
1023
|
+
shimmer.wrap(sequencerPackage.default.prototype, 'shard', shard => function () {
|
|
1024
|
+
const shardedTests = shard.apply(this, arguments)
|
|
1025
|
+
|
|
1026
|
+
if (!shardedTests.length || !isSuitesSkippingEnabled || !skippableSuites.length) {
|
|
1027
|
+
return shardedTests
|
|
1028
|
+
}
|
|
1029
|
+
const [test] = shardedTests
|
|
1030
|
+
const rootDir = test?.context?.config?.rootDir
|
|
1031
|
+
|
|
1032
|
+
return applySuiteSkipping(shardedTests, rootDir, frameworkVersion)
|
|
1033
|
+
})
|
|
1034
|
+
return sequencerPackage
|
|
1035
|
+
})
|
|
1036
|
+
|
|
984
1037
|
addHook({
|
|
985
1038
|
name: '@jest/reporters',
|
|
986
1039
|
file: 'build/coverage_reporter.js',
|
|
@@ -993,11 +1046,23 @@ addHook({
|
|
|
993
1046
|
versions: ['>=26.6.2']
|
|
994
1047
|
}, coverageReporterWrapper)
|
|
995
1048
|
|
|
1049
|
+
addHook({
|
|
1050
|
+
name: '@jest/reporters',
|
|
1051
|
+
versions: ['>=30.0.0']
|
|
1052
|
+
}, (reporters) => {
|
|
1053
|
+
return shimmer.wrap(reporters, 'CoverageReporter', coverageReporterWrapper, { replaceGetter: true })
|
|
1054
|
+
})
|
|
1055
|
+
|
|
996
1056
|
addHook({
|
|
997
1057
|
name: '@jest/core',
|
|
998
1058
|
file: 'build/cli/index.js',
|
|
999
|
-
versions: ['>=24.8.0']
|
|
1000
|
-
},
|
|
1059
|
+
versions: ['>=24.8.0 <30.0.0']
|
|
1060
|
+
}, getCliWrapper(false))
|
|
1061
|
+
|
|
1062
|
+
addHook({
|
|
1063
|
+
name: '@jest/core',
|
|
1064
|
+
versions: ['>=30.0.0']
|
|
1065
|
+
}, getCliWrapper(true))
|
|
1001
1066
|
|
|
1002
1067
|
function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
1003
1068
|
const adapter = jestAdapter.default ?? jestAdapter
|
|
@@ -1006,45 +1071,40 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
|
1006
1071
|
if (!environment) {
|
|
1007
1072
|
return adapter.apply(this, arguments)
|
|
1008
1073
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
status = 'fail'
|
|
1025
|
-
}
|
|
1074
|
+
testSuiteStartCh.publish({
|
|
1075
|
+
testSuite: environment.testSuite,
|
|
1076
|
+
testEnvironmentOptions: environment.testEnvironmentOptions,
|
|
1077
|
+
testSourceFile: environment.testSourceFile,
|
|
1078
|
+
displayName: environment.displayName,
|
|
1079
|
+
frameworkVersion: jestVersion
|
|
1080
|
+
})
|
|
1081
|
+
return adapter.apply(this, arguments).then(suiteResults => {
|
|
1082
|
+
const { numFailingTests, skipped, failureMessage: errorMessage } = suiteResults
|
|
1083
|
+
let status = 'pass'
|
|
1084
|
+
if (skipped) {
|
|
1085
|
+
status = 'skipped'
|
|
1086
|
+
} else if (numFailingTests !== 0) {
|
|
1087
|
+
status = 'fail'
|
|
1088
|
+
}
|
|
1026
1089
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1090
|
+
/**
|
|
1091
|
+
* Child processes do not each request ITR configuration, so the jest's parent process
|
|
1092
|
+
* needs to pass them the configuration. This is done via _ddTestCodeCoverageEnabled, which
|
|
1093
|
+
* controls whether coverage is reported.
|
|
1094
|
+
*/
|
|
1095
|
+
if (environment.testEnvironmentOptions?._ddTestCodeCoverageEnabled) {
|
|
1096
|
+
const root = environment.repositoryRoot || environment.rootDir
|
|
1034
1097
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1098
|
+
const coverageFiles = getCoveredFilenamesFromCoverage(environment.global.__coverage__)
|
|
1099
|
+
.map(filename => getTestSuitePath(filename, root))
|
|
1037
1100
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
testSuiteFinishCh.publish({ status: 'fail', error })
|
|
1046
|
-
throw error
|
|
1047
|
-
})
|
|
1101
|
+
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.testSourceFile })
|
|
1102
|
+
}
|
|
1103
|
+
testSuiteFinishCh.publish({ status, errorMessage })
|
|
1104
|
+
return suiteResults
|
|
1105
|
+
}).catch(error => {
|
|
1106
|
+
testSuiteFinishCh.publish({ status: 'fail', error })
|
|
1107
|
+
throw error
|
|
1048
1108
|
})
|
|
1049
1109
|
})
|
|
1050
1110
|
if (jestAdapter.default) {
|
|
@@ -1056,6 +1116,12 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
|
1056
1116
|
return jestAdapter
|
|
1057
1117
|
}
|
|
1058
1118
|
|
|
1119
|
+
addHook({
|
|
1120
|
+
name: 'jest-circus',
|
|
1121
|
+
file: 'build/runner.js',
|
|
1122
|
+
versions: ['>=30.0.0']
|
|
1123
|
+
}, jestAdapterWrapper)
|
|
1124
|
+
|
|
1059
1125
|
addHook({
|
|
1060
1126
|
name: 'jest-circus',
|
|
1061
1127
|
file: 'build/legacy-code-todo-rewrite/jestAdapter.js',
|
|
@@ -1064,9 +1130,7 @@ addHook({
|
|
|
1064
1130
|
|
|
1065
1131
|
function configureTestEnvironment (readConfigsResult) {
|
|
1066
1132
|
const { configs } = readConfigsResult
|
|
1067
|
-
|
|
1068
|
-
testSessionConfigurationCh.publish(configs.map(config => config.testEnvironmentOptions))
|
|
1069
|
-
})
|
|
1133
|
+
testSessionConfigurationCh.publish(configs.map(config => config.testEnvironmentOptions))
|
|
1070
1134
|
// We can't directly use isCodeCoverageEnabled when reporting coverage in `jestAdapterWrapper`
|
|
1071
1135
|
// because `jestAdapterWrapper` runs in a different process. We have to go through `testEnvironmentOptions`
|
|
1072
1136
|
configs.forEach(config => {
|
|
@@ -1102,21 +1166,19 @@ function configureTestEnvironment (readConfigsResult) {
|
|
|
1102
1166
|
}
|
|
1103
1167
|
|
|
1104
1168
|
function jestConfigAsyncWrapper (jestConfig) {
|
|
1105
|
-
shimmer.wrap(jestConfig, 'readConfigs', readConfigs => async function () {
|
|
1169
|
+
return shimmer.wrap(jestConfig, 'readConfigs', readConfigs => async function () {
|
|
1106
1170
|
const readConfigsResult = await readConfigs.apply(this, arguments)
|
|
1107
1171
|
configureTestEnvironment(readConfigsResult)
|
|
1108
1172
|
return readConfigsResult
|
|
1109
1173
|
})
|
|
1110
|
-
return jestConfig
|
|
1111
1174
|
}
|
|
1112
1175
|
|
|
1113
1176
|
function jestConfigSyncWrapper (jestConfig) {
|
|
1114
|
-
shimmer.wrap(jestConfig, 'readConfigs', readConfigs => function () {
|
|
1177
|
+
return shimmer.wrap(jestConfig, 'readConfigs', readConfigs => function () {
|
|
1115
1178
|
const readConfigsResult = readConfigs.apply(this, arguments)
|
|
1116
1179
|
configureTestEnvironment(readConfigsResult)
|
|
1117
1180
|
return readConfigsResult
|
|
1118
1181
|
})
|
|
1119
|
-
return jestConfig
|
|
1120
1182
|
}
|
|
1121
1183
|
|
|
1122
1184
|
addHook({
|
|
@@ -1167,51 +1229,9 @@ addHook({
|
|
|
1167
1229
|
*/
|
|
1168
1230
|
addHook({
|
|
1169
1231
|
name: '@jest/core',
|
|
1170
|
-
versions: ['>=24.8.0'],
|
|
1232
|
+
versions: ['>=24.8.0 <30.0.0'],
|
|
1171
1233
|
file: 'build/SearchSource.js'
|
|
1172
|
-
},
|
|
1173
|
-
const SearchSource = searchSourcePackage.default ?? searchSourcePackage
|
|
1174
|
-
|
|
1175
|
-
shimmer.wrap(SearchSource.prototype, 'getTestPaths', getTestPaths => async function () {
|
|
1176
|
-
const testPaths = await getTestPaths.apply(this, arguments)
|
|
1177
|
-
const [{ rootDir, shard }] = arguments
|
|
1178
|
-
|
|
1179
|
-
if (isKnownTestsEnabled) {
|
|
1180
|
-
const projectSuites = testPaths.tests.map(test => getTestSuitePath(test.path, test.context.config.rootDir))
|
|
1181
|
-
const isFaulty =
|
|
1182
|
-
getIsFaultyEarlyFlakeDetection(projectSuites, knownTests?.jest || {}, earlyFlakeDetectionFaultyThreshold)
|
|
1183
|
-
if (isFaulty) {
|
|
1184
|
-
log.error('Early flake detection is disabled because the number of new suites is too high.')
|
|
1185
|
-
isEarlyFlakeDetectionEnabled = false
|
|
1186
|
-
isKnownTestsEnabled = false
|
|
1187
|
-
const testEnvironmentOptions = testPaths.tests[0]?.context?.config?.testEnvironmentOptions
|
|
1188
|
-
// Project config is shared among all tests, so we can modify it here
|
|
1189
|
-
if (testEnvironmentOptions) {
|
|
1190
|
-
testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled = false
|
|
1191
|
-
testEnvironmentOptions._ddIsKnownTestsEnabled = false
|
|
1192
|
-
}
|
|
1193
|
-
isEarlyFlakeDetectionFaulty = true
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
if (shard?.shardCount > 1 || !isSuitesSkippingEnabled || !skippableSuites.length) {
|
|
1198
|
-
// If the user is using jest sharding, we want to apply the filtering of tests in the shard process.
|
|
1199
|
-
// The reason for this is the following:
|
|
1200
|
-
// The tests for different shards are likely being run in different CI jobs so
|
|
1201
|
-
// the requests to the skippable endpoint might be done at different times and their responses might be different.
|
|
1202
|
-
// If the skippable endpoint is returning different suites and we filter the list of tests here,
|
|
1203
|
-
// the base list of tests that is used for sharding might be different,
|
|
1204
|
-
// causing the shards to potentially run the same suite.
|
|
1205
|
-
return testPaths
|
|
1206
|
-
}
|
|
1207
|
-
const { tests } = testPaths
|
|
1208
|
-
|
|
1209
|
-
const suitesToRun = applySuiteSkipping(tests, rootDir, frameworkVersion)
|
|
1210
|
-
return { ...testPaths, tests: suitesToRun }
|
|
1211
|
-
})
|
|
1212
|
-
|
|
1213
|
-
return searchSourcePackage
|
|
1214
|
-
})
|
|
1234
|
+
}, searchSourceWrapper)
|
|
1215
1235
|
|
|
1216
1236
|
// from 25.1.0 on, readConfigs becomes async
|
|
1217
1237
|
addHook({
|
|
@@ -1259,19 +1279,27 @@ addHook({
|
|
|
1259
1279
|
return runtimePackage
|
|
1260
1280
|
})
|
|
1261
1281
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1282
|
+
function onMessageWrapper (onMessage) {
|
|
1283
|
+
return function () {
|
|
1284
|
+
const [code, data] = arguments[0]
|
|
1285
|
+
if (code === JEST_WORKER_TRACE_PAYLOAD_CODE) { // datadog trace payload
|
|
1286
|
+
workerReportTraceCh.publish(data)
|
|
1287
|
+
return
|
|
1288
|
+
}
|
|
1289
|
+
if (code === JEST_WORKER_COVERAGE_PAYLOAD_CODE) { // datadog coverage payload
|
|
1290
|
+
workerReportCoverageCh.publish(data)
|
|
1291
|
+
return
|
|
1292
|
+
}
|
|
1293
|
+
if (code === JEST_WORKER_LOGS_PAYLOAD_CODE) { // datadog logs payload
|
|
1294
|
+
workerReportLogsCh.publish(data)
|
|
1295
|
+
return
|
|
1296
|
+
}
|
|
1297
|
+
return onMessage.apply(this, arguments)
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
function sendWrapper (send) {
|
|
1302
|
+
return function (request) {
|
|
1275
1303
|
if (!isKnownTestsEnabled && !isTestManagementTestsEnabled && !isImpactedTestsEnabled) {
|
|
1276
1304
|
return send.apply(this, arguments)
|
|
1277
1305
|
}
|
|
@@ -1309,30 +1337,47 @@ addHook({
|
|
|
1309
1337
|
}
|
|
1310
1338
|
}
|
|
1311
1339
|
}
|
|
1312
|
-
|
|
1313
1340
|
return send.apply(this, arguments)
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
function enqueueWrapper (enqueue) {
|
|
1345
|
+
return function () {
|
|
1346
|
+
shimmer.wrap(arguments[0], 'onStart', onStart => function (worker) {
|
|
1347
|
+
if (worker && !wrappedWorkers.has(worker)) {
|
|
1348
|
+
shimmer.wrap(worker._child, 'send', sendWrapper)
|
|
1349
|
+
shimmer.wrap(worker, '_onMessage', onMessageWrapper)
|
|
1350
|
+
worker._child.on('message', worker._onMessage.bind(worker))
|
|
1351
|
+
wrappedWorkers.add(worker)
|
|
1352
|
+
}
|
|
1353
|
+
return onStart.apply(this, arguments)
|
|
1354
|
+
})
|
|
1355
|
+
return enqueue.apply(this, arguments)
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
/*
|
|
1360
|
+
* This hook does three things:
|
|
1361
|
+
* - Pass known tests to the workers.
|
|
1362
|
+
* - Pass test management tests to the workers.
|
|
1363
|
+
* - Receive trace, coverage and logs payloads from the workers.
|
|
1364
|
+
*/
|
|
1365
|
+
addHook({
|
|
1366
|
+
name: 'jest-worker',
|
|
1367
|
+
versions: ['>=24.9.0 <30.0.0'],
|
|
1368
|
+
file: 'build/workers/ChildProcessWorker.js'
|
|
1369
|
+
}, (childProcessWorker) => {
|
|
1370
|
+
const ChildProcessWorker = childProcessWorker.default
|
|
1371
|
+
shimmer.wrap(ChildProcessWorker.prototype, 'send', sendWrapper)
|
|
1372
|
+
shimmer.wrap(ChildProcessWorker.prototype, '_onMessage', onMessageWrapper)
|
|
1337
1373
|
return childProcessWorker
|
|
1338
1374
|
})
|
|
1375
|
+
|
|
1376
|
+
addHook({
|
|
1377
|
+
name: 'jest-worker',
|
|
1378
|
+
versions: ['>=30.0.0']
|
|
1379
|
+
}, (jestWorkerPackage) => {
|
|
1380
|
+
shimmer.wrap(jestWorkerPackage.FifoQueue.prototype, 'enqueue', enqueueWrapper)
|
|
1381
|
+
shimmer.wrap(jestWorkerPackage.PriorityQueue.prototype, 'enqueue', enqueueWrapper)
|
|
1382
|
+
return jestWorkerPackage
|
|
1383
|
+
})
|