Skip to content

Commit 21e0408

Browse files
authored
[test-optimization] [SDTEST-1784] Co-relate Playwright tests with RUM sessions (#5509)
1 parent 0c9d24a commit 21e0408

File tree

6 files changed

+170
-2
lines changed

6 files changed

+170
-2
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { test, expect } = require('@playwright/test')
2+
3+
test.beforeEach(async ({ page }) => {
4+
await page.goto(process.env.PW_BASE_URL)
5+
})
6+
7+
test.describe('playwright', () => {
8+
test('should have RUM active', async ({ page }) => {
9+
await expect(page.locator('.hello-world')).toHaveText([
10+
'Hello World'
11+
])
12+
})
13+
})

integration-tests/ci-visibility/web-app-server.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ module.exports = http.createServer((req, res) => {
1111
<title>Hello World</title>
1212
<script>
1313
window.DD_RUM = {
14+
getInternalContext: () => {
15+
return true
16+
},
1417
stopSession: () => {
1518
return true
1619
}

integration-tests/playwright/playwright.spec.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ const {
4040
TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX,
4141
TEST_HAS_FAILED_ALL_RETRIES,
4242
TEST_NAME,
43-
TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED
43+
TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED,
44+
TEST_IS_RUM_ACTIVE,
45+
TEST_BROWSER_VERSION
4446
} = require('../../packages/dd-trace/src/plugins/util/test')
4547
const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env')
4648
const { ERROR_MESSAGE } = require('../../packages/dd-trace/src/constants')
@@ -1417,6 +1419,39 @@ versions.forEach((version) => {
14171419
})
14181420
})
14191421
})
1422+
1423+
context('correlation between tests and RUM sessions', () => {
1424+
it('can correlate tests and RUM sessions', (done) => {
1425+
const receiverPromise = receiver
1426+
.gatherPayloadsMaxTimeout(({ url }) => url === '/api/v2/citestcycle', (payloads) => {
1427+
const events = payloads.flatMap(({ payload }) => payload.events)
1428+
const playwrightTest = events.find(event => event.type === 'test').content
1429+
assert.include(playwrightTest.meta, {
1430+
[TEST_BROWSER_NAME]: 'chromium',
1431+
[TEST_TYPE]: 'browser',
1432+
[TEST_IS_RUM_ACTIVE]: 'true'
1433+
})
1434+
assert.property(playwrightTest.meta, TEST_BROWSER_VERSION)
1435+
})
1436+
1437+
childProcess = exec(
1438+
'./node_modules/.bin/playwright test -c playwright.config.js active-test-span-rum-test.js',
1439+
{
1440+
cwd,
1441+
env: {
1442+
...getCiVisAgentlessConfig(receiver.port),
1443+
PW_BASE_URL: `http://localhost:${webAppPort}`,
1444+
TEST_DIR: './ci-visibility/playwright-tests-rum'
1445+
},
1446+
stdio: 'pipe'
1447+
}
1448+
)
1449+
1450+
childProcess.on('exit', () => {
1451+
receiverPromise.then(() => done()).catch(done)
1452+
})
1453+
})
1454+
})
14201455
}
14211456
})
14221457
})

