/
test.ts
115 lines (88 loc) · 3.6 KB
/
test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { expect } from '@playwright/test';
import { sentryTest } from '../../../utils/fixtures';
import { getCustomRecordingEvents, shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers';
const COUNT = 250;
const THROTTLE_LIMIT = 300;
sentryTest(
'throttles breadcrumbs when many requests are made at the same time',
async ({ getLocalTestUrl, page, forceFlushReplay }) => {
if (shouldSkipReplayTest()) {
sentryTest.skip();
}
const reqPromise0 = waitForReplayRequest(page, 0);
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 'test-id' }),
});
});
let scriptsLoaded = 0;
let fetchLoaded = 0;
await page.route('**/virtual-assets/script-**', route => {
scriptsLoaded++;
return route.fulfill({
status: 200,
contentType: 'text/javascript',
body: `const aha = ${'xx'.repeat(20_000)};`,
});
});
await page.route('**/virtual-assets/fetch-**', route => {
fetchLoaded++;
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ fetchResponse: 'aa'.repeat(20_000) }),
});
});
const url = await getLocalTestUrl({ testDir: __dirname });
await page.goto(url);
await reqPromise0;
const reqPromise1 = waitForReplayRequest(
page,
(_event, res) => {
const { performanceSpans } = getCustomRecordingEvents(res);
return performanceSpans.some(span => span.op === 'resource.script');
},
5_000,
);
await page.click('[data-network]');
await page.click('[data-fetch]');
await page.waitForFunction('window.__isLoaded()');
await forceFlushReplay();
const { performanceSpans, breadcrumbs } = getCustomRecordingEvents(await reqPromise1);
// All assets have been _loaded_
expect(scriptsLoaded).toBe(COUNT);
expect(fetchLoaded).toBe(COUNT);
// But only some have been captured by replay
// We check for <= THROTTLE_LIMIT, as there have been some captured before, which take up some of the throttle limit
expect(performanceSpans.length).toBeLessThanOrEqual(THROTTLE_LIMIT);
expect(performanceSpans.length).toBeGreaterThan(THROTTLE_LIMIT - 10);
expect(breadcrumbs.filter(({ category }) => category === 'replay.throttled').length).toBe(1);
// Now we wait for 6s (5s + some wiggle room), and make some requests again
await page.waitForTimeout(6_000);
await forceFlushReplay();
const reqPromise2 = waitForReplayRequest(
page,
(_event, res) => {
const { performanceSpans } = getCustomRecordingEvents(res);
return performanceSpans.some(span => span.op === 'resource.script');
},
5_000,
);
await page.click('[data-network]');
await page.click('[data-fetch]');
await forceFlushReplay();
const { performanceSpans: performanceSpans2, breadcrumbs: breadcrumbs2 } = getCustomRecordingEvents(
await reqPromise2,
);
// All assets have been _loaded_
expect(scriptsLoaded).toBe(COUNT * 2);
expect(fetchLoaded).toBe(COUNT * 2);
// But only some have been captured by replay
// We check for <= THROTTLE_LIMIT, as there have been some captured before, which take up some of the throttle limit
expect(performanceSpans2.length).toBeLessThanOrEqual(THROTTLE_LIMIT);
expect(performanceSpans2.length).toBeGreaterThan(THROTTLE_LIMIT - 10);
expect(breadcrumbs2.filter(({ category }) => category === 'replay.throttled').length).toBe(1);
},
);