Skip to content

Commit

Permalink
ref(test): Trigger top-level errors inside sandbox.
Browse files Browse the repository at this point in the history
  • Loading branch information
onurtemizkan committed Apr 22, 2024
1 parent 9a7e276 commit babbed8
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 133 deletions.
6 changes: 3 additions & 3 deletions dev-packages/browser-integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ or `init.js` is not defined in a case folder.

`subject.js` contains the logic that sets up the environment to be tested. It also can be defined locally and as a group
fallback. Unlike `template.hbs` and `init.js`, it's not required to be defined for a group, as there may be cases that
does not require a subject, instead the logic is injected using `injectScriptAndGetEvents` from `utils/helpers.ts`.
does not require a subject.

`test.ts` is required for each test case, which contains the assertions (and if required the script injection logic).
For every case, any set of `init.js`, `template.hbs` and `subject.js` can be defined locally, and each one of them will
have precedence over the default definitions of the test group.

To test page multi-page navigations, you can specify additional `page-*.html` (e.g. `page-0.html`, `page-1.html`) files.
These will also be compiled and initialized with the same `init.js` and `subject.js` files that are applied to
`template.hbs/html`. Note: `page-*.html` file lookup **doesn not** fall back to the parent directories, meaning that
page files have to be directly in the `test.ts` directory.
`template.hbs/html`. Note: `page-*.html` file lookup **does not** fall back to the parent directories, meaning that page
files have to be directly in the `test.ts` directory.

