Skip to content

Commit

Permalink
test: Port breadcrumb tests from karma runner (getsentry#11436)
Browse files Browse the repository at this point in the history
I want to remove the karma/mocha based tests in the browser package. To
accomplish this, I'll be porting 1 test suite a day from the old
integration tests to playwright. Today is Day 2:
`packages/browser/test/integration/suites/breadcrumbs.js`

This adds console and history breadcrumb tests (which didn't exist
before), and expands upon the dom and xhr/fetch tests, and cleans up
some code here and there as well.

ref getsentry#11084
day 1: getsentry#11412
  • Loading branch information
AbhiPrasad authored and cadesalaberry committed Apr 19, 2024
1 parent f98e855 commit cfeb509
Show file tree
Hide file tree
Showing 20 changed files with 317 additions and 791 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
console.log('One');
console.warn('Two', { a: 1 });
console.error('Error 2', { b: { c: [] } });

// Passed assertions _should not_ be captured
console.assert(1 + 1 === 2, 'math works');
// Failed assertions _should_ be captured
console.assert(1 + 1 === 3, 'math broke');

Sentry.captureException('test exception');
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/browser';

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

sentryTest('should capture console breadcrumbs', async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });

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

expect(eventData.breadcrumbs).toEqual([
{
category: 'console',
data: { arguments: ['One'], logger: 'console' },
level: 'log',
message: 'One',
timestamp: expect.any(Number),
},
{
category: 'console',
data: { arguments: ['Two', { a: 1 }], logger: 'console' },
level: 'warning',
message: 'Two [object Object]',
timestamp: expect.any(Number),
},
{
category: 'console',
data: { arguments: ['Error 2', { b: '[Object]' }], logger: 'console' },
level: 'error',
message: 'Error 2 [object Object]',
timestamp: expect.any(Number),
},
{
category: 'console',
data: {
arguments: ['math broke'],
logger: 'console',
},
level: 'log',
message: 'Assertion failed: math broke',
timestamp: expect.any(Number),
},
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
defaultIntegrations: false,
integrations: [Sentry.breadcrumbsIntegration()],
sampleRate: 1,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const click = new MouseEvent('click');
function kaboom() {
throw new Error('lol');
}
Object.defineProperty(click, 'target', { get: kaboom });
const input = document.getElementById('input1');
input.dispatchEvent(click);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input id="input1" type="text" />
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/browser';

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

// see: https://github.com/getsentry/sentry-javascript/issues/768
sentryTest(
'should record breadcrumb if accessing the target property of an event throws an exception',
async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });

await page.goto(url);

const promise = getFirstSentryEnvelopeRequest<Event>(page);

await page.locator('#input1').pressSequentially('test', { delay: 1 });

await page.evaluate('Sentry.captureException("test exception")');

const eventData = await promise;

expect(eventData.breadcrumbs).toHaveLength(1);
expect(eventData.breadcrumbs).toEqual([
{
category: 'ui.input',
message: 'body > input#input1[type="text"]',
timestamp: expect.any(Number),
},
]);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const input = document.getElementsByTagName('input')[0];
input.addEventListener('build', function (evt) {
evt.stopPropagation();
});

const customEvent = new CustomEvent('build', { detail: 1 });
input.dispatchEvent(customEvent);

Sentry.captureException('test exception');
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input id="input1" type="text" />
<input id="input2" type="text" />
<input id="annotated-input" data-sentry-component="AnnotatedInput" type="text" />
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

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

sentryTest('breadcrumbs listener should not fail with custom event', async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });

let error = undefined;
page.on('pageerror', err => {
error = err;
});

const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.breadcrumbs).toBeUndefined();
expect(error).toBeUndefined();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input id="input1" type="text" />
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/browser';

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

sentryTest(
'should correctly capture multiple consecutive breadcrumbs if they are of different type',
async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });

await page.goto(url);

const promise = getFirstSentryEnvelopeRequest<Event>(page);

// These inputs will be debounced
await page.locator('#input1').pressSequentially('abc', { delay: 1 });
await page.locator('#input1').pressSequentially('def', { delay: 1 });
await page.locator('#input1').pressSequentially('ghi', { delay: 1 });

await page.locator('#input1').click();
await page.locator('#input1').click();
await page.locator('#input1').click();

// This input should not be debounced
await page.locator('#input1').pressSequentially('jkl', { delay: 1 });

await page.evaluate('Sentry.captureException("test exception")');

const eventData = await promise;

expect(eventData.breadcrumbs).toEqual([
{
category: 'ui.input',
message: 'body > input#input1[type="text"]',
timestamp: expect.any(Number),
},
{
category: 'ui.click',
message: 'body > input#input1[type="text"]',
timestamp: expect.any(Number),
},
{
category: 'ui.input',
message: 'body > input#input1[type="text"]',
timestamp: expect.any(Number),
},
]);
},
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const xhr = new XMLHttpRequest();

fetch('http://localhost:7654/foo').then(() => {
Sentry.captureException('test error');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fetch(new Request('http://localhost:7654/foo')).then(() => {
Sentry.captureException('test error');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/types';

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

sentryTest('captures Breadcrumb for basic GET request that uses request object', async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });

await page.route('**/foo', route => {
return route.fulfill({
status: 200,
body: JSON.stringify({
userNames: ['John', 'Jane'],
}),
headers: {
'Content-Type': 'application/json',
},
});
});

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

expect(eventData.exception?.values).toHaveLength(1);

expect(eventData?.breadcrumbs?.length).toBe(1);
expect(eventData!.breadcrumbs![0]).toEqual({
timestamp: expect.any(Number),
category: 'fetch',
type: 'http',
data: {
method: 'GET',
status_code: 200,
url: 'http://localhost:7654/foo',
},
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const xhr = new XMLHttpRequest();

fetch('http://localhost:7654/foo', {
method: 'POST',
body: '{"my":"body"}',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
defaultIntegrations: false,
integrations: [Sentry.breadcrumbsIntegration()],
sampleRate: 1,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
history.pushState({}, '', '/foo');
history.pushState({}, '', '/bar?a=1#fragment');
history.pushState({}, '', {});
history.pushState({}, '', null);
history.replaceState({}, '', '/bar?a=1#fragment');

Sentry.captureException('test exception');
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/browser';

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

sentryTest('should record history changes as navigation breadcrumbs', async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });

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

expect(eventData.breadcrumbs).toEqual([
{
category: 'navigation',
data: {
from: '/index.html',
to: '/foo',
},
timestamp: expect.any(Number),
},
{
category: 'navigation',
data: {
from: '/foo',
to: '/bar?a=1#fragment',
},
timestamp: expect.any(Number),
},
{
category: 'navigation',
data: {
from: '/bar?a=1#fragment',
to: '[object Object]',
},
timestamp: expect.any(Number),
},
{
category: 'navigation',
data: {
from: '[object Object]',
to: '/bar?a=1#fragment',
},
timestamp: expect.any(Number),
},
]);
});
Loading

0 comments on commit cfeb509

Please sign in to comment.