dd-trace
Version:
Datadog APM tracing client for JavaScript
153 lines (135 loc) • 4.92 kB
JavaScript
/* eslint-disable */
let isEarlyFlakeDetectionEnabled = false
let isKnownTestsEnabled = false
let knownTestsForSuite = []
let suiteTests = []
let earlyFlakeDetectionNumRetries = 0
let isTestManagementEnabled = false
let testManagementAttemptToFixRetries = 0
let testManagementTests = {}
// 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.
let originalWindow
// If the test is using multi domain with cy.origin, trying to access
// window properties will result in a cross origin error.
function safeGetRum (window) {
try {
return window.DD_RUM
} catch (e) {
return null
}
}
function isNewTest (test) {
return !knownTestsForSuite.includes(test.fullTitle())
}
function getTestProperties (testName) {
// We neeed to do it in this way because of compatibility with older versions as '?' is not supported in older versions of Cypress
const properties = testManagementTests[testName] && testManagementTests[testName].properties || {};
const { attempt_to_fix: isAttemptToFix, disabled: isDisabled, quarantined: isQuarantined } = properties;
return { isAttemptToFix, isDisabled, isQuarantined };
}
function retryTest (test, suiteTests, numRetries, tags) {
for (let retryIndex = 0; retryIndex < numRetries; retryIndex++) {
const clonedTest = test.clone()
// TODO: signal in framework logs that this is a retry.
// TODO: Change it so these tests are allowed to fail.
// TODO: figure out if reported duration is skewed.
suiteTests.unshift(clonedTest)
tags.forEach(tag => {
clonedTest[tag] = true
})
}
}
const oldRunTests = Cypress.mocha.getRunner().runTests
Cypress.mocha.getRunner().runTests = function (suite, fn) {
if (!isKnownTestsEnabled && !isTestManagementEnabled) {
return oldRunTests.apply(this, arguments)
}
// We copy the new tests at the beginning of the suite run (runTests), so that they're run
// multiple times.
suite.tests.forEach(test => {
const testName = test.fullTitle()
const { isAttemptToFix } = getTestProperties(testName)
if (isTestManagementEnabled) {
if (isAttemptToFix && !test.isPending()) {
test._ddIsAttemptToFix = true
retryTest(test, suite.tests, testManagementAttemptToFixRetries, ['_ddIsAttemptToFix'])
}
}
if (isKnownTestsEnabled) {
if (!test._ddIsNew && !test.isPending() && isNewTest(test)) {
test._ddIsNew = true
if (isEarlyFlakeDetectionEnabled && !isAttemptToFix) {
retryTest(test, suite.tests, earlyFlakeDetectionNumRetries, ['_ddIsNew', '_ddIsEfdRetry'])
}
}
}
})
return oldRunTests.apply(this, [suite, fn])
}
beforeEach(function () {
cy.task('dd:beforeEach', {
testName: Cypress.mocha.getRunner().suite.ctx.currentTest.fullTitle(),
testSuite: Cypress.mocha.getRootSuite().file
}).then(({ traceId, shouldSkip }) => {
Cypress.env('traceId', traceId)
if (shouldSkip) {
this.skip()
}
})
cy.window().then(win => {
originalWindow = win
})
})
before(function () {
cy.task('dd:testSuiteStart', {
testSuite: Cypress.mocha.getRootSuite().file,
testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute
}).then((suiteConfig) => {
if (suiteConfig) {
isEarlyFlakeDetectionEnabled = suiteConfig.isEarlyFlakeDetectionEnabled
isKnownTestsEnabled = suiteConfig.isKnownTestsEnabled
knownTestsForSuite = suiteConfig.knownTestsForSuite
earlyFlakeDetectionNumRetries = suiteConfig.earlyFlakeDetectionNumRetries
isTestManagementEnabled = suiteConfig.isTestManagementEnabled
testManagementAttemptToFixRetries = suiteConfig.testManagementAttemptToFixRetries
testManagementTests = suiteConfig.testManagementTests
}
})
})
after(() => {
try {
if (safeGetRum(originalWindow)) {
originalWindow.dispatchEvent(new Event('beforeunload'))
}
} catch (e) {
// ignore error. It's usually a multi origin issue.
}
})
afterEach(function () {
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
const testInfo = {
testName: currentTest.fullTitle(),
testSuite: Cypress.mocha.getRootSuite().file,
testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute,
state: currentTest.state,
error: currentTest.err,
isNew: currentTest._ddIsNew,
isEfdRetry: currentTest._ddIsEfdRetry,
isAttemptToFix: currentTest._ddIsAttemptToFix
}
try {
testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
} catch (e) {}
if (safeGetRum(originalWindow)) {
testInfo.isRUMActive = true
}
let coverage
try {
coverage = originalWindow.__coverage__
} catch (e) {
// ignore error and continue
}
cy.task('dd:afterEach', { test: testInfo, coverage })
})