Skip to content

Commit

Permalink
fix flakyness ??
Browse files Browse the repository at this point in the history
  • Loading branch information
mydea committed Jun 22, 2023
1 parent 4389c5e commit 7bec65f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect } from '@playwright/test';

import { sentryTest } from '../../../../utils/fixtures';
import { getCustomRecordingEvents, shouldSkipReplayTest, waitForReplayRequest } from '../../../../utils/replayHelpers';
import {
getCustomRecordingEvents,
shouldSkipReplayTest,
waitForReplayRequest,
waitForReplayRequests,
} from '../../../../utils/replayHelpers';

sentryTest('captures multi click when not detecting slow click', async ({ getLocalTestUrl, page }) => {
if (shouldSkipReplayTest()) {
Expand Down Expand Up @@ -79,47 +84,34 @@ sentryTest('captures multiple multi clicks', async ({ getLocalTestUrl, page, for
await page.goto(url);
await reqPromise0;

let lastMultiClickSegmentId: number | undefined;
let multiClickBreadcrumbCount = 0;

const reqPromise1 = waitForReplayRequest(page, (event, res) => {
const reqsPromise = waitForReplayRequests(page, (_event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);
const count = breadcrumbs.filter(breadcrumb => breadcrumb.category === 'ui.multiClick').length;

const check = !lastMultiClickSegmentId && breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.multiClick');
if (check) {
lastMultiClickSegmentId = event.segment_id;
}
return check;
});

const reqPromise2 = waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);
multiClickBreadcrumbCount += count;

const check =
!!lastMultiClickSegmentId &&
event.segment_id > lastMultiClickSegmentId &&
breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.multiClick');
if (check) {
lastMultiClickSegmentId = event.segment_id;
if (multiClickBreadcrumbCount === 2) {
return true;
}
return check;
});

const time = Date.now();
return false;
});

await page.click('#mutationButtonImmediately', { clickCount: 4 });
await forceFlushReplay();

// Ensure we waited at least 1s, which is the threshold to create a new ui.click breadcrumb
await waitForFunction(() => Date.now() - time > 1000);
await new Promise(resolve => setTimeout(resolve, 1001));

await page.click('#mutationButtonImmediately', { clickCount: 2 });

const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1);
await forceFlushReplay();

const { breadcrumbs: breadcrumb2 } = getCustomRecordingEvents(await reqPromise2);
const responses = await reqsPromise;

const slowClickBreadcrumbs = breadcrumbs
.concat(breadcrumb2)
const slowClickBreadcrumbs = responses
.flatMap(res => getCustomRecordingEvents(res).breadcrumbs)
.filter(breadcrumb => breadcrumb.category === 'ui.multiClick');

expect(slowClickBreadcrumbs).toEqual([
Expand Down Expand Up @@ -165,10 +157,3 @@ sentryTest('captures multiple multi clicks', async ({ getLocalTestUrl, page, for
},
]);
});

async function waitForFunction(cb: () => boolean, timeout = 2000, increment = 100) {
while (timeout > 0 && !cb()) {
await new Promise(resolve => setTimeout(resolve, increment));
await waitForFunction(cb, timeout - increment, increment);
}
}
40 changes: 40 additions & 0 deletions packages/browser-integration-tests/utils/replayHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,46 @@ export function waitForReplayRequest(
);
}

/**
* Wait until a callback returns true, collecting all replay responses along the way.
* This can be useful when you don't know if stuff will be in one or multiple replay requests.
*/
export function waitForReplayRequests(
page: Page,
callback: (event: ReplayEvent, res: Response) => boolean,
timeout?: number,
): Promise<Response[]> {
const responses: Response[] = [];

return new Promise<Response[]>(resolve => {
void page.waitForResponse(
res => {
const req = res.request();

const event = getReplayEventFromRequest(req);

if (!event) {
return false;
}

responses.push(res);

try {
if (callback(event, res)) {
resolve(responses);
return true;
}

return false;
} catch {
return false;
}
},
timeout ? { timeout } : undefined,
);
});
}

export function isReplayEvent(event: Event): event is ReplayEvent {
return event.type === 'replay_event';
}
Expand Down

0 comments on commit 7bec65f

Please sign in to comment.