```
suites/
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
import { getFirstSentryEnvelopeRequest, runScriptInSandbox } from '../../../../../utils/helpers';

sentryTest(
'should catch onerror calls with non-string first argument gracefully',
async ({ getLocalTestPath, page }) => {
const url = await getLocalTestPath({ testDir: __dirname });

const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
await page.goto(url);

runScriptInSandbox(page, {
content: `
throw {
type: 'Error',
otherKey: 'otherValue',
};
`,
});

const eventData = await getFirstSentryEnvelopeRequest<Event>(page);

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../../utils/fixtures';
import { getMultipleSentryEnvelopeRequests } from '../../../../../utils/helpers';
import { getMultipleSentryEnvelopeRequests, runScriptInSandbox } from '../../../../../utils/helpers';

sentryTest(
'should NOT catch an exception already caught [but rethrown] via Sentry.captureException',
async ({ getLocalTestPath, page }) => {
const url = await getLocalTestPath({ testDir: __dirname });

const events = await getMultipleSentryEnvelopeRequests<Event>(page, 2, { url });
await page.goto(url);

runScriptInSandbox(page, {
content: `
try {
foo();
} catch (e) {
Sentry.captureException(e);
throw e;
}
`,
});

const events = await getMultipleSentryEnvelopeRequests<Event>(page, 1);

expect(events[0].exception?.values).toHaveLength(1);
expect(events[0].exception?.values?.[0]).toMatchObject({
Expand All @@ -24,19 +37,5 @@ sentryTest(
frames: expect.any(Array),
},
});

// This is not a refernece error, but another generic error
expect(events[1].exception?.values).toHaveLength(1);
expect(events[1].exception?.values?.[0]).toMatchObject({
type: 'Error',
value: 'error 2',
mechanism: {
type: 'generic',
handled: true,
},
stacktrace: {
frames: expect.any(Array),
},
});
},
);

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
import { getFirstSentryEnvelopeRequest, runScriptInSandbox } from '../../../../../utils/helpers';

sentryTest('should catch syntax errors', async ({ getLocalTestPath, page }) => {
const url = await getLocalTestPath({ testDir: __dirname });

const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
await page.goto(url);

runScriptInSandbox(page, {
content: `
foo{}; // SyntaxError
`,
});

const eventData = await getFirstSentryEnvelopeRequest<Event>(page);

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
import { getFirstSentryEnvelopeRequest, runScriptInSandbox } from '../../../../../utils/helpers';

sentryTest('should catch thrown errors', async ({ getLocalTestPath, page }) => {
const url = await getLocalTestPath({ testDir: __dirname });

const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
await page.goto(url);

runScriptInSandbox(page, {
content: `
throw new Error('realError');
`,
});

const eventData = await getFirstSentryEnvelopeRequest<Event>(page);

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
import { getFirstSentryEnvelopeRequest, runScriptInSandbox } from '../../../../../utils/helpers';

sentryTest('should catch thrown objects', async ({ getLocalTestPath, page }) => {
const url = await getLocalTestPath({ testDir: __dirname });

const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
await page.goto(url);

runScriptInSandbox(page, {
content: `
throw {
error: 'stuff is broken',
somekey: 'ok'
};`,
});

const eventData = await getFirstSentryEnvelopeRequest<Event>(page);

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
import { getFirstSentryEnvelopeRequest, runScriptInSandbox } from '../../../../../utils/helpers';

sentryTest('should catch thrown strings', async ({ getLocalTestPath, page }) => {
const url = await getLocalTestPath({ testDir: __dirname });

const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
await page.goto(url);

runScriptInSandbox(page, {
content: `
throw 'stringError';
`,
});

const eventData = await getFirstSentryEnvelopeRequest<Event>(page);

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,34 @@ import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

import { sentryTest } from '../../../../utils/fixtures';
import { getMultipleSentryEnvelopeRequests, shouldSkipTracingTest } from '../../../../utils/helpers';
import {
getMultipleSentryEnvelopeRequests,
runScriptInSandbox,
shouldSkipTracingTest,
} from '../../../../utils/helpers';

sentryTest('should capture an error within a sync startSpan callback', async ({ getLocalTestPath, page }) => {
if (shouldSkipTracingTest()) {
sentryTest.skip();
}

const url = await getLocalTestPath({ testDir: __dirname });
const gotoPromise = page.goto(url);
const envelopePromise = getMultipleSentryEnvelopeRequests<Event>(page, 2);
await page.goto(url);

runScriptInSandbox(page, {
content: `
function run() {
Sentry.startSpan({ name: 'parent_span' }, () => {
throw new Error('Sync Error');
});
}
setTimeout(run);
`,
});

const events = await getMultipleSentryEnvelopeRequests<Event>(page, 2);

const [, events] = await Promise.all([gotoPromise, envelopePromise]);
const txn = events.find(event => event.type === 'transaction');
const err = events.find(event => !event.type);

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';
import { sentryTest } from '../../../../utils/fixtures';
import { getMultipleSentryEnvelopeRequests, shouldSkipTracingTest } from '../../../../utils/helpers';
import {
getMultipleSentryEnvelopeRequests,
runScriptInSandbox,
shouldSkipTracingTest,
} from '../../../../utils/helpers';

sentryTest(
'should put the pageload transaction name onto an error event caught during pageload',
Expand All @@ -14,6 +18,12 @@ sentryTest(

await page.goto(url);

runScriptInSandbox(page, {
content: `
throw new Error('Error during pageload');
`,
});

const [e1, e2] = await getMultipleSentryEnvelopeRequests<Event>(page, 2);

const pageloadTxnEvent = e1.type === 'transaction' ? e1 : e2;
Expand Down
35 changes: 13 additions & 22 deletions dev-packages/browser-integration-tests/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,17 @@ export const countEnvelopes = async (
* Run script at the given path inside the test environment.
*
* @param {Page} page
* @param {string} path
* @param {{ path?: string; content?: string }} impl
* @return {*} {Promise<void>}
*/
async function runScriptInSandbox(page: Page, path: string): Promise<void> {
await page.addScriptTag({ path });
async function runScriptInSandbox(
page: Page,
impl: {
path?: string;
content?: string;
},
): Promise<void> {
await page.addScriptTag({ path: impl.path, content: impl.content });
}

/**
Expand Down Expand Up @@ -333,26 +339,11 @@ async function getFirstSentryEnvelopeRequest<T>(
}

/**
* Manually inject a script into the page of given URL.
* This function is useful to create more complex test subjects that can't be achieved by pre-built pages.
* The given script should be vanilla browser JavaScript
* Trigger an error in the page context.
* This function is useful to test error handling in the page.
*
* @param {Page} page
* @param {string} url
* @param {string} scriptPath
* @return {*} {Promise<Array<Event>>}
* @param {unknown} error
*/
async function injectScriptAndGetEvents(page: Page, url: string, scriptPath: string): Promise<Array<Event>> {
await page.goto(url);
await runScriptInSandbox(page, scriptPath);

return getSentryEvents(page);
}

export {
runScriptInSandbox,
getMultipleSentryEnvelopeRequests,
getFirstSentryEnvelopeRequest,
getSentryEvents,
injectScriptAndGetEvents,
};
export { runScriptInSandbox, getMultipleSentryEnvelopeRequests, getFirstSentryEnvelopeRequest, getSentryEvents };

0 comments on commit babbed8

Please sign in to comment.