Skip to content

Commit 19b0cc4

Browse files
committed
Add onerror tests.
1 parent f6b6b3d commit 19b0cc4

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
const { test, expect } = require('@playwright/test');
2+
const Sentry = require('@sentry/browser');
3+
4+
const { getSentryEvents } = require('./utils/helpers');
5+
6+
test.describe('window.onerror', () => {
7+
test.beforeEach(async ({ baseURL, page }) => {
8+
await page.goto(baseURL);
9+
});
10+
11+
test('should catch syntax errors', async ({ page }) => {
12+
const eventData = await getSentryEvents(page, () => {
13+
eval('foo{};');
14+
});
15+
16+
expect(eventData[0].exception.values[0].type).toMatch(/SyntaxError/);
17+
// Frame count test is skipped for this one
18+
// because what we get from an `eval` inside `getSentryEvents`
19+
// is not just from `eval`'s context.
20+
});
21+
test('should catch thrown strings', async ({ page }) => {
22+
const eventData = await getSentryEvents(page, () => {
23+
function throwStringError() {
24+
throw 'stringError';
25+
}
26+
27+
throwStringError();
28+
});
29+
30+
expect(eventData[0].exception.values[0].value).toMatch(/stringError$/);
31+
expect(eventData[0].exception.values[0].stacktrace.frames).toHaveLength(1);
32+
expect(eventData[0].exception.values[0].stacktrace.frames[0]['function']).toMatch(
33+
/throwStringError|\?|global code/i,
34+
);
35+
});
36+
37+
test('should catch thrown objects', async ({ page }) => {
38+
const eventData = await getSentryEvents(page, () => {
39+
function throwObjectError() {
40+
// never do this; just making sure Raven.js handles this case
41+
// gracefully2
42+
throw { error: 'stuff is broken', somekey: 'ok' };
43+
}
44+
45+
throwObjectError();
46+
});
47+
48+
expect(eventData[0].exception.values[0].value).toBe('Non-Error exception captured with keys: error, somekey');
49+
expect(eventData[0].exception.values[0].stacktrace.frames).toHaveLength(1);
50+
expect(eventData[0].exception.values[0].stacktrace.frames[0]['function']).toMatch(
51+
/throwObjectError|\?|global code/i,
52+
);
53+
});
54+
55+
test('should catch thrown errors', async ({ page }) => {
56+
const eventData = await getSentryEvents(page, () => {
57+
function throwRealError() {
58+
throw new Error('realError');
59+
}
60+
throwRealError();
61+
});
62+
63+
expect(eventData[0].exception.values[0].type).toMatch(/^Error/);
64+
expect(eventData[0].exception.values[0].value).toMatch(/realError$/);
65+
// FIXME: Frames inconsistent due to how `getSentryEvents` injects code into browser.
66+
// expect(eventData[0].exception.values[0].stacktrace.frames.length).toBeGreaterThanOrEqual(1);
67+
// expect(eventData[0].exception.values[0].stacktrace.frames.length).toBeLessThanOrEqual(2);
68+
// expect(eventData[0].exception.values[0].stacktrace.frames[0]['function']).toMatch(/\?|global code|throwRealError/i);
69+
});
70+
71+
test('should onerror calls with non-string first argument gracefully', async ({ page }) => {
72+
const eventData = await getSentryEvents(page, () => {
73+
window.onerror({
74+
type: 'error',
75+
otherKey: 'hi',
76+
});
77+
});
78+
79+
expect(eventData[0].exception.values[0].type).toBe('Error');
80+
expect(eventData[0].exception.values[0].value).toBe('Non-Error exception captured with keys: otherKey, type');
81+
expect(eventData[0].extra.__serialized__).toMatchObject({
82+
type: 'error',
83+
otherKey: 'hi',
84+
});
85+
});
86+
87+
test('should NOT catch an exception already caught [but rethrown] via Sentry.captureException', async ({ page }) => {
88+
const eventData = await getSentryEvents(page, () => {
89+
try {
90+
// eslint-disable-next-line no-undef
91+
foo();
92+
} catch (e) {
93+
Sentry.captureException(e);
94+
throw e; // intentionally re-throw
95+
}
96+
});
97+
98+
expect(eventData).toHaveLength(1);
99+
});
100+
});

0 commit comments

Comments
 (0)