Skip to content

Commit 386f4e7

Browse files
[test optimization] Fix cy.window for multi origin tests (#5185)
1 parent 51a58bc commit 386f4e7

File tree

5 files changed

+108
-32
lines changed

5 files changed

+108
-32
lines changed

integration-tests/cypress-esm-config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import cypress from 'cypress'
44
async function runCypress () {
55
await cypress.run({
66
config: {
7-
defaultCommandTimeout: 100,
7+
defaultCommandTimeout: 1000,
88
e2e: {
99
setupNodeEvents (on, config) {
1010
if (process.env.CYPRESS_ENABLE_INCOMPATIBLE_PLUGIN) {

integration-tests/cypress.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const cypressFailFast = require('cypress-fail-fast/plugin')
44
const ddTracePlugin = require('dd-trace/ci/cypress/plugin')
55

66
module.exports = {
7-
defaultCommandTimeout: 100,
7+
defaultCommandTimeout: 1000,
88
e2e: {
99
setupNodeEvents (on, config) {
1010
if (process.env.CYPRESS_ENABLE_INCOMPATIBLE_PLUGIN) {

integration-tests/cypress/cypress.spec.js

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict'
22

3+
const http = require('http')
34
const { exec } = require('child_process')
45

56
const getPort = require('get-port')
@@ -74,7 +75,7 @@ moduleTypes.forEach(({
7475
describe(`cypress@${version} ${type}`, function () {
7576
this.retries(2)
7677
this.timeout(60000)
77-
let sandbox, cwd, receiver, childProcess, webAppPort
78+
let sandbox, cwd, receiver, childProcess, webAppPort, secondWebAppServer
7879

7980
if (type === 'commonJS') {
8081
testCommand = testCommand(version)
@@ -91,6 +92,9 @@ moduleTypes.forEach(({
9192
after(async () => {
9293
await sandbox.remove()
9394
await new Promise(resolve => webAppServer.close(resolve))
95+
if (secondWebAppServer) {
96+
await new Promise(resolve => secondWebAppServer.close(resolve))
97+
}
9498
})
9599

96100
beforeEach(async function () {
@@ -1636,5 +1640,56 @@ moduleTypes.forEach(({
16361640
})
16371641
})
16381642
})
1643+
1644+
// cy.origin is not available in old versions of Cypress
1645+
if (version === 'latest') {
1646+
it('does not crash for multi origin tests', async () => {
1647+
const {
1648+
NODE_OPTIONS, // NODE_OPTIONS dd-trace config does not work with cypress
1649+
...restEnvVars
1650+
} = getCiVisEvpProxyConfig(receiver.port)
1651+
1652+
const secondWebAppPort = await getPort()
1653+
1654+
secondWebAppServer = http.createServer((req, res) => {
1655+
res.setHeader('Content-Type', 'text/html')
1656+
res.writeHead(200)
1657+
res.end(`
1658+
<!DOCTYPE html>
1659+
<html>
1660+
<div class="hella-world">Hella World</div>
1661+
</html>
1662+
`)
1663+
})
1664+
1665+
secondWebAppServer.listen(secondWebAppPort)
1666+
1667+
const specToRun = 'cypress/e2e/multi-origin.js'
1668+
1669+
childProcess = exec(
1670+
version === 'latest' ? testCommand : `${testCommand} --spec ${specToRun}`,
1671+
{
1672+
cwd,
1673+
env: {
1674+
...restEnvVars,
1675+
CYPRESS_BASE_URL: `http://localhost:${webAppPort}`,
1676+
CYPRESS_BASE_URL_SECOND: `http://localhost:${secondWebAppPort}`,
1677+
SPEC_PATTERN: specToRun
1678+
},
1679+
stdio: 'pipe'
1680+
}
1681+
)
1682+
1683+
await receiver
1684+
.gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), payloads => {
1685+
const events = payloads.flatMap(({ payload }) => payload.events)
1686+
assert.equal(events.length, 4)
1687+
1688+
const test = events.find(event => event.type === 'test').content
1689+
assert.equal(test.resource, 'cypress/e2e/multi-origin.js.tests multiple origins')
1690+
assert.equal(test.meta[TEST_STATUS], 'pass')
1691+
})
1692+
})
1693+
}
16391694
})
16401695
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* eslint-disable */
2+
3+
it('tests multiple origins', () => {
4+
// Visit first site
5+
cy.visit('/');
6+
cy.get('.hello-world')
7+
.should('have.text', 'Hello World')
8+
9+
// Visit second site
10+
cy.origin(Cypress.env('BASE_URL_SECOND'), () => {
11+
cy.visit('/')
12+
cy.get('.hella-world').should('have.text', 'Hella World')
13+
});
14+
});

packages/datadog-plugin-cypress/src/support.js

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ let isKnownTestsEnabled = false
44
let knownTestsForSuite = []
55
let suiteTests = []
66
let earlyFlakeDetectionNumRetries = 0
7+
// We need to grab the original window as soon as possible,
8+
// in case the test changes the origin. If the test does change the origin,
9+
// any call to `cy.window()` will result in a cross origin error.
10+
let originalWindow
711

812
// If the test is using multi domain with cy.origin, trying to access
913
// window properties will result in a cross origin error.
@@ -61,6 +65,9 @@ beforeEach(function () {
6165
this.skip()
6266
}
6367
})
68+
cy.window().then(win => {
69+
originalWindow = win
70+
})
6471
})
6572

6673
before(function () {
@@ -78,39 +85,39 @@ before(function () {
7885
})
7986

8087
after(() => {
81-
cy.window().then(win => {
82-
if (safeGetRum(win)) {
83-
win.dispatchEvent(new Event('beforeunload'))
88+
try {
89+
if (safeGetRum(originalWindow)) {
90+
originalWindow.dispatchEvent(new Event('beforeunload'))
8491
}
85-
})
92+
} catch (e) {
93+
// ignore error. It's usually a multi origin issue.
94+
}
8695
})
8796

8897

8998
afterEach(function () {
90-
cy.window().then(win => {
91-
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
92-
const testInfo = {
93-
testName: currentTest.fullTitle(),
94-
testSuite: Cypress.mocha.getRootSuite().file,
95-
testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute,
96-
state: currentTest.state,
97-
error: currentTest.err,
98-
isNew: currentTest._ddIsNew,
99-
isEfdRetry: currentTest._ddIsEfdRetry
100-
}
101-
try {
102-
testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
103-
} catch (e) {}
99+
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
100+
const testInfo = {
101+
testName: currentTest.fullTitle(),
102+
testSuite: Cypress.mocha.getRootSuite().file,
103+
testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute,
104+
state: currentTest.state,
105+
error: currentTest.err,
106+
isNew: currentTest._ddIsNew,
107+
isEfdRetry: currentTest._ddIsEfdRetry
108+
}
109+
try {
110+
testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
111+
} catch (e) {}
104112

105-
if (safeGetRum(win)) {
106-
testInfo.isRUMActive = true
107-
}
108-
let coverage
109-
try {
110-
coverage = win.__coverage__
111-
} catch (e) {
112-
// ignore error and continue
113-
}
114-
cy.task('dd:afterEach', { test: testInfo, coverage })
115-
})
113+
if (safeGetRum(originalWindow)) {
114+
testInfo.isRUMActive = true
115+
}
116+
let coverage
117+
try {
118+
coverage = originalWindow.__coverage__
119+
} catch (e) {
120+
// ignore error and continue
121+
}
122+
cy.task('dd:afterEach', { test: testInfo, coverage })
116123
})

0 commit comments

Comments
 (0)