dd-trace 6.10.0 → 6.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -17
- package/index.d.ts +108 -3
- package/initialize.mjs +28 -17
- package/openfeature.js +2 -2
- package/package.json +11 -8
- package/packages/datadog-esbuild/index.js +0 -34
- package/packages/datadog-instrumentations/src/anthropic.js +210 -15
- package/packages/datadog-instrumentations/src/aws-sdk.js +9 -1
- package/packages/datadog-instrumentations/src/browser-bunyan.js +11 -0
- package/packages/datadog-instrumentations/src/bunyan.js +3 -16
- package/packages/datadog-instrumentations/src/cucumber.js +26 -11
- package/packages/datadog-instrumentations/src/cypress-config.js +182 -16
- package/packages/datadog-instrumentations/src/cypress-legacy-finalizers.js +30 -0
- package/packages/datadog-instrumentations/src/cypress.js +2 -0
- package/packages/datadog-instrumentations/src/fastify.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bunyan.js +22 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +9 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -8
- package/packages/datadog-instrumentations/src/jest.js +25 -17
- package/packages/datadog-instrumentations/src/mariadb.js +278 -21
- package/packages/datadog-instrumentations/src/mocha/main.js +539 -55
- package/packages/datadog-instrumentations/src/mocha/utils.js +130 -17
- package/packages/datadog-instrumentations/src/playwright-reporter.js +99 -0
- package/packages/datadog-instrumentations/src/playwright.js +149 -2
- package/packages/datadog-instrumentations/src/router.js +2 -0
- package/packages/datadog-instrumentations/src/vitest-main.js +11 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +163 -44
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -8
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-browser-bunyan/src/index.js +9 -0
- package/packages/datadog-plugin-bunyan/src/index.js +5 -8
- package/packages/datadog-plugin-cucumber/src/index.js +11 -0
- package/packages/datadog-plugin-cypress/src/after-run.js +5 -1
- package/packages/datadog-plugin-cypress/src/after-spec.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +81 -29
- package/packages/datadog-plugin-cypress/src/finalization.js +76 -0
- package/packages/datadog-plugin-cypress/src/index.js +12 -6
- package/packages/datadog-plugin-cypress/src/plugin.js +16 -3
- package/packages/datadog-plugin-dd-trace-api/src/index.js +4 -0
- package/packages/datadog-plugin-electron/src/index.js +2 -0
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +6 -0
- package/packages/datadog-plugin-mocha/src/index.js +56 -1
- package/packages/datadog-plugin-nats/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/tracing.js +41 -30
- package/packages/datadog-plugin-openai-agents/src/integration.js +1 -0
- package/packages/datadog-plugin-playwright/src/index.js +42 -13
- package/packages/datadog-plugin-vitest/src/index.js +6 -0
- package/packages/datadog-webpack/index.js +0 -11
- package/packages/dd-trace/index.js +0 -1
- package/packages/dd-trace/src/agent/info.js +6 -5
- package/packages/dd-trace/src/aiguard/client.js +100 -1
- package/packages/dd-trace/src/aiguard/errors.js +41 -0
- package/packages/dd-trace/src/aiguard/evaluation.js +357 -0
- package/packages/dd-trace/src/aiguard/integrations/anthropic.js +70 -0
- package/packages/dd-trace/src/aiguard/integrations/index.js +4 -0
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +423 -0
- package/packages/dd-trace/src/aiguard/messages/openai.js +1 -24
- package/packages/dd-trace/src/aiguard/messages/utils.js +28 -0
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +1 -11
- package/packages/dd-trace/src/aiguard/sdk.js +22 -278
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -12
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +1 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +27 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +21 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +164 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +365 -32
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +201 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -5
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +39 -0
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +6 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
- package/packages/dd-trace/src/config/index.js +13 -2
- package/packages/dd-trace/src/config/major-overrides.js +7 -0
- package/packages/dd-trace/src/config/supported-configurations.json +14 -0
- package/packages/dd-trace/src/datastreams/index.js +2 -0
- package/packages/dd-trace/src/datastreams/manager.js +9 -2
- package/packages/dd-trace/src/datastreams/processor.js +15 -13
- package/packages/dd-trace/src/datastreams/size.js +5 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +49 -9
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +6 -4
- package/packages/dd-trace/src/exporters/common/writer.js +11 -6
- package/packages/dd-trace/src/llmobs/experiments/client.js +163 -5
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +241 -87
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +280 -20
- package/packages/dd-trace/src/llmobs/experiments/index.js +58 -59
- package/packages/dd-trace/src/llmobs/experiments/noop.js +71 -3
- package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/util.js +41 -5
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +12 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -2
- package/packages/dd-trace/src/noop/proxy.js +3 -4
- package/packages/dd-trace/src/openfeature/flagging_provider.js +18 -2
- package/packages/dd-trace/src/openfeature/remote_config.js +1 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +7 -7
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +2 -1
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +67 -11
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +14 -3
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +25 -12
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +2 -5
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +96 -43
- package/packages/dd-trace/src/opentracing/tracer.js +5 -2
- package/packages/dd-trace/src/otel-thread-ctx.js +387 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/jest.js +4 -3
- package/packages/dd-trace/src/plugins/util/test.js +9 -9
- package/packages/dd-trace/src/plugins/util/web.js +3 -0
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +37 -90
- package/packages/dd-trace/src/profiling/webspan-utils.js +45 -0
- package/packages/dd-trace/src/proxy.js +38 -29
- package/packages/dd-trace/src/ritm.js +9 -2
- package/packages/dd-trace/src/serverless.js +37 -0
- package/packages/dd-trace/src/span_format.js +1 -0
- package/packages/dd-trace/src/span_stats.js +30 -3
- package/packages/dd-trace/src/storage-channels.js +86 -0
- package/packages/dd-trace/src/tracer.js +9 -2
- package/packages/dd-trace/src/tracer_metadata.js +14 -1
- package/packages/dd-trace/src/web-tags-cache.js +132 -0
- package/vendor/dist/@datadog/openfeature-node-server/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +0 -65
- package/packages/datadog-webpack/src/optional-peer-loader.js +0 -17
- package/packages/dd-trace/src/feature-registry.js +0 -29
- package/packages/dd-trace/src/openfeature/register.js +0 -35
- package/packages/dd-trace/src/openfeature/require-provider.js +0 -18
|
@@ -35,9 +35,13 @@ const testSuiteErrorCh = channel('ci:mocha:test-suite:error')
|
|
|
35
35
|
/** @typedef {{ length: number, [index: number]: unknown } & Iterable<unknown>} ArgumentsLike */
|
|
36
36
|
|
|
37
37
|
const testToContext = new WeakMap()
|
|
38
|
+
const originalEfdFns = new WeakMap()
|
|
38
39
|
const originalFns = new WeakMap()
|
|
40
|
+
const originalPendingByTest = new WeakMap()
|
|
41
|
+
const originalRetriesByTest = new WeakMap()
|
|
39
42
|
const testToStartLine = new WeakMap()
|
|
40
43
|
const testFileToSuiteCtx = new Map()
|
|
44
|
+
const datadogRetryOriginals = new WeakMap()
|
|
41
45
|
const wrappedFunctions = new WeakSet()
|
|
42
46
|
const newTests = {}
|
|
43
47
|
const efdTests = {}
|
|
@@ -169,6 +173,7 @@ function wrapOriginalEfdTest (test, retryPolicy) {
|
|
|
169
173
|
}
|
|
170
174
|
test._ddEfdDurationWrapped = true
|
|
171
175
|
const originalFn = test.fn
|
|
176
|
+
originalEfdFns.set(test, originalFn)
|
|
172
177
|
test.fn = shimmer.wrapFunction(originalFn, originalFn => function () {
|
|
173
178
|
const start = performance.now()
|
|
174
179
|
const recordDuration = () => {
|
|
@@ -265,6 +270,7 @@ function isEarlyFlakeDetectionTest (test, config) {
|
|
|
265
270
|
function retryTest (test, numRetries, tags, retryPolicy) {
|
|
266
271
|
const suite = test.parent
|
|
267
272
|
const isEfdRetry = tags.includes('_ddIsEfdRetry')
|
|
273
|
+
if (!originalRetriesByTest.has(test)) originalRetriesByTest.set(test, test.retries())
|
|
268
274
|
disableMochaRetries(test)
|
|
269
275
|
if (isEfdRetry) {
|
|
270
276
|
wrapOriginalEfdTest(test, retryPolicy)
|
|
@@ -272,6 +278,7 @@ function retryTest (test, numRetries, tags, retryPolicy) {
|
|
|
272
278
|
for (let retryIndex = 0; retryIndex < numRetries; retryIndex++) {
|
|
273
279
|
const clonedTest = test.clone()
|
|
274
280
|
disableMochaRetries(clonedTest)
|
|
281
|
+
datadogRetryOriginals.set(clonedTest, test)
|
|
275
282
|
suite.addTest(clonedTest)
|
|
276
283
|
if (isEfdRetry) {
|
|
277
284
|
clonedTest._ddEfdRetryIndex = retryIndex + 1
|
|
@@ -295,6 +302,91 @@ function retryTest (test, numRetries, tags, retryPolicy) {
|
|
|
295
302
|
}
|
|
296
303
|
}
|
|
297
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Restores a runnable function wrapped with its Test Optimization context.
|
|
307
|
+
*
|
|
308
|
+
* @param {import('mocha').Runnable} runnable
|
|
309
|
+
* @returns {void}
|
|
310
|
+
*/
|
|
311
|
+
function restoreRunnableFunction (runnable) {
|
|
312
|
+
const wrappedFunction = runnable.fn
|
|
313
|
+
if (!wrappedFunctions.has(wrappedFunction)) return
|
|
314
|
+
|
|
315
|
+
runnable.fn = originalFns.get(wrappedFunction)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Restores a test function wrapped to measure its EFD duration.
|
|
320
|
+
*
|
|
321
|
+
* @param {import('mocha').Test} test
|
|
322
|
+
* @returns {void}
|
|
323
|
+
*/
|
|
324
|
+
function restoreEfdTestFunction (test) {
|
|
325
|
+
if (!originalEfdFns.has(test)) return
|
|
326
|
+
|
|
327
|
+
test.fn = originalEfdFns.get(test)
|
|
328
|
+
originalEfdFns.delete(test)
|
|
329
|
+
delete test._ddEfdDurationWrapped
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Clears state that belongs to one Mocha runner execution and removes retry clones from prior executions.
|
|
334
|
+
*
|
|
335
|
+
* @param {import('mocha').Suite} rootSuite
|
|
336
|
+
* @returns {void}
|
|
337
|
+
*/
|
|
338
|
+
function resetRunState (rootSuite) {
|
|
339
|
+
for (const key of Object.keys(newTests)) delete newTests[key]
|
|
340
|
+
for (const key of Object.keys(efdTests)) delete efdTests[key]
|
|
341
|
+
newTestsWithDynamicNames.clear()
|
|
342
|
+
testsAttemptToFix.clear()
|
|
343
|
+
testsQuarantined.clear()
|
|
344
|
+
testsStatuses.clear()
|
|
345
|
+
efdRetryCountByTestFullName.clear()
|
|
346
|
+
efdSlowAbortedTests.clear()
|
|
347
|
+
attemptToFixExecutions.clear()
|
|
348
|
+
loggedAttemptToFixTests.clear()
|
|
349
|
+
|
|
350
|
+
const suites = [rootSuite]
|
|
351
|
+
while (suites.length) {
|
|
352
|
+
const suite = suites.pop()
|
|
353
|
+
const originalTests = []
|
|
354
|
+
const retainedTests = new Set()
|
|
355
|
+
for (const runnable of suite.tests) {
|
|
356
|
+
const test = datadogRetryOriginals.get(runnable) || runnable
|
|
357
|
+
if (retainedTests.has(test)) continue
|
|
358
|
+
retainedTests.add(test)
|
|
359
|
+
|
|
360
|
+
restoreRunnableFunction(test)
|
|
361
|
+
restoreEfdTestFunction(test)
|
|
362
|
+
if (originalPendingByTest.has(test)) {
|
|
363
|
+
test.pending = originalPendingByTest.get(test)
|
|
364
|
+
originalPendingByTest.delete(test)
|
|
365
|
+
}
|
|
366
|
+
if (originalRetriesByTest.has(test)) {
|
|
367
|
+
test.retries(originalRetriesByTest.get(test))
|
|
368
|
+
originalRetriesByTest.delete(test)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
delete test._ddIsAttemptToFix
|
|
372
|
+
delete test._ddIsDisabled
|
|
373
|
+
delete test._ddIsQuarantined
|
|
374
|
+
delete test._ddIsModified
|
|
375
|
+
delete test._ddIsNew
|
|
376
|
+
delete test._ddShouldSkipEfdRetry
|
|
377
|
+
delete test._ddTestFinishStarted
|
|
378
|
+
delete test._ddTestFinishPublished
|
|
379
|
+
delete test._ddIsFinalAttempt
|
|
380
|
+
delete test._ddHookFailed
|
|
381
|
+
delete test._ddReporterStartFailed
|
|
382
|
+
delete test._ddReporterTerminalFailed
|
|
383
|
+
originalTests.push(test)
|
|
384
|
+
}
|
|
385
|
+
suite.tests = originalTests
|
|
386
|
+
suites.push(...suite.suites)
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
298
390
|
function getSuitesByTestFile (root) {
|
|
299
391
|
const suitesByTestFile = {}
|
|
300
392
|
function getSuites (suite) {
|
|
@@ -371,6 +463,19 @@ function getTestContext (test) {
|
|
|
371
463
|
return testToContext.get(key)
|
|
372
464
|
}
|
|
373
465
|
|
|
466
|
+
/**
|
|
467
|
+
* Claims publication of a test finish event across Mocha's terminal event paths.
|
|
468
|
+
*
|
|
469
|
+
* @param {object} test
|
|
470
|
+
* @returns {boolean}
|
|
471
|
+
*/
|
|
472
|
+
function startTestFinish (test) {
|
|
473
|
+
if (test._ddTestFinishStarted || test._ddTestFinishPublished) return false
|
|
474
|
+
|
|
475
|
+
test._ddTestFinishStarted = true
|
|
476
|
+
return true
|
|
477
|
+
}
|
|
478
|
+
|
|
374
479
|
/**
|
|
375
480
|
* Copies Test Management metadata from Mocha's original runnable to its native retry clone.
|
|
376
481
|
* @param {{
|
|
@@ -413,11 +518,7 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
|
413
518
|
const test = isTestHook ? this.ctx.currentTest : this
|
|
414
519
|
|
|
415
520
|
// we restore the original user defined function
|
|
416
|
-
|
|
417
|
-
const originalFn = originalFns.get(this.fn)
|
|
418
|
-
this.fn = originalFn
|
|
419
|
-
wrappedFunctions.delete(this.fn)
|
|
420
|
-
}
|
|
521
|
+
restoreRunnableFunction(this)
|
|
421
522
|
|
|
422
523
|
if (isDatadogManagedRetryTest(test, libraryConfig)) {
|
|
423
524
|
disableMochaRetries(this)
|
|
@@ -460,11 +561,7 @@ function getOnTestHandler (isMain) {
|
|
|
460
561
|
|
|
461
562
|
// This may be a retry. If this is the case, `test.fn` is already wrapped,
|
|
462
563
|
// so we need to restore it.
|
|
463
|
-
|
|
464
|
-
const originalFn = originalFns.get(test.fn)
|
|
465
|
-
test.fn = originalFn
|
|
466
|
-
wrappedFunctions.delete(test.fn)
|
|
467
|
-
}
|
|
564
|
+
restoreRunnableFunction(test)
|
|
468
565
|
|
|
469
566
|
inheritDatadogPropertiesFromRetriedTest(test)
|
|
470
567
|
|
|
@@ -527,6 +624,9 @@ function getOnTestHandler (isMain) {
|
|
|
527
624
|
}
|
|
528
625
|
|
|
529
626
|
if (!isAttemptToFix && isDisabled) {
|
|
627
|
+
if (!originalPendingByTest.has(test)) {
|
|
628
|
+
originalPendingByTest.set(test, test.pending)
|
|
629
|
+
}
|
|
530
630
|
test.pending = true
|
|
531
631
|
}
|
|
532
632
|
|
|
@@ -701,9 +801,16 @@ function getOnTestEndHandler (config, finalAttemptHandlers) {
|
|
|
701
801
|
if (test._ddShouldSkipEfdRetry) {
|
|
702
802
|
return
|
|
703
803
|
}
|
|
804
|
+
const shouldWaitForHitProbe = test._retriedTest?._ddShouldWaitForHitProbe
|
|
704
805
|
const ctx = getTestContext(test)
|
|
705
806
|
const status = getTestStatus(test)
|
|
706
|
-
const shouldFinishTest = ctx && (
|
|
807
|
+
const shouldFinishTest = ctx && (
|
|
808
|
+
test._ddReporterStartFailed ||
|
|
809
|
+
test._ddReporterTerminalFailed ||
|
|
810
|
+
!getAfterEachHooks(test).length ||
|
|
811
|
+
(test._ddIsDisabled && !test._ddIsAttemptToFix)
|
|
812
|
+
)
|
|
813
|
+
if (shouldFinishTest && !startTestFinish(test)) return
|
|
707
814
|
let testFinishInfo
|
|
708
815
|
let isFinalAttempt = false
|
|
709
816
|
|
|
@@ -729,11 +836,12 @@ function getOnTestEndHandler (config, finalAttemptHandlers) {
|
|
|
729
836
|
finalAttemptHandlers?.onStart?.(test)
|
|
730
837
|
}
|
|
731
838
|
|
|
732
|
-
if (
|
|
839
|
+
if (shouldWaitForHitProbe) {
|
|
733
840
|
await waitForHitProbe()
|
|
734
841
|
}
|
|
735
842
|
|
|
736
843
|
if (shouldFinishTest) {
|
|
844
|
+
test._ddTestFinishPublished = true
|
|
737
845
|
testFinishCh.publish({
|
|
738
846
|
status,
|
|
739
847
|
hasBeenRetried: isMochaRetry(test),
|
|
@@ -760,10 +868,11 @@ function getOnHookEndHandler (config, finalAttemptHandlers) {
|
|
|
760
868
|
const ctx = getTestContext(test)
|
|
761
869
|
// Disabled tests are already finished in getOnTestEndHandler,
|
|
762
870
|
// skip to avoid double-publishing
|
|
763
|
-
if (ctx && (!test._ddIsDisabled || test._ddIsAttemptToFix)) {
|
|
871
|
+
if (ctx && (!test._ddIsDisabled || test._ddIsAttemptToFix) && startTestFinish(test)) {
|
|
764
872
|
const testFinishInfo = getTestFinishInfo(test, status, config, ctx.err || test.err)
|
|
765
873
|
const isFinalAttempt = testFinishInfo.finalStatus !== undefined
|
|
766
874
|
const publishTestFinish = () => {
|
|
875
|
+
test._ddTestFinishPublished = true
|
|
767
876
|
testFinishCh.publish({
|
|
768
877
|
status,
|
|
769
878
|
hasBeenRetried: isMochaRetry(test),
|
|
@@ -887,11 +996,13 @@ function getOnFailHandler (isMain, config) {
|
|
|
887
996
|
testContext = getTestContext(test)
|
|
888
997
|
}
|
|
889
998
|
if (testContext) {
|
|
890
|
-
if (isHook) {
|
|
891
|
-
|
|
892
|
-
|
|
999
|
+
if (isHook && startTestFinish(test)) {
|
|
1000
|
+
const hookError = new Error(`${testOrHook.fullTitle()}: ${err.message}`, { cause: err })
|
|
1001
|
+
hookError.name = err.name
|
|
1002
|
+
hookError.stack = err.stack
|
|
1003
|
+
testContext.err = hookError
|
|
893
1004
|
errorCh.runStores(testContext, () => {})
|
|
894
|
-
const testFinishInfo = getTestFinishInfo(test, 'fail', config,
|
|
1005
|
+
const testFinishInfo = getTestFinishInfo(test, 'fail', config, hookError)
|
|
895
1006
|
// ATR never retries hook failures: this.retries(N) is set in runnableWrapper
|
|
896
1007
|
// which only runs when the test function executes — hooks bypass that path,
|
|
897
1008
|
// so _retries stays at -1 and getIsLastRetry returns false, leaving finalStatus
|
|
@@ -906,6 +1017,7 @@ function getOnFailHandler (isMain, config) {
|
|
|
906
1017
|
// test.state is never set to 'failed' for hook failures (Mocha marks the hook,
|
|
907
1018
|
// not the test). Flag it so finishRootSuiteForFile can compute the correct status.
|
|
908
1019
|
test._ddHookFailed = true
|
|
1020
|
+
test._ddTestFinishPublished = true
|
|
909
1021
|
testFinishCh.publish({
|
|
910
1022
|
status: 'fail',
|
|
911
1023
|
hasBeenRetried: isMochaRetry(test),
|
|
@@ -1088,6 +1200,7 @@ module.exports = {
|
|
|
1088
1200
|
getOnPendingHandler,
|
|
1089
1201
|
testFileToSuiteCtx,
|
|
1090
1202
|
getRunTestsWrapper,
|
|
1203
|
+
resetRunState,
|
|
1091
1204
|
newTests,
|
|
1092
1205
|
efdTests,
|
|
1093
1206
|
newTestsWithDynamicNames,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { channel } = require('dc-polyfill')
|
|
4
|
+
|
|
5
|
+
const reporterErrorCh = channel('ci:playwright:reporter:error')
|
|
6
|
+
const PLAYWRIGHT_REPORTER_ERROR_MESSAGE = 'Error in reporter'
|
|
7
|
+
const PLAYWRIGHT_REPORTER_ERROR_CALLER_RE =
|
|
8
|
+
/^\s*at wrapAsync .*?[\\/]playwright[\\/]lib[\\/]runner[\\/]index\.js:\d+:\d+\)?$/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Identifies the private Playwright 1.60-1.61 reporter error fallback without
|
|
12
|
+
* interpreting identical user console output as a framework error.
|
|
13
|
+
*
|
|
14
|
+
* @param {unknown} message - First console.error argument
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
function isPlaywrightReporterError (message) {
|
|
18
|
+
if (message !== PLAYWRIGHT_REPORTER_ERROR_MESSAGE) return false
|
|
19
|
+
|
|
20
|
+
const originalPrepareStackTrace = Error.prepareStackTrace
|
|
21
|
+
try {
|
|
22
|
+
Error.prepareStackTrace = (_, callSites) => callSites
|
|
23
|
+
const stack = new Error('Playwright reporter error provenance').stack
|
|
24
|
+
return PLAYWRIGHT_REPORTER_ERROR_CALLER_RE.test(`at ${stack?.[2]?.toString() || ''}`)
|
|
25
|
+
} finally {
|
|
26
|
+
Error.prepareStackTrace = originalPrepareStackTrace
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class DatadogPlaywrightReporter {
|
|
31
|
+
/**
|
|
32
|
+
* Restores console error after Playwright completes the reporter lifecycle.
|
|
33
|
+
*
|
|
34
|
+
* @returns {void}
|
|
35
|
+
*/
|
|
36
|
+
static restoreConsoleError () {
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
if (console.error === DatadogPlaywrightReporter.consoleError) {
|
|
39
|
+
try {
|
|
40
|
+
// eslint-disable-next-line no-console
|
|
41
|
+
console.error = DatadogPlaywrightReporter.originalConsoleError
|
|
42
|
+
} catch {}
|
|
43
|
+
}
|
|
44
|
+
DatadogPlaywrightReporter.consoleError = undefined
|
|
45
|
+
DatadogPlaywrightReporter.originalConsoleError = undefined
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Marks the beginning of reporter finalization so later reporter errors can be identified.
|
|
50
|
+
*
|
|
51
|
+
* @returns {void}
|
|
52
|
+
*/
|
|
53
|
+
onEnd () {
|
|
54
|
+
this.isFinalizing = true
|
|
55
|
+
// Playwright 1.60 and 1.61 only expose reporter errors through this exact console call.
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
const originalConsoleError = console.error
|
|
58
|
+
const reporter = this
|
|
59
|
+
const consoleError = function (message, error) {
|
|
60
|
+
if (isPlaywrightReporterError(message)) {
|
|
61
|
+
reporter.onError(error)
|
|
62
|
+
}
|
|
63
|
+
return originalConsoleError.apply(this, arguments)
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
67
|
+
console.error = consoleError
|
|
68
|
+
} catch {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
// An accessor may ignore the assignment without throwing.
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
if (console.error !== consoleError) return
|
|
74
|
+
|
|
75
|
+
DatadogPlaywrightReporter.originalConsoleError = originalConsoleError
|
|
76
|
+
DatadogPlaywrightReporter.consoleError = consoleError
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Reports errors emitted by Playwright while later reporters are finalizing.
|
|
81
|
+
*
|
|
82
|
+
* @param {unknown} error
|
|
83
|
+
* @returns {void}
|
|
84
|
+
*/
|
|
85
|
+
onError (error) {
|
|
86
|
+
if (this.isFinalizing) reporterErrorCh.publish(error)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Keeps the internal reporter from affecting Playwright's output reporter selection.
|
|
91
|
+
*
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
printsToStdio () {
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = DatadogPlaywrightReporter
|
|
@@ -45,6 +45,7 @@ const testSkipCh = channel('ci:playwright:test:skip')
|
|
|
45
45
|
const testSessionStartCh = channel('ci:playwright:session:start')
|
|
46
46
|
const testSessionConfigurationCh = channel('ci:playwright:session:configuration')
|
|
47
47
|
const testSessionFinishCh = channel('ci:playwright:session:finish')
|
|
48
|
+
const reporterErrorCh = channel('ci:playwright:reporter:error')
|
|
48
49
|
|
|
49
50
|
const libraryConfigurationCh = channel('ci:playwright:library-configuration')
|
|
50
51
|
const knownTestsCh = channel('ci:playwright:known-tests')
|
|
@@ -81,6 +82,8 @@ const isFailureScreenshotUploadEnabled =
|
|
|
81
82
|
getValueFromEnvSources('DD_TEST_FAILURE_SCREENSHOTS_ENABLED') === true
|
|
82
83
|
|
|
83
84
|
let applyRepeatEachIndex = null
|
|
85
|
+
let reporterError
|
|
86
|
+
let hasReporterError = false
|
|
84
87
|
|
|
85
88
|
let startedSuites = []
|
|
86
89
|
|
|
@@ -134,8 +137,10 @@ const DD_PROPERTIES_REQUEST = 'ddPropertiesRequest'
|
|
|
134
137
|
const DD_PROPERTIES_RESPONSE = 'ddProperties'
|
|
135
138
|
const kDdPlaywrightDisabledTestIds = Symbol('ddPlaywrightDisabledTestIds')
|
|
136
139
|
const kDdPlaywrightFailureScreenshots = Symbol('ddPlaywrightFailureScreenshots')
|
|
140
|
+
const kDdPlaywrightReporterConfigured = Symbol('ddPlaywrightReporterConfigured')
|
|
137
141
|
const kDdPlaywrightWorkerHostInstrumented = Symbol('ddPlaywrightWorkerHostInstrumented')
|
|
138
142
|
const kDdPlaywrightWorkerInstrumented = Symbol('ddPlaywrightWorkerInstrumented')
|
|
143
|
+
const instrumentedPlaywrightReporters = new WeakSet()
|
|
139
144
|
const PLAYWRIGHT_FAILURE_SCREENSHOT_PATH_RE = /(?:^|[\\/])test-failed-\d+\.png$/
|
|
140
145
|
const automaticFailureScreenshotPaths = new Set()
|
|
141
146
|
|
|
@@ -1252,6 +1257,17 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
|
|
|
1252
1257
|
function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
1253
1258
|
// Config parameter is only available from >=1.55.0
|
|
1254
1259
|
return async function (config) {
|
|
1260
|
+
reporterError = undefined
|
|
1261
|
+
hasReporterError = false
|
|
1262
|
+
let restoreReporterConsoleError
|
|
1263
|
+
if (satisfies(playwrightVersion, '>=1.60.0') && config?.config) {
|
|
1264
|
+
const DatadogPlaywrightReporter = require('./playwright-reporter')
|
|
1265
|
+
restoreReporterConsoleError = DatadogPlaywrightReporter.restoreConsoleError
|
|
1266
|
+
if (!config.config[kDdPlaywrightReporterConfigured]) {
|
|
1267
|
+
Object.defineProperty(config.config, kDdPlaywrightReporterConfigured, { value: true })
|
|
1268
|
+
config.config.reporter.unshift([require.resolve('./playwright-reporter')])
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1255
1271
|
rootDir = getRootDir(this, config)
|
|
1256
1272
|
const projects = getProjectsFromRunner(this, config)
|
|
1257
1273
|
const isFailureScreenshotEnabled = isFailureScreenshotCaptureEnabled(projects)
|
|
@@ -1367,7 +1383,27 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1367
1383
|
}
|
|
1368
1384
|
}
|
|
1369
1385
|
|
|
1370
|
-
let runAllTestsReturn
|
|
1386
|
+
let runAllTestsReturn
|
|
1387
|
+
try {
|
|
1388
|
+
runAllTestsReturn = await runAllTests.apply(this, arguments)
|
|
1389
|
+
} catch (error) {
|
|
1390
|
+
try {
|
|
1391
|
+
await getChannelPromise(testSessionFinishCh, {
|
|
1392
|
+
status: 'fail',
|
|
1393
|
+
error: hasReporterError ? reporterError : error,
|
|
1394
|
+
isEarlyFlakeDetectionEnabled,
|
|
1395
|
+
isEarlyFlakeDetectionFaulty,
|
|
1396
|
+
isTestManagementTestsEnabled,
|
|
1397
|
+
})
|
|
1398
|
+
} catch (finalizationError) {
|
|
1399
|
+
log.error('Playwright test session finalization error: %s', finalizationError)
|
|
1400
|
+
}
|
|
1401
|
+
reporterError = undefined
|
|
1402
|
+
hasReporterError = false
|
|
1403
|
+
throw error
|
|
1404
|
+
} finally {
|
|
1405
|
+
restoreReporterConsoleError?.()
|
|
1406
|
+
}
|
|
1371
1407
|
|
|
1372
1408
|
// Tests that have only skipped tests may reach this point
|
|
1373
1409
|
// Skipped tests may or may not go through `testBegin` or `testEnd`
|
|
@@ -1422,12 +1458,21 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1422
1458
|
logTestOptimizationSummary({ attemptToFixExecutions, newTestsWithDynamicNames })
|
|
1423
1459
|
loggedAttemptToFixTests.clear()
|
|
1424
1460
|
|
|
1461
|
+
const finalizationError = reporterError
|
|
1462
|
+
const finalStatus = hasReporterError
|
|
1463
|
+
? 'fail'
|
|
1464
|
+
: (preventedToFail ? 'pass' : STATUS_TO_TEST_STATUS[sessionStatus])
|
|
1425
1465
|
await getChannelPromise(testSessionFinishCh, {
|
|
1426
|
-
status:
|
|
1466
|
+
status: finalStatus,
|
|
1467
|
+
error: finalizationError,
|
|
1427
1468
|
isEarlyFlakeDetectionEnabled,
|
|
1428
1469
|
isEarlyFlakeDetectionFaulty,
|
|
1429
1470
|
isTestManagementTestsEnabled,
|
|
1430
1471
|
})
|
|
1472
|
+
if (hasReporterError) {
|
|
1473
|
+
if (typeof runAllTestsReturn === 'string') runAllTestsReturn = 'failed'
|
|
1474
|
+
else runAllTestsReturn.status = 'failed'
|
|
1475
|
+
}
|
|
1431
1476
|
|
|
1432
1477
|
startedSuites = []
|
|
1433
1478
|
remainingTestsByFile = {}
|
|
@@ -1444,6 +1489,8 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1444
1489
|
ddPropertiesByTestId.clear()
|
|
1445
1490
|
ddPropertiesRequestsByTestId.clear()
|
|
1446
1491
|
disabledTestIds.clear()
|
|
1492
|
+
reporterError = undefined
|
|
1493
|
+
hasReporterError = false
|
|
1447
1494
|
|
|
1448
1495
|
// TODO: we can trick playwright into thinking the session passed by returning
|
|
1449
1496
|
// 'passed' here. We might be able to use this for both EFD and Test Management tests.
|
|
@@ -1451,6 +1498,68 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
1451
1498
|
}
|
|
1452
1499
|
}
|
|
1453
1500
|
|
|
1501
|
+
/**
|
|
1502
|
+
* Records errors thrown or rejected by Playwright reporters before Playwright converts them into run status.
|
|
1503
|
+
*
|
|
1504
|
+
* @param {object} reportersPackage
|
|
1505
|
+
* @returns {object}
|
|
1506
|
+
*/
|
|
1507
|
+
function reportersHook (reportersPackage) {
|
|
1508
|
+
return shimmer.wrap(reportersPackage, 'createReporters', createReporters => async function () {
|
|
1509
|
+
const reporters = await createReporters.apply(this, arguments)
|
|
1510
|
+
for (const reporter of reporters) {
|
|
1511
|
+
if (instrumentedPlaywrightReporters.has(reporter)) continue
|
|
1512
|
+
|
|
1513
|
+
const onEnd = reporter.onEnd
|
|
1514
|
+
const onExit = reporter.onExit
|
|
1515
|
+
try {
|
|
1516
|
+
if (typeof onEnd === 'function') {
|
|
1517
|
+
reporter.onEnd = async function () {
|
|
1518
|
+
try {
|
|
1519
|
+
return await onEnd.apply(this, arguments)
|
|
1520
|
+
} catch (error) {
|
|
1521
|
+
recordReporterError(error)
|
|
1522
|
+
throw error
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (typeof onExit === 'function') {
|
|
1527
|
+
reporter.onExit = async function () {
|
|
1528
|
+
try {
|
|
1529
|
+
return await onExit.apply(this, arguments)
|
|
1530
|
+
} catch (error) {
|
|
1531
|
+
recordReporterError(error)
|
|
1532
|
+
throw error
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
} catch {
|
|
1537
|
+
continue
|
|
1538
|
+
}
|
|
1539
|
+
if (reporter.onEnd !== onEnd || reporter.onExit !== onExit) instrumentedPlaywrightReporters.add(reporter)
|
|
1540
|
+
}
|
|
1541
|
+
return reporters
|
|
1542
|
+
}, { replaceGetter: true })
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
/**
|
|
1546
|
+
* Records errors from the reporter multiplexer used by Playwright before 1.38.
|
|
1547
|
+
*
|
|
1548
|
+
* @param {object} reportersPackage
|
|
1549
|
+
* @returns {object}
|
|
1550
|
+
*/
|
|
1551
|
+
function reporterMultiplexerHook (reportersPackage) {
|
|
1552
|
+
shimmer.wrap(reportersPackage.Multiplexer.prototype, 'onEnd', onEnd => async function () {
|
|
1553
|
+
try {
|
|
1554
|
+
return await onEnd.apply(this, arguments)
|
|
1555
|
+
} catch (error) {
|
|
1556
|
+
recordReporterError(error)
|
|
1557
|
+
throw error
|
|
1558
|
+
}
|
|
1559
|
+
})
|
|
1560
|
+
return reportersPackage
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1454
1563
|
function runnerHook (runnerExport, playwrightVersion) {
|
|
1455
1564
|
shimmer.wrap(
|
|
1456
1565
|
runnerExport.Runner.prototype,
|
|
@@ -1550,6 +1659,32 @@ pageGotoCh.subscribe({
|
|
|
1550
1659
|
},
|
|
1551
1660
|
})
|
|
1552
1661
|
|
|
1662
|
+
reporterErrorCh.subscribe((error) => {
|
|
1663
|
+
recordReporterError(error)
|
|
1664
|
+
})
|
|
1665
|
+
|
|
1666
|
+
/**
|
|
1667
|
+
* Records a reporter failure even when the reporter throws a falsy value.
|
|
1668
|
+
*
|
|
1669
|
+
* @param {unknown} error
|
|
1670
|
+
* @returns {void}
|
|
1671
|
+
*/
|
|
1672
|
+
function recordReporterError (error) {
|
|
1673
|
+
if (hasReporterError) return
|
|
1674
|
+
|
|
1675
|
+
let normalizedError
|
|
1676
|
+
try {
|
|
1677
|
+
const errorObject = error && typeof error === 'object' ? error : undefined
|
|
1678
|
+
normalizedError = new Error(errorObject?.message || errorObject?.value || String(error))
|
|
1679
|
+
normalizedError.name = errorObject?.name || normalizedError.name
|
|
1680
|
+
normalizedError.stack = errorObject?.stack || normalizedError.stack
|
|
1681
|
+
} catch {
|
|
1682
|
+
normalizedError = new Error('Playwright reporter failed')
|
|
1683
|
+
}
|
|
1684
|
+
reporterError = normalizedError
|
|
1685
|
+
hasReporterError = true
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1553
1688
|
/**
|
|
1554
1689
|
* Records a path created by Playwright's automatic screenshot recorder.
|
|
1555
1690
|
*
|
|
@@ -1597,6 +1732,12 @@ if (DD_MAJOR < 6) { // <1.38.0 is only supported up to version 5
|
|
|
1597
1732
|
file: 'lib/runner/runner.js',
|
|
1598
1733
|
versions: ['>=1.31.0 <1.38.0'],
|
|
1599
1734
|
}, runnerHook)
|
|
1735
|
+
|
|
1736
|
+
addHook({
|
|
1737
|
+
name: '@playwright/test',
|
|
1738
|
+
file: 'lib/reporters/multiplexer.js',
|
|
1739
|
+
versions: ['>=1.18.0 <1.38.0'],
|
|
1740
|
+
}, reporterMultiplexerHook)
|
|
1600
1741
|
}
|
|
1601
1742
|
|
|
1602
1743
|
addHook({
|
|
@@ -1617,6 +1758,12 @@ addHook({
|
|
|
1617
1758
|
versions: ['>=1.38.0 <1.60.0'],
|
|
1618
1759
|
}, runnerHook)
|
|
1619
1760
|
|
|
1761
|
+
addHook({
|
|
1762
|
+
name: 'playwright',
|
|
1763
|
+
file: 'lib/runner/reporters.js',
|
|
1764
|
+
versions: ['>=1.38.0 <1.60.0'],
|
|
1765
|
+
}, reportersHook)
|
|
1766
|
+
|
|
1620
1767
|
addHook({
|
|
1621
1768
|
name: 'playwright',
|
|
1622
1769
|
file: 'lib/runner/testRunner.js',
|
|
@@ -596,6 +596,7 @@ const visitedParams = new WeakSet()
|
|
|
596
596
|
function wrapHandleRequest (original) {
|
|
597
597
|
return function wrappedHandleRequest (...args) {
|
|
598
598
|
const req = args[0]
|
|
599
|
+
// eslint-disable-next-line no-restricted-syntax -- arbitrary param names; publishing {} sets a WAF address
|
|
599
600
|
if (routerParamStartCh.hasSubscribers && !visitedParams.has(req.params) && Object.keys(req.params).length) {
|
|
600
601
|
visitedParams.add(req.params)
|
|
601
602
|
|
|
@@ -635,6 +636,7 @@ function wrapParam (original) {
|
|
|
635
636
|
args[1] = shimmer.wrapFunction(args[1], (originalFn) => {
|
|
636
637
|
return function wrappedFn (...fnArgs) {
|
|
637
638
|
const req = fnArgs[0]
|
|
639
|
+
// eslint-disable-next-line no-restricted-syntax -- arbitrary param names; publishing {} sets a WAF address
|
|
638
640
|
if (routerParamStartCh.hasSubscribers && Object.keys(req.params).length && !visitedParams.has(req.params)) {
|
|
639
641
|
visitedParams.add(req.params)
|
|
640
642
|
|
|
@@ -67,6 +67,7 @@ const coverageWrappedProviders = new WeakSet()
|
|
|
67
67
|
const finishWrappedContexts = new WeakSet()
|
|
68
68
|
const runFilesWrappedPrototypes = new WeakSet()
|
|
69
69
|
const activeRunFilesContexts = new WeakSet()
|
|
70
|
+
const runErrorsByContext = new WeakMap()
|
|
70
71
|
let isFlakyTestRetriesEnabled = false
|
|
71
72
|
let flakyTestRetriesCount = 0
|
|
72
73
|
let isEarlyFlakeDetectionEnabled = false
|
|
@@ -1195,15 +1196,18 @@ function getFinishWrapper (exitOrClose) {
|
|
|
1195
1196
|
}
|
|
1196
1197
|
|
|
1197
1198
|
const failedSuites = this.state.getFailedFilepaths()
|
|
1198
|
-
|
|
1199
|
-
|
|
1199
|
+
const runError = runErrorsByContext.get(this)
|
|
1200
|
+
runErrorsByContext.delete(this)
|
|
1201
|
+
let error = runError
|
|
1202
|
+
if (!error && failedSuites.length) {
|
|
1200
1203
|
error = new Error(`Test suites failed: ${failedSuites.length}.`)
|
|
1201
1204
|
}
|
|
1202
1205
|
|
|
1203
1206
|
const flushPromise = getChannelPromise(testSessionFinishCh, {
|
|
1204
|
-
status: areAllSuitesSkipped ? 'skip' : getSessionStatus(this.state),
|
|
1207
|
+
status: runError ? 'fail' : (areAllSuitesSkipped ? 'skip' : getSessionStatus(this.state)),
|
|
1205
1208
|
testCodeCoverageLinesTotal,
|
|
1206
1209
|
error,
|
|
1210
|
+
isTestSessionFinalizationError: Boolean(runError),
|
|
1207
1211
|
isEarlyFlakeDetectionEnabled,
|
|
1208
1212
|
isEarlyFlakeDetectionFaulty,
|
|
1209
1213
|
isTestManagementTestsEnabled,
|
|
@@ -1376,6 +1380,9 @@ function wrapVitestRunFiles (Vitest, frameworkVersion) {
|
|
|
1376
1380
|
activeRunFilesContexts.add(this)
|
|
1377
1381
|
try {
|
|
1378
1382
|
return await runFiles.apply(this, arguments)
|
|
1383
|
+
} catch (error) {
|
|
1384
|
+
runErrorsByContext.set(this, error)
|
|
1385
|
+
throw error
|
|
1379
1386
|
} finally {
|
|
1380
1387
|
activeRunFilesContexts.delete(this)
|
|
1381
1388
|
}
|
|
@@ -1677,6 +1684,7 @@ async function reportTypecheckFile (file, sessionConfiguration, frameworkVersion
|
|
|
1677
1684
|
}
|
|
1678
1685
|
|
|
1679
1686
|
await getChannelPromise(testSuiteFinishCh, {
|
|
1687
|
+
deferFlush: true,
|
|
1680
1688
|
frameworkVersion,
|
|
1681
1689
|
status: getTypecheckTaskStatus(file),
|
|
1682
1690
|
...testSuiteCtx.currentStore,
|