From 5a957c382b4955a051e8e0a4f523e1c8aa5a1889 Mon Sep 17 00:00:00 2001 From: Juan Fernandez Date: Mon, 23 Feb 2026 10:52:02 +0100 Subject: [PATCH 1/3] fix rum and cypress integration --- .../datadog-plugin-cypress/src/support.js | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/datadog-plugin-cypress/src/support.js b/packages/datadog-plugin-cypress/src/support.js index 0ae56a24e78..1df1d1a9c9e 100644 --- a/packages/datadog-plugin-cypress/src/support.js +++ b/packages/datadog-plugin-cypress/src/support.js @@ -1,5 +1,8 @@ 'use strict' +const DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id' +const DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS = 500 + let isEarlyFlakeDetectionEnabled = false let isKnownTestsEnabled = false let knownTestsForSuite = [] @@ -15,9 +18,10 @@ const retryReasonsByTestName = new Map() // Track quarantined test errors - we catch them in Cypress.on('fail') but need to report to Datadog const quarantinedTestErrors = new Map() -// We need to grab the original window as soon as possible, -// in case the test changes the origin. If the test does change the origin, -// any call to `cy.window()` will result in a cross origin error. +// Track the most recently loaded window in the AUT. Updated via the 'window:load' +// event so we always get the real app window (after cy.visit()), not the +// about:blank window that exists when beforeEach runs. If the test later navigates +// to a cross-origin URL, safeGetRum() handles the access error. let originalWindow // If the test is using multi domain with cy.origin, trying to access @@ -165,18 +169,21 @@ beforeEach(function () { retryReasonsByTestName.delete(testName) } + cy.on('window:load', (win) => { + originalWindow = win + }) + cy.task('dd:beforeEach', { testName, testSuite: Cypress.mocha.getRootSuite().file, }).then(({ traceId, shouldSkip }) => { - Cypress.env('traceId', traceId) + if (traceId) { + cy.setCookie(DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME, traceId) + } if (shouldSkip) { this.skip() } }) - cy.window().then(win => { - originalWindow = win - }) }) before(function () { @@ -241,8 +248,14 @@ afterEach(function () { testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line } catch {} - if (safeGetRum(originalWindow)) { + const rum = safeGetRum(originalWindow) + if (rum) { testInfo.isRUMActive = true + if (rum.stopSession) { + rum.stopSession() + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS) + } } let coverage try { From 3dc87d5559019500507f6eaea8adb36c3a59309a Mon Sep 17 00:00:00 2001 From: Juan Fernandez Date: Mon, 23 Feb 2026 14:59:54 +0100 Subject: [PATCH 2/3] fix testIsolation: false --- .../datadog-plugin-cypress/src/support.js | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/datadog-plugin-cypress/src/support.js b/packages/datadog-plugin-cypress/src/support.js index 1df1d1a9c9e..1aede6796bb 100644 --- a/packages/datadog-plugin-cypress/src/support.js +++ b/packages/datadog-plugin-cypress/src/support.js @@ -178,7 +178,31 @@ beforeEach(function () { testSuite: Cypress.mocha.getRootSuite().file, }).then(({ traceId, shouldSkip }) => { if (traceId) { - cy.setCookie(DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME, traceId) + cy.setCookie(DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME, traceId).then(() => { + // When testIsolation:false, the page is not reset between tests, so the RUM session + // stopped in afterEach must be explicitly restarted so events in this test are + // associated with the new testExecutionId. + // + // After stopSession(), the RUM SDK creates a new session upon a user interaction + // (click, scroll, keydown, or touchstart). We dispatch a synthetic click on the window + // to trigger session renewal, then call startView() to establish a view boundary. + if (!isTestIsolationEnabled && originalWindow) { + const rum = safeGetRum(originalWindow) + if (rum) { + try { + const evt = new originalWindow.MouseEvent('click', { bubbles: true, cancelable: true }) + // The browser-sdk addEventListener wrapper filters out untrusted synthetic events + // unless __ddIsTrusted is set. Set it so the click triggers expandOrRenewSession(). + // See: https://github.com/DataDog/browser-sdk/blob/v6.27.1/packages/core/src/browser/addEventListener.ts#L119 + Object.defineProperty(evt, '__ddIsTrusted', { value: true }) + originalWindow.dispatchEvent(evt) + } catch {} + if (rum.startView) { + rum.startView() + } + } + } + }) } if (shouldSkip) { this.skip() From 178bd54088f8e8e21438e9620dacb9850edf482f Mon Sep 17 00:00:00 2001 From: Juan Fernandez Date: Mon, 23 Feb 2026 15:51:14 +0100 Subject: [PATCH 3/3] make it configurable --- packages/datadog-plugin-cypress/src/cypress-plugin.js | 4 ++++ packages/datadog-plugin-cypress/src/support.js | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/datadog-plugin-cypress/src/cypress-plugin.js b/packages/datadog-plugin-cypress/src/cypress-plugin.js index 0e8b693efab..4e97bf7a176 100644 --- a/packages/datadog-plugin-cypress/src/cypress-plugin.js +++ b/packages/datadog-plugin-cypress/src/cypress-plugin.js @@ -306,6 +306,9 @@ class CypressPlugin { this.isTestIsolationEnabled = getIsTestIsolationEnabled(cypressConfig) + const envFlushWait = Number(getValueFromEnvSources('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) + this.rumFlushWaitMillis = Number.isFinite(envFlushWait) ? envFlushWait : undefined + if (!this.isTestIsolationEnabled) { log.warn('Test isolation is disabled, retries will not be enabled') } @@ -823,6 +826,7 @@ class CypressPlugin { isModifiedTest: this.getIsTestModified(testSuiteAbsolutePath), repositoryRoot: this.repositoryRoot, isTestIsolationEnabled: this.isTestIsolationEnabled, + rumFlushWaitMillis: this.rumFlushWaitMillis, } if (this.testSuiteSpan) { diff --git a/packages/datadog-plugin-cypress/src/support.js b/packages/datadog-plugin-cypress/src/support.js index 1aede6796bb..e50bc812f1c 100644 --- a/packages/datadog-plugin-cypress/src/support.js +++ b/packages/datadog-plugin-cypress/src/support.js @@ -1,7 +1,7 @@ 'use strict' const DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id' -const DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS = 500 +let rumFlushWaitMillis = 500 let isEarlyFlakeDetectionEnabled = false let isKnownTestsEnabled = false @@ -226,6 +226,9 @@ before(function () { isImpactedTestsEnabled = suiteConfig.isImpactedTestsEnabled isModifiedTest = suiteConfig.isModifiedTest isTestIsolationEnabled = suiteConfig.isTestIsolationEnabled + if (Number.isFinite(suiteConfig.rumFlushWaitMillis)) { + rumFlushWaitMillis = suiteConfig.rumFlushWaitMillis + } } }) }) @@ -278,7 +281,7 @@ afterEach(function () { if (rum.stopSession) { rum.stopSession() // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS) + cy.wait(rumFlushWaitMillis) } } let coverage