Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/datadog-plugin-cypress/src/cypress-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
Expand Down Expand Up @@ -823,6 +826,7 @@ class CypressPlugin {
isModifiedTest: this.getIsTestModified(testSuiteAbsolutePath),
repositoryRoot: this.repositoryRoot,
isTestIsolationEnabled: this.isTestIsolationEnabled,
rumFlushWaitMillis: this.rumFlushWaitMillis,
}

if (this.testSuiteSpan) {
Expand Down
56 changes: 48 additions & 8 deletions packages/datadog-plugin-cypress/src/support.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
'use strict'

const DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id'
let rumFlushWaitMillis = 500

let isEarlyFlakeDetectionEnabled = false
let isKnownTestsEnabled = false
let knownTestsForSuite = []
Expand All @@ -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
Expand Down Expand Up @@ -165,18 +169,45 @@ 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).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()
}
})
cy.window().then(win => {
originalWindow = win
})
})

before(function () {
Expand All @@ -195,6 +226,9 @@ before(function () {
isImpactedTestsEnabled = suiteConfig.isImpactedTestsEnabled
isModifiedTest = suiteConfig.isModifiedTest
isTestIsolationEnabled = suiteConfig.isTestIsolationEnabled
if (Number.isFinite(suiteConfig.rumFlushWaitMillis)) {
rumFlushWaitMillis = suiteConfig.rumFlushWaitMillis
}
}
})
})
Expand Down Expand Up @@ -241,8 +275,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(rumFlushWaitMillis)
}
}
let coverage
try {
Expand Down
Loading