Skip to content

Commit b61d820

Browse files
AbhiPrasadmydea
andauthored
test(browser): Port builtin tests to playwright (#11733)
This ports `packages/browser/test/integration/suites/builtins.js` to playwright. It also re-organizes the `eventListener` test structure to be a little more organized. The new test suites added are instrumentation for `xhr` and `requestAnimationFrame` Co-authored-by: Francesco Novy <[email protected]>
1 parent 0a440dd commit b61d820

File tree

30 files changed

+315
-332
lines changed

30 files changed

+315
-332
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
});
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect } from '@playwright/test';
22

3-
import { sentryTest } from '../../../../utils/fixtures';
3+
import { sentryTest } from '../../../../../utils/fixtures';
44

55
sentryTest(
66
'Event listener instrumentation should attach the same event listener only once',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function clickHandler() {
2+
throw new Error('event_listener_error');
3+
}
4+
5+
window.addEventListener('click', clickHandler);
6+
7+
document.body.click();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
6+
7+
sentryTest('should capture built-in handlers fn name in mechanism data', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
11+
12+
expect(eventData.exception?.values).toHaveLength(1);
13+
expect(eventData.exception?.values?.[0]).toMatchObject({
14+
type: 'Error',
15+
value: 'event_listener_error',
16+
mechanism: {
17+
type: 'instrument',
18+
handled: false,
19+
data: {
20+
function: 'addEventListener',
21+
handler: 'clickHandler',
22+
target: 'EventTarget',
23+
},
24+
},
25+
stacktrace: {
26+
frames: expect.any(Array),
27+
},
28+
});
29+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// store references to original, unwrapped built-ins in order to make assertions re: wrapped functions
2+
window.originalBuiltIns = {
3+
addEventListener: document.addEventListener,
4+
};
5+
6+
import * as Sentry from '@sentry/browser';
7+
8+
window.Sentry = Sentry;
9+
10+
Sentry.init({
11+
dsn: 'https://[email protected]/1337',
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const div = document.createElement('div');
2+
document.body.appendChild(div);
3+
window.capturedCall = false;
4+
const captureFn = function () {
5+
window.capturedCall = true;
6+
};
7+
// Use original addEventListener to simulate non-wrapped behavior (callback is attached without __sentry_wrapped__)
8+
window.originalBuiltIns.addEventListener.call(div, 'click', captureFn);
9+
// Then attach the same callback again, but with already wrapped method
10+
div.addEventListener('click', captureFn);
11+
div.removeEventListener('click', captureFn);
12+
div.dispatchEvent(new MouseEvent('click'));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../../../utils/fixtures';
4+
5+
sentryTest(
6+
'should remove the original callback if it was registered before Sentry initialized (w. original method)',
7+
async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
await page.goto(url);
11+
12+
const capturedCalled = await page.evaluate(() => {
13+
// @ts-expect-error defined in subject.js
14+
return window.capturedCall;
15+
});
16+
17+
expect(capturedCalled).toBe(false);
18+
},
19+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const div = document.createElement('div');
2+
document.body.appendChild(div);
3+
const fooFn = function () {
4+
throw new Error('foo');
5+
};
6+
const barFn = function () {
7+
throw new Error('bar');
8+
};
9+
div.addEventListener('click', fooFn);
10+
div.addEventListener('click', barFn);
11+
div.removeEventListener('click', barFn);
12+
div.dispatchEvent(new MouseEvent('click'));
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
6+
7+
sentryTest('should transparently remove event listeners from wrapped functions', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
11+
12+
expect(eventData.exception?.values).toHaveLength(1);
13+
expect(eventData.exception?.values?.[0]).toMatchObject({
14+
type: 'Error',
15+
value: 'foo',
16+
mechanism: {
17+
type: 'instrument',
18+
handled: false,
19+
},
20+
stacktrace: {
21+
frames: expect.any(Array),
22+
},
23+
});
24+
});

0 commit comments

Comments
 (0)