Skip to content

Commit

Permalink
Migrate shadowDom.scenario.ts to Playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
sethfowler-datadog committed Jan 24, 2025
1 parent f0c939f commit dc360fb
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 37 deletions.
21 changes: 13 additions & 8 deletions packages/core/test/getCurrentJasmineSpec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
let currentSpec: jasmine.SpecResult | null = null

export function getCurrentJasmineSpec() {
if (typeof globalThis['jasmine'] !== 'object') {
throw new Error('Not inside a Jasmine test')
}
return currentSpec
}

jasmine.getEnv().addReporter({
specStarted(specResult) {
currentSpec = specResult
},
specDone() {
currentSpec = null
},
})
if (typeof globalThis['jasmine'] === 'object') {
globalThis['jasmine'].getEnv().addReporter({
specStarted(specResult) {
currentSpec = specResult
},
specDone() {
currentSpec = null
},
})
}
11 changes: 8 additions & 3 deletions packages/core/test/registerCleanupTask.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
const cleanupTasks: Array<() => void> = []

export function registerCleanupTask(task: () => void) {
if (typeof globalThis['afterEach'] !== 'function') {
throw new Error('Not inside a Jasmine test')
}
cleanupTasks.unshift(task)
}

afterEach(() => {
cleanupTasks.splice(0).forEach((task) => task())
})
if (typeof globalThis['afterEach'] === 'function') {
afterEach(() => {
cleanupTasks.splice(0).forEach((task) => task())
})
}
1 change: 1 addition & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default defineConfig({
'**/logs.scenario.ts',
'**/microfrontend.scenario.ts',
'**/sessionStore.scenario.ts',
'**/shadowDom.scenario.ts',
'**/transport.scenario.ts',
'**/views.scenario.ts',
'**/vitals.scenario.ts',
Expand Down
45 changes: 19 additions & 26 deletions test/e2e/scenario/recorder/shadowDom.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
findTextNode,
} from '@datadog/browser-rum/test'

import { flushEvents, createTest, bundleSetup, html } from '../../lib/framework'
import { test, expect } from '@playwright/test'
import { createTest, bundleSetup, html } from '../../lib/framework'

/** Will generate the following HTML
* ```html
Expand Down Expand Up @@ -156,15 +157,15 @@ class DivWithStyle extends HTMLElement {
</script>
`

describe('recorder with shadow DOM', () => {
test.describe('recorder with shadow DOM', () => {
createTest('can record fullsnapshot with the detail inside the shadow root')
.withRum({ defaultPrivacyLevel: 'allow' })
.withSetup(bundleSetup)
.withBody(html`
${divShadowDom}
<my-div />
`)
.run(async ({ intakeRegistry }) => {
.run(async ({ flushEvents, intakeRegistry }) => {
await flushEvents()

expect(intakeRegistry.replaySegments.length).toBe(1)
Expand All @@ -184,10 +185,10 @@ describe('recorder with shadow DOM', () => {
${divWithStyleShadowDom}
<div-with-style />
`)
.run(async ({ intakeRegistry }) => {
if (!(await isAdoptedStyleSheetsSupported())) {
return pending('adoptedStyleSheets is not supported in this browser')
}
.run(async ({ flushEvents, intakeRegistry, page }) => {
const isAdoptedStyleSheetsSupported = await page.evaluate(() => document.adoptedStyleSheets !== undefined)
test.skip(!isAdoptedStyleSheetsSupported, 'adoptedStyleSheets is not supported in this browser')

await flushEvents()

expect(intakeRegistry.replaySegments.length).toBe(1)
Expand All @@ -210,7 +211,7 @@ describe('recorder with shadow DOM', () => {
<div data-dd-privacy="mask-user-input"><my-input-field id="privacy-set-outside" /></div>
<my-input-field privacy="mask-user-input" id="privacy-set-inside" />
`)
.run(async ({ intakeRegistry }) => {
.run(async ({ flushEvents, intakeRegistry }) => {
await flushEvents()

expect(intakeRegistry.replaySegments.length).toBe(1)
Expand All @@ -223,7 +224,7 @@ describe('recorder with shadow DOM', () => {
shadowRoot: outsideShadowRoot,
textContent: outsideTextContent,
} = findElementsInShadowDom(fullSnapshot.data.node, 'privacy-set-outside')
expect(outsideShadowRoot?.isShadowRoot).toBeTrue()
expect(outsideShadowRoot?.isShadowRoot).toBe(true)
expect(outsideInput?.attributes.value).toBe('***')
expect(outsideTextContent).toBe('field privacy-set-outside: ')

Expand All @@ -232,7 +233,7 @@ describe('recorder with shadow DOM', () => {
shadowRoot: insideShadowRoot,
textContent: insideTextContent,
} = findElementsInShadowDom(fullSnapshot.data.node, 'privacy-set-inside')
expect(insideShadowRoot?.isShadowRoot).toBeTrue()
expect(insideShadowRoot?.isShadowRoot).toBe(true)
expect(insideInput?.attributes.value).toBe('***')
expect(insideTextContent).toBe('field privacy-set-inside: ')
})
Expand All @@ -244,8 +245,8 @@ describe('recorder with shadow DOM', () => {
${divShadowDom}
<my-div />
`)
.run(async ({ intakeRegistry }) => {
const div = await getNodeInsideShadowDom('my-div', 'div')
.run(async ({ flushEvents, intakeRegistry, page }) => {
const div = page.locator('my-div div')
await div.click()
await flushEvents()
expect(intakeRegistry.replaySegments.length).toBe(1)
Expand All @@ -266,16 +267,17 @@ describe('recorder with shadow DOM', () => {
${divShadowDom}
<my-div id="host" />
`)
.run(async ({ intakeRegistry }) => {
await browser.execute(() => {
.run(async ({ flushEvents, intakeRegistry, page }) => {
await page.evaluate(() => {
const host = document.body.querySelector('#host') as HTMLElement
const div = host.shadowRoot!.querySelector('div') as HTMLElement
div.innerText = 'titi'
})
await flushEvents()
expect(intakeRegistry.replaySegments.length).toBe(1)
const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidatorFromSegment(
intakeRegistry.replaySegments[0]
intakeRegistry.replaySegments[0],
{ expect }
)
validate({
adds: [
Expand All @@ -300,8 +302,8 @@ describe('recorder with shadow DOM', () => {
${scrollableDivShadowDom}
<my-scrollable-div id="host" />
`)
.run(async ({ intakeRegistry }) => {
const button = await getNodeInsideShadowDom('my-scrollable-div', 'button')
.run(async ({ flushEvents, intakeRegistry, page }) => {
const button = page.locator('my-scrollable-div button')

// Triggering scrollTo from the test itself is not allowed
// Thus, a callback to scroll the div was added to the button 'click' event
Expand Down Expand Up @@ -337,12 +339,3 @@ function findElementsInShadowDom(node: SerializedNodeWithId, id: string) {
expect(textContent).toBeTruthy()
return { shadowHost, shadowRoot, input, text, textContent }
}

async function getNodeInsideShadowDom(hostTag: string, selector: string) {
const host = await $(hostTag)
return host.shadow$(selector)
}

function isAdoptedStyleSheetsSupported(): Promise<boolean> {
return browser.execute(() => document.adoptedStyleSheets !== undefined)
}

0 comments on commit dc360fb

Please sign in to comment.