Skip to content

Commit

Permalink
test: Unflake slow click test (#13252)
Browse files Browse the repository at this point in the history
  • Loading branch information
lforst authored Aug 6, 2024
1 parent 69d4823 commit 9ed2112
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 148 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/flaky-test-detector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ jobs:
CHANGED_TEST_PATHS: ${{ steps.changed.outputs.browser_integration_files }}
TEST_RUN_COUNT: 'AUTO'

- name: Artifacts upload
- name: Upload Playwright Traces
uses: actions/upload-artifact@v4
if: failure() && steps.test.outcome == 'failure'
with:
name: playwright-test-results
path: test-results
path: dev-packages/browser-integration-tests/test-results
retention-days: 5
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,51 @@ sentryTest('mutation after threshold results in slow click', async ({ forceFlush

const url = await getLocalTestUrl({ testDir: __dirname });

await Promise.all([waitForReplayRequest(page, 0), page.goto(url)]);
await forceFlushReplay();
const replayRequestPromise = waitForReplayRequest(page, 0);

const segmentReqWithSlowClickBreadcrumbPromise = waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.slowClickDetected');
});

const [req1] = await Promise.all([
waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);
await page.goto(url);
await replayRequestPromise;

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.slowClickDetected');
}),
await forceFlushReplay();

await page.locator('#mutationButton').click();

page.locator('#mutationButton').click(),
]);
const segmentReqWithSlowClick = await segmentReqWithSlowClickBreadcrumbPromise;

const { breadcrumbs } = getCustomRecordingEvents(req1);
const { breadcrumbs } = getCustomRecordingEvents(segmentReqWithSlowClick);

const slowClickBreadcrumbs = breadcrumbs.filter(breadcrumb => breadcrumb.category === 'ui.slowClickDetected');

expect(slowClickBreadcrumbs).toEqual([
{
category: 'ui.slowClickDetected',
type: 'default',
data: {
endReason: 'mutation',
clickCount: 1,
node: {
attributes: {
id: 'mutationButton',
},
id: expect.any(Number),
tagName: 'button',
textContent: '******* ********',
expect(slowClickBreadcrumbs).toContainEqual({
category: 'ui.slowClickDetected',
type: 'default',
data: {
endReason: 'mutation',
clickCount: 1,
node: {
attributes: {
id: 'mutationButton',
},
nodeId: expect.any(Number),
timeAfterClickMs: expect.any(Number),
url: 'http://sentry-test.io/index.html',
id: expect.any(Number),
tagName: 'button',
textContent: '******* ********',
},
message: 'body > button#mutationButton',
timestamp: expect.any(Number),
nodeId: expect.any(Number),
timeAfterClickMs: expect.any(Number),
url: 'http://sentry-test.io/index.html',
},
]);
message: 'body > button#mutationButton',
timestamp: expect.any(Number),
});

expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeGreaterThan(3000);
expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeLessThan(3500);
expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeLessThan(3501);
});

sentryTest('multiple clicks are counted', async ({ getLocalTestUrl, page }) => {
Expand All @@ -78,49 +80,50 @@ sentryTest('multiple clicks are counted', async ({ getLocalTestUrl, page }) => {

const url = await getLocalTestUrl({ testDir: __dirname });

await Promise.all([waitForReplayRequest(page, 0), page.goto(url)]);
const replayRequestPromise = waitForReplayRequest(page, 0);
const segmentReqWithSlowClickBreadcrumbPromise = waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

const [req1] = await Promise.all([
waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);
return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.slowClickDetected');
});

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.slowClickDetected');
}),
page.locator('#mutationButton').click({ clickCount: 4 }),
]);
await page.goto(url);
await replayRequestPromise;

const { breadcrumbs } = getCustomRecordingEvents(req1);
await page.locator('#mutationButton').click({ clickCount: 4 });

const segmentReqWithSlowClick = await segmentReqWithSlowClickBreadcrumbPromise;

const { breadcrumbs } = getCustomRecordingEvents(segmentReqWithSlowClick);

const slowClickBreadcrumbs = breadcrumbs.filter(breadcrumb => breadcrumb.category === 'ui.slowClickDetected');
const multiClickBreadcrumbs = breadcrumbs.filter(breadcrumb => breadcrumb.category === 'ui.multiClick');

