11'use strict'
22
3+ const DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id'
4+ let rumFlushWaitMillis = 500
5+
36let isEarlyFlakeDetectionEnabled = false
47let isKnownTestsEnabled = false
58let knownTestsForSuite = [ ]
@@ -15,9 +18,10 @@ const retryReasonsByTestName = new Map()
1518// Track quarantined test errors - we catch them in Cypress.on('fail') but need to report to Datadog
1619const quarantinedTestErrors = new Map ( )
1720
18- // We need to grab the original window as soon as possible,
19- // in case the test changes the origin. If the test does change the origin,
20- // any call to `cy.window()` will result in a cross origin error.
21+ // Track the most recently loaded window in the AUT. Updated via the 'window:load'
22+ // event so we always get the real app window (after cy.visit()), not the
23+ // about:blank window that exists when beforeEach runs. If the test later navigates
24+ // to a cross-origin URL, safeGetRum() handles the access error.
2125let originalWindow
2226
2327// If the test is using multi domain with cy.origin, trying to access
@@ -165,18 +169,45 @@ beforeEach(function () {
165169 retryReasonsByTestName . delete ( testName )
166170 }
167171
172+ cy . on ( 'window:load' , ( win ) => {
173+ originalWindow = win
174+ } )
175+
168176 cy . task ( 'dd:beforeEach' , {
169177 testName,
170178 testSuite : Cypress . mocha . getRootSuite ( ) . file ,
171179 } ) . then ( ( { traceId, shouldSkip } ) => {
172- Cypress . env ( 'traceId' , traceId )
180+ if ( traceId ) {
181+ cy . setCookie ( DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME , traceId ) . then ( ( ) => {
182+ // When testIsolation:false, the page is not reset between tests, so the RUM session
183+ // stopped in afterEach must be explicitly restarted so events in this test are
184+ // associated with the new testExecutionId.
185+ //
186+ // After stopSession(), the RUM SDK creates a new session upon a user interaction
187+ // (click, scroll, keydown, or touchstart). We dispatch a synthetic click on the window
188+ // to trigger session renewal, then call startView() to establish a view boundary.
189+ if ( ! isTestIsolationEnabled && originalWindow ) {
190+ const rum = safeGetRum ( originalWindow )
191+ if ( rum ) {
192+ try {
193+ const evt = new originalWindow . MouseEvent ( 'click' , { bubbles : true , cancelable : true } )
194+ // The browser-sdk addEventListener wrapper filters out untrusted synthetic events
195+ // unless __ddIsTrusted is set. Set it so the click triggers expandOrRenewSession().
196+ // See: https://github.com/DataDog/browser-sdk/blob/v6.27.1/packages/core/src/browser/addEventListener.ts#L119
197+ Object . defineProperty ( evt , '__ddIsTrusted' , { value : true } )
198+ originalWindow . dispatchEvent ( evt )
199+ } catch { }
200+ if ( rum . startView ) {
201+ rum . startView ( )
202+ }
203+ }
204+ }
205+ } )
206+ }
173207 if ( shouldSkip ) {
174208 this . skip ( )
175209 }
176210 } )
177- cy . window ( ) . then ( win => {
178- originalWindow = win
179- } )
180211} )
181212
182213before ( function ( ) {
@@ -195,6 +226,9 @@ before(function () {
195226 isImpactedTestsEnabled = suiteConfig . isImpactedTestsEnabled
196227 isModifiedTest = suiteConfig . isModifiedTest
197228 isTestIsolationEnabled = suiteConfig . isTestIsolationEnabled
229+ if ( Number . isFinite ( suiteConfig . rumFlushWaitMillis ) ) {
230+ rumFlushWaitMillis = suiteConfig . rumFlushWaitMillis
231+ }
198232 }
199233 } )
200234} )
@@ -241,8 +275,14 @@ afterEach(function () {
241275 testInfo . testSourceLine = Cypress . mocha . getRunner ( ) . currentRunnable . invocationDetails . line
242276 } catch { }
243277
244- if ( safeGetRum ( originalWindow ) ) {
278+ const rum = safeGetRum ( originalWindow )
279+ if ( rum ) {
245280 testInfo . isRUMActive = true
281+ if ( rum . stopSession ) {
282+ rum . stopSession ( )
283+ // eslint-disable-next-line cypress/no-unnecessary-waiting
284+ cy . wait ( rumFlushWaitMillis )
285+ }
246286 }
247287 let coverage
248288 try {
0 commit comments