Skip to content

Commit 17c3132

Browse files
authored
test(replay): Add integration test for privacy (#7055)
Adds an integration test for default privacy settings.
1 parent 274f489 commit 17c3132

File tree

4 files changed

+303
-2
lines changed

4 files changed

+303
-2
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { Replay } from '@sentry/replay';
3+
4+
window.Sentry = Sentry;
5+
window.Replay = new Replay({
6+
flushMinDelay: 200,
7+
flushMaxDelay: 200,
8+
useCompression: false,
9+
});
10+
11+
Sentry.init({
12+
dsn: 'https://[email protected]/1337',
13+
sampleRate: 0,
14+
replaysSessionSampleRate: 1.0,
15+
replaysOnErrorSampleRate: 0.0,
16+
17+
integrations: [window.Replay],
18+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head><meta charset="utf-8" /></head>
4+
<body>
5+
<button aria-label="Click me" onclick="console.log('Test log')">Click me</button>
6+
<div>This should be masked by default</div>
7+
<div data-sentry-unmask>This should be unmasked due to data attribute</div>
8+
<input placeholder="Placeholder should be masked" />
9+
<div title="Title should be masked">Title should be masked</div>
10+
<svg style="width:200px;height:200px" viewBox="0 0 80 80"><path d=""/></svg>
11+
<svg style="width:200px;height:200px" class="sentry-unblock" viewBox="0 0 80 80" data-sentry-unblock><path d=""/></svg>
12+
<img style="width:100px;height:100px" src="file:///none.png" />
13+
<img data-sentry-unblock style="width:100px;height:100px" src="file:///none.png" />
14+
</body>
15+
</html>
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
import { expect } from '@playwright/test';
2+
import { EventType } from '@sentry-internal/rrweb';
3+
import type { RecordingEvent } from '@sentry/replay/build/npm/types/types';
4+
5+
import { sentryTest } from '../../../utils/fixtures';
6+
import { envelopeRequestParser } from '../../../utils/helpers';
7+
import { waitForReplayRequest } from '../../../utils/replayHelpers';
8+
9+
sentryTest('should have the correct default privacy settings', async ({ getLocalTestPath, page }) => {
10+
// Replay bundles are es6 only
11+
if (process.env.PW_BUNDLE && process.env.PW_BUNDLE.startsWith('bundle_es5')) {
12+
sentryTest.skip();
13+
}
14+
15+
const reqPromise0 = waitForReplayRequest(page, 0);
16+
17+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
18+
return route.fulfill({
19+
status: 200,
20+
contentType: 'application/json',
21+
body: JSON.stringify({ id: 'test-id' }),
22+
});
23+
});
24+
25+
const url = await getLocalTestPath({ testDir: __dirname });
26+
27+
await page.goto(url);
28+
const replayPayload = envelopeRequestParser<RecordingEvent[]>(await reqPromise0, 5);
29+
const checkoutEvent = replayPayload.find(({ type }) => type === EventType.FullSnapshot);
30+
31+
expect(checkoutEvent?.data).toEqual({
32+
node: {
33+
type: 0,
34+
childNodes: [
35+
{
36+
type: 1,
37+
name: 'html',
38+
publicId: '',
39+
systemId: '',
40+
id: 2,
41+
},
42+
{
43+
type: 2,
44+
tagName: 'html',
45+
attributes: {},
46+
childNodes: [
47+
{
48+
type: 2,
49+
tagName: 'head',
50+
attributes: {},
51+
childNodes: [
52+
{
53+
type: 2,
54+
tagName: 'meta',
55+
attributes: {
56+
charset: 'utf-8',
57+
},
58+
childNodes: [],
59+
id: 5,
60+
},
61+
],
62+
id: 4,
63+
},
64+
{
65+
type: 3,
66+
textContent: '\n ',
67+
id: 6,
68+
},
69+
{
70+
type: 2,
71+
tagName: 'body',
72+
attributes: {},
73+
childNodes: [
74+
{
75+
type: 3,
76+
textContent: '\n ',
77+
id: 8,
78+
},
79+
{
80+
type: 2,
81+
tagName: 'button',
82+
attributes: {
83+
'aria-label': 'Click me',
84+
onclick: "console.log('Test log')",
85+
},
86+
childNodes: [
87+
{
88+
type: 3,
89+
textContent: '***** **',
90+
id: 10,
91+
},
92+
],
93+
id: 9,
94+
},
95+
{
96+
type: 3,
97+
textContent: '\n ',
98+
id: 11,
99+
},
100+
{
101+
type: 2,
102+
tagName: 'div',
103+
attributes: {},
104+
childNodes: [
105+
{
106+
type: 3,
107+
textContent: '**** ****** ** ****** ** *******',
108+
id: 13,
109+
},
110+
],
111+
id: 12,
112+
},
113+
{
114+
type: 3,
115+
textContent: '\n ',
116+
id: 14,
117+
},
118+
{
119+
type: 2,
120+
tagName: 'div',
121+
attributes: {
122+
'data-sentry-unmask': '',
123+
},
124+
childNodes: [
125+
{
126+
type: 3,
127+
textContent: 'This should be unmasked due to data attribute',
128+
id: 16,
129+
},
130+
],
131+
id: 15,
132+
},
133+
{
134+
type: 3,
135+
textContent: '\n ',
136+
id: 17,
137+
},
138+
{
139+
type: 2,
140+
tagName: 'input',
141+
attributes: {
142+
placeholder: 'Placeholder should be masked',
143+
},
144+
childNodes: [],
145+
id: 18,
146+
},
147+
{
148+
type: 3,
149+
textContent: '\n ',
150+
id: 19,
151+
},
152+
{
153+
type: 2,
154+
tagName: 'div',
155+
attributes: {
156+
title: 'Title should be masked',
157+
},
158+
childNodes: [
159+
{
160+
type: 3,
161+
textContent: '***** ****** ** ******',
162+
id: 21,
163+
},
164+
],
165+
id: 20,
166+
},
167+
{
168+
type: 3,
169+
textContent: '\n ',
170+
id: 22,
171+
},
172+
{
173+
type: 2,
174+
tagName: 'svg',
175+
attributes: {
176+
rr_width: '200px',
177+
rr_height: '200px',
178+
},
179+
childNodes: [],
180+
isSVG: true,
181+
id: 23,
182+
},
183+
{
184+
type: 3,
185+
textContent: '\n ',
186+
id: 24,
187+
},
188+
{
189+
type: 2,
190+
tagName: 'svg',
191+
attributes: {
192+
style: 'width:200px;height:200px',
193+
class: 'sentry-unblock',
194+
viewBox: '0 0 80 80',
195+
'data-sentry-unblock': '',
196+
},
197+
childNodes: [
198+
{
199+
type: 2,
200+
tagName: 'path',
201+
attributes: {
202+
rr_width: '0px',
203+
rr_height: '0px',
204+
},
205+
childNodes: [],
206+
isSVG: true,
207+
id: 26,
208+
},
209+
],
210+
isSVG: true,
211+
id: 25,
212+
},
213+
{
214+
type: 3,
215+
textContent: '\n ',
216+
id: 27,
217+
},
218+
{
219+
type: 2,
220+
tagName: 'img',
221+
attributes: {
222+
rr_width: '100px',
223+
rr_height: '100px',
224+
},
225+
childNodes: [],
226+
id: 28,
227+
},
228+
{
229+
type: 3,
230+
textContent: '\n ',
231+
id: 29,
232+
},
233+
{
234+
type: 2,
235+
tagName: 'img',
236+
attributes: {
237+
'data-sentry-unblock': '',
238+
style: 'width:100px;height:100px',
239+
src: 'file:///none.png',
240+
},
241+
childNodes: [],
242+
id: 30,
243+
},
244+
{
245+
type: 3,
246+
textContent: '\n ',
247+
id: 31,
248+
},
249+
{
250+
type: 3,
251+
textContent: '\n\n',
252+
id: 32,
253+
},
254+
],
255+
id: 7,
256+
},
257+
],
258+
id: 3,
259+
},
260+
],
261+
id: 1,
262+
},
263+
initialOffset: {
264+
left: 0,
265+
top: 0,
266+
},
267+
});
268+
});

packages/integration-tests/utils/helpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ export const envelopeParser = (request: Request | null): unknown[] => {
1717
});
1818
};
1919

20-
export const envelopeRequestParser = (request: Request | null, envelopeIndex = 2): Event => {
21-
return envelopeParser(request)[envelopeIndex] as Event;
20+
export const envelopeRequestParser = <T = Event>(request: Request | null, envelopeIndex = 2): T => {
21+
return envelopeParser(request)[envelopeIndex] as T;
2222
};
2323

2424
export const envelopeHeaderRequestParser = (request: Request | null): EventEnvelopeHeaders => {

0 commit comments

Comments
 (0)