Skip to content
Open
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
68 changes: 25 additions & 43 deletions test/e2e/lib/framework/createTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ import { IntakeRegistry } from './intakeRegistry'
import { flushEvents } from './flushEvents'
import type { Servers } from './httpServers'
import { getTestServers, waitForServersIdle } from './httpServers'
import type { SetupFactory, SetupOptions } from './pageSetups'
import { html, DEFAULT_SETUPS, npmSetup, reactSetup } from './pageSetups'
import type { SetupFactory, SetupOptions, WorkerOptions } from './pageSetups'
import { buildWorkerScript, html, DEFAULT_SETUPS, npmSetup, reactSetup } from './pageSetups'
import { createIntakeServerApp } from './serverApps/intake'
import { createMockServerApp } from './serverApps/mock'
import type { Extension } from './createExtension'
import { isBrowserStack } from './environment'

interface LogsWorkerOptions {
importScript?: boolean
nativeLog?: boolean
}
import '../types/global'

export function createTest(title: string) {
return new TestBuilder(title)
Expand All @@ -42,7 +39,6 @@ interface TestContext {
flushEvents: () => Promise<void>
deleteAllCookies: () => Promise<void>
sendXhr: (url: string, headers?: string[][]) => Promise<string>
interactWithWorker: (cb: (worker: ServiceWorker) => void) => Promise<void>
}

type TestRunner = (testContext: TestContext) => Promise<void> | void
Expand All @@ -62,8 +58,8 @@ class TestBuilder {
rumConfiguration?: RumInitConfiguration
logsConfiguration?: LogsInitConfiguration
} = {}
private useServiceWorker: boolean = false
private hostName?: string
private workerOptions?: WorkerOptions

constructor(private title: string) {}

Expand Down Expand Up @@ -135,37 +131,20 @@ class TestBuilder {
return this
}

withWorker({ importScript = false, nativeLog = false }: LogsWorkerOptions = {}) {
if (!this.useServiceWorker) {
this.useServiceWorker = true

const isModule = !importScript

const params = []
if (importScript) {
params.push('importScripts=true')
}
if (nativeLog) {
params.push('nativeLog=true')
}

const query = params.length > 0 ? `?${params.join('&')}` : ''
const url = `/sw.js${query}`

const options = isModule ? '{ type: "module" }' : '{}'

// Service workers require HTTPS or localhost due to browser security restrictions
this.hostName = 'localhost'
this.withBody(html`
<script>
if (!window.myServiceWorker && 'serviceWorker' in navigator) {
navigator.serviceWorker.register('${url}', ${options}).then((registration) => {
window.myServiceWorker = registration
})
}
</script>
`)
}
withWorker(testCase: WorkerOptions['testCase'], registrationOptions: RegistrationOptions = {}) {
this.workerOptions = { ...registrationOptions, testCase }

// Service workers require HTTPS or localhost due to browser security restrictions
this.withHostName('localhost')
this.withBody(html`
<script>
if (!window.myServiceWorker && 'serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', ${JSON.stringify(registrationOptions)}).then((registration) => {
window.myServiceWorker = registration
})
}
</script>
`)

return this
}
Expand Down Expand Up @@ -194,6 +173,7 @@ class TestBuilder {
testFixture: this.testFixture,
extension: this.extension,
hostName: this.hostName,
workerOptions: this.workerOptions,
}

if (this.alsoRunWithRumSlim) {
Expand Down Expand Up @@ -270,7 +250,12 @@ function declareTest(title: string, setupOptions: SetupOptions, factory: SetupFa
servers.intake.bindServerApp(createIntakeServerApp(testContext.intakeRegistry))

const setup = factory(setupOptions, servers)
servers.base.bindServerApp(createMockServerApp(servers, setup, setupOptions.remoteConfiguration))
servers.base.bindServerApp(
createMockServerApp(servers, setup, {
remoteConfiguration: setupOptions.remoteConfiguration,
workerScript: buildWorkerScript(setupOptions, servers),
})
)
servers.crossOrigin.bindServerApp(createMockServerApp(servers, setup))

await setUpTest(browserLogs, testContext)
Expand Down Expand Up @@ -312,9 +297,6 @@ function createTestContext(
browserLogsManager.clear()
}
},
interactWithWorker: async (cb: (worker: ServiceWorker) => void) => {
await page.evaluate(`(${cb.toString()})(window.myServiceWorker.active)`)
},
flushBrowserLogs: () => browserLogsManager.clear(),
flushEvents: () => flushEvents(page),
deleteAllCookies: () => deleteAllCookies(browserContext),
Expand Down
10 changes: 9 additions & 1 deletion test/e2e/lib/framework/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
export { createTest } from './createTest'
export { DEFAULT_RUM_CONFIGURATION, DEFAULT_LOGS_CONFIGURATION } from '../helpers/configuration'
export { createExtension } from './createExtension'
export { bundleSetup, html, npmSetup, reactSetup, formatConfiguration, createCrossOriginScriptUrls } from './pageSetups'
export {
bundleSetup,
html,
js,
npmSetup,
reactSetup,
formatConfiguration,
createCrossOriginScriptUrls,
} from './pageSetups'
export { IntakeRegistry } from './intakeRegistry'
export { getTestServers, waitForServersIdle } from './httpServers'
export { flushEvents } from './flushEvents'
Expand Down
42 changes: 22 additions & 20 deletions test/e2e/lib/framework/pageSetups.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { generateUUID, INTAKE_URL_PARAMETERS } from '@datadog/browser-core'
import type { LogsInitConfiguration } from '@datadog/browser-logs'
import type { LogsInitConfiguration, DatadogLogs } from '@datadog/browser-logs'
import type { RumInitConfiguration, RemoteConfiguration } from '@datadog/browser-rum-core'
import type test from '@playwright/test'
import { DEFAULT_LOGS_CONFIGURATION } from '../helpers/configuration'
import { isBrowserStack, isContinuousIntegration } from './environment'
import type { Servers } from './httpServers'

export interface WorkerOptions extends RegistrationOptions {
testCase: (self: WorkerGlobalScope & { DD_LOGS?: DatadogLogs }) => void
}
export interface SetupOptions {
rum?: RumInitConfiguration
useRumSlim: boolean
Expand All @@ -27,11 +30,7 @@ export interface SetupOptions {
logsConfiguration?: LogsInitConfiguration
}
hostName?: string
}

export interface WorkerOptions {
importScripts?: boolean
nativeLog?: boolean
workerOptions?: WorkerOptions
}

export type SetupFactory = (options: SetupOptions, servers: Servers) => string
Expand Down Expand Up @@ -209,20 +208,25 @@ export function reactSetup(options: SetupOptions, servers: Servers, appName: str
})
}

export function workerSetup(options: WorkerOptions, servers: Servers) {
return js`
${options.importScripts ? js`importScripts('/datadog-logs.js');` : js`import '/datadog-logs.js';`}
export function buildWorkerScript(options: SetupOptions, servers: Servers) {
let script = ''

if (!options.workerOptions) {
return script
}

if (options.logs) {
script += js`
${options.workerOptions.type === 'module' ? js`import '/datadog-logs.js';` : js`importScripts('/datadog-logs.js');`}

// Initialize DD_LOGS in service worker
DD_LOGS.init(${formatConfiguration({ ...DEFAULT_LOGS_CONFIGURATION, forwardConsoleLogs: 'all', forwardErrorsToLogs: true }, servers)})

// Handle messages from main thread
self.addEventListener('message', (event) => {
const message = event.data;

${options.nativeLog ? js`console.log(message);` : js`DD_LOGS.logger.log(message);`}
});
DD_LOGS.init(${formatConfiguration({ ...DEFAULT_LOGS_CONFIGURATION, ...options.logs }, servers)})
`
}

script += `;(${options.workerOptions.testCase.toString()})(self);`

return script
}

export function basePage({ header, body }: { header?: string; body?: string }) {
Expand All @@ -244,9 +248,7 @@ export function html(parts: readonly string[], ...vars: string[]) {
return parts.reduce((full, part, index) => full + vars[index - 1] + part)
}

function js(parts: readonly string[], ...vars: string[]) {
return parts.reduce((full, part, index) => full + vars[index - 1] + part)
}
export const js = html

function setupEventBridge(servers: Servers) {
const baseHostname = new URL(servers.base.origin).hostname
Expand Down
13 changes: 6 additions & 7 deletions test/e2e/lib/framework/serverApps/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import type { RemoteConfiguration } from '@datadog/browser-rum-core'
import { getSdkBundlePath, getTestAppBundlePath } from '../sdkBuilds'
import type { MockServerApp, Servers } from '../httpServers'
import { DEV_SERVER_BASE_URL } from '../../helpers/playwright'
import { workerSetup } from '../pageSetups'

export const LARGE_RESPONSE_MIN_BYTE_SIZE = 100_000

interface MockServerOptions {
remoteConfiguration?: RemoteConfiguration
workerScript?: string
}
export function createMockServerApp(
servers: Servers,
setup: string,
remoteConfiguration?: RemoteConfiguration
{ remoteConfiguration, workerScript }: MockServerOptions = {}
): MockServerApp {
const app = express()
let largeResponseBytesWritten = 0
Expand Down Expand Up @@ -46,11 +49,7 @@ export function createMockServerApp(
})

app.get('/sw.js', (_req, res) => {
const query = _req.query

res
.contentType('application/javascript')
.send(workerSetup({ importScripts: Boolean(query.importScripts), nativeLog: Boolean(query.nativeLog) }, servers))
res.contentType('application/javascript').send(workerScript)
})

function generateLargeResponse(res: ServerResponse, chunkText: string) {
Expand Down
8 changes: 4 additions & 4 deletions test/e2e/lib/types/global.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { LogsGlobal } from '@datadog/browser-logs'
import type { RumGlobal } from '@datadog/browser-rum'
import type { DatadogLogs } from '@datadog/browser-logs'
import type { DatadogRum } from '@datadog/browser-rum'

declare global {
interface Window {
DD_LOGS?: LogsGlobal
DD_RUM?: RumGlobal
DD_LOGS?: DatadogLogs
DD_RUM?: DatadogRum
}
}
37 changes: 18 additions & 19 deletions test/e2e/scenario/logs.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,49 @@ declare global {

test.describe('logs', () => {
createTest('service worker with worker logs - esm')
.withWorker()
.run(async ({ flushEvents, intakeRegistry, browserName, interactWithWorker }) => {
.withLogs()
.withWorker(
function (self) {
self.DD_LOGS!.logger.log('Some message')
},
{ type: 'module' }
)
.run(async ({ flushEvents, intakeRegistry, browserName }) => {
test.skip(browserName !== 'chromium', 'Non-Chromium browsers do not support ES modules in Service Workers')

await interactWithWorker((worker) => {
worker.postMessage('Some message')
})

await flushEvents()

expect(intakeRegistry.logsRequests).toHaveLength(1)
expect(intakeRegistry.logsEvents[0].message).toBe('Some message')
})

createTest('service worker with worker logs - importScripts')
.withWorker({ importScript: true })
.run(async ({ flushEvents, intakeRegistry, browserName, interactWithWorker }) => {
.withLogs()
.withWorker(function (self) {
self.DD_LOGS!.logger.log('Other message')
})
.run(async ({ flushEvents, intakeRegistry, browserName }) => {
test.skip(
browserName === 'webkit',
'BrowserStack overrides the localhost URL with bs-local.com and cannot be used to install a Service Worker'
)

await interactWithWorker((worker) => {
worker.postMessage('Other message')
})

await flushEvents()

expect(intakeRegistry.logsRequests).toHaveLength(1)
expect(intakeRegistry.logsEvents[0].message).toBe('Other message')
})

createTest('service worker console forwarding')
.withWorker({ importScript: true, nativeLog: true })
.run(async ({ flushEvents, intakeRegistry, interactWithWorker, browserName }) => {
.withLogs({ forwardConsoleLogs: 'all', forwardErrorsToLogs: true })
.withWorker(function () {
console.log('SW console log test')
})
.run(async ({ flushEvents, intakeRegistry, browserName }) => {
test.skip(
browserName === 'webkit',
'BrowserStack overrides the localhost URL with bs-local.com and cannot be used to install a Service Worker'
)

await interactWithWorker((worker) => {
worker.postMessage('SW console log test')
})

await flushEvents()

// Expect logs for console, error, and report events from service worker
Expand Down
1 change: 1 addition & 0 deletions test/e2e/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"target": "ES2022",
"module": "ES2020",
"types": ["node", "ajv"],
"lib": ["ESNext", "DOM", "WebWorker"],
"allowJs": true,
"noEmit": true
}
Expand Down