Skip to content

Commit

Permalink
🧪 Update browser matrix for tests (#2884)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-lebeau authored Jul 30, 2024
1 parent fac13ee commit 9d19ead
Show file tree
Hide file tree
Showing 17 changed files with 135 additions and 77 deletions.
4 changes: 4 additions & 0 deletions packages/core/src/browser/fetchObservable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ describe('fetch proxy', () => {
})

it('should track fetch aborted by AbortController', (done) => {
if (!window.AbortController) {
pending('AbortController is not supported')
}

const controller = new AbortController()
void fetch(FAKE_URL, { signal: controller.signal })
controller.abort('AbortError')
Expand Down
46 changes: 30 additions & 16 deletions packages/core/src/domain/error/trackRuntimeError.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { disableJasmineUncaughtExceptionTracking, collectAsyncCalls } from '../../../test'
import { disableJasmineUncaughtExceptionTracking, collectAsyncCalls, registerCleanupTask } from '../../../test'
import { Observable } from '../../tools/observable'
import { isIE } from '../../tools/utils/browserDetection'
import type { UnhandledErrorCallback } from './trackRuntimeError'
Expand All @@ -9,11 +9,8 @@ describe('trackRuntimeError', () => {
const ERROR_MESSAGE = 'foo'

let originalOnErrorHandler: OnErrorEventHandler
let onErrorSpy: jasmine.Spy

let originalOnUnhandledRejectionHandler: Window['onunhandledrejection']
let onUnhandledrejectionSpy: jasmine.Spy

let onErrorSpy: jasmine.Spy
let notifyError: jasmine.Spy
let stopRuntimeErrorTracking: () => void

Expand All @@ -22,9 +19,7 @@ describe('trackRuntimeError', () => {
onErrorSpy = jasmine.createSpy()
window.onerror = onErrorSpy

originalOnUnhandledRejectionHandler = window.onunhandledrejection
onUnhandledrejectionSpy = jasmine.createSpy()
window.onunhandledrejection = onUnhandledrejectionSpy
onUnhandledrejectionSpy = setupOnUnhandledrejectionSpy()

notifyError = jasmine.createSpy()
const errorObservable = new Observable<RawError>()
Expand All @@ -35,7 +30,6 @@ describe('trackRuntimeError', () => {
afterEach(() => {
stopRuntimeErrorTracking()
window.onerror = originalOnErrorHandler
window.onunhandledrejection = originalOnUnhandledRejectionHandler
})

it('should collect unhandled error', (done) => {
Expand All @@ -52,6 +46,11 @@ describe('trackRuntimeError', () => {
if (isIE()) {
pending('no promise support')
}

if (!('onunhandledrejection' in window)) {
pending('onunhandledrejection not supported')
}

disableJasmineUncaughtExceptionTracking()

setTimeout(() => {
Expand Down Expand Up @@ -278,23 +277,23 @@ describe('instrumentOnError', () => {
})

describe('instrumentUnhandledRejection', () => {
let originalOnUnhandledRejectionHandler: Window['onunhandledrejection']
let onUnhandledrejectionSpy: jasmine.Spy
let onUnhandledrejectionSpy: jasmine.Spy | null
let stopCollectingUnhandledError: () => void
let callbackSpy: jasmine.Spy<UnhandledErrorCallback>
const ERROR_MESSAGE = 'foo'

beforeEach(() => {
if (!('onunhandledrejection' in window)) {
pending('onunhandledrejection not supported')
}

callbackSpy = jasmine.createSpy()
originalOnUnhandledRejectionHandler = window.onunhandledrejection
onUnhandledrejectionSpy = jasmine.createSpy()
window.onunhandledrejection = onUnhandledrejectionSpy
onUnhandledrejectionSpy = setupOnUnhandledrejectionSpy()
;({ stop: stopCollectingUnhandledError } = instrumentUnhandledRejection(callbackSpy))
})

afterEach(() => {
window.onunhandledrejection = originalOnUnhandledRejectionHandler
stopCollectingUnhandledError()
stopCollectingUnhandledError?.()
})

it('should call original unhandled rejection handler', () => {
Expand All @@ -315,3 +314,18 @@ describe('instrumentUnhandledRejection', () => {
expect(stack).toBeDefined()
})
})

function setupOnUnhandledrejectionSpy() {
const onUnhandledrejectionSpy = jasmine.createSpy()
const originalOnUnhandledRejectionHandler: Window['onunhandledrejection'] = window.onunhandledrejection

if ('onunhandledrejection' in window) {
window.onunhandledrejection = onUnhandledrejectionSpy

registerCleanupTask(() => {
window.onunhandledrejection = originalOnUnhandledRejectionHandler
})
}

return onUnhandledrejectionSpy
}
11 changes: 10 additions & 1 deletion packages/core/src/tools/instrumentMethod.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('instrumentMethod', () => {
})

it('sets an event handler even if it was originally undefined', () => {
const object: { onevent?: () => void } = {}
const object: { onevent?: () => void } = { onevent: undefined }

const instrumentationSpy = jasmine.createSpy()
instrumentMethod(object, 'onevent', instrumentationSpy)
Expand All @@ -48,6 +48,15 @@ describe('instrumentMethod', () => {
expect(instrumentationSpy).toHaveBeenCalled()
})

it('do not set an event handler even if the event is not supported (i.e. property does not exist on object)', () => {
const object: { onevent?: () => void } = {}

const instrumentationSpy = jasmine.createSpy()
instrumentMethod(object, 'onevent', instrumentationSpy)

expect('onevent' in object).toBeFalse()
})

it('calls the instrumentation with method target and parameters', () => {
const object = { method: (a: number, b: number) => a + b }
const instrumentationSpy = jasmine.createSpy<(call: InstrumentedMethodCall<typeof object, 'method'>) => void>()
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tools/instrumentMethod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function instrumentMethod<TARGET extends { [key: string]: any }, METHOD e
let original = targetPrototype[method]

if (typeof original !== 'function') {
if (startsWith(method, 'on')) {
if (method in targetPrototype && startsWith(method, 'on')) {
original = noop as TARGET[METHOD]
} else {
return { stop: noop }
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tools/serialisation/sanitize.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('sanitize', () => {
const symbolFunction: (description: string) => any = (window as any).Symbol
if (typeof symbolFunction === 'function') {
const symbol = symbolFunction('description')
expect(sanitize(symbol)).toEqual('[Symbol] description')
expect(sanitize(symbol)).toMatch(/\[Symbol\] (?:Symbol\()?description\)?/)
} else {
pending('Symbol is not supported on this browser')
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/test/emulate/mockStorages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export function mockCookie(): MockStorage {
let cookie = ''

return {
getSpy: spyOnProperty(Document.prototype, 'cookie', 'get').and.callFake(() => cookie),
setSpy: spyOnProperty(Document.prototype, 'cookie', 'set').and.callFake((newCookie) => (cookie = newCookie)),
getSpy: spyOnProperty(document, 'cookie', 'get').and.callFake(() => cookie),
setSpy: spyOnProperty(document, 'cookie', 'set').and.callFake((newCookie) => (cookie = newCookie)),
currentValue: () => cookie,
setCurrentValue: (key, newCookie) => (cookie = `${key}=${newCookie}`),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,19 +186,10 @@ describe('computeXhrResponseData', () => {
})

describe('computeFetchResponseText', () => {
let onunhandledrejectionSpy: jasmine.Spy

beforeEach(() => {
if (isIE()) {
pending('IE does not support the fetch API')
}

onunhandledrejectionSpy = jasmine.createSpy()
window.onunhandledrejection = onunhandledrejectionSpy

registerCleanupTask(() => {
window.onunhandledrejection = null
})
})

it('computes response text from Response objects', (done) => {
Expand Down
4 changes: 0 additions & 4 deletions packages/rum-core/src/domain/requestCollection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,10 @@ describe('collect fetch', () => {
;({ stop: stopFetchTracking } = trackFetch(lifeCycle, configuration, tracerStub as Tracer))

fetch = window.fetch as MockFetch
window.onunhandledrejection = (ev: PromiseRejectionEvent) => {
throw new Error(`unhandled rejected promise \n ${ev.reason as string}`)
}

registerCleanupTask(() => {
stopFetchTracking()
mockFetchManager.reset()
window.onunhandledrejection = null
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { LifeCycle, LifeCycleEventType } from '../../lifeCycle'
import { RumPerformanceEntryType } from '../../../browser/performanceObservable'
import type { RumConfiguration } from '../../configuration'
import type { CumulativeLayoutShift } from './trackCumulativeLayoutShift'
import { MAX_WINDOW_DURATION, trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'
import { isLayoutShiftSupported, MAX_WINDOW_DURATION, trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'

interface StartCLSTrackingArgs {
viewStart: RelativeTime
Expand Down Expand Up @@ -41,11 +41,7 @@ describe('trackCumulativeLayoutShift', () => {
}

beforeEach(() => {
if (
!window.PerformanceObserver ||
!PerformanceObserver.supportedEntryTypes ||
!PerformanceObserver.supportedEntryTypes.includes('layout-shift')
) {
if (!isLayoutShiftSupported()) {
pending('No LayoutShift API support')
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export function trackCumulativeLayoutShift(
}

let maxClsValue = 0
// WeakRef is not supported in IE11 and Safari mobile, but so is the layout shift API, so this code won't be executed in these browsers
let maxClsTarget: WeakRef<HTMLElement> | undefined
let maxClsStartTime: Duration | undefined

Expand Down Expand Up @@ -138,5 +137,5 @@ function slidingSessionWindow() {
* Check whether `layout-shift` is supported by the browser.
*/
export function isLayoutShiftSupported() {
return supportPerformanceTimingEvent(RumPerformanceEntryType.LAYOUT_SHIFT)
return supportPerformanceTimingEvent(RumPerformanceEntryType.LAYOUT_SHIFT) && 'WeakRef' in window
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ describe('createRouter', () => {
let router: ReturnType<typeof createMemoryRouter>

beforeEach(() => {
if (!window.AbortController) {
pending('createMemoryRouter rely on AbortController')
}

startViewSpy = jasmine.createSpy()
initializeReactPlugin({
configuration: {
Expand All @@ -22,7 +26,7 @@ describe('createRouter', () => {
})

afterEach(() => {
router.dispose()
router?.dispose()
})

it('creates a new view when the router is created', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ describe('trackViewportResize', () => {
if (isIE()) {
pending('IE not supported')
}

if (!window.visualViewport) {
pending('visualViewport not supported')
}

configuration = { defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW } as RumConfiguration
elementsScrollPositions = createElementsScrollPositions()
visualViewportResizeCallback = jasmine.createSpy()
Expand Down
2 changes: 1 addition & 1 deletion test/browsers.conf.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const browserConfigurations: Array<{
export type BrowserConfigurations = Array<{
sessionName: string
name: string
version?: string
Expand Down
39 changes: 39 additions & 0 deletions test/e2e/browsers.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Capabilities: https://www.browserstack.com/automate/capabilities

/**
* @type {import('../browsers.conf').BrowserConfigurations}
*/
const browserConfigurations = [
{
sessionName: 'Edge',
name: 'Edge',
version: '100.0',
os: 'Windows',
osVersion: '11',
},
{
sessionName: 'Firefox',
name: 'Firefox',
version: '91.0',
os: 'Windows',
osVersion: '11',
},
{
sessionName: 'Safari desktop',
name: 'Safari',
version: '14.1',
os: 'OS X',
osVersion: 'Big Sur',
},
{
sessionName: 'Chrome mobile',
name: 'chrome',
os: 'android',
osVersion: '12.0',
device: 'Google Pixel 6 Pro',
},
]

module.exports = {
browserConfigurations,
}
47 changes: 19 additions & 28 deletions test/e2e/wdio.bs.conf.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,33 @@
import type { Options } from '@wdio/types'
import { browserConfigurations } from '../browsers.conf'
import { getBuildInfos } from '../envUtils'
import { browserConfigurations } from './browsers.conf'
import { config as baseConfig } from './wdio.base.conf'

export const config: Options.Testrunner = {
...baseConfig,

specFileRetries: 1,

capabilities: browserConfigurations
.filter(
(configuration) =>
configuration.sessionName !== 'IE' &&
// Safari mobile on iOS <= 14.0 does not support
// the way we flush events on page change
// TODO check newer version on browserstack
configuration.sessionName !== 'Safari mobile'
)
.map((configuration) =>
// See https://www.browserstack.com/automate/capabilities?tag=selenium-4
// Make sure to look at the "W3C Protocol" tab
({
browserName: configuration.name,
browserVersion: configuration.version,
'bstack:options': {
os: configuration.os,
osVersion: configuration.osVersion,
deviceName: configuration.device,
capabilities: browserConfigurations.map((configuration) =>
// See https://www.browserstack.com/automate/capabilities?tag=selenium-4
// Make sure to look at the "W3C Protocol" tab
({
browserName: configuration.name,
browserVersion: configuration.version,
'bstack:options': {
os: configuration.os,
osVersion: configuration.osVersion,
deviceName: configuration.device,

appiumVersion: '1.22.0',
seleniumVersion: '4.1.2',
appiumVersion: '1.22.0',
seleniumVersion: '4.1.2',

sessionName: configuration.sessionName,
projectName: 'browser sdk e2e',
buildName: getBuildInfos(),
},
})
),
sessionName: configuration.sessionName,
projectName: 'browser sdk e2e',
buildName: getBuildInfos(),
},
})
),
logLevels: {
'@wdio/browserstack-service': 'info',
},
Expand Down
Loading

0 comments on commit 9d19ead

Please sign in to comment.