Skip to content

Commit 44821f3

Browse files
committed
test: Make some replay tests less flaky
?? let's see if this makes sense...
1 parent 9fe67aa commit 44821f3

File tree

2 files changed

+65
-16
lines changed
  • dev-packages/browser-integration-tests

2 files changed

+65
-16
lines changed

dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseSize/test.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { expect } from '@playwright/test';
33
import { sentryTest } from '../../../../../utils/fixtures';
44
import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers';
55
import {
6-
getCustomRecordingEvents,
6+
collectReplayRequests,
7+
getReplayPerformanceSpans,
78
shouldSkipReplayTest,
8-
waitForReplayRequest,
99
} from '../../../../../utils/replayHelpers';
1010

1111
sentryTest('captures response size from Content-Length header if available', async ({ getLocalTestPath, page }) => {
@@ -35,7 +35,10 @@ sentryTest('captures response size from Content-Length header if available', asy
3535
});
3636

3737
const requestPromise = waitForErrorRequest(page);
38-
const replayRequestPromise1 = waitForReplayRequest(page, 0);
38+
39+
const replayRequestPromise = collectReplayRequests(page, recordingEvents => {
40+
return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch');
41+
});
3942

4043
const url = await getLocalTestPath({ testDir: __dirname });
4144
await page.goto(url);
@@ -67,9 +70,8 @@ sentryTest('captures response size from Content-Length header if available', asy
6770
},
6871
});
6972

70-
const replayReq1 = await replayRequestPromise1;
71-
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
72-
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
73+
const { replayRecordingSnapshots } = await replayRequestPromise;
74+
expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([
7375
{
7476
data: {
7577
method: 'GET',
@@ -123,7 +125,10 @@ sentryTest('captures response size without Content-Length header', async ({ getL
123125
});
124126

125127
const requestPromise = waitForErrorRequest(page);
126-
const replayRequestPromise1 = waitForReplayRequest(page, 0);
128+
129+
const replayRequestPromise = collectReplayRequests(page, recordingEvents => {
130+
return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch');
131+
});
127132

128133
const url = await getLocalTestPath({ testDir: __dirname });
129134
await page.goto(url);
@@ -155,9 +160,8 @@ sentryTest('captures response size without Content-Length header', async ({ getL
155160
},
156161
});
157162

158-
const replayReq1 = await replayRequestPromise1;
159-
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
160-
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
163+
const { replayRecordingSnapshots } = await replayRequestPromise;
164+
expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([
161165
{
162166
data: {
163167
method: 'GET',
@@ -208,7 +212,10 @@ sentryTest('captures response size from non-text response body', async ({ getLoc
208212
});
209213

210214
const requestPromise = waitForErrorRequest(page);
211-
const replayRequestPromise1 = waitForReplayRequest(page, 0);
215+
216+
const replayRequestPromise = collectReplayRequests(page, recordingEvents => {
217+
return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch');
218+
});
212219

213220
const url = await getLocalTestPath({ testDir: __dirname });
214221
await page.goto(url);
@@ -241,9 +248,8 @@ sentryTest('captures response size from non-text response body', async ({ getLoc
241248
},
242249
});
243250

244-
const replayReq1 = await replayRequestPromise1;
245-
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
246-
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
251+
const { replayRecordingSnapshots } = await replayRequestPromise;
252+
expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([
247253
{
248254
data: {
249255
method: 'POST',

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

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,49 @@ export function waitForReplayRequest(
104104
);
105105
}
106106

107+
/**
108+
* Collect replay requests until a given callback is satisfied.
109+
* This can be used to ensure we wait correctly,
110+
* when we don't know in which request a certain replay event/snapshot will be.
111+
*/
112+
export function collectReplayRequests(
113+
page: Page,
114+
callback: (replayRecordingEvents: RecordingSnapshot[], replayEvents: ReplayEvent[]) => boolean,
115+
): Promise<{ replayEvents: ReplayEvent[]; replayRecordingSnapshots: RecordingSnapshot[] }> {
116+
const replayEvents: ReplayEvent[] = [];
117+
const replayRecordingSnapshots: RecordingSnapshot[] = [];
118+
119+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
120+
const promise = page.waitForResponse(res => {
121+
const req = res.request();
122+
123+
const event = getReplayEventFromRequest(req);
124+
125+
if (!event) {
126+
return false;
127+
}
128+
129+
replayEvents.push(event);
130+
replayRecordingSnapshots.push(...getDecompressedRecordingEvents(req));
131+
132+
try {
133+
return callback(replayRecordingSnapshots, replayEvents);
134+
} catch {
135+
return false;
136+
}
137+
});
138+
139+
const replayRequestPromise = async (): Promise<{
140+
replayEvents: ReplayEvent[];
141+
replayRecordingSnapshots: RecordingSnapshot[];
142+
}> => {
143+
await promise;
144+
return { replayEvents, replayRecordingSnapshots };
145+
};
146+
147+
return replayRequestPromise();
148+
}
149+
107150
/**
108151
* Wait until a callback returns true, collecting all replay responses along the way.
109152
* This can be useful when you don't know if stuff will be in one or multiple replay requests.
@@ -246,14 +289,14 @@ function getAllCustomRrwebRecordingEvents(recordingEvents: RecordingEvent[]): Cu
246289
return recordingEvents.filter(isCustomSnapshot).map(event => event.data);
247290
}
248291

249-
function getReplayBreadcrumbs(recordingEvents: RecordingSnapshot[], category?: string): Breadcrumb[] {
292+
export function getReplayBreadcrumbs(recordingEvents: RecordingSnapshot[], category?: string): Breadcrumb[] {
250293
return getAllCustomRrwebRecordingEvents(recordingEvents)
251294
.filter(data => data.tag === 'breadcrumb')
252295
.map(data => data.payload)
253296
.filter(payload => !category || payload.category === category);
254297
}
255298

256-
function getReplayPerformanceSpans(recordingEvents: RecordingEvent[]): PerformanceSpan[] {
299+
export function getReplayPerformanceSpans(recordingEvents: RecordingSnapshot[]): PerformanceSpan[] {
257300
return getAllCustomRrwebRecordingEvents(recordingEvents)
258301
.filter(data => data.tag === 'performanceSpan')
259302
.map(data => data.payload) as PerformanceSpan[];

0 commit comments

Comments
 (0)