expect(slowClickBreadcrumbs).toEqual([
{
category: 'ui.slowClickDetected',
type: 'default',
data: {
endReason: 'mutation',
clickCount: 4,
node: {
attributes: {
id: 'mutationButton',
},
id: expect.any(Number),
tagName: 'button',
textContent: '******* ********',
expect(slowClickBreadcrumbs).toContainEqual({
category: 'ui.slowClickDetected',
type: 'default',
data: {
endReason: expect.stringMatching(/^(mutation|timeout)$/),
clickCount: 4,
node: {
attributes: {
id: 'mutationButton',
},
nodeId: expect.any(Number),
timeAfterClickMs: expect.any(Number),
url: 'http://sentry-test.io/index.html',
id: expect.any(Number),
tagName: 'button',
textContent: '******* ********',
},
message: 'body > button#mutationButton',
timestamp: expect.any(Number),
nodeId: expect.any(Number),
timeAfterClickMs: expect.any(Number),
url: 'http://sentry-test.io/index.html',
},
]);
message: 'body > button#mutationButton',
timestamp: expect.any(Number),
});
expect(multiClickBreadcrumbs.length).toEqual(0);

expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeGreaterThan(3000);
expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeLessThan(3500);
expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeLessThan(3501);
});

sentryTest('immediate mutation does not trigger slow click', async ({ forceFlushReplay, getLocalTestUrl, page }) => {
Expand All @@ -138,7 +141,15 @@ sentryTest('immediate mutation does not trigger slow click', async ({ forceFlush

const url = await getLocalTestUrl({ testDir: __dirname });

await Promise.all([waitForReplayRequest(page, 0), page.goto(url)]);
const replayRequestPromise = waitForReplayRequest(page, 0);
const segmentReqWithClickBreadcrumbPromise = waitForReplayRequest(page, (_event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click');
});

await page.goto(url);
await replayRequestPromise;
await forceFlushReplay();

let slowClickCount = 0;
Expand All @@ -150,36 +161,29 @@ sentryTest('immediate mutation does not trigger slow click', async ({ forceFlush
slowClickCount += slowClicks.length;
});

const [req1] = await Promise.all([
waitForReplayRequest(page, (_event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click');
}),
page.locator('#mutationButtonImmediately').click(),
]);

const { breadcrumbs } = getCustomRecordingEvents(req1);

expect(breadcrumbs).toEqual([
{
category: 'ui.click',
data: {
node: {
attributes: {
id: 'mutationButtonImmediately',
},
id: expect.any(Number),
tagName: 'button',
textContent: '******* ******** ***********',
await page.locator('#mutationButtonImmediately').click();

const segmentReqWithSlowClick = await segmentReqWithClickBreadcrumbPromise;

const { breadcrumbs } = getCustomRecordingEvents(segmentReqWithSlowClick);

expect(breadcrumbs).toContainEqual({
category: 'ui.click',
data: {
node: {
attributes: {
id: 'mutationButtonImmediately',
},
nodeId: expect.any(Number),
id: expect.any(Number),
tagName: 'button',
textContent: '******* ******** ***********',
},
message: 'body > button#mutationButtonImmediately',
timestamp: expect.any(Number),
type: 'default',
nodeId: expect.any(Number),
},
]);
message: 'body > button#mutationButtonImmediately',
timestamp: expect.any(Number),
type: 'default',
});

// Ensure we wait for timeout, to make sure no slow click is created
// Waiting for 3500 + 1s rounding room
Expand All @@ -204,39 +208,41 @@ sentryTest('inline click handler does not trigger slow click', async ({ forceFlu

const url = await getLocalTestUrl({ testDir: __dirname });

await Promise.all([waitForReplayRequest(page, 0), page.goto(url)]);
const replayRequestPromise = waitForReplayRequest(page, 0);
const segmentReqWithClickBreadcrumbPromise = waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click');
});

await page.goto(url);
await replayRequestPromise;

await forceFlushReplay();

const [req1] = await Promise.all([
waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click');
}),
page.locator('#mutationButtonInline').click(),
]);

const { breadcrumbs } = getCustomRecordingEvents(req1);

expect(breadcrumbs).toEqual([
{
category: 'ui.click',
data: {
node: {
attributes: {
id: 'mutationButtonInline',
},
id: expect.any(Number),
tagName: 'button',
textContent: '******* ******** ***********',
await page.locator('#mutationButtonInline').click();

const segmentReqWithClick = await segmentReqWithClickBreadcrumbPromise;

const { breadcrumbs } = getCustomRecordingEvents(segmentReqWithClick);

expect(breadcrumbs).toContainEqual({
category: 'ui.click',
data: {
node: {
attributes: {
id: 'mutationButtonInline',
},
nodeId: expect.any(Number),
id: expect.any(Number),
tagName: 'button',
textContent: '******* ******** ***********',
},
message: 'body > button#mutationButtonInline',
timestamp: expect.any(Number),
type: 'default',
nodeId: expect.any(Number),
},
]);
message: 'body > button#mutationButtonInline',
timestamp: expect.any(Number),
type: 'default',
});
});

sentryTest('mouseDown events are considered', async ({ getLocalTestUrl, page }) => {
Expand All @@ -254,36 +260,36 @@ sentryTest('mouseDown events are considered', async ({ getLocalTestUrl, page })

const url = await getLocalTestUrl({ testDir: __dirname });

await Promise.all([waitForReplayRequest(page, 0), page.goto(url)]);

const [req1] = await Promise.all([
waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click');
}),
page.locator('#mouseDownButton').click(),
]);

const { breadcrumbs } = getCustomRecordingEvents(req1);

expect(breadcrumbs).toEqual([
{
category: 'ui.click',
data: {
node: {
attributes: {
id: 'mouseDownButton',
},
id: expect.any(Number),
tagName: 'button',
textContent: '******* ******** ** ***** ****',
const replayRequestPromise = waitForReplayRequest(page, 0);
const segmentReqWithClickBreadcrumbPromise = waitForReplayRequest(page, (event, res) => {
const { breadcrumbs } = getCustomRecordingEvents(res);

return breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click');
});

await page.goto(url);
await replayRequestPromise;

await page.locator('#mouseDownButton').click();
const segmentReqWithClick = await segmentReqWithClickBreadcrumbPromise;

const { breadcrumbs } = getCustomRecordingEvents(segmentReqWithClick);

expect(breadcrumbs).toContainEqual({
category: 'ui.click',
data: {
node: {
attributes: {
id: 'mouseDownButton',
},
nodeId: expect.any(Number),
id: expect.any(Number),
tagName: 'button',
textContent: '******* ******** ** ***** ****',
},
message: 'body > button#mouseDownButton',
timestamp: expect.any(Number),
type: 'default',
nodeId: expect.any(Number),
},
]);
message: 'body > button#mouseDownButton',
timestamp: expect.any(Number),
type: 'default',
});
});

0 comments on commit 9ed2112

Please sign in to comment.