Skip to content

Commit 5d41853

Browse files
committed
add tests
1 parent 62d9d07 commit 5d41853

File tree

3 files changed

+188
-22
lines changed

3 files changed

+188
-22
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<button data-log>Log button</button>
8+
<button data-log-large>Log button</button>
9+
10+
<script>
11+
const massiveObject = createLargeObject(10);
12+
13+
document.querySelector('[data-log]').addEventListener('click', () => {
14+
console.log('Test log', document.body);
15+
});
16+
17+
function createLargeObject(remainingDepth) {
18+
const massiveObject = {};
19+
20+
for (let i = 0; i < 3; i++) {
21+
const item = {
22+
aa: remainingDepth > 0 ? createLargeObject(remainingDepth - 1) : 'a'.repeat(50),
23+
bb: 'b'.repeat(50),
24+
cc: 'c'.repeat(50),
25+
dd: 'd'.repeat(50),
26+
};
27+
28+
massiveObject[`item-${i}`] = item;
29+
}
30+
31+
return massiveObject;
32+
}
33+
34+
document.querySelector('[data-log-large]').addEventListener('click', () => {
35+
console.log(massiveObject);
36+
});
37+
</script>
38+
</body>
39+
</html>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../utils/fixtures';
4+
import { getCustomRecordingEvents, shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers';
5+
6+
sentryTest('should capture console messages in replay', async ({ getLocalTestPath, page, forceFlushReplay }) => {
7+
// console integration is not used in bundles/loader
8+
const bundle = process.env.PW_BUNDLE || '';
9+
if (shouldSkipReplayTest() || bundle.startsWith('bundle_') || bundle.startsWith('loader_')) {
10+
sentryTest.skip();
11+
}
12+
13+
const reqPromise0 = waitForReplayRequest(page, 0);
14+
15+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
16+
return route.fulfill({
17+
status: 200,
18+
contentType: 'application/json',
19+
body: JSON.stringify({ id: 'test-id' }),
20+
});
21+
});
22+
23+
const url = await getLocalTestPath({ testDir: __dirname });
24+
25+
await page.goto(url);
26+
await reqPromise0;
27+
28+
const reqPromise1 = waitForReplayRequest(
29+
page,
30+
(_event, res) => {
31+
const { breadcrumbs } = getCustomRecordingEvents(res);
32+
33+
return breadcrumbs.filter(breadcrumb => breadcrumb.category === 'console').length > 0;
34+
},
35+
5_000,
36+
);
37+
38+
await page.click('[data-log]');
39+
40+
await forceFlushReplay();
41+
42+
const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1);
43+
44+
expect(breadcrumbs.filter(breadcrumb => breadcrumb.category === 'console')).toEqual([
45+
{
46+
timestamp: expect.any(Number),
47+
type: 'default',
48+
category: 'console',
49+
data: { arguments: ['Test log', '[HTMLElement: HTMLBodyElement]'], logger: 'console' },
50+
level: 'log',
51+
message: 'Test log [object HTMLBodyElement]',
52+
},
53+
]);
54+
});
55+
56+
sentryTest('should capture very large console logs', async ({ getLocalTestPath, page, forceFlushReplay }) => {
57+
// console integration is not used in bundles/loader
58+
const bundle = process.env.PW_BUNDLE || '';
59+
if (shouldSkipReplayTest() || bundle.startsWith('bundle_') || bundle.startsWith('loader_')) {
60+
sentryTest.skip();
61+
}
62+
63+
const reqPromise0 = waitForReplayRequest(page, 0);
64+
65+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
66+
return route.fulfill({
67+
status: 200,
68+
contentType: 'application/json',
69+
body: JSON.stringify({ id: 'test-id' }),
70+
});
71+
});
72+
73+
const url = await getLocalTestPath({ testDir: __dirname });
74+
75+
await page.goto(url);
76+
await reqPromise0;
77+
78+
const reqPromise1 = waitForReplayRequest(
79+
page,
80+
(_event, res) => {
81+
const { breadcrumbs } = getCustomRecordingEvents(res);
82+
83+
return breadcrumbs.filter(breadcrumb => breadcrumb.category === 'console').length > 0;
84+
},
85+
5_000,
86+
);
87+
88+
await page.click('[data-log-large]');
89+
90+
await forceFlushReplay();
91+
92+
const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1);
93+
94+
expect(breadcrumbs.filter(breadcrumb => breadcrumb.category === 'console')).toEqual([
95+
{
96+
timestamp: expect.any(Number),
97+
type: 'default',
98+
category: 'console',
99+
data: {
100+
arguments: [
101+
expect.objectContaining({
102+
'item-0': {
103+
aa: expect.objectContaining({
104+
'item-0': {
105+
aa: expect.any(Object),
106+
bb: expect.any(String),
107+
cc: expect.any(String),
108+
dd: expect.any(String),
109+
},
110+
}),
111+
bb: expect.any(String),
112+
cc: expect.any(String),
113+
dd: expect.any(String),
114+
},
115+
}),
116+
],
117+
logger: 'console',
118+
},
119+
level: 'log',
120+
message: '[object Object]',
121+
},
122+
]);
123+
});

packages/browser-integration-tests/utils/replayHelpers.ts

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,38 +49,42 @@ export type RecordingSnapshot = FullRecordingSnapshot | IncrementalRecordingSnap
4949
export function waitForReplayRequest(
5050
page: Page,
5151
segmentIdOrCallback?: number | ((event: ReplayEvent, res: Response) => boolean),
52+
timeout?: number,
5253
): Promise<Response> {
5354
const segmentId = typeof segmentIdOrCallback === 'number' ? segmentIdOrCallback : undefined;
5455
const callback = typeof segmentIdOrCallback === 'function' ? segmentIdOrCallback : undefined;
5556

56-
return page.waitForResponse(res => {
57-
const req = res.request();
57+
return page.waitForResponse(
58+
res => {
59+
const req = res.request();
5860

59-
const postData = req.postData();
60-
if (!postData) {
61-
return false;
62-
}
63-
64-
try {
65-
const event = envelopeRequestParser(req);
66-
67-
if (!isReplayEvent(event)) {
61+
const postData = req.postData();
62+
if (!postData) {
6863
return false;
6964
}
7065

71-
if (callback) {
72-
return callback(event, res);
73-
}
66+
try {
67+
const event = envelopeRequestParser(req);
7468

75-
if (segmentId !== undefined) {
76-
return event.segment_id === segmentId;
77-
}
69+
if (!isReplayEvent(event)) {
70+
return false;
71+
}
7872

79-
return true;
80-
} catch {
81-
return false;
82-
}
83-
});
73+
if (callback) {
74+
return callback(event, res);
75+
}
76+
77+
if (segmentId !== undefined) {
78+
return event.segment_id === segmentId;
79+
}
80+
81+
return true;
82+
} catch {
83+
return false;
84+
}
85+
},
86+
timeout ? { timeout } : undefined,
87+
);
8488
}
8589

8690
export function isReplayEvent(event: Event): event is ReplayEvent {

0 commit comments

Comments
 (0)