From 54d98e73a2d3976577e2bf7f8ee320cff8e69896 Mon Sep 17 00:00:00 2001 From: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Date: Tue, 8 Apr 2025 01:13:01 +0530 Subject: [PATCH] fix: all flaky e2e tests (#20476) * fix: all flaky e2e tests * update * Update basic.e2e.ts * Update basic.e2e.ts * update * Update basic.e2e.ts * update * update * push * update * final * update * fix --- .../apps/analytics/analyticsApps.e2e.ts | 2 +- apps/web/playwright/bookings-list.e2e.ts | 5 +++-- apps/web/playwright/event-types.e2e.ts | 8 ++++++-- apps/web/playwright/fixtures/apps.ts | 2 +- apps/web/playwright/hash-my-url.e2e.ts | 5 +++-- apps/web/playwright/lib/testUtils.ts | 4 ++++ .../manage-booking-questions.e2e.ts | 3 ++- .../web/playwright/managed-event-types.e2e.ts | 20 +++++++++++++++---- .../playwright/organization/booking.e2e.ts | 1 + apps/web/playwright/out-of-office.e2e.ts | 10 ++++++++-- .../playwright/settings/upload-avatar.e2e.ts | 7 +++---- .../playwright/tests/basic.e2e.ts | 7 ++----- .../outOfOffice/OutOfOfficeEntriesList.tsx | 2 +- 13 files changed, 51 insertions(+), 25 deletions(-) diff --git a/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts b/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts index 7dff3a5e19..343541ae6a 100644 --- a/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts +++ b/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts @@ -34,7 +34,7 @@ test.describe("check analytics Apps", () => { const user = await users.create(); await user.apiLogin(); const eventTypes = await user.getUserEventsAsOwner(); - const eventTypesIds = eventTypes.map((item) => item.id); + const eventTypesIds = eventTypes.map((item) => item.id).slice(0, 3); await page.goto("/apps/categories/analytics"); await appsPage.installAnalyticsApp(app, eventTypesIds); for (const id of eventTypesIds) { diff --git a/apps/web/playwright/bookings-list.e2e.ts b/apps/web/playwright/bookings-list.e2e.ts index 7fb39c2ce0..d5a3b70637 100644 --- a/apps/web/playwright/bookings-list.e2e.ts +++ b/apps/web/playwright/bookings-list.e2e.ts @@ -357,13 +357,14 @@ test.describe("Bookings", () => { await page.locator('[data-testid="add-filter-item-userId"]').click(); await page.locator('[data-testid="filter-popover-trigger-userId"]').click(); - const bookingsGetResponse2 = page.waitForResponse((response) => - /\/api\/trpc\/bookings\/get.*/.test(response.url()) + const bookingsGetResponse2 = page.waitForResponse( + (response) => response.url().includes("/api/trpc/bookings/get?batch=1") && response.status() === 200 ); await page .locator(`[data-testid="multi-select-options-userId"] [role="option"]:has-text("${thirdUser.name}")`) .click(); await bookingsGetResponse2; + await expect(page.locator('text="Cancel event"').nth(0)).toBeVisible(); //expect only 3 bookings (out of 4 total) to be shown in list. //where ThirdUser is either organizer or attendee diff --git a/apps/web/playwright/event-types.e2e.ts b/apps/web/playwright/event-types.e2e.ts index 55aa7d5285..97ba03386d 100644 --- a/apps/web/playwright/event-types.e2e.ts +++ b/apps/web/playwright/event-types.e2e.ts @@ -75,8 +75,12 @@ test.describe("Event Types tests", () => { const eventTitle = `my recurring event ${nonce}`; await createNewEventType(page, { eventTitle }); - // eslint-disable-next-line playwright/no-wait-for-timeout - await page.waitForTimeout(1000); // waits for 1 second + // fix the race condition + await page.waitForSelector('[data-testid="event-title"]'); + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toHaveAttribute( + "aria-current", + "page" + ); await page.click("[data-testid=vertical-tab-recurring]"); await expect(page.locator("[data-testid=recurring-event-collapsible]")).toBeHidden(); diff --git a/apps/web/playwright/fixtures/apps.ts b/apps/web/playwright/fixtures/apps.ts index 71a50ad513..f63dd643c4 100644 --- a/apps/web/playwright/fixtures/apps.ts +++ b/apps/web/playwright/fixtures/apps.ts @@ -123,7 +123,7 @@ export function createAppsFixture(page: Page) { }, verifyAppsInfoNew: async (app: string, eventTypeId: number) => { await page.goto(`event-types/${eventTypeId}?tabName=apps`); - await page.waitForLoadState("domcontentloaded"); + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toContainText("Event Setup"); // fix the race condition await expect(page.locator(`[data-testid='${app}-app-switch'][data-state="checked"]`)).toBeVisible(); }, }; diff --git a/apps/web/playwright/hash-my-url.e2e.ts b/apps/web/playwright/hash-my-url.e2e.ts index b47fd3f29d..35685f9ace 100644 --- a/apps/web/playwright/hash-my-url.e2e.ts +++ b/apps/web/playwright/hash-my-url.e2e.ts @@ -34,8 +34,9 @@ test.describe("hash my url", () => { const $url = await page.locator('//*[@data-testid="generated-hash-url-0"]').inputValue(); // click update - await page.locator('[data-testid="update-eventtype"]').press("Enter"); - + await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", { + action: () => page.locator("[data-testid=update-eventtype]").click(), + }); // book using generated url hash await page.goto($url); await selectFirstAvailableTimeSlotNextMonth(page); diff --git a/apps/web/playwright/lib/testUtils.ts b/apps/web/playwright/lib/testUtils.ts index 84762de8c4..fe7a92d417 100644 --- a/apps/web/playwright/lib/testUtils.ts +++ b/apps/web/playwright/lib/testUtils.ts @@ -218,6 +218,10 @@ export const createNewSeatedEventType = async (page: Page, args: { eventTitle: s const eventTitle = args.eventTitle; await createNewEventType(page, { eventTitle }); await page.waitForSelector('[data-testid="event-title"]'); + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toHaveAttribute( + "aria-current", + "page" + ); await page.locator('[data-testid="vertical-tab-event_advanced_tab_title"]').click(); await page.locator('[data-testid="offer-seats-toggle"]').click(); await page.locator('[data-testid="update-eventtype"]').click(); diff --git a/apps/web/playwright/manage-booking-questions.e2e.ts b/apps/web/playwright/manage-booking-questions.e2e.ts index fb88c8b5b9..08da60940f 100644 --- a/apps/web/playwright/manage-booking-questions.e2e.ts +++ b/apps/web/playwright/manage-booking-questions.e2e.ts @@ -754,6 +754,7 @@ test.describe("Text area min and max characters text", () => { await page.waitForSelector('[data-testid="event-types"]'); await createNewEventType(page, { eventTitle }); await page.waitForSelector('[data-testid="event-title"]'); + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toContainText("Event Setup"); //fix the race condition await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toHaveAttribute( "aria-current", "page" @@ -841,7 +842,7 @@ test.describe("Text area min and max characters text", () => { ); await cancelQuestion(); // Save the event type - await page.locator("[data-testid=update-eventtype]").click(); + await saveEventType(page); // Get the url of data-testid="preview-button" const previewButton = await page.locator('[data-testid="preview-button"]'); diff --git a/apps/web/playwright/managed-event-types.e2e.ts b/apps/web/playwright/managed-event-types.e2e.ts index b14d4718cf..767ab3618f 100644 --- a/apps/web/playwright/managed-event-types.e2e.ts +++ b/apps/web/playwright/managed-event-types.e2e.ts @@ -21,16 +21,23 @@ test.describe("Managed Event Types", () => { /** We don't use setupManagedEvent here to test the actual creation flow */ test("Can create managed event type", async ({ page, users }) => { // Creating the owner user of the team - const adminUser = await users.create(null, { - hasTeam: true, - teammates: [{ name: "teammate-1" }], - }); + const adminUser = await users.create( + { name: "Owner" }, + { + hasTeam: true, + teammates: [{ name: "teammate-1" }], + } + ); // Creating the member user of the team // First we work with owner user, logging in await adminUser.apiLogin(); // Let's create a team // Going to create an event type await page.goto("/event-types"); + const tabItem = page.getByTestId(`horizontal-tab-Owner`); + await expect(tabItem).toBeVisible(); + // We wait until loading is finished + await page.waitForSelector('[data-testid="event-types"]'); await page.getByTestId("new-event-type").click(); await page.getByTestId("option-team-1").click(); // Expecting we can add a managed event type as team owner @@ -72,6 +79,11 @@ test.describe("Managed Event Types", () => { const { adminUser, managedEvent } = await setupManagedEvent({ users }); await adminUser.apiLogin(); await page.goto(`/event-types/${managedEvent.id}?tabName=setup`); + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toHaveAttribute( + "aria-current", + "page" + ); // fix the race condition + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toContainText("Event Setup"); //fix the race condition await page.locator("#location-select").click(); const optionText = await getByKey(page, "organizer_default_conferencing_app"); await expect(optionText).toBeVisible(); diff --git a/apps/web/playwright/organization/booking.e2e.ts b/apps/web/playwright/organization/booking.e2e.ts index cce657cb1c..035adeec27 100644 --- a/apps/web/playwright/organization/booking.e2e.ts +++ b/apps/web/playwright/organization/booking.e2e.ts @@ -625,6 +625,7 @@ const markPhoneNumberAsRequiredAndEmailAsOptional = async (page: Page, eventId: const markPhoneNumberAsRequiredField = async (page: Page, eventId: number) => { await page.goto(`/event-types/${eventId}?tabName=advanced`); + await expect(page.getByTestId("vertical-tab-event_setup_tab_title")).toContainText("Event Setup"); // fix the race condition await page.locator('[data-testid="field-attendeePhoneNumber"] [data-testid="toggle-field"]').click(); await page.locator('[data-testid="field-attendeePhoneNumber"] [data-testid="edit-field-action"]').click(); diff --git a/apps/web/playwright/out-of-office.e2e.ts b/apps/web/playwright/out-of-office.e2e.ts index e984c968ac..c13e4714c6 100644 --- a/apps/web/playwright/out-of-office.e2e.ts +++ b/apps/web/playwright/out-of-office.e2e.ts @@ -765,7 +765,10 @@ test.describe("Out of office", () => { //By Default future OOO will be displayed //1 OOO record should be visible for member3, end=currentDate+4days - expect(await page.locator('[data-testid^="table-redirect-"]').count()).toBe(1); + const oooEntries = page.locator('[data-testid="ooo-actions"]'); + const oooEntriesCount = await oooEntries.count(); + + expect(oooEntriesCount).toBe(1); await expect(page.locator(`data-testid=table-redirect-n-a`).nth(0)).toBeVisible(); //Default filter 'Last 7 Days' when DateRange Filter is selected @@ -794,7 +797,10 @@ test.describe("Out of office", () => { await entriesListRespPromise; //2 OOO records should be visible end=currentDate-4days, end=currentDate-12days - expect(await page.locator('[data-testid^="table-redirect-"]').count()).toBe(2); + const oooEntries = page.locator('[data-testid="ooo-actions"]'); + const oooEntriesCount = await oooEntries.count(); + + expect(oooEntriesCount).toBe(2); await expect( page.locator(`data-testid=table-redirect-${member2User?.username}`).nth(0) ).toBeVisible(); diff --git a/apps/web/playwright/settings/upload-avatar.e2e.ts b/apps/web/playwright/settings/upload-avatar.e2e.ts index 9ead8f6dde..e6d15ba89e 100644 --- a/apps/web/playwright/settings/upload-avatar.e2e.ts +++ b/apps/web/playwright/settings/upload-avatar.e2e.ts @@ -64,11 +64,10 @@ test.describe("User Avatar", async () => { ); // verify objectKey is passed to the OG image // yes, OG image URI encodes at multiple places.. don't want to mess with that. + const ogImageLocator = page.locator('meta[property="og:image"]'); + await expect(ogImageLocator).toHaveCount(1); const searchParam = `meetingImage=${encodeURIComponent(`${CAL_URL}/api/avatar/${objectKey}.png`)}`; - await expect(page.locator('meta[property="og:image"]')).toHaveAttribute( - "content", - new RegExp(encodeURIComponent(searchParam)) - ); + await expect(ogImageLocator).toHaveAttribute("content", new RegExp(encodeURIComponent(searchParam))); }); }); }); diff --git a/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts b/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts index 877cdab77a..3ab2efe9ee 100644 --- a/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts +++ b/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts @@ -439,7 +439,7 @@ test.describe("Routing Forms", () => { const user = await createUserAndLogin({ users, page }); const routingForm = user.routingForms[0]; await gotoRoutingLink({ page, formId: routingForm.id }); - page.click('button[type="submit"]'); + await page.click('button[type="submit"]'); const firstInputMissingValue = await page.evaluate(() => { return document.querySelectorAll("input")[0].validity.valueMissing; }); @@ -828,11 +828,8 @@ async function addAllTypesOfFieldsAndSaveForm( page: Page, form: { description: string; label: string } ) { - const appRoutingFormsRespPromise = page.waitForResponse((response) => - /\/api\/trpc\/appRoutingForms*/.test(response.url()) - ); await page.goto(`apps/routing-forms/form-edit/${formId}`); - await appRoutingFormsRespPromise; + await expect(page.locator('text="Test Preview"')).toBeVisible(); await page.click('[data-testid="add-field"]'); const { optionsInUi: fieldTypesList } = await verifySelectOptions( diff --git a/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx b/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx index 6bf011dc14..c009f1e09b 100644 --- a/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx +++ b/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx @@ -237,7 +237,7 @@ function OutOfOfficeEntriesListContent() { return ( <> {row.original && !isPending && !isFetching ? ( -