refactor: remove networkidle waiters (#16483)
* refactor: remove networkidle waiters * Update out-of-office.e2e.ts * Update auth-index.e2e.ts * WIP * Update booking-limits.e2e.ts * fix-conflicts * fix failed e2e tests --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: unknown <adhabal2002@gmail.com>
This commit is contained in:
co-authored by
Anik Dhabal Babu
unknown
parent
9bfd933699
commit
747591fded
@@ -1,22 +1,27 @@
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
import { test } from "../lib/fixtures";
|
||||
import { submitAndWaitForResponse } from "../lib/testUtils";
|
||||
|
||||
test.describe("Can signup from a team invite", async () => {
|
||||
test.beforeEach(async ({ users }) => {
|
||||
const proUser = await users.create();
|
||||
await proUser.apiLogin();
|
||||
});
|
||||
test.afterEach(async ({ users }) => users.deleteAll());
|
||||
test.afterEach(async ({ users }) => {
|
||||
await users.deleteAll();
|
||||
});
|
||||
|
||||
test("Team invites validations work and can accept invite", async ({ browser, page, users, prisma }) => {
|
||||
const [proUser] = users.get();
|
||||
const teamName = `${proUser.username}'s Team`;
|
||||
const testUser = {
|
||||
username: `${proUser.username}-member`,
|
||||
password: `${proUser.username}-member`,
|
||||
// At least one number, lower and uppercase letters
|
||||
password: `${proUser.username}-MEMBER`,
|
||||
email: `${proUser.username}-member@example.com`,
|
||||
};
|
||||
await page.goto("/settings/teams/new");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Create a new team
|
||||
await page.locator('input[name="name"]').fill(teamName);
|
||||
@@ -26,72 +31,65 @@ test.describe("Can signup from a team invite", async () => {
|
||||
// Add new member to team
|
||||
await page.click('[data-testid="new-member-button"]');
|
||||
await page.fill('input[id="inviteUser"]', testUser.email);
|
||||
await page.click('[data-testid="invite-new-member-button"]');
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
// TODO: Adapt to new flow
|
||||
const tokenObj = await prisma.verificationToken.findFirstOrThrow({
|
||||
where: { identifier: testUser.email },
|
||||
select: { token: true },
|
||||
});
|
||||
|
||||
// Wait for the invite to be sent
|
||||
/*await page.waitForSelector(`[data-testid="member-email"][data-email="${testUser.email}"]`);
|
||||
if (!proUser.username) throw Error("Test username is null, can't continue");
|
||||
|
||||
const tokenObj = await prisma.verificationToken.findFirstOrThrow({
|
||||
where: { identifier: testUser.email },
|
||||
select: { token: true },
|
||||
});
|
||||
// Open a new user window to accept the invite
|
||||
const context = await browser.newContext();
|
||||
const newPage = await context.newPage();
|
||||
await newPage.goto(`/auth/signup?token=${tokenObj.token}&callbackUrl=/settings/teams`);
|
||||
// We wait on locales so we prevent password lost on re-render
|
||||
await newPage.locator('text="Create your account"').waitFor();
|
||||
|
||||
if (!proUser.username) throw Error("Test username is null, can't continue");
|
||||
// Fill in form
|
||||
await newPage.fill('input[name="username"]', proUser.username); // Invalid username
|
||||
await newPage.fill('input[name="password"]', testUser.password);
|
||||
await submitAndWaitForResponse(newPage, "/api/auth/signup", { expectedStatusCode: 409 });
|
||||
await expect(newPage.locator('text="Username or email is already taken"')).toBeVisible();
|
||||
|
||||
// Open a new user window to accept the invite
|
||||
const newPage = await browser.newPage();
|
||||
await newPage.goto(`/auth/signup?token=${tokenObj.token}&callbackUrl=${WEBAPP_URL}/settings/teams`);
|
||||
// Successful signup
|
||||
// TODO: Form errors don't disappear when corrected and resubmitted, so we need to refresh
|
||||
await newPage.reload();
|
||||
await newPage.fill('input[name="username"]', testUser.username);
|
||||
await newPage.fill('input[name="password"]', testUser.password);
|
||||
await submitAndWaitForResponse(newPage, "/api/auth/signup", { expectedStatusCode: 201 });
|
||||
// Since it's a new user, it shoud be redirected to the onboarding
|
||||
await newPage.locator('text="Welcome to Cal.com!"').waitFor();
|
||||
await expect(newPage.locator('text="Welcome to Cal.com!"')).toBeVisible();
|
||||
// We don't need the new browser anymore
|
||||
await newPage.close();
|
||||
|
||||
// Fill in form
|
||||
await newPage.fill('input[name="username"]', proUser.username); // Invalid username
|
||||
await newPage.fill('input[name="email"]', testUser.email);
|
||||
await newPage.fill('input[name="password"]', testUser.password);
|
||||
await newPage.fill('input[name="passwordcheck"]', testUser.password);
|
||||
await newPage.press('input[name="passwordcheck"]', "Enter"); // Press Enter to submit
|
||||
const createdUser = await prisma.user.findUniqueOrThrow({
|
||||
where: { email: testUser.email },
|
||||
include: {
|
||||
teams: { include: { team: true } },
|
||||
password: {
|
||||
select: { hash: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await expect(newPage.locator('text="Username already taken"')).toBeVisible();
|
||||
console.log("createdUser", createdUser);
|
||||
|
||||
// Email address is already registered
|
||||
// TODO: Form errors don't disappear when corrected and resubmitted, so we need to refresh
|
||||
await newPage.reload();
|
||||
await newPage.fill('input[name="username"]', testUser.username);
|
||||
await newPage.fill('input[name="email"]', `${proUser.username}@example.com`); // Taken email
|
||||
await newPage.fill('input[name="password"]', testUser.password);
|
||||
await newPage.fill('input[name="passwordcheck"]', testUser.password);
|
||||
await newPage.press('input[name="passwordcheck"]', "Enter"); // Press Enter to submit
|
||||
await expect(newPage.locator('text="Email address is already registered"')).toBeVisible();
|
||||
|
||||
// Successful signup
|
||||
// TODO: Form errors don't disappear when corrected and resubmitted, so we need to refresh
|
||||
await newPage.reload();
|
||||
await newPage.fill('input[name="username"]', testUser.username);
|
||||
await newPage.fill('input[name="email"]', testUser.email);
|
||||
await newPage.fill('input[name="password"]', testUser.password);
|
||||
await newPage.fill('input[name="passwordcheck"]', testUser.password);
|
||||
await newPage.press('input[name="passwordcheck"]', "Enter"); // Press Enter to submit
|
||||
await expect(newPage.locator(`[data-testid="login-form"]`)).toBeVisible();
|
||||
|
||||
// We don't need the new browser anymore
|
||||
await newPage.close();
|
||||
|
||||
const createdUser = await prisma.user.findUniqueOrThrow({
|
||||
where: { email: testUser.email },
|
||||
include: { teams: { include: { team: true } } },
|
||||
});
|
||||
|
||||
console.log("createdUser", createdUser);
|
||||
|
||||
// Check that the user was created
|
||||
expect(createdUser).not.toBeNull();
|
||||
expect(createdUser.username).toBe(testUser.username);
|
||||
expect(createdUser.password).not.toBeNull();
|
||||
expect(createdUser.emailVerified).not.toBeNull();
|
||||
// Check that the user accepted the team invite
|
||||
expect(createdUser.teams).toHaveLength(1);
|
||||
expect(createdUser.teams[0].team.name).toBe(teamName);
|
||||
expect(createdUser.teams[0].role).toBe("MEMBER");
|
||||
expect(createdUser.teams[0].accepted).toBe(true);*/
|
||||
// Check that the user was created
|
||||
expect(createdUser).not.toBeNull();
|
||||
expect(createdUser.username).toBe(testUser.username);
|
||||
expect(createdUser.password?.hash).not.toBeNull();
|
||||
expect(createdUser.emailVerified).not.toBeNull();
|
||||
// Check that the user accepted the team invite
|
||||
expect(createdUser.teams).toHaveLength(1);
|
||||
expect(createdUser.teams[0].team.name).toBe(teamName);
|
||||
expect(createdUser.teams[0].role).toBe("MEMBER");
|
||||
expect(createdUser.teams[0].accepted).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { expect } from "@playwright/test";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
|
||||
import { test } from "./lib/fixtures";
|
||||
import { localize } from "./lib/testUtils";
|
||||
import { localize, submitAndWaitForResponse } from "./lib/testUtils";
|
||||
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
|
||||
@@ -39,7 +39,7 @@ test.describe("Availablity", () => {
|
||||
const nextMonth = dayjs().add(1, "month").startOf("month");
|
||||
const troubleshooterURL = `/availability/troubleshoot?date=${nextMonth.format("YYYY-MM-DD")}`;
|
||||
await page.goto(troubleshooterURL);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('[data-testid="troubleshooter-busy-time"]')).toHaveCount(1);
|
||||
});
|
||||
|
||||
@@ -121,18 +121,17 @@ test.describe("Availablity", () => {
|
||||
await test.step("Can delete a schedule", async () => {
|
||||
await page.getByTestId("go-back-button").click();
|
||||
await page.locator('[data-testid="schedules"] > li').nth(1).getByTestId("schedule-more").click();
|
||||
await page.locator('[data-testid="delete-schedule"]').click();
|
||||
const toast = await page.waitForSelector('[data-testid="toast-success"]');
|
||||
expect(toast).toBeTruthy();
|
||||
|
||||
await submitAndWaitForResponse(page, "/api/trpc/availability/schedule.delete?batch=1", {
|
||||
action: () => page.locator('[data-testid="delete-schedule"]').click(),
|
||||
});
|
||||
await expect(page.locator('[data-testid="schedules"] > li').nth(1)).toHaveCount(0);
|
||||
});
|
||||
await test.step("Cannot delete the last schedule", async () => {
|
||||
await page.locator('[data-testid="schedules"] > li').nth(0).getByTestId("schedule-more").click();
|
||||
await page.locator('[data-testid="delete-schedule"]').click();
|
||||
// FIXME: Check on toast to be present causes flakiness, cannot check for response since it's client side validated as well
|
||||
const toast = await page.waitForSelector('[data-testid="toast-error"]');
|
||||
expect(toast).toBeTruthy();
|
||||
|
||||
await expect(page.locator('[data-testid="schedules"] > li').nth(0)).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
@@ -183,8 +182,7 @@ test.describe("Availablity", () => {
|
||||
|
||||
await page.locator("[id=timeZone-lg-viewport]").fill("bras");
|
||||
await page.getByTestId("select-option-America/Sao_Paulo").click();
|
||||
await page.getByRole("button", { name: save }).click();
|
||||
await expect(page.getByTestId("toast-success").last()).toBeVisible();
|
||||
await submitAndWaitForResponse(page, "/api/trpc/availability/schedule.update?batch=1");
|
||||
await page.getByTestId("add-override").click();
|
||||
await page.getByTestId("incrementMonth").click();
|
||||
await page.getByRole("button", { name: "20" }).click();
|
||||
@@ -192,7 +190,6 @@ test.describe("Availablity", () => {
|
||||
await page.getByTestId("add-override-submit-btn").click();
|
||||
await page.getByTestId("dialog-rejection").click();
|
||||
await page.getByTestId("date-overrides-list").getByRole("button").nth(1).click();
|
||||
await page.getByRole("button", { name: save }).click();
|
||||
await expect(page.getByTestId("toast-success").last()).toBeVisible();
|
||||
await submitAndWaitForResponse(page, "/api/trpc/availability/schedule.update?batch=1");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,13 +59,12 @@ const getLastEventUrlWithMonth = (user: Awaited<ReturnType<typeof createUserWith
|
||||
return `/${user.username}/${user.eventTypes.at(-1)?.slug}?month=${date.format("YYYY-MM")}`;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip("Booking limits", () => {
|
||||
test.describe("Booking limits", () => {
|
||||
entries(BOOKING_LIMITS_SINGLE).forEach(([limitKey, bookingLimit]) => {
|
||||
const limitUnit = intervalLimitKeyToUnit(limitKey);
|
||||
|
||||
// test one limit at a time
|
||||
test(limitUnit, async ({ page, users }) => {
|
||||
test.fixme(`Per ${limitUnit}`, async ({ page, users }) => {
|
||||
const slug = `booking-limit-${limitUnit}`;
|
||||
const singleLimit = { [limitKey]: bookingLimit };
|
||||
|
||||
@@ -166,7 +165,7 @@ test.skip("Booking limits", () => {
|
||||
|
||||
await page.locator('[data-testid="confirm-reschedule-button"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
|
||||
const newBooking = await prisma.booking.findFirstOrThrow({ where: { fromReschedule: bookingId } });
|
||||
|
||||
@@ -300,10 +300,10 @@ testBothFutureAndLegacyRoutes.describe("pro user", () => {
|
||||
await eventTypeLink.waitFor();
|
||||
await eventTypeLink.click();
|
||||
|
||||
await pageTwo.waitForLoadState("networkidle");
|
||||
// await pageTwo.waitForLoadState("networkidle");
|
||||
await pageTwo.locator('[data-testid="incrementMonth"]').waitFor();
|
||||
await pageTwo.click('[data-testid="incrementMonth"]');
|
||||
await pageTwo.waitForLoadState("networkidle");
|
||||
// await pageTwo.waitForLoadState("networkidle");
|
||||
await pageTwo.locator('[data-testid="day"][data-disabled="false"]').nth(0).waitFor();
|
||||
await pageTwo.locator('[data-testid="day"][data-disabled="false"]').nth(0).click();
|
||||
|
||||
@@ -337,10 +337,10 @@ testBothFutureAndLegacyRoutes.describe("pro user", () => {
|
||||
await page.locator('[data-testid="back"]').waitFor();
|
||||
await page.click('[data-testid="back"]');
|
||||
|
||||
await pageTwo.waitForLoadState("networkidle");
|
||||
// await pageTwo.waitForLoadState("networkidle");
|
||||
await pageTwo.locator('[data-testid="incrementMonth"]').waitFor();
|
||||
await pageTwo.click('[data-testid="incrementMonth"]');
|
||||
await pageTwo.waitForLoadState("networkidle");
|
||||
// await pageTwo.waitForLoadState("networkidle");
|
||||
await pageTwo.locator('[data-testid="day"][data-disabled="false"]').nth(0).waitFor();
|
||||
await pageTwo.locator('[data-testid="day"][data-disabled="false"]').nth(0).click();
|
||||
|
||||
@@ -509,7 +509,7 @@ testBothFutureAndLegacyRoutes.describe("Booking round robin event", () => {
|
||||
// books 9AM slots for 120 minutes (test-user is not available at this time, availability starts at 10)
|
||||
await page.locator('[data-testid="time"]').nth(0).click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.locator('[name="name"]').fill("Test name");
|
||||
await page.locator('[name="email"]').fill(`${randomString(4)}@example.com`);
|
||||
@@ -541,7 +541,7 @@ testBothFutureAndLegacyRoutes.describe("Booking round robin event", () => {
|
||||
// Again book a 9AM slot for 120 minutes where test-user is not available
|
||||
await page.locator('[data-testid="time"]').nth(0).click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.locator('[name="name"]').fill("Test name");
|
||||
await page.locator('[name="email"]').fill(`${randomString(4)}@example.com`);
|
||||
|
||||
@@ -104,7 +104,9 @@ test.describe("Booking with Seats", () => {
|
||||
|
||||
// confirm cancellation
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.locator("text=This event is canceled")).toBeVisible();
|
||||
|
||||
const updatedBooking = await prisma.booking.findFirst({
|
||||
where: { id: booking.id },
|
||||
@@ -227,9 +229,9 @@ test.describe("Reschedule for booking with seats", () => {
|
||||
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page).toHaveURL(/\/booking\/.*/);
|
||||
await expect(page.locator("text=You are no longer attending this event")).toBeVisible();
|
||||
|
||||
await page.goto(
|
||||
`/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[1].referenceUid}`
|
||||
@@ -238,9 +240,9 @@ test.describe("Reschedule for booking with seats", () => {
|
||||
// Page should not be 404
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page).toHaveURL(/\/booking\/.*/);
|
||||
await expect(page.locator("text=You are no longer attending this event")).toBeVisible();
|
||||
});
|
||||
|
||||
test("Should book with seats and hide attendees info from showAttendees true", async ({
|
||||
@@ -406,7 +408,7 @@ test.describe("Reschedule for booking with seats", () => {
|
||||
|
||||
await expect(page).toHaveURL(/\/booking\/.*/);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const updatedBooking = await prisma.booking.findFirst({
|
||||
where: { id: booking.id },
|
||||
|
||||
@@ -13,7 +13,7 @@ test.describe("Change Password Test", () => {
|
||||
|
||||
expect(pro.username).toBeTruthy();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// Fill form
|
||||
await page.locator('[name="oldPassword"]').fill(String(pro.username));
|
||||
|
||||
@@ -9,7 +9,7 @@ test.describe("Change Theme Test", () => {
|
||||
|
||||
await page.goto("/settings/my-account/appearance");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
//Click the "Dark" theme label
|
||||
await page.click('[data-testid="theme-dark"]');
|
||||
//Click the update button
|
||||
@@ -29,7 +29,7 @@ test.describe("Change Theme Test", () => {
|
||||
|
||||
await page.goto("/settings/my-account/appearance");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
//Click the "Light" theme label
|
||||
await page.click('[data-testid="theme-light"]');
|
||||
//Click the update theme button
|
||||
|
||||
@@ -60,7 +60,7 @@ test.describe("Change username on settings", () => {
|
||||
page.click("[data-testid=save-username]"),
|
||||
page.getByTestId("toast-success").waitFor(),
|
||||
]);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const updatedUser = await prisma.user.findUniqueOrThrow({
|
||||
where: {
|
||||
@@ -149,7 +149,7 @@ test.describe("Change username on settings", () => {
|
||||
const usernameInput = page.locator("[data-testid=username-input]");
|
||||
|
||||
await usernameInput.fill(previousUsername);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator("[data-testid=update-username-btn]").nth(0)).toBeHidden();
|
||||
await expect(page.locator("[data-testid=update-username-btn]").nth(1)).toBeHidden();
|
||||
});
|
||||
|
||||
@@ -70,7 +70,7 @@ test("dynamic booking info prefilled by query params", async ({ page, users }) =
|
||||
const free = await users.create({ username: "free.example" });
|
||||
await page.goto(`/${pro.username}+${free.username}?duration=${duration}`);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const listItemByDurationTestId = (duration: number) => `multiple-choice-${duration}mins`;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ testBothFutureAndLegacyRoutes.describe("Event Types tests", () => {
|
||||
const nonce = randomString(3);
|
||||
const eventTitle = `my recurring event ${nonce}`;
|
||||
await createNewEventType(page, { eventTitle });
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.click("[data-testid=vertical-tab-recurring]");
|
||||
await expect(page.locator("[data-testid=recurring-event-collapsible]")).toBeHidden();
|
||||
@@ -270,14 +270,14 @@ testBothFutureAndLegacyRoutes.describe("Event Types tests", () => {
|
||||
await addAnotherLocation(page, "Cal Video (Global)");
|
||||
|
||||
await saveEventType(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// Remove Attendee Phone Number Location
|
||||
const removeButtomId = "delete-locations.0.type";
|
||||
await page.getByTestId(removeButtomId).click();
|
||||
|
||||
await saveEventType(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await gotoBookingPage(page);
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
|
||||
@@ -62,11 +62,11 @@ export function createAppsFixture(page: Page) {
|
||||
}
|
||||
await page.locator("[data-testid=display-location]").last().check();
|
||||
await saveEventType(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await gotoBookingPage(page);
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
await bookTimeSlot(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
await expect(page.locator("[data-testid=where] ")).toContainText(app.label);
|
||||
@@ -94,11 +94,11 @@ export function createAppsFixture(page: Page) {
|
||||
verifyConferencingAppNew: async (app: TApp, eventTypeIds: number[]) => {
|
||||
for (const id of eventTypeIds) {
|
||||
await page.goto(`/event-types/${id}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await gotoBookingPage(page);
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
await bookTimeSlot(page, { name: `Test Testson`, email: `test@example.com` });
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
await expect(page.locator("[data-testid=where] ")).toContainText(app.label);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ test.describe("hash my url", () => {
|
||||
// click update
|
||||
await page.locator('[data-testid="update-eventtype"]').press("Enter");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// book using generated url hash
|
||||
await page.goto($url);
|
||||
@@ -61,7 +61,7 @@ test.describe("hash my url", () => {
|
||||
await page.locator("[data-testid=update-eventtype]").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await page.locator(".primary-navigation >> text=Advanced").click();
|
||||
const $url2 = await page.locator('//*[@data-testid="generated-hash-url"]').inputValue();
|
||||
expect($url2.includes("somethingrandom")).toBeTruthy();
|
||||
|
||||
@@ -41,6 +41,7 @@ test.describe("Users can impersonate", async () => {
|
||||
await stopImpersonatingButton.click();
|
||||
await expect(stopImpersonatingButton).toBeHidden();
|
||||
|
||||
// await page.waitForLoadState("networkidle");
|
||||
// Return to user
|
||||
const ogUser = await impersonatedUsernameInput.inputValue();
|
||||
|
||||
|
||||
@@ -75,11 +75,10 @@ test.describe("Insights", async () => {
|
||||
|
||||
// go to insights page
|
||||
await page.goto("/insights");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForURL(/.*\/insights\?teamId=[^&]*&isAll=false.*/);
|
||||
|
||||
// expect url to have isAll and TeamId in query params
|
||||
expect(page.url()).toContain("isAll=false");
|
||||
expect(page.url()).toContain("teamId=");
|
||||
await expect(page).toHaveURL(/.*\/insights\?teamId=[^&]*&isAll=false.*/);
|
||||
});
|
||||
|
||||
test("should be able to go to insights as members", async ({ page, users }) => {
|
||||
@@ -92,12 +91,10 @@ test.describe("Insights", async () => {
|
||||
// go to insights page
|
||||
await page.goto("/insights");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForURL(/.*\/insights\?userId=[^&]*&isAll=false.*/);
|
||||
|
||||
// expect url to have isAll and TeamId in query params
|
||||
|
||||
expect(page.url()).toContain("isAll=false");
|
||||
expect(page.url()).not.toContain("teamId=");
|
||||
await expect(page).toHaveURL(/.*\/insights\?userId=[^&]*&isAll=false.*/);
|
||||
});
|
||||
|
||||
test("team select filter should have 2 teams and your account option only as member", async ({
|
||||
@@ -113,7 +110,7 @@ test.describe("Insights", async () => {
|
||||
// go to insights page
|
||||
await page.goto("/insights");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// get div from team select filter with this class flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1
|
||||
await page.getByTestId("dashboard-shell").getByText("Team: test-insights").click();
|
||||
@@ -137,7 +134,7 @@ test.describe("Insights", async () => {
|
||||
await owner.apiLogin();
|
||||
|
||||
await page.goto("/insights");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.getByTestId("dashboard-shell").getByText("All").nth(1).click();
|
||||
|
||||
@@ -223,7 +220,7 @@ test.describe("Insights", async () => {
|
||||
)
|
||||
.nth(0)
|
||||
.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await page
|
||||
.locator(
|
||||
@@ -231,7 +228,7 @@ test.describe("Insights", async () => {
|
||||
)
|
||||
.nth(1)
|
||||
.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
// press escape button to close the filter
|
||||
await page.keyboard.press("Escape");
|
||||
|
||||
@@ -250,7 +247,7 @@ test.describe("Insights", async () => {
|
||||
await owner.apiLogin();
|
||||
|
||||
await page.goto("/insights");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
|
||||
|
||||
@@ -430,3 +430,15 @@ export async function gotoBookingPage(page: Page) {
|
||||
export async function saveEventType(page: Page) {
|
||||
await page.locator("[data-testid=update-eventtype]").click();
|
||||
}
|
||||
|
||||
/** Fastest way so far to test for saving changes and form submissions */
|
||||
export async function submitAndWaitForResponse(
|
||||
page: Page,
|
||||
url: string,
|
||||
{ action = () => page.locator('[type="submit"]').click(), expectedStatusCode = 200 } = {}
|
||||
) {
|
||||
const submitPromise = page.waitForResponse(url);
|
||||
await action();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(expectedStatusCode);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,12 @@ import { apiLogin } from "playwright/fixtures/users";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
import { test, type Fixtures } from "./lib/fixtures";
|
||||
import { bookTimeSlot, localize, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils";
|
||||
import {
|
||||
bookTimeSlot,
|
||||
localize,
|
||||
submitAndWaitForResponse,
|
||||
selectFirstAvailableTimeSlotNextMonth,
|
||||
} from "./lib/testUtils";
|
||||
|
||||
test.afterEach(async ({ users }) => {
|
||||
await users.deleteAll();
|
||||
@@ -98,7 +103,7 @@ test.describe("Managed Event Types", () => {
|
||||
const optionText = await getByKey(page, "organizer_default_conferencing_app");
|
||||
await expect(optionText).toBeVisible();
|
||||
await optionText.click();
|
||||
await submitAndWaitForResponse(page);
|
||||
await saveAndWaitForResponse(page);
|
||||
|
||||
await page.getByTestId("vertical-tab-assignment").click();
|
||||
await gotoBookingPage(page);
|
||||
@@ -177,7 +182,7 @@ test.describe("Managed Event Types", () => {
|
||||
await memberPage.waitForURL("event-types/**");
|
||||
await expect(memberPage.locator('input[name="title"]')).toBeEditable();
|
||||
await memberPage.locator('input[name="title"]').fill(`Managed Event Title`);
|
||||
await submitAndWaitForResponse(memberPage);
|
||||
await saveAndWaitForResponse(memberPage);
|
||||
|
||||
// We edit the managed event as original owner
|
||||
const adminContext = await browser.newContext();
|
||||
@@ -188,7 +193,7 @@ test.describe("Managed Event Types", () => {
|
||||
await adminPage.getByTestId("event-types").locator(`a[title="${teamEventTitle}"]`).click();
|
||||
await adminPage.waitForURL("event-types/**");
|
||||
await adminPage.locator('input[name="length"]').fill(`45`);
|
||||
await submitAndWaitForResponse(adminPage);
|
||||
await saveAndWaitForResponse(adminPage);
|
||||
await adminContext.close();
|
||||
|
||||
await memberPage.goto("/event-types");
|
||||
@@ -200,7 +205,7 @@ test.describe("Managed Event Types", () => {
|
||||
expect(await memberPage.locator(`input[name="title"]`).getAttribute("value")).toBe(`Managed Event Title`);
|
||||
await memberPage.locator('input[name="title"]').fill(`managed`);
|
||||
// Save changes
|
||||
await submitAndWaitForResponse(memberPage);
|
||||
await saveAndWaitForResponse(memberPage);
|
||||
});
|
||||
|
||||
const MANAGED_EVENT_TABS: { slug: string; locator: (page: Page) => Locator | Promise<Locator> }[] = [
|
||||
@@ -252,9 +257,6 @@ async function gotoBookingPage(page: Page) {
|
||||
await page.goto(previewLink ?? "");
|
||||
}
|
||||
|
||||
async function submitAndWaitForResponse(page: Page) {
|
||||
const submitPromise = page.waitForResponse("/api/trpc/eventTypes/update?batch=1");
|
||||
await page.locator('[type="submit"]').click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
async function saveAndWaitForResponse(page: Page) {
|
||||
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1");
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ test.describe("OAuth Provider", () => {
|
||||
`auth/oauth2/authorize?client_id=${client.clientId}&redirect_uri=${client.redirectUri}&response_type=code&scope=READ_PROFILE&state=1234`
|
||||
);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await page.getByTestId("allow-button").click();
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
@@ -112,7 +112,7 @@ test.describe("OAuth Provider", () => {
|
||||
`auth/oauth2/authorize?client_id=${client.clientId}&redirect_uri=${client.redirectUri}&response_type=code&scope=READ_PROFILE&state=1234`
|
||||
);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.locator("#account-select").click();
|
||||
|
||||
|
||||
@@ -47,14 +47,13 @@ test.describe("user1NotMemberOfOrg1 is part of team1MemberOfOrg1", () => {
|
||||
|
||||
await user1NotMemberOfOrg1.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const userEventLinksLocators = await page
|
||||
.locator(`[data-testid=slug-${user1NotMemberOfOrg1.username}] [data-testid="preview-link-button"]`)
|
||||
.all();
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const userEventLinksSelector = `[data-testid=slug-${user1NotMemberOfOrg1.username}] [data-testid="preview-link-button"]`;
|
||||
await page.waitForSelector(userEventLinksSelector);
|
||||
|
||||
// Get all the event links
|
||||
const userEventLinksLocators = await page.locator(userEventLinksSelector).all();
|
||||
expect(userEventLinksLocators.length).toBeGreaterThan(0);
|
||||
|
||||
for (const userEventLinkLocator of userEventLinksLocators) {
|
||||
const href = await userEventLinkLocator.getAttribute("href");
|
||||
expect(href).toContain(WEBAPP_URL);
|
||||
|
||||
@@ -13,7 +13,7 @@ export const inviteUserToOrganization = async ({
|
||||
usersFixture: ReturnType<typeof createUsersFixture>;
|
||||
}) => {
|
||||
await page.goto("/settings/organizations/members");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const invitedUserEmail = usersFixture.trackEmail({
|
||||
username: email.split("@")[0],
|
||||
domain: email.split("@")[1],
|
||||
@@ -36,7 +36,7 @@ export const inviteExistingUserToOrganization = async ({
|
||||
usersFixture: ReturnType<typeof createUsersFixture>;
|
||||
}) => {
|
||||
await page.goto("/settings/organizations/members");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await inviteAnEmail(page, user.email);
|
||||
await page.waitForSelector('[data-testid="toast-success"]');
|
||||
@@ -46,12 +46,12 @@ export const inviteExistingUserToOrganization = async ({
|
||||
export async function acceptTeamOrOrgInvite(page: Page) {
|
||||
await page.goto("/settings/teams");
|
||||
await page.click('[data-testid^="accept-invitation"]');
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
}
|
||||
|
||||
async function inviteAnEmail(page: Page, invitedUserEmail: string) {
|
||||
await page.locator('button:text("Add")').click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.locator('button:text("Send invite")').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ test.describe("Organization", () => {
|
||||
const orgName = capitalize(`${orgOwnerUser.username}`);
|
||||
const orgSlug = `myOrg-${uuid()}`.toLowerCase();
|
||||
await page.goto("/settings/organizations/new");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("Basic info", async () => {
|
||||
// Check required fields
|
||||
@@ -192,7 +192,7 @@ test.describe("Organization", () => {
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(2);
|
||||
const lastRemoveMemberButton = page.getByTestId("remove-member-button").last();
|
||||
await lastRemoveMemberButton.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
await page.getByTestId("publish-button").click();
|
||||
// Waiting to be in next step URL
|
||||
@@ -232,7 +232,7 @@ test.describe("Organization", () => {
|
||||
expect(url).toContain(expectedUrl);
|
||||
|
||||
await fillStripeTestCheckout(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const upgradeButtonHidden = await page.getByTestId("upgrade_org_banner_button");
|
||||
|
||||
@@ -268,7 +268,7 @@ test.describe("Organization", () => {
|
||||
});
|
||||
|
||||
await page.goto("/settings/organizations/new");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("Basic info", async () => {
|
||||
// Check required fields
|
||||
@@ -309,7 +309,7 @@ test.describe("Organization", () => {
|
||||
await orgOwnerUser.apiLogin();
|
||||
const orgName = capitalize(`${orgOwnerUsername}`);
|
||||
await page.goto("/settings/organizations/new");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("Basic info", async () => {
|
||||
// These values are infered due to an existing user being signed
|
||||
@@ -320,7 +320,7 @@ test.describe("Organization", () => {
|
||||
await page.locator("input[name=slug]").fill(orgOwnerUsername);
|
||||
|
||||
await page.locator("button[type=submit]").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
});
|
||||
|
||||
await test.step("About the organization", async () => {
|
||||
@@ -364,7 +364,7 @@ test.describe("Organization", () => {
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(2);
|
||||
const lastRemoveMemberButton = page.getByTestId("remove-member-button").last();
|
||||
await lastRemoveMemberButton.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
await page.getByTestId("publish-button").click();
|
||||
// Waiting to be in next step URL
|
||||
@@ -402,7 +402,7 @@ test.describe("Organization", () => {
|
||||
expect(url).toContain(expectedUrl);
|
||||
|
||||
await fillStripeTestCheckout(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const upgradeButtonHidden = await page.getByTestId("upgrade_org_banner_button");
|
||||
|
||||
@@ -455,7 +455,7 @@ test.describe("Organization", () => {
|
||||
await slugLocator.fill(`example-${stringUUID}`);
|
||||
|
||||
await page.locator("button[type=submit]").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
});
|
||||
|
||||
await test.step("About the organization", async () => {
|
||||
@@ -499,7 +499,7 @@ test.describe("Organization", () => {
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(2);
|
||||
const lastRemoveMemberButton = page.getByTestId("remove-member-button").last();
|
||||
await lastRemoveMemberButton.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
await page.getByTestId("publish-button").click();
|
||||
// Waiting to be in next step URL
|
||||
@@ -547,7 +547,7 @@ test.describe("Organization", () => {
|
||||
expect(url).toContain(expectedUrl);
|
||||
|
||||
await fillStripeTestCheckout(page);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const upgradeButtonHidden = await page.getByTestId("upgrade_org_banner_button");
|
||||
|
||||
@@ -557,7 +557,7 @@ test.describe("Organization", () => {
|
||||
await test.step("Ensure correctnumberOfTeams are migrated", async () => {
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
await page.goto("/teams");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const teamListItems = await page.getByTestId("team-list-item-link").all();
|
||||
|
||||
// Number of teams migrated + the two created in the create teams step
|
||||
|
||||
@@ -24,7 +24,7 @@ test.describe("Organization", () => {
|
||||
const { team: org } = await orgOwner.getOrgMembership();
|
||||
await orgOwner.apiLogin();
|
||||
await page.goto("/settings/organizations/members");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("By email", async () => {
|
||||
const invitedUserEmail = users.trackEmail({ username: "rick", domain: "domain.com" });
|
||||
@@ -104,7 +104,7 @@ test.describe("Organization", () => {
|
||||
|
||||
await test.step("By email", async () => {
|
||||
await page.goto(`/settings/teams/${team.id}/members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const invitedUserEmail = users.trackEmail({ username: "rick", domain: "domain.com" });
|
||||
// '-domain' because the email doesn't match orgAutoAcceptEmail
|
||||
const usernameDerivedFromEmail = `${invitedUserEmail.split("@")[0]}-domain`;
|
||||
@@ -126,7 +126,7 @@ test.describe("Organization", () => {
|
||||
email: invitedUserEmail,
|
||||
});
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const inviteLink = await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
emails,
|
||||
@@ -206,7 +206,7 @@ test.describe("Organization", () => {
|
||||
const { team: org } = await orgOwner.getOrgMembership();
|
||||
await orgOwner.apiLogin();
|
||||
await page.goto("/settings/organizations/members");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("By email", async () => {
|
||||
const invitedUserEmail = users.trackEmail({ username: "rick", domain: "example.com" });
|
||||
@@ -309,6 +309,7 @@ test.describe("Organization", () => {
|
||||
.locator('input[name="email"]')
|
||||
.fill(`${existingUser.username}-differnet-email@example.com`);
|
||||
await page.locator('input[name="password"]').fill("Password99!");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('button[type="submit"]')).toBeDisabled();
|
||||
});
|
||||
});
|
||||
@@ -333,7 +334,7 @@ test.describe("Organization", () => {
|
||||
|
||||
await test.step("By email", async () => {
|
||||
await page.goto(`/settings/teams/${team.id}/members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const invitedUserEmail = users.trackEmail({ username: "rick", domain: "example.com" });
|
||||
const usernameDerivedFromEmail = invitedUserEmail.split("@")[0];
|
||||
await inviteAnEmail(page, invitedUserEmail);
|
||||
@@ -488,7 +489,7 @@ export async function signupFromEmailInviteLink({
|
||||
async function inviteAnEmail(page: Page, invitedUserEmail: string) {
|
||||
await page.locator('button:text("Add")').click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.locator('button:text("Send invite")').click();
|
||||
const response = await submitPromise;
|
||||
|
||||
@@ -57,7 +57,7 @@ test.describe("Teams", () => {
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(2);
|
||||
const lastRemoveMemberButton = page.getByTestId("remove-member-button").last();
|
||||
await lastRemoveMemberButton.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
|
||||
// Cleanup here since this user is created without our fixtures.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect } from "@playwright/test";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
@@ -7,6 +7,7 @@ import { randomString } from "@calcom/lib/random";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { test } from "./lib/fixtures";
|
||||
import { submitAndWaitForResponse } from "./lib/testUtils";
|
||||
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
test.afterEach(async ({ users }) => {
|
||||
@@ -20,10 +21,8 @@ test.describe("Out of office", () => {
|
||||
await user.apiLogin();
|
||||
|
||||
await page.goto("/settings/my-account/out-of-office");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.getByTestId("add_entry_ooo").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.getByTestId("reason_select").click();
|
||||
|
||||
await page.getByTestId("select-option-4").click();
|
||||
@@ -32,7 +31,9 @@ test.describe("Out of office", () => {
|
||||
await page.getByTestId("notes_input").fill("Demo notes");
|
||||
|
||||
// send request
|
||||
await submitAndWaitForResponse(page);
|
||||
await saveAndWaitForResponse(page);
|
||||
|
||||
await expect(page.locator(`data-testid=table-redirect-n-a`)).toBeVisible();
|
||||
});
|
||||
|
||||
test("User can configure booking redirect", async ({ page, users }) => {
|
||||
@@ -67,10 +68,8 @@ test.describe("Out of office", () => {
|
||||
await user.apiLogin();
|
||||
|
||||
await page.goto(`/settings/my-account/out-of-office`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.getByTestId("add_entry_ooo").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.getByTestId("reason_select").click();
|
||||
|
||||
await page.getByTestId("select-option-4").click();
|
||||
@@ -86,7 +85,10 @@ test.describe("Out of office", () => {
|
||||
await page.locator("#react-select-3-input").press("Enter");
|
||||
|
||||
// send request
|
||||
await submitAndWaitForResponse(page);
|
||||
await saveAndWaitForResponse(page);
|
||||
|
||||
// expect table-redirect-toUserId to be visible
|
||||
await expect(page.locator(`data-testid=table-redirect-${userTo.username}`)).toBeVisible();
|
||||
});
|
||||
|
||||
test("User can edit out of office entry", async ({ page, users }) => {
|
||||
@@ -146,7 +148,6 @@ test.describe("Out of office", () => {
|
||||
await user.apiLogin();
|
||||
|
||||
await page.goto(`/settings/my-account/out-of-office`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// expect table-redirect-toUserId to be visible
|
||||
await expect(page.locator(`data-testid=table-redirect-${userTo.username}`)).toBeVisible();
|
||||
@@ -163,7 +164,16 @@ test.describe("Out of office", () => {
|
||||
await page.locator("#react-select-3-input").press("Enter");
|
||||
|
||||
// send request
|
||||
await submitAndWaitForResponse(page);
|
||||
await saveAndWaitForResponse(page);
|
||||
|
||||
// expect entry with new username exist.
|
||||
await expect(page.locator(`data-testid=table-redirect-${userToSecond.username}`)).toBeVisible();
|
||||
|
||||
// expect new note to be present.
|
||||
await expect(page.locator(`data-testid=ooo-entry-note-${userToSecond.username}`)).toBeVisible();
|
||||
await expect(page.locator(`data-testid=ooo-entry-note-${userToSecond.username}`)).toContainText(
|
||||
"Changed notes"
|
||||
);
|
||||
});
|
||||
|
||||
test("Profile redirection", async ({ page, users }) => {
|
||||
@@ -187,7 +197,6 @@ test.describe("Out of office", () => {
|
||||
});
|
||||
|
||||
await page.goto(`/${user.username}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const eventTypeLink = page.locator('[data-testid="event-type-link"]').first();
|
||||
await eventTypeLink.click();
|
||||
@@ -195,9 +204,9 @@ test.describe("Out of office", () => {
|
||||
await expect(page.getByTestId("away-emoji")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
async function submitAndWaitForResponse(page: Page) {
|
||||
const submitPromise = page.waitForResponse("/api/trpc/viewer/outOfOfficeCreateOrUpdate?batch=1");
|
||||
await page.getByTestId("create-or-edit-entry-ooo-redirect").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
async function saveAndWaitForResponse(page: Page) {
|
||||
await submitAndWaitForResponse(page, "/api/trpc/viewer/outOfOfficeCreateOrUpdate?batch=1", {
|
||||
action: () => page.getByTestId("create-or-edit-entry-ooo-redirect").click(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export {};
|
||||
// await test.step("Settings should so no calendars connected", async () => {
|
||||
// const settingsCog = page.locator(`[data-testid=overlay-calendar-settings-button]`);
|
||||
// await settingsCog.click();
|
||||
// await page.waitForLoadState("networkidle");
|
||||
// // await page.waitForLoadState("networkidle");
|
||||
// const emptyScreenLocator = page.locator(`[data-testid=empty-screen]`);
|
||||
// await expect(emptyScreenLocator).toBeVisible();
|
||||
// });
|
||||
|
||||
@@ -43,7 +43,7 @@ testBothFutureAndLegacyRoutes.describe("Payment", (routeVariant) => {
|
||||
|
||||
await page.goto(`${user.username}/30-min`);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
await bookTimeSlot(page);
|
||||
|
||||
@@ -198,7 +198,7 @@ test.describe("Update Profile", () => {
|
||||
secondaryEmail: string;
|
||||
}) => {
|
||||
await test.step("the user receives the correct invitation link", async () => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const verificationToken = await prisma.verificationToken.findFirst({
|
||||
where: {
|
||||
identifier: secondaryEmail,
|
||||
@@ -248,7 +248,7 @@ test.describe("Update Profile", () => {
|
||||
expect(await secondaryEmailConfirmDialog.isVisible()).toBe(false);
|
||||
|
||||
await test.step("the user receives the correct invitation link", async () => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const verificationToken = await prisma.verificationToken.findFirst({
|
||||
where: {
|
||||
identifier: secondaryEmail,
|
||||
|
||||
@@ -96,7 +96,7 @@ test.describe("Reschedule Tests", async () => {
|
||||
|
||||
await page.locator('[data-testid="confirm-reschedule-button"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const alertMessage = "Username or email is already taken";
|
||||
|
||||
@@ -52,7 +52,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const alertMessage = "Username or email is already taken";
|
||||
|
||||
@@ -83,7 +83,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
|
||||
// Signup with premium username name
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// Fill form
|
||||
await page.locator('input[name="username"]').fill("rock");
|
||||
@@ -111,7 +111,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// Fill form
|
||||
await page.locator('input[name="username"]').fill(userToCreate.username);
|
||||
@@ -179,7 +179,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
|
||||
const signupUrlWithToken = `/signup?token=${token}`;
|
||||
await page.goto(signupUrlWithToken);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const usernameField = page.locator('input[name="username"]');
|
||||
const emailField = page.locator('input[name="email"]');
|
||||
@@ -250,7 +250,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
const { team } = await teamOwner.getFirstTeamMembership();
|
||||
await teamOwner.apiLogin();
|
||||
await page.goto(`/settings/teams/${team.id}/members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("Invite User to team", async () => {
|
||||
// TODO: This invite logic should live in a fixture - its used in team and orgs invites (Duplicated from team/org invites)
|
||||
@@ -258,7 +258,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
await page.locator(`button:text("${t("add")}")`).click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.locator(`button:text("${t("send_invite")}")`).click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const inviteLink = await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
emails,
|
||||
|
||||
@@ -19,7 +19,7 @@ test.describe("Team", () => {
|
||||
const { team } = await teamOwner.getFirstTeamMembership();
|
||||
await teamOwner.apiLogin();
|
||||
await page.goto(`/settings/teams/${team.id}/members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("To the team by email (external user)", async () => {
|
||||
const invitedUserEmail = users.trackEmail({
|
||||
@@ -29,7 +29,7 @@ test.describe("Team", () => {
|
||||
await page.locator(`button:text("${t("add")}")`).click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.locator(`button:text("${t("send_invite")}")`).click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
const inviteLink = await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
emails,
|
||||
@@ -66,7 +66,7 @@ test.describe("Team", () => {
|
||||
// Check newly invited member is not pending anymore
|
||||
await page.bringToFront();
|
||||
await page.goto(`/settings/teams/${team.id}/members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(
|
||||
page.locator(`[data-testid="email-${invitedUserEmail.replace("@", "")}-pending"]`)
|
||||
).toHaveCount(0);
|
||||
@@ -103,7 +103,7 @@ test.describe("Team", () => {
|
||||
const { team } = await teamOwner.getFirstTeamMembership();
|
||||
await teamOwner.apiLogin();
|
||||
await page.goto(`/settings/teams/${team.id}/members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("To the organization by email (internal user)", async () => {
|
||||
const invitedUserEmail = users.trackEmail({
|
||||
@@ -113,7 +113,7 @@ test.describe("Team", () => {
|
||||
await page.locator(`button:text("${t("add")}")`).click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.locator(`button:text("${t("send_invite")}")`).click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
emails,
|
||||
|
||||
@@ -44,7 +44,7 @@ testBothFutureAndLegacyRoutes.describe("Teams - NonOrg", (routeVariant) => {
|
||||
await user.apiLogin();
|
||||
|
||||
page.goto(`/settings/teams/${team.id}/onboard-members`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await test.step("Can add members", async () => {
|
||||
// Click [data-testid="new-member-button"]
|
||||
|
||||
@@ -47,7 +47,7 @@ test.describe("Unpublished", () => {
|
||||
const { team: org } = await owner.getOrgMembership();
|
||||
const { requestedSlug } = org.metadata as { requestedSlug: string };
|
||||
await page.goto(`/org/${requestedSlug}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(org.name)}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`div:text("${description("organization")}")`)).toHaveCount(1);
|
||||
@@ -65,7 +65,7 @@ test.describe("Unpublished", () => {
|
||||
const { requestedSlug } = org.metadata as { requestedSlug: string };
|
||||
const [{ slug: subteamSlug }] = org.children as { slug: string }[];
|
||||
await page.goto(`/org/${requestedSlug}/team/${subteamSlug}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(org.name)}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`div:text("${description("organization")}")`)).toHaveCount(1);
|
||||
@@ -84,7 +84,7 @@ test.describe("Unpublished", () => {
|
||||
const [{ slug: subteamSlug, id: subteamId }] = org.children as { slug: string; id: number }[];
|
||||
const { slug: subteamEventSlug } = await owner.getFirstTeamEvent(subteamId);
|
||||
await page.goto(`/org/${requestedSlug}/team/${subteamSlug}/${subteamEventSlug}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(org.name)}")`)).toHaveCount(1);
|
||||
@@ -97,7 +97,7 @@ test.describe("Unpublished", () => {
|
||||
const { team: org } = await owner.getOrgMembership();
|
||||
const { requestedSlug } = org.metadata as { requestedSlug: string };
|
||||
await page.goto(`/org/${requestedSlug}/${owner.username}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(org.name)}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`div:text("${description("organization")}")`)).toHaveCount(1);
|
||||
@@ -110,7 +110,7 @@ test.describe("Unpublished", () => {
|
||||
const { requestedSlug } = org.metadata as { requestedSlug: string };
|
||||
const [{ slug: ownerEventType }] = owner.eventTypes;
|
||||
await page.goto(`/org/${requestedSlug}/${owner.username}/${ownerEventType}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(org.name)}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`div:text("${description("organization")}")`)).toHaveCount(1);
|
||||
|
||||
@@ -577,9 +577,11 @@ test.describe("MEETING_ENDED, MEETING_STARTED", async () => {
|
||||
expect(newMeetingEndedTriggers.length).toBe(0);
|
||||
|
||||
// disable webhook
|
||||
await page.click('[data-testid="webhook-switch"]');
|
||||
await page.getByTestId("webhook-switch").click();
|
||||
const response = await page.waitForResponse("/api/trpc/webhook/edit?batch=1");
|
||||
expect(response.status()).toBe(200);
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const scheduledTriggersAfterDisabling = await prisma.webhookScheduledTriggers.findMany({
|
||||
where: {
|
||||
@@ -608,7 +610,7 @@ test.describe("FORM_SUBMITTED", async () => {
|
||||
|
||||
await user.apiLogin();
|
||||
const webhookReceiver = await webhooks.createReceiver();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
const form = await routingForms.create({
|
||||
name: "Test Form",
|
||||
@@ -624,7 +626,7 @@ test.describe("FORM_SUBMITTED", async () => {
|
||||
],
|
||||
});
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await gotoRoutingLink({ page, formId: form.id });
|
||||
const fieldName = "name";
|
||||
@@ -693,7 +695,7 @@ test.describe("FORM_SUBMITTED", async () => {
|
||||
],
|
||||
});
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
await gotoRoutingLink({ page, formId: form.id });
|
||||
const textFieldIdentifier = "name";
|
||||
|
||||
@@ -365,6 +365,7 @@ test.describe("Routing Forms", () => {
|
||||
const routingForm = user.routingForms[0];
|
||||
await page.goto(`apps/routing-forms/form-edit/${routingForm.id}`);
|
||||
await page.click('[data-testid="test-preview"]');
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
//event redirect
|
||||
await page.fill('[data-testid="form-field-Test field"]', "event-routing");
|
||||
|
||||
@@ -57,12 +57,14 @@ if (IS_EMBED_REACT_TEST) {
|
||||
});
|
||||
}
|
||||
|
||||
const DEFAULT_CHROMIUM = {
|
||||
const DEFAULT_CHROMIUM: NonNullable<PlaywrightTestConfig["projects"]>[number]["use"] = {
|
||||
...devices["Desktop Chrome"],
|
||||
timezoneId: "Europe/London",
|
||||
storageState: {
|
||||
cookies: [
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore TS definitions for USE are wrong.
|
||||
url: WEBAPP_URL,
|
||||
name: "calcom-timezone-dialog",
|
||||
expires: -1,
|
||||
@@ -73,6 +75,10 @@ const DEFAULT_CHROMIUM = {
|
||||
locale: "en-US",
|
||||
/** If navigation takes more than this, then something's wrong, let's fail fast. */
|
||||
navigationTimeout: DEFAULT_NAVIGATION_TIMEOUT,
|
||||
// chromium-specific permissions - Chromium seems to be the only browser type that requires perms
|
||||
contextOptions: {
|
||||
permissions: ["clipboard-read", "clipboard-write"],
|
||||
},
|
||||
};
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
@@ -96,10 +102,6 @@ const config: PlaywrightTestConfig = {
|
||||
locale: "en-US",
|
||||
trace: "retain-on-failure",
|
||||
headless,
|
||||
// chromium-specific permissions - Chromium seems to be the only browser type that requires perms
|
||||
contextOptions: {
|
||||
permissions: ["clipboard-read", "clipboard-write"],
|
||||
},
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user