Skip to content

Commit b64b2ae

Browse files
AbhiPrasadLms24
andauthored
test: Port onerror tests to playwright (#11666)
This ports `packages/browser/test/integration/suites/onerror.js` to playwright. Because I couldn't throw top level errors without generating script errors, I elected to simulate `window.onerror` being called. Co-authored-by: Lukas Stracke <[email protected]>
1 parent c90048f commit b64b2ae

File tree

19 files changed

+239
-176
lines changed

19 files changed

+239
-176
lines changed
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+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
function run() {
2+
window.onerror({
3+
type: 'error',
4+
otherKey: 'hi',
5+
});
6+
}
7+
8+
run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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(
8+
'should catch onerror calls with non-string first argument gracefully',
9+
async ({ getLocalTestPath, page }) => {
10+
const url = await getLocalTestPath({ testDir: __dirname });
11+
12+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
13+
14+
expect(eventData.exception?.values).toHaveLength(1);
15+
expect(eventData.exception?.values?.[0]).toMatchObject({
16+
type: 'Error',
17+
value: 'Object captured as exception with keys: otherKey, type',
18+
mechanism: {
19+
type: 'onerror',
20+
handled: false,
21+
},
22+
stacktrace: {
23+
frames: expect.any(Array),
24+
},
25+
});
26+
},
27+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function run() {
2+
try {
3+
try {
4+
foo();
5+
} catch (e) {
6+
Sentry.captureException(e);
7+
throw e; // intentionally re-throw
8+
}
9+
} catch (e) {
10+
// simulate window.onerror without generating a Script error
11+
window.onerror('error', 'file.js', 1, 1, e);
12+
}
13+
}
14+
15+
run();
16+
17+
Sentry.captureException(new Error('error 2'));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getMultipleSentryEnvelopeRequests } from '../../../../../utils/helpers';
6+
7+
sentryTest(
8+
'should NOT catch an exception already caught [but rethrown] via Sentry.captureException',
9+
async ({ getLocalTestPath, page }) => {
10+
const url = await getLocalTestPath({ testDir: __dirname });
11+
12+
const events = await getMultipleSentryEnvelopeRequests<Event>(page, 2, { url });
13+
14+
expect(events[0].exception?.values).toHaveLength(1);
15+
expect(events[0].exception?.values?.[0]).toMatchObject({
16+
type: 'ReferenceError',
17+
// this exact error message varies between browsers, but they should all reference 'foo'
18+
value: expect.stringContaining('foo'),
19+
mechanism: {
20+
type: 'generic',
21+
handled: true,
22+
},
23+
stacktrace: {
24+
frames: expect.any(Array),
25+
},
26+
});
27+
28+
// This is not a refernece error, but another generic error
29+
expect(events[1].exception?.values).toHaveLength(1);
30+
expect(events[1].exception?.values?.[0]).toMatchObject({
31+
type: 'Error',
32+
value: 'error 2',
33+
mechanism: {
34+
type: 'generic',
35+
handled: true,
36+
},
37+
stacktrace: {
38+
frames: expect.any(Array),
39+
},
40+
});
41+
},
42+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function run() {
2+
try {
3+
eval('foo{};');
4+
} catch (e) {
5+
// simulate window.onerror without generating a Script error
6+
window.onerror('error', 'file.js', 1, 1, e);
7+
}
8+
}
9+
10+
run();
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 catch syntax errors', 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: 'SyntaxError',
15+
value: "Unexpected token '{'",
16+
mechanism: {
17+
type: 'onerror',
18+
handled: false,
19+
},
20+
stacktrace: {
21+
frames: expect.any(Array),
22+
},
23+
});
24+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function run() {
2+
try {
3+
throw new Error('realError');
4+
} catch (e) {
5+
// simulate window.onerror without generating a Script error
6+
window.onerror('error', 'file.js', 1, 1, e);
7+
}
8+
}
9+
10+
run();
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 catch thrown errors', 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: 'realError',
16+
mechanism: {
17+
type: 'onerror',
18+
handled: false,
19+
},
20+
stacktrace: {
21+
frames: expect.any(Array),
22+
},
23+
});
24+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function run() {
2+
try {
3+
throw { error: 'stuff is broken', somekey: 'ok' };
4+
} catch (e) {
5+
// simulate window.onerror without generating a Script error
6+
window.onerror('error', 'file.js', 1, 1, e);
7+
}
8+
}
9+
10+
run();
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 catch thrown objects', 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: 'Object captured as exception with keys: error, somekey',
16+
mechanism: {
17+
type: 'onerror',
18+
handled: false,
19+
},
20+
stacktrace: {
21+
frames: expect.any(Array),
22+
},
23+
});
24+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function run() {
2+
try {
3+
throw 'stringError';
4+
} catch (e) {
5+
// simulate window.onerror without generating a Script error
6+
window.onerror('error', 'file.js', 1, 1, e);
7+
}
8+
}
9+
10+
run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 catch thrown strings', 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: 'stringError',
16+
mechanism: {
17+
type: 'onerror',
18+
handled: false,
19+
},
20+
stacktrace: {
21+
frames: expect.any(Array),
22+
},
23+
});
24+
25+
expect(eventData.exception?.values?.[0].stacktrace?.frames).toHaveLength(1);
26+
});

packages/browser/test/integration/subjects/console-logs.js

-13
This file was deleted.

packages/browser/test/integration/subjects/throw-error.js

-4
This file was deleted.

packages/browser/test/integration/subjects/throw-object.js

-7
This file was deleted.

packages/browser/test/integration/subjects/throw-string.js

-5
This file was deleted.

0 commit comments

Comments
 (0)