packages/datadog-instrumentations/src/helpers/hooks.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ module.exports = {
111111
pino: () => require('../pino'),
112112
'pino-pretty': () => require('../pino'),
113113
playwright: () => require('../playwright'),
114+
'playwright-core': () => require('../playwright'),
114115
'promise-js': () => require('../promise-js'),
115116
promise: () => require('../promise'),
116117
protobufjs: () => require('../protobufjs'),

packages/datadog-instrumentations/src/playwright.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const testSuiteStartCh = channel('ci:playwright:test-suite:start')
2323
const testSuiteFinishCh = channel('ci:playwright:test-suite:finish')
2424

2525
const workerReportCh = channel('ci:playwright:worker:report')
26+
const testPageGotoCh = channel('ci:playwright:test:page-goto')
2627

2728
const testToAr = new WeakMap()
2829
const testSuiteToAr = new Map()
@@ -783,6 +784,37 @@ addHook({
783784
return processHostPackage
784785
})
785786

787+
addHook({
788+
name: 'playwright-core',
789+
file: 'lib/client/page.js',
790+
versions: ['>=1.38.0']
791+
}, (pagePackage) => {
792+
shimmer.wrap(pagePackage.Page.prototype, 'goto', goto => async function (url, options) {
793+
const response = await goto.apply(this, arguments)
794+
795+
const page = this
796+
797+
const isRumActive = await page.evaluate(() => {
798+
if (window.DD_RUM && window.DD_RUM.getInternalContext) {
799+
return !!window.DD_RUM.getInternalContext()
800+
} else {
801+
return false
802+
}
803+
})
804+
805+
if (isRumActive) {
806+
testPageGotoCh.publish({
807+
isRumActive,
808+
page
809+
})
810+
}
811+
812+
return response
813+
})
814+
815+
return pagePackage
816+
})
817+
786818
// Only in worker
787819
addHook({
788820
name: 'playwright',
@@ -822,6 +854,55 @@ addHook({
822854
browserName
823855
})
824856

857+
let existAfterEachHook = false
858+
859+
// We try to find an existing afterEach hook with _ddHook to avoid adding a new one
860+
for (const hook of test.parent._hooks) {
861+
if (hook.type === 'afterEach' && hook._ddHook) {
862+
existAfterEachHook = true
863+
break
864+
}
865+
}
866+
867+
// In cases where there is no afterEach hook with _ddHook, we need to add one
868+
if (!existAfterEachHook) {
869+
test.parent._hooks.push({
870+
type: 'afterEach',
871+
fn: async function ({ page }) {
872+
try {
873+
if (page) {
874+
const isRumActive = await page.evaluate(() => {
875+
if (window.DD_RUM && window.DD_RUM.stopSession) {
876+
window.DD_RUM.stopSession()
877+
return true
878+
} else {
879+
return false
880+
}
881+
})
882+
883+
if (isRumActive) {
884+
const url = page.url()
885+
if (url) {
886+
const domain = new URL(url).hostname
887+
await page.context().addCookies([{
888+
name: 'datadog-ci-visibility-test-execution-id',
889+
value: '',
890+
domain,
891+
expires: 0,
892+
path: '/'
893+
}])
894+
}
895+
}
896+
}
897+
} catch (e) {
898+
// ignore errors
899+
}
900+
},
901+
title: 'afterEach hook',
902+
_ddHook: true
903+
})
904+
}
905+
825906
res = _runTest.apply(this, arguments)
826907

827908
testInfo = this._currentTest

packages/datadog-plugin-playwright/src/index.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ const {
3131
TEST_MODULE,
3232
TEST_SUITE,
3333
TEST_SUITE_ID,
34-
TEST_NAME
34+
TEST_NAME,
35+
TEST_IS_RUM_ACTIVE,
36+
TEST_BROWSER_VERSION
3537
} = require('../../dd-trace/src/plugins/util/test')
3638
const { RESOURCE_NAME } = require('../../../ext/tags')
3739
const { COMPONENT } = require('../../dd-trace/src/constants')
@@ -147,6 +149,36 @@ class PlaywrightPlugin extends CiPlugin {
147149
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
148150
})
149151

152+
this.addSub('ci:playwright:test:page-goto', ({
153+
isRumActive,
154+
page
155+
}) => {
156+
const store = storage('legacy').getStore()
157+
const span = store && store.span
158+
if (!span) return
159+
160+
if (isRumActive) {
161+
span.setTag(TEST_IS_RUM_ACTIVE, 'true')
162+
163+
if (page) {
164+
const browserVersion = page.context().browser().version()
165+
166+
if (browserVersion) {
167+
span.setTag(TEST_BROWSER_VERSION, browserVersion)
168+
}
169+
170+
const url = page.url()
171+
const domain = new URL(url).hostname
172+
page.context().addCookies([{
173+
name: 'datadog-ci-visibility-test-execution-id',
174+
value: span.context().toTraceId(),
175+
domain,
176+
path: '/'
177+
}])
178+
}
179+
}
180+
})
181+
150182
this.addSub('ci:playwright:test:start', ({
151183
testName,
152184
testSuiteAbsolutePath,
@@ -240,6 +272,8 @@ class PlaywrightPlugin extends CiPlugin {
240272
const span = store && store.span
241273
if (!span) return
242274

275+
const isRUMActive = span.context()._tags[TEST_IS_RUM_ACTIVE]
276+
243277
span.setTag(TEST_STATUS, testStatus)
244278

245279
if (error) {
@@ -307,6 +341,7 @@ class PlaywrightPlugin extends CiPlugin {
307341
{
308342
hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS],
309343
isNew,
344+
isRum: isRUMActive,
310345
browserDriver: 'playwright'
311346
}
312347
)

0 commit comments

Comments
 (0)