From a8e2ba4663693da1ca4127f2a817b1a962e98ead Mon Sep 17 00:00:00 2001 From: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Date: Tue, 16 Dec 2025 18:00:50 +0530 Subject: [PATCH] Revert "fix: improve E2E test stability and reduce flakiness (#25897)" (#25919) This reverts commit b83f8dd6b8174cf799ff7694b48d34e0337c2bfd. --- .../apps/analytics/analyticsApps.e2e.ts | 4 +- .../booking-duplicate-api-calls.e2e.ts | 7 +-- apps/web/playwright/booking-seats.e2e.ts | 6 +-- apps/web/playwright/change-theme.e2e.ts | 3 +- .../playwright/embed-code-generator.e2e.ts | 32 ++++++------- .../web/playwright/eventType/limit-tab.e2e.ts | 3 +- apps/web/playwright/fixtures/apps.ts | 8 ++-- apps/web/playwright/integrations.e2e.ts | 9 ++-- apps/web/playwright/lib/testUtils.ts | 46 +++++-------------- apps/web/playwright/login.e2e.ts | 5 +- .../organization-invitation.e2e.ts | 6 +-- .../organization/organization-privacy.e2e.ts | 9 ++-- apps/web/playwright/signup.e2e.ts | 27 ++++++----- .../playwright/team/team-invitation.e2e.ts | 21 +++------ 14 files changed, 72 insertions(+), 114 deletions(-) diff --git a/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts b/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts index cbf1b76ad5..343541ae6a 100644 --- a/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts +++ b/apps/web/playwright/apps/analytics/analyticsApps.e2e.ts @@ -17,8 +17,8 @@ test.describe("check analytics Apps", () => { await user.apiLogin(); await page.goto("apps/categories/analytics"); await appsPage.installAnalyticsAppSkipConfigure(app); - // Wait for navigation to complete instead of fixed 1s wait - await page.waitForLoadState("networkidle"); + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(1000); // waits for 1 second await page.goto("/event-types"); await appsPage.goToEventType("30 min"); await appsPage.goToAppsTab(); diff --git a/apps/web/playwright/booking-duplicate-api-calls.e2e.ts b/apps/web/playwright/booking-duplicate-api-calls.e2e.ts index 7668237466..41ce78aa48 100644 --- a/apps/web/playwright/booking-duplicate-api-calls.e2e.ts +++ b/apps/web/playwright/booking-duplicate-api-calls.e2e.ts @@ -27,12 +27,7 @@ async function testDuplicateAPICalls( }); await page.goto(url); - // Wait for the booking page to fully load and time slots to appear instead of fixed 5s wait - await page.waitForLoadState("networkidle"); - // Also wait for the calendar to be visible as a more specific indicator - await page.locator('[data-testid="calendar"]').or(page.locator('[data-testid="time"]')).first().waitFor({ state: "visible", timeout: 10000 }).catch(() => { - // If neither element appears, the page might have a different structure - continue anyway - }); + await page.waitForTimeout(5000); return { totalCalls: trpcCalls.length + apiV2Calls.length, diff --git a/apps/web/playwright/booking-seats.e2e.ts b/apps/web/playwright/booking-seats.e2e.ts index abb82f0f64..37bbaf6e45 100644 --- a/apps/web/playwright/booking-seats.e2e.ts +++ b/apps/web/playwright/booking-seats.e2e.ts @@ -555,8 +555,7 @@ test.describe("Reschedule for booking with seats", () => { await page.waitForSelector('[data-testid="bookings"]'); await page.locator('[data-testid="booking-actions-dropdown"]').nth(0).click(); - // Wait for the dropdown menu to appear instead of fixed 2s wait - await page.locator('[data-testid="reschedule"]').waitFor({ state: "visible" }); + await page.waitForTimeout(2000); const href = await page.locator('[data-testid="reschedule"]').getAttribute("href"); const url = new URL(href!, page.url()); const seatReferenceUid = url.searchParams.get('seatReferenceUid'); @@ -564,8 +563,7 @@ test.describe("Reschedule for booking with seats", () => { await page.reload(); await page.waitForSelector('[data-testid="bookings"]'); await page.locator('[data-testid="booking-actions-dropdown"]').nth(0).click(); - // Wait for the dropdown menu to appear instead of fixed 2s wait - await page.locator('[data-testid="reschedule"]').waitFor({ state: "visible" }); + await page.waitForTimeout(2000); } await page.locator('[data-testid="reschedule"]').click(); await expect(page.getByText("Seats available").first()).toBeVisible(); diff --git a/apps/web/playwright/change-theme.e2e.ts b/apps/web/playwright/change-theme.e2e.ts index 57ee3e5533..adee17b390 100644 --- a/apps/web/playwright/change-theme.e2e.ts +++ b/apps/web/playwright/change-theme.e2e.ts @@ -55,8 +55,7 @@ test.describe("Change App Theme Test", () => { const toast2 = await page.waitForSelector('[data-testid="toast-success"]'); expect(toast2).toBeTruthy(); - // Wait for localStorage to be updated after theme change instead of fixed 3s wait - await page.waitForFunction(() => localStorage.getItem("app-theme") !== null, { timeout: 5000 }); + await page.waitForTimeout(3000); const themeValue = await page.evaluate(() => localStorage.getItem("app-theme")); expect(themeValue).toBe("light"); diff --git a/apps/web/playwright/embed-code-generator.e2e.ts b/apps/web/playwright/embed-code-generator.e2e.ts index 28c3995c2f..c70daf7cfe 100644 --- a/apps/web/playwright/embed-code-generator.e2e.ts +++ b/apps/web/playwright/embed-code-generator.e2e.ts @@ -59,8 +59,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: null, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "inline", calLink: `${pro.username}/multiple-duration`, @@ -96,8 +96,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: null, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "floating-popup", calLink: `${pro.username}/multiple-duration`, @@ -133,8 +133,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: null, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "element-click", calLink: `${pro.username}/multiple-duration`, @@ -172,8 +172,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: null, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "inline", calLink: decodeURIComponent(embedUrl), @@ -229,8 +229,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: org.slug, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "inline", calLink: `${user.username}/multiple-duration`, @@ -269,8 +269,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: org.slug, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "floating-popup", calLink: `${user.username}/multiple-duration`, @@ -308,8 +308,8 @@ test.describe("Embed Code Generator Tests", () => { orgSlug: org.slug, }); - // Wait for the preview iframe to be ready instead of fixed 1s wait - await page.locator('iframe[data-testid="embed-preview"]').waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + // To prevent early timeouts + await page.waitForTimeout(1000); await expectToContainValidPreviewIframe(page, { embedType: "element-click", calLink: `${user.username}/multiple-duration`, @@ -326,8 +326,8 @@ function chooseEmbedType(page: Page, embedType: EmbedType) { } async function goToReactCodeTab(page: Page) { - // Wait for the React tab to be visible instead of fixed 1s wait - await page.locator("[data-testid=horizontal-tab-react]").waitFor({ state: "visible" }); + // To prevent early timeo + await page.waitForTimeout(1000); await page.locator("[data-testid=horizontal-tab-react]").click(); } diff --git a/apps/web/playwright/eventType/limit-tab.e2e.ts b/apps/web/playwright/eventType/limit-tab.e2e.ts index ad1f5da10b..3b9887c9d7 100644 --- a/apps/web/playwright/eventType/limit-tab.e2e.ts +++ b/apps/web/playwright/eventType/limit-tab.e2e.ts @@ -18,8 +18,7 @@ test.describe("Limits Tab - Event Type", () => { await bookingPage.updateEventType(); const eventTypePage = await bookingPage.previewEventType(); - // Wait for time slots to load instead of fixed 10s wait - await eventTypePage.getByTestId("time").first().waitFor({ state: "visible", timeout: 30000 }); + await eventTypePage.waitForTimeout(10000); const counter = await eventTypePage.getByTestId("time").count(); await bookingPage.checkTimeSlotsCount(eventTypePage, counter); diff --git a/apps/web/playwright/fixtures/apps.ts b/apps/web/playwright/fixtures/apps.ts index 4d9468ca30..e2c359b105 100644 --- a/apps/web/playwright/fixtures/apps.ts +++ b/apps/web/playwright/fixtures/apps.ts @@ -33,8 +33,8 @@ export function createAppsFixture(page: Page) { await page.click('[data-testid="install-app-button-personal"]'); await page.waitForURL(`apps/installation/event-types?slug=${app}`); - // Wait for event type checkboxes to be visible instead of fixed 1s wait - await page.locator('[data-testid^="select-event-type-"]').first().waitFor({ state: "visible" }); + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(1000); for (const id of eventTypeIds) { await page.click(`[data-testid="select-event-type-${id}"]`); } @@ -81,8 +81,8 @@ export function createAppsFixture(page: Page) { await page.getByTestId("install-app-button").click(); await page.waitForURL(`apps/installation/event-types?slug=${app.slug}`); - // Wait for event type checkboxes to be visible instead of fixed 1s wait - await page.locator('[data-testid^="select-event-type-"]').first().waitFor({ state: "visible" }); + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(1000); for (const id of eventTypeIds) { await page.click(`[data-testid="select-event-type-${id}"]`); } diff --git a/apps/web/playwright/integrations.e2e.ts b/apps/web/playwright/integrations.e2e.ts index 2785818f98..23622a1ed5 100644 --- a/apps/web/playwright/integrations.e2e.ts +++ b/apps/web/playwright/integrations.e2e.ts @@ -99,10 +99,13 @@ const addLocationIntegrationToFirstEvent = async function ({ user }: { user: { u }; async function bookEvent(page: Page, calLink: string) { - // Navigate to the booking page and wait for calendar to be ready + // Let current month dates fully render. + // There is a bug where if we don't let current month fully render and quickly click go to next month, current month gets rendered + // This doesn't seem to be replicable with the speed of a person, only during automation. + // It would also allow correct snapshot to be taken for current month. + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(1000); await page.goto(`/${calLink}`); - // Wait for the calendar day elements to be visible instead of fixed 1s wait - await page.locator('[data-testid="day"][data-disabled="false"]').first().waitFor({ state: "visible" }); await page.locator('[data-testid="day"][data-disabled="false"]').nth(0).click(); page.locator('[data-testid="time"]').nth(0).click(); diff --git a/apps/web/playwright/lib/testUtils.ts b/apps/web/playwright/lib/testUtils.ts index eb534982c9..238f568d1e 100644 --- a/apps/web/playwright/lib/testUtils.ts +++ b/apps/web/playwright/lib/testUtils.ts @@ -109,30 +109,19 @@ export async function selectFirstAvailableTimeSlotNextMonth(page: Page | Frame) // Let current month dates fully render. await page.getByTestId("incrementMonth").click(); - // Wait for the calendar to update after month increment before clicking - const availableDay = page.locator('[data-testid="day"][data-disabled="false"]').nth(0); - await availableDay.waitFor({ state: "visible" }); - await availableDay.click(); + // Waiting for full month increment + await page.locator('[data-testid="day"][data-disabled="false"]').nth(0).click(); - // Wait for time slots to load after selecting a day - const timeSlot = page.locator('[data-testid="time"]').nth(0); - await timeSlot.waitFor({ state: "visible" }); - await timeSlot.click(); + await page.locator('[data-testid="time"]').nth(0).click(); } export async function selectSecondAvailableTimeSlotNextMonth(page: Page) { // Let current month dates fully render. await page.getByTestId("incrementMonth").click(); - // Wait for the calendar to update after month increment before clicking - const availableDay = page.locator('[data-testid="day"][data-disabled="false"]').nth(1); - await availableDay.waitFor({ state: "visible" }); - await availableDay.click(); + await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click(); - // Wait for time slots to load after selecting a day - const timeSlot = page.locator('[data-testid="time"]').nth(0); - await timeSlot.waitFor({ state: "visible" }); - await timeSlot.click(); + await page.locator('[data-testid="time"]').nth(0).click(); } export async function bookEventOnThisPage(page: Page) { @@ -264,9 +253,8 @@ export async function gotoRoutingLink({ await page.goto(`${previewLink}${queryString ? `?${queryString}` : ""}`); - // Wait for the form to be fully loaded and stable before interacting - // This replaces the previous hardcoded 2s wait with a proper Playwright wait - await page.waitForLoadState("networkidle"); + // HACK: There seems to be some issue with the inputs to the form getting reset if we don't wait. + await new Promise((resolve) => setTimeout(resolve, 2000)); } export async function installAppleCalendar(page: Page) { @@ -286,31 +274,21 @@ export async function getInviteLink(page: Page) { export async function getEmailsReceivedByUser({ emails, userEmail, - maxRetries = 10, - retryIntervalMs = 500, + waitForEmailMs = 5000, }: { emails?: ReturnType; userEmail: string; - maxRetries?: number; - retryIntervalMs?: number; + waitForEmailMs?: number; }): Promise { if (!emails) return null; - // Use retry logic instead of a fixed wait to handle email delivery timing - for (let attempt = 0; attempt < maxRetries; attempt++) { - const matchingEmails = await emails.search(userEmail, "to"); - if (matchingEmails?.total) { - return matchingEmails; - } - // Wait before retrying - await new Promise((resolve) => setTimeout(resolve, retryIntervalMs)); - } + // Wait for email to be sent/received + await new Promise((resolve) => setTimeout(resolve, waitForEmailMs)); - // Final attempt after all retries const matchingEmails = await emails.search(userEmail, "to"); if (!matchingEmails?.total) { console.log( - `No emails received by ${userEmail} after ${maxRetries} retries. All emails sent to:`, + `No emails received by ${userEmail}. All emails sent to:`, (await emails.messages())?.items.map((e) => e.to) ); } diff --git a/apps/web/playwright/login.e2e.ts b/apps/web/playwright/login.e2e.ts index 191447377c..3a898e5629 100644 --- a/apps/web/playwright/login.e2e.ts +++ b/apps/web/playwright/login.e2e.ts @@ -72,11 +72,10 @@ test.describe("Login and logout tests", () => { test("Should warn when password is incorrect", async ({ page, users }) => { const alertMessage = (await localize("en"))("incorrect_email_password"); // by default password===username with the users fixture - // Use unique username to avoid collisions with parallel tests - const user = await users.create(); + const pro = await users.create({ username: "pro" }); // login with a wrong password - await login({ username: user.username, password: "wrong" }, page); + await login({ username: pro.username, password: "wrong" }, page); // assert for the visibility of the localized alert message await expect(page.locator(`text=${alertMessage}`)).toBeVisible(); diff --git a/apps/web/playwright/organization/organization-invitation.e2e.ts b/apps/web/playwright/organization/organization-invitation.e2e.ts index 4d0a4582c3..df4baa9123 100644 --- a/apps/web/playwright/organization/organization-invitation.e2e.ts +++ b/apps/web/playwright/organization/organization-invitation.e2e.ts @@ -582,8 +582,7 @@ async function expectUserToBeAMemberOfTeam({ // Check newly invited member is not pending anymore await page.goto(`/settings/teams/${teamId}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the member list to be ready instead of fixed 1s wait - await page.locator(`[data-testid="member-${username}"]`).waitFor({ state: "visible", timeout: 10000 }); + await page.waitForTimeout(1000); // Add a small delay to ensure UI is fully loaded expect( ( await page @@ -613,8 +612,7 @@ async function copyInviteLink(page: Page, teamPage?: boolean) { if (teamIdMatch && teamIdMatch[1]) { await page.goto(`/settings/teams/${teamIdMatch[1]}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded } await page.getByTestId("new-member-button").click(); } else { diff --git a/apps/web/playwright/organization/organization-privacy.e2e.ts b/apps/web/playwright/organization/organization-privacy.e2e.ts index d960d041d4..0968461fb7 100644 --- a/apps/web/playwright/organization/organization-privacy.e2e.ts +++ b/apps/web/playwright/organization/organization-privacy.e2e.ts @@ -128,8 +128,7 @@ test.describe("Organization - Privacy", () => { await page.goto(`/settings/teams/${teamId}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the page content to be ready instead of fixed 500ms wait - await page.waitForLoadState("networkidle"); + await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded // As a user we can not see the member list when a team is private const hiddenTableLocator = await page.getByTestId("team-member-list-container"); @@ -188,8 +187,7 @@ test.describe("Organization - Privacy", () => { // 1) All team members can see members in team await page.goto(`/settings/teams/${teamId}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the member list to be ready instead of fixed 500ms wait - await page.getByTestId("team-member-list-container").waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + await page.waitForTimeout(500); const memberTableLocator = await page.getByTestId("team-member-list-container"); await expect(memberTableLocator).toBeVisible(); @@ -203,8 +201,7 @@ test.describe("Organization - Privacy", () => { // 3) Admin/Owner can see members in team await page.goto(`/settings/teams/${teamId}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the member list to be ready instead of fixed 500ms wait - await page.getByTestId("team-member-list-container").waitFor({ state: "visible", timeout: 5000 }).catch(() => {}); + await page.waitForTimeout(500); const adminTableLocator = await page.getByTestId("team-member-list-container"); await expect(adminTableLocator).toBeVisible(); diff --git a/apps/web/playwright/signup.e2e.ts b/apps/web/playwright/signup.e2e.ts index 59c785b6c9..e637cef135 100644 --- a/apps/web/playwright/signup.e2e.ts +++ b/apps/web/playwright/signup.e2e.ts @@ -182,7 +182,7 @@ test.describe("Email Signup Flow Test", async () => { // Verify that the username is the same as the one provided and isn't accidentally changed to email derived username - That happens only for organization member signup expect(dbUser?.username).toBe(userToCreate.username); }); - test("Signup fields prefilled with query params", async ({ page }) => { + test("Signup fields prefilled with query params", async ({ page, users }) => { const signupUrlWithParams = "/signup?username=rick-jones&email=rick-jones%40example.com"; await page.goto(signupUrlWithParams); await preventFlakyTest(page); @@ -254,18 +254,19 @@ test.describe("Email Signup Flow Test", async () => { await prisma.verificationToken.deleteMany({ where: { identifier: createdtoken.identifier } }); await prisma.team.deleteMany({ where: { id: createdtoken.teamId! } }); }); - test("Email verification sent if enabled", async ({ page, emails, users, features }) => { + test("Email verification sent if enabled", async ({ page, prisma, emails, users, features }) => { const EmailVerifyFlag = features.get("email-verification")?.enabled; // eslint-disable-next-line playwright/no-skipped-test test.skip(!EmailVerifyFlag || !IS_MAILHOG_ENABLED, "Skipping check - Email verify disabled"); - // Use the features fixture to set the flag - it will be reset in beforeEach via features.reset() - await features.set("email-verification", true); - // Use unique username with timestamp to avoid collisions with parallel tests - const uniqueUsername = `email-verify-${Date.now()}`; + // Ensure email verification before testing (TODO: this could break other tests but we can fix that later) + await prisma.feature.update({ + where: { slug: "email-verification" }, + data: { enabled: true }, + }); const userToCreate = users.buildForSignup({ - email: users.trackEmail({ username: uniqueUsername, domain: "example.com" }), - username: uniqueUsername, + email: users.trackEmail({ username: "email-verify", domain: "example.com" }), + username: "email-verify", password: "Password99!", }); @@ -353,18 +354,16 @@ test.describe("Email Signup Flow Test", async () => { }); }); - test("Checkbox for cookie consent does not need to be checked", async ({ page }) => { + test("Checkbox for cookie consent does not need to be checked", async ({ page, users }) => { await page.goto("/signup"); await preventFlakyTest(page); // Navigate to email form await page.getByTestId("continue-with-email-button").click(); - // Fill form with unique username to avoid collisions with parallel tests - // Note: This test doesn't submit the form, so we don't need to create a real user - const uniqueUsername = `cookie-test-${Date.now()}`; - await page.locator('input[name="username"]').fill(uniqueUsername); - await page.locator('input[name="email"]').fill(`${uniqueUsername}@example.com`); + // Fill form + await page.locator('input[name="username"]').fill("pro"); + await page.locator('input[name="email"]').fill("pro@example.com"); await page.locator('input[name="password"]').fill("Password99!"); const submitButton = page.getByTestId("signup-submit-button"); diff --git a/apps/web/playwright/team/team-invitation.e2e.ts b/apps/web/playwright/team/team-invitation.e2e.ts index 33199f0160..fb934709eb 100644 --- a/apps/web/playwright/team/team-invitation.e2e.ts +++ b/apps/web/playwright/team/team-invitation.e2e.ts @@ -30,8 +30,7 @@ test.describe("Team", () => { }); await page.goto(`/settings/teams/${team.id}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible and clickable instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded await page.getByTestId("new-member-button").click(); await page.locator('input[name="inviteUser"]').fill(invitedUserEmail); await page.getByText(t("send_invite")).click(); @@ -83,16 +82,14 @@ test.describe("Team", () => { await page.goto(`/settings/teams/${team.id}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible and clickable instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded await page.getByTestId("new-member-button").click(); const inviteLink = await getInviteLink(page); const context = await browser.newContext(); const inviteLinkPage = await context.newPage(); await inviteLinkPage.goto(inviteLink); - // Wait for the form to be fully loaded instead of fixed 3s wait - await inviteLinkPage.locator("button[type=submit]").waitFor({ state: "visible" }); + await inviteLinkPage.waitForTimeout(3000); await inviteLinkPage.locator("button[type=submit]").click(); await expect(inviteLinkPage.locator('[data-testid="field-error"]')).toHaveCount(2); @@ -119,8 +116,7 @@ test.describe("Team", () => { }); await page.goto(`/settings/teams/${team.id}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible and clickable instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded await page.getByTestId("new-member-button").click(); await page.locator('input[name="inviteUser"]').fill(invitedUserEmail); await page.getByText(t("send_invite")).click(); @@ -168,8 +164,7 @@ test.describe("Team", () => { await page.goto(`/settings/teams/${team.id}/settings`); await page.goto(`/settings/teams/${team.id}/members`); await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible and clickable instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded await page.getByTestId("new-member-button").click(); await page.locator('input[name="inviteUser"]').fill(invitedMember.email); await page.getByText(t("send_invite")).click(); @@ -213,8 +208,7 @@ test.describe("Team", () => { await test.step("Send invitation to existing user", async () => { await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); await page.getByTestId("new-member-button").click(); await page.locator('input[name="inviteUser"]').fill(invitedUser.email); await page.getByText(t("send_invite")).click(); @@ -278,8 +272,7 @@ test.describe("Team", () => { await test.step("Send invitation to specific user", async () => { await page.waitForLoadState("domcontentloaded"); - // Wait for the new member button to be visible instead of fixed 500ms wait - await page.getByTestId("new-member-button").waitFor({ state: "visible" }); + await page.waitForTimeout(500); await page.getByTestId("new-member-button").click(); await page.locator('input[name="inviteUser"]').fill(invitedUser.email); await page.getByText(t("send_invite")).click();