fix: fixed the flaky e2e tests that failed the most times and refactor (#16364)
* fix: fixed the flaky tests that failed maximum times * Update action-based.e2e.ts * another * add * add another * update * fix * add * fix * update * update and add * fix * update * update * chnages * chore: updates * reafactor and following best practice * fix * add and update * update * update and fix * fix type * another test * update * Update organization-invitation.e2e.ts * refactor and update * fix * final update
This commit is contained in:
@@ -85,7 +85,7 @@ test.describe("Availablity", () => {
|
||||
await page.locator('[form="availability-form"][type="submit"]').click();
|
||||
|
||||
await expect(dateOverrideList).toHaveCount(3);
|
||||
await expect(await page.getByTitle(deleteButtonTitle).isVisible()).toBe(false);
|
||||
await expect(page.getByTitle(deleteButtonTitle)).toBeHidden();
|
||||
});
|
||||
|
||||
test("Can create date override on current day in a negative timezone", async ({ page }) => {
|
||||
|
||||
@@ -297,6 +297,7 @@ testBothFutureAndLegacyRoutes.describe("pro user", () => {
|
||||
|
||||
await pageTwo.waitForSelector('[data-testid="event-type-link"]');
|
||||
const eventTypeLink = pageTwo.locator('[data-testid="event-type-link"]').first();
|
||||
await eventTypeLink.waitFor();
|
||||
await eventTypeLink.click();
|
||||
|
||||
await pageTwo.waitForLoadState("networkidle");
|
||||
@@ -330,6 +331,7 @@ testBothFutureAndLegacyRoutes.describe("pro user", () => {
|
||||
|
||||
await pageTwo.waitForSelector('[data-testid="event-type-link"]');
|
||||
const eventTypeLinkTwo = pageTwo.locator('[data-testid="event-type-link"]').first();
|
||||
await eventTypeLinkTwo.waitFor();
|
||||
await eventTypeLinkTwo.click();
|
||||
|
||||
await page.locator('[data-testid="back"]').waitFor();
|
||||
|
||||
@@ -180,7 +180,7 @@ test.describe("Reschedule for booking with seats", () => {
|
||||
await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click();
|
||||
|
||||
// Validate that the number of seats its 10
|
||||
expect(await page.locator("text=9 / 10 Seats available").count()).toEqual(0);
|
||||
await expect(page.locator("text=9 / 10 Seats available")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("Should cancel with seats but event should be still accessible and with one less attendee/seat", async ({
|
||||
|
||||
@@ -96,8 +96,8 @@ test.skip("it contains the right event details", async ({ page }) => {
|
||||
const response = await page.goto(`http://acme.cal.local:3000/owner1+member1`);
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
expect(await page.locator('[data-testid="event-title"]').textContent()).toBe("Group Meeting");
|
||||
expect(await page.locator('[data-testid="event-meta"]').textContent()).toContain("Acme Inc");
|
||||
await expect(page.locator('[data-testid="event-title"]')).toHaveText("Group Meeting");
|
||||
await expect(page.locator('[data-testid="event-meta"]')).toContainText("Acme Inc");
|
||||
|
||||
expect((await page.locator('[data-testid="event-meta"] [data-testid="avatar"]').all()).length).toBe(3);
|
||||
});
|
||||
|
||||
@@ -118,9 +118,10 @@ testBothFutureAndLegacyRoutes.describe("Event Types tests", () => {
|
||||
expect(formTitle).toBe(firstTitle);
|
||||
expect(formSlug).toContain(firstSlug);
|
||||
|
||||
const test = await page.getByTestId("continue").click();
|
||||
const toast = await page.waitForSelector('[data-testid="toast-success"]');
|
||||
expect(toast).toBeTruthy();
|
||||
const submitPromise = page.waitForResponse("/api/trpc/eventTypes/duplicate?batch=1");
|
||||
await page.getByTestId("continue").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
});
|
||||
|
||||
test("edit first event", async ({ page }) => {
|
||||
|
||||
@@ -57,8 +57,10 @@ test.describe("hash my url", () => {
|
||||
await page.getByTestId("vertical-tab-event_setup_tab_title").click();
|
||||
await page.locator("[data-testid=event-title]").first().fill("somethingrandom");
|
||||
await page.locator("[data-testid=event-slug]").first().fill("somethingrandom");
|
||||
const submitPromise = page.waitForResponse("/api/trpc/eventTypes/update?batch=1");
|
||||
await page.locator("[data-testid=update-eventtype]").click();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.locator(".primary-navigation >> text=Advanced").click();
|
||||
const $url2 = await page.locator('//*[@data-testid="generated-hash-url"]').inputValue();
|
||||
|
||||
@@ -18,10 +18,8 @@ test.describe("Users can impersonate", async () => {
|
||||
const userToImpersonate = await users.create({ disableImpersonation: false });
|
||||
|
||||
await user.apiLogin();
|
||||
await page.waitForLoadState();
|
||||
|
||||
await page.goto("/settings/admin/impersonation");
|
||||
await page.waitForLoadState();
|
||||
await expect(page.getByText("User Impersonation")).toBeVisible();
|
||||
const adminInput = page.getByTestId("admin-impersonation-input");
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore the username does exist
|
||||
@@ -41,8 +39,8 @@ test.describe("Users can impersonate", async () => {
|
||||
await expect(impersonatedUser).toBe(userToImpersonate.username);
|
||||
|
||||
await stopImpersonatingButton.click();
|
||||
await expect(stopImpersonatingButton).toBeHidden();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
// Return to user
|
||||
const ogUser = await impersonatedUsernameInput.inputValue();
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ test.describe("Insights", async () => {
|
||||
await page.getByRole("button", { name: "Clear" }).click();
|
||||
|
||||
// expect for "Team: test-insight" text in page
|
||||
expect(await page.locator("text=Team: test-insights").isVisible()).toBeTruthy();
|
||||
await expect(page.locator("text=Team: test-insights")).toBeVisible();
|
||||
});
|
||||
|
||||
test("should test download button", async ({ page, users }) => {
|
||||
@@ -255,13 +255,13 @@ test.describe("Insights", async () => {
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
|
||||
// Expect download button to be visible
|
||||
expect(await page.locator("text=Download").isVisible()).toBeTruthy();
|
||||
await expect(page.locator("text=Download")).toBeVisible();
|
||||
|
||||
// Click on Download button
|
||||
await page.getByText("Download").click();
|
||||
|
||||
// Expect as csv option to be visible
|
||||
expect(await page.locator("text=as CSV").isVisible()).toBeTruthy();
|
||||
await expect(page.locator("text=as CSV")).toBeVisible();
|
||||
|
||||
// Start waiting for download before clicking. Note no await.
|
||||
await page.getByText("as CSV").click();
|
||||
|
||||
@@ -173,7 +173,7 @@ test.describe("Stripe integration skip true", () => {
|
||||
await page.click('[data-testid="cancel"]');
|
||||
await page.click('[data-testid="confirm_cancel"]');
|
||||
|
||||
await expect(await page.locator('[data-testid="cancelled-headline"]').first()).toBeVisible();
|
||||
await expect(page.locator('[data-testid="cancelled-headline"]').first()).toBeVisible();
|
||||
});
|
||||
|
||||
test.describe("When event is paid and confirmed", () => {
|
||||
@@ -242,12 +242,12 @@ test.describe("Stripe integration skip true", () => {
|
||||
await page.goto(`${user.username}/${eventType?.slug}`);
|
||||
|
||||
// Confirm MXN currency it's displayed use expect
|
||||
await expect(await page.getByText("MX$200.00")).toBeVisible();
|
||||
await expect(page.getByText("MX$200.00")).toBeVisible();
|
||||
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
|
||||
// Confirm again in book form page
|
||||
await expect(await page.getByText("MX$200.00")).toBeVisible();
|
||||
await expect(page.getByText("MX$200.00")).toBeVisible();
|
||||
|
||||
// --- fill form
|
||||
await page.fill('[name="name"]', "Stripe Stripeson");
|
||||
@@ -260,7 +260,7 @@ test.describe("Stripe integration skip true", () => {
|
||||
await page.waitForURL("/payment/*");
|
||||
|
||||
// Confirm again in book form page
|
||||
await expect(await page.getByText("MX$200.00")).toBeVisible();
|
||||
await expect(page.getByText("MX$200.00")).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -403,7 +403,7 @@ test.describe("Stripe integration with the new app install flow skip flase", ()
|
||||
await page.click('[data-testid="cancel"]');
|
||||
await page.click('[data-testid="confirm_cancel"]');
|
||||
|
||||
await expect(await page.locator('[data-testid="cancelled-headline"]').first()).toBeVisible();
|
||||
await expect(page.locator('[data-testid="cancelled-headline"]').first()).toBeVisible();
|
||||
});
|
||||
|
||||
test.describe("When event is paid and confirmed skip false", () => {
|
||||
@@ -477,12 +477,12 @@ test.describe("Stripe integration with the new app install flow skip flase", ()
|
||||
await page.goto(`${user.username}/${eventType?.slug}`);
|
||||
|
||||
// Confirm MXN currency it's displayed use expect
|
||||
await expect(await page.getByText("MX$200.00")).toBeVisible();
|
||||
await expect(page.getByText("MX$200.00")).toBeVisible();
|
||||
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
|
||||
// Confirm again in book form page
|
||||
await expect(await page.getByText("MX$200.00")).toBeVisible();
|
||||
await expect(page.getByText("MX$200.00")).toBeVisible();
|
||||
|
||||
// --- fill form
|
||||
await page.fill('[name="name"]', "Stripe Stripeson");
|
||||
@@ -495,7 +495,7 @@ test.describe("Stripe integration with the new app install flow skip flase", ()
|
||||
await page.waitForURL("/payment/*");
|
||||
|
||||
// Confirm again in book form page
|
||||
await expect(await page.getByText("MX$200.00")).toBeVisible();
|
||||
await expect(page.getByText("MX$200.00")).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -98,7 +98,7 @@ export function createHttpServer(opts: { requestHandler?: RequestHandler } = {})
|
||||
|
||||
export async function selectFirstAvailableTimeSlotNextMonth(page: Page | Frame) {
|
||||
// Let current month dates fully render.
|
||||
await page.click('[data-testid="incrementMonth"]');
|
||||
await page.getByTestId("incrementMonth").click();
|
||||
|
||||
// Waiting for full month increment
|
||||
await page.locator('[data-testid="day"][data-disabled="false"]').nth(0).click();
|
||||
@@ -108,7 +108,7 @@ export async function selectFirstAvailableTimeSlotNextMonth(page: Page | Frame)
|
||||
|
||||
export async function selectSecondAvailableTimeSlotNextMonth(page: Page) {
|
||||
// Let current month dates fully render.
|
||||
await page.click('[data-testid="incrementMonth"]');
|
||||
await page.getByTestId("incrementMonth").click();
|
||||
|
||||
await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click();
|
||||
|
||||
@@ -212,7 +212,8 @@ export async function installAppleCalendar(page: Page) {
|
||||
}
|
||||
|
||||
export async function getInviteLink(page: Page) {
|
||||
const response = await page.waitForResponse("**/api/trpc/teams/createInvite?batch=1");
|
||||
const response = await page.waitForResponse("/api/trpc/teams/createInvite?batch=1");
|
||||
expect(response.status()).toBe(200);
|
||||
const json = await response.json();
|
||||
return json[0].result.data.json.inviteLink as string;
|
||||
}
|
||||
|
||||
@@ -131,9 +131,7 @@ test.describe("Manage Booking Questions", () => {
|
||||
email: "booker@example.com",
|
||||
});
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
expect(await page.locator('[data-testid="attendee-name-John Doe"]').nth(0).textContent()).toBe(
|
||||
"John Doe"
|
||||
);
|
||||
await expect(page.locator('[data-testid="attendee-name-John Doe"]').first()).toHaveText("John Doe");
|
||||
await expectWebhookToBeCalled(webhookReceiver, {
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_CREATED,
|
||||
payload: {
|
||||
@@ -747,7 +745,9 @@ test.describe("Text area min and max characters text", () => {
|
||||
// goto the advanced tab
|
||||
await page.click('[href$="tabName=advanced"]');
|
||||
const insertQuestion = async (questionName: string) => {
|
||||
await page.click('[data-testid="add-field"]');
|
||||
const element = page.locator('[data-testid="add-field"]');
|
||||
await element.scrollIntoViewIfNeeded();
|
||||
await element.click();
|
||||
const locatorForSelect = page.locator("[id=test-field-type]").nth(0);
|
||||
await locatorForSelect.click();
|
||||
await locatorForSelect.locator(`text="Long Text"`).click();
|
||||
@@ -860,14 +860,14 @@ test.describe("Text area min and max characters text", () => {
|
||||
await textAreaWithMin5Max10.fill("1234");
|
||||
await submitForm();
|
||||
// Expect the text: Min. 5 characters to be visible
|
||||
expect(await page.locator(`text=Min. 5 characters required`).isVisible()).toBe(true);
|
||||
await expect(page.locator(`text=Min. 5 characters required`)).toBeVisible();
|
||||
|
||||
// update the text area with min 5 to have 5 characters
|
||||
await textAreaWithMin5.fill("12345");
|
||||
await submitForm();
|
||||
|
||||
// Expect the text: Min. 5 characters to still be visible because textAreaWithMin5Max10 has less than 5 characters
|
||||
expect(await page.locator(`text=Min. 5 characters required`).isVisible()).toBe(true);
|
||||
await expect(page.locator(`text=Min. 5 characters required`)).toBeVisible();
|
||||
|
||||
// Expect the text: Max. 10 characters to be visible and have value 1234567890
|
||||
expect(await textAreaWithMax10.inputValue()).toBe("1234567890");
|
||||
@@ -878,7 +878,7 @@ test.describe("Text area min and max characters text", () => {
|
||||
await submitForm();
|
||||
|
||||
// Expect the text: Max. 5 characters to be hidden
|
||||
expect(await page.locator(`text=Min. 5 characters required`).isVisible()).toBe(false);
|
||||
await expect(page.locator(`text=Min. 5 characters required`)).toBeHidden();
|
||||
|
||||
await expect(page.locator('text="This meeting is scheduled"')).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -505,15 +505,15 @@ async function bookTeamEvent({
|
||||
await expect(page.getByTestId("success-page")).toBeVisible();
|
||||
|
||||
// The title of the booking
|
||||
if (event.schedulingType === SchedulingType.ROUND_ROBIN) {
|
||||
if (event.schedulingType === SchedulingType.ROUND_ROBIN && teamMatesObj) {
|
||||
const bookingTitle = await page.getByTestId("booking-title").textContent();
|
||||
|
||||
expect(
|
||||
teamMatesObj?.some((teamMate) => {
|
||||
const BookingTitle = `${event.title} between ${teamMate.name} and ${testName}`;
|
||||
return BookingTitle === bookingTitle;
|
||||
})
|
||||
).toBe(true);
|
||||
const isMatch = teamMatesObj?.some((teamMate) => {
|
||||
const expectedTitle = `${event.title} between ${teamMate.name} and ${testName}`;
|
||||
return expectedTitle.trim() === bookingTitle?.trim();
|
||||
});
|
||||
|
||||
expect(isMatch).toBe(true);
|
||||
} else {
|
||||
const BookingTitle = `${event.title} between ${team.name} and ${testName}`;
|
||||
await expect(page.getByTestId("booking-title")).toHaveText(BookingTitle);
|
||||
|
||||
@@ -170,7 +170,7 @@ test.describe("Organization", () => {
|
||||
|
||||
await test.step("On-board administrators", async () => {
|
||||
await page.waitForSelector('[data-testid="pending-member-list"]');
|
||||
expect(await page.getByTestId("pending-member-item").count()).toBe(1);
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
|
||||
const adminEmail = users.trackEmail({ username: "rick", domain: `example.com` });
|
||||
|
||||
@@ -342,7 +342,7 @@ test.describe("Organization", () => {
|
||||
|
||||
await test.step("On-board administrators", async () => {
|
||||
await page.waitForSelector('[data-testid="pending-member-list"]');
|
||||
expect(await page.getByTestId("pending-member-item").count()).toBe(1);
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
|
||||
const adminEmail = users.trackEmail({ username: "rick", domain: `example.com` });
|
||||
|
||||
@@ -477,7 +477,7 @@ test.describe("Organization", () => {
|
||||
|
||||
await test.step("On-board administrators", async () => {
|
||||
await page.waitForSelector('[data-testid="pending-member-list"]');
|
||||
expect(await page.getByTestId("pending-member-item").count()).toBe(1);
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
|
||||
const adminEmail = users.trackEmail({ username: "rick", domain: `example.com` });
|
||||
|
||||
|
||||
@@ -301,12 +301,14 @@ test.describe("Organization", () => {
|
||||
await test.step("Signing up with the previous username of the migrated user - shouldn't be allowed", async () => {
|
||||
await page.goto("/signup");
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
await page.locator('input[name="username"]').fill(existingUser.username!);
|
||||
const usernameInput = page.locator('input[name="username"]');
|
||||
await usernameInput.waitFor({ state: "attached" });
|
||||
await usernameInput.waitFor({ state: "visible" });
|
||||
await usernameInput.fill(existingUser.username!);
|
||||
await page
|
||||
.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();
|
||||
});
|
||||
});
|
||||
@@ -486,8 +488,11 @@ 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.locator('button:text("Send invite")').click();
|
||||
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;
|
||||
expect(response.status()).toBe(200);
|
||||
}
|
||||
|
||||
async function expectUserToBeAMemberOfOrganization({
|
||||
@@ -505,8 +510,8 @@ async function expectUserToBeAMemberOfOrganization({
|
||||
}) {
|
||||
// Check newly invited member is not pending anymore
|
||||
await page.goto("/settings/organizations/members");
|
||||
expect(await page.locator(`[data-testid="member-${username}-username"]`).textContent()).toBe(username);
|
||||
expect(await page.locator(`[data-testid="member-${username}-email"]`).textContent()).toBe(email);
|
||||
await expect(page.locator(`[data-testid="member-${username}-username"]`)).toHaveText(username);
|
||||
await expect(page.locator(`[data-testid="member-${username}-email"]`)).toHaveText(email);
|
||||
expect((await page.locator(`[data-testid="member-${username}-role"]`).textContent())?.toLowerCase()).toBe(
|
||||
role.toLowerCase()
|
||||
);
|
||||
@@ -535,6 +540,7 @@ async function expectUserToBeAMemberOfTeam({
|
||||
// Check newly invited member is not pending anymore
|
||||
await page.goto(`/settings/teams/${teamId}/members`);
|
||||
await page.reload();
|
||||
await page.waitForLoadState("domcontentloaded");
|
||||
expect(
|
||||
(
|
||||
await page.locator(`[data-testid="member-${username}"] [data-testid=member-role]`).textContent()
|
||||
|
||||
@@ -38,7 +38,7 @@ test.describe("Teams", () => {
|
||||
if (IS_TEAM_BILLING_ENABLED) await fillStripeTestCheckout(page);
|
||||
await expect(page).toHaveURL(/\/settings\/teams\/(\d+)\/onboard-members.*$/i);
|
||||
await page.waitForSelector('[data-testid="pending-member-list"]');
|
||||
expect(await page.getByTestId("pending-member-item").count()).toBe(1);
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
});
|
||||
|
||||
await test.step("Can add members", async () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import type { Page } from "@playwright/test";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
@@ -8,7 +9,9 @@ import prisma from "@calcom/prisma";
|
||||
import { test } from "./lib/fixtures";
|
||||
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
test.afterEach(({ users }) => users.deleteAll());
|
||||
test.afterEach(async ({ users }) => {
|
||||
await users.deleteAll();
|
||||
});
|
||||
|
||||
test.describe("Out of office", () => {
|
||||
test("User can create out of office entry", async ({ page, users }) => {
|
||||
@@ -27,9 +30,9 @@ test.describe("Out of office", () => {
|
||||
|
||||
await page.getByTestId("notes_input").click();
|
||||
await page.getByTestId("notes_input").fill("Demo notes");
|
||||
await page.getByTestId("create-or-edit-entry-ooo-redirect").click();
|
||||
|
||||
await expect(page.locator(`data-testid=table-redirect-n-a`)).toBeVisible();
|
||||
// send request
|
||||
await submitAndWaitForResponse(page);
|
||||
});
|
||||
|
||||
test("User can configure booking redirect", async ({ page, users }) => {
|
||||
@@ -83,10 +86,7 @@ test.describe("Out of office", () => {
|
||||
await page.locator("#react-select-3-input").press("Enter");
|
||||
|
||||
// send request
|
||||
await page.getByTestId("create-or-edit-entry-ooo-redirect").click();
|
||||
|
||||
// expect table-redirect-toUserId to be visible
|
||||
await expect(page.locator(`data-testid=table-redirect-${userTo.username}`)).toBeVisible();
|
||||
await submitAndWaitForResponse(page);
|
||||
});
|
||||
|
||||
test("User can edit out of office entry", async ({ page, users }) => {
|
||||
@@ -163,16 +163,7 @@ test.describe("Out of office", () => {
|
||||
await page.locator("#react-select-3-input").press("Enter");
|
||||
|
||||
// send request
|
||||
await page.getByTestId("create-or-edit-entry-ooo-redirect").click();
|
||||
|
||||
// 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"
|
||||
);
|
||||
await submitAndWaitForResponse(page);
|
||||
});
|
||||
|
||||
test("Profile redirection", async ({ page, users }) => {
|
||||
@@ -204,3 +195,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);
|
||||
}
|
||||
|
||||
@@ -40,14 +40,14 @@ test.describe("Payment app", () => {
|
||||
await page.goto(`${user.username}/${paymentEvent?.slug}`);
|
||||
|
||||
// expect 200 sats to be displayed in page
|
||||
expect(await page.locator("text=200 sats").first()).toBeTruthy();
|
||||
await expect(page.locator("text=200 sats").first()).toBeVisible();
|
||||
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
expect(await page.locator("text=200 sats").first()).toBeTruthy();
|
||||
await expect(page.locator("text=200 sats").first()).toBeVisible();
|
||||
|
||||
// go to /event-types and check if the price is 200 sats
|
||||
await page.goto(`event-types/`);
|
||||
expect(await page.locator("text=200 sats").first()).toBeTruthy();
|
||||
await expect(page.locator("text=200 sats").first()).toBeVisible();
|
||||
});
|
||||
|
||||
test("Should be able to edit stripe price, currency", async ({ page, users }) => {
|
||||
|
||||
@@ -126,7 +126,7 @@ test.describe("Update Profile", () => {
|
||||
|
||||
await page.getByTestId("profile-update-email-submit-button").click();
|
||||
|
||||
expect(await page.getByTestId("toast-success").textContent()).toContain(email);
|
||||
await expect(page.getByTestId("toast-success")).toContainText(email);
|
||||
|
||||
// Instead of dealing with emails in e2e lets just get the token and navigate to it
|
||||
const verificationToken = await prisma.verificationToken.findFirst({
|
||||
@@ -144,7 +144,7 @@ test.describe("Update Profile", () => {
|
||||
|
||||
await page.goto(verifyUrl);
|
||||
|
||||
expect(await page.getByTestId("toast-success").textContent()).toContain(email);
|
||||
await expect(page.getByTestId("toast-success")).toContainText(email);
|
||||
|
||||
// After email verification is successfull. user is sent to /event-types
|
||||
await page.waitForURL("/event-types");
|
||||
@@ -179,7 +179,7 @@ test.describe("Update Profile", () => {
|
||||
|
||||
await page.getByTestId("profile-update-email-submit-button").click();
|
||||
|
||||
expect(await page.getByTestId("toast-success").isVisible()).toBe(true);
|
||||
await expect(page.getByTestId("toast-success")).toBeVisible();
|
||||
|
||||
const emailInputUpdated = page.getByTestId("profile-form-email-0");
|
||||
|
||||
@@ -298,17 +298,19 @@ test.describe("Update Profile", () => {
|
||||
|
||||
await page.getByTestId("secondary-email-confirm-done-button").click();
|
||||
|
||||
await expect(secondaryEmailInput).toBeHidden();
|
||||
|
||||
return { user, email, secondaryEmail };
|
||||
};
|
||||
|
||||
test("Newly added secondary email should show as Unverified", async ({ page, users }) => {
|
||||
await createSecondaryEmail({ page, users });
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-0-primary-badge").isVisible()).toEqual(true);
|
||||
expect(await page.getByTestId("profile-form-email-0-unverified-badge").isVisible()).toEqual(false);
|
||||
await expect(page.getByTestId("profile-form-email-0-primary-badge")).toBeVisible();
|
||||
await expect(page.getByTestId("profile-form-email-0-unverified-badge")).toBeHidden();
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-1-primary-badge").isVisible()).toEqual(false);
|
||||
expect(await page.getByTestId("profile-form-email-1-unverified-badge").isVisible()).toEqual(true);
|
||||
await expect(page.getByTestId("profile-form-email-1-primary-badge")).toBeHidden();
|
||||
await expect(page.getByTestId("profile-form-email-1-unverified-badge")).toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: This test is extremely flaky and has been failing a lot, blocking many PRs. Fix this.
|
||||
@@ -316,8 +318,8 @@ test.describe("Update Profile", () => {
|
||||
test.skip("Can verify the newly added secondary email", async ({ page, users, prisma }) => {
|
||||
const { secondaryEmail } = await createSecondaryEmail({ page, users });
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-1-primary-badge").isVisible()).toEqual(false);
|
||||
expect(await page.getByTestId("profile-form-email-1-unverified-badge").isVisible()).toEqual(true);
|
||||
await expect(page.getByTestId("profile-form-email-1-primary-badge")).toBeHidden();
|
||||
await expect(page.getByTestId("profile-form-email-1-unverified-badge")).toBeVisible();
|
||||
// Instead of dealing with emails in e2e lets just get the token and navigate to it
|
||||
const verificationToken = await prisma.verificationToken.findFirst({
|
||||
where: {
|
||||
@@ -334,8 +336,8 @@ test.describe("Update Profile", () => {
|
||||
|
||||
await page.goto(verifyUrl);
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-1-primary-badge").isVisible()).toEqual(false);
|
||||
expect(await page.getByTestId("profile-form-email-1-unverified-badge").isVisible()).toEqual(false);
|
||||
await expect(page.getByTestId("profile-form-email-1-primary-badge")).toBeHidden();
|
||||
await expect(page.getByTestId("profile-form-email-1-unverified-badge")).toBeVisible();
|
||||
});
|
||||
|
||||
test("Can delete the newly added secondary email", async ({ page, users }) => {
|
||||
@@ -344,7 +346,7 @@ test.describe("Update Profile", () => {
|
||||
await page.getByTestId("secondary-email-action-group-button").nth(1).click();
|
||||
await page.getByTestId("secondary-email-delete-button").click();
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-1").isVisible()).toEqual(false);
|
||||
await expect(page.getByTestId("profile-form-email-1")).toBeHidden();
|
||||
});
|
||||
|
||||
test("Can make the newly added secondary email as the primary email and login", async ({
|
||||
@@ -372,8 +374,8 @@ test.describe("Update Profile", () => {
|
||||
await page.getByTestId("secondary-email-action-group-button").nth(1).click();
|
||||
await page.getByTestId("secondary-email-make-primary-button").click();
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-1-primary-badge").isVisible()).toEqual(true);
|
||||
expect(await page.getByTestId("profile-form-email-1-unverified-badge").isVisible()).toEqual(false);
|
||||
await expect(page.getByTestId("profile-form-email-1-primary-badge")).toBeVisible();
|
||||
await expect(page.getByTestId("profile-form-email-1-unverified-badge")).toBeHidden();
|
||||
});
|
||||
|
||||
// TODO: This test is extremely flaky and has been failing a lot, blocking many PRs. Fix this.
|
||||
@@ -396,9 +398,9 @@ test.describe("Update Profile", () => {
|
||||
await emails.deleteMessage(receivedEmails.items[0].ID);
|
||||
}
|
||||
|
||||
expect(await page.getByTestId("profile-form-email-1-unverified-badge").isVisible()).toEqual(true);
|
||||
await expect(page.getByTestId("profile-form-email-1-unverified-badge")).toBeVisible();
|
||||
await page.getByTestId("secondary-email-action-group-button").nth(1).click();
|
||||
expect(await page.locator("button[data-testid=resend-verify-email-button]").isDisabled()).toEqual(false);
|
||||
await expect(page.locator("button[data-testid=resend-verify-email-button]")).toBeEnabled();
|
||||
await page.getByTestId("resend-verify-email-button").click();
|
||||
|
||||
await testEmailVerificationLink({ page, prisma, emails, secondaryEmail });
|
||||
@@ -411,7 +413,7 @@ test.describe("Update Profile", () => {
|
||||
await page.goto(`${WEBAPP_URL}/api/auth/verify-email?token=${verificationToken?.token}`);
|
||||
|
||||
await page.getByTestId("secondary-email-action-group-button").nth(1).click();
|
||||
expect(await page.locator("button[data-testid=resend-verify-email-button]").isVisible()).toEqual(false);
|
||||
expect(await page.getByTestId("profile-form-email-1-unverified-badge").isVisible()).toEqual(false);
|
||||
await expect(page.locator("button[data-testid=resend-verify-email-button]")).toBeHidden();
|
||||
await expect(page.getByTestId("profile-form-email-1-unverified-badge")).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -192,7 +192,7 @@ test.describe("Organization Logo", async () => {
|
||||
await test.step("it shows the correct logo on the unpublished public page", async () => {
|
||||
await page.goto(`/org/${requestedSlug}`);
|
||||
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
|
||||
await expect(page.locator(`img`)).toHaveAttribute(
|
||||
"src",
|
||||
|
||||
@@ -210,13 +210,17 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("domcontentloaded");
|
||||
|
||||
// Fill form
|
||||
await page.locator('input[name="username"]').fill(userToCreate.username);
|
||||
await page.locator('input[name="email"]').fill(userToCreate.email);
|
||||
await page.locator('input[name="password"]').fill(userToCreate.password);
|
||||
|
||||
await page.click('button[type="submit"]');
|
||||
const submitButton = page.locator('button[type="submit"]');
|
||||
await submitButton.waitFor({ state: "attached" });
|
||||
await expect(submitButton).toBeEnabled();
|
||||
await submitButton.click();
|
||||
|
||||
await page.waitForURL((url) => url.pathname.includes("/auth/verify-email"));
|
||||
// Find the newly created user and add it to the fixture store
|
||||
|
||||
@@ -54,14 +54,14 @@ testBothFutureAndLegacyRoutes.describe("Teams - NonOrg", (routeVariant) => {
|
||||
// Click [data-testid="invite-new-member-button"]
|
||||
await page.locator('[data-testid="invite-new-member-button"]').click();
|
||||
await expect(page.locator(`li:has-text("${inviteeEmail}")`)).toBeVisible();
|
||||
expect(await page.locator('[data-testid="pending-member-item"]').count()).toBe(2);
|
||||
await expect(page.locator('[data-testid="pending-member-item"]')).toHaveCount(2);
|
||||
});
|
||||
|
||||
await test.step("Can remove members", async () => {
|
||||
const removeMemberButton = page.locator('[data-testid="remove-member-button"]');
|
||||
await removeMemberButton.click();
|
||||
await removeMemberButton.waitFor({ state: "hidden" });
|
||||
expect(await page.locator('[data-testid="pending-member-item"]').count()).toBe(1);
|
||||
await expect(page.locator('[data-testid="pending-member-item"]')).toHaveCount(1);
|
||||
// Cleanup here since this user is created without our fixtures.
|
||||
await prisma.user.delete({ where: { email: inviteeEmail } });
|
||||
});
|
||||
|
||||
@@ -20,9 +20,9 @@ test.describe("Unpublished", () => {
|
||||
const { team } = await owner.getFirstTeamMembership();
|
||||
const { requestedSlug } = team.metadata as { requestedSlug: string };
|
||||
await page.goto(`/team/${requestedSlug}`);
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(team.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("team")}")`).count()).toBe(1);
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(team.name)}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`div:text("${description("team")}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
|
||||
@@ -36,9 +36,9 @@ test.describe("Unpublished", () => {
|
||||
const { requestedSlug } = team.metadata as { requestedSlug: string };
|
||||
const { slug: teamEventSlug } = await owner.getFirstTeamEvent(team.id);
|
||||
await page.goto(`/team/${requestedSlug}/${teamEventSlug}`);
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(team.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("team")}")`).count()).toBe(1);
|
||||
await expect(page.locator('[data-testid="empty-screen"]')).toHaveCount(1);
|
||||
await expect(page.locator(`h2:has-text("${title(team.name)}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`div:text("${description("team")}")`)).toHaveCount(1);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
|
||||
@@ -48,9 +48,9 @@ test.describe("Unpublished", () => {
|
||||
const { requestedSlug } = org.metadata as { requestedSlug: string };
|
||||
await page.goto(`/org/${requestedSlug}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(org.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("organization")}")`).count()).toBe(1);
|
||||
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);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
|
||||
@@ -66,9 +66,9 @@ test.describe("Unpublished", () => {
|
||||
const [{ slug: subteamSlug }] = org.children as { slug: string }[];
|
||||
await page.goto(`/org/${requestedSlug}/team/${subteamSlug}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(org.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("organization")}")`).count()).toBe(1);
|
||||
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);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
|
||||
@@ -86,9 +86,9 @@ test.describe("Unpublished", () => {
|
||||
await page.goto(`/org/${requestedSlug}/team/${subteamSlug}/${subteamEventSlug}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(org.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("organization")}")`).count()).toBe(1);
|
||||
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);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
|
||||
@@ -98,9 +98,9 @@ test.describe("Unpublished", () => {
|
||||
const { requestedSlug } = org.metadata as { requestedSlug: string };
|
||||
await page.goto(`/org/${requestedSlug}/${owner.username}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(org.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("organization")}")`).count()).toBe(1);
|
||||
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);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
|
||||
@@ -111,9 +111,9 @@ test.describe("Unpublished", () => {
|
||||
const [{ slug: ownerEventType }] = owner.eventTypes;
|
||||
await page.goto(`/org/${requestedSlug}/${owner.username}/${ownerEventType}`);
|
||||
await page.waitForLoadState("networkidle");
|
||||
expect(await page.locator('[data-testid="empty-screen"]').count()).toBe(1);
|
||||
expect(await page.locator(`h2:has-text("${title(org.name)}")`).count()).toBe(1);
|
||||
expect(await page.locator(`div:text("${description("organization")}")`).count()).toBe(1);
|
||||
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);
|
||||
await expect(page.locator(`img`)).toHaveAttribute("src", /.*/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -577,9 +577,9 @@ test.describe("MEETING_ENDED, MEETING_STARTED", async () => {
|
||||
expect(newMeetingEndedTriggers.length).toBe(0);
|
||||
|
||||
// disable webhook
|
||||
await page.click('[data-testid="webhook-switch"]');
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.getByTestId("webhook-switch").click();
|
||||
const response = await page.waitForResponse("/api/trpc/webhook/edit?batch=1");
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
const scheduledTriggersAfterDisabling = await prisma.webhookScheduledTriggers.findMany({
|
||||
where: {
|
||||
|
||||
@@ -26,6 +26,7 @@ test.describe("Workflow Tab - Event Type", () => {
|
||||
await fillNameInput("Edited Workflow");
|
||||
await saveWorkflow();
|
||||
await page.getByTestId("go-back-button").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await hasWorkflowInList("Edited Workflow");
|
||||
});
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ test.describe("Routing Forms", () => {
|
||||
|
||||
await page.waitForSelector('[data-testid="routing-forms-list"]');
|
||||
// Ensure that it's visible in forms list
|
||||
expect(await page.locator('[data-testid="routing-forms-list"] > div').count()).toBe(1);
|
||||
await expect(page.locator('[data-testid="routing-forms-list"] > div')).toHaveCount(1);
|
||||
|
||||
await gotoRoutingLink({ page, formId });
|
||||
await expect(page.locator("text=Test Form Name")).toBeVisible();
|
||||
@@ -60,8 +60,8 @@ test.describe("Routing Forms", () => {
|
||||
label,
|
||||
});
|
||||
|
||||
expect(await page.inputValue(`[data-testid="description"]`)).toBe(description);
|
||||
expect(await page.locator('[data-testid="field"]').count()).toBe(types.length);
|
||||
await expect(page.locator('[data-testid="description"]')).toHaveValue(description);
|
||||
await expect(page.locator('[data-testid="field"]')).toHaveCount(types.length);
|
||||
|
||||
fields.forEach((item, index) => {
|
||||
createdFields[index] = { label: item.label, typeIndex: index };
|
||||
@@ -113,7 +113,7 @@ test.describe("Routing Forms", () => {
|
||||
//FIXME: Figure out why this delay is required. Without it field count comes out to be 1 only
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
expect(await page.locator('[data-testid="field"]').count()).toBe(2);
|
||||
await expect(page.locator('[data-testid="field"]')).toHaveCount(2);
|
||||
await expectCurrentFormToHaveFields(page, { 1: { label: "F1 Field1", typeIndex: 1 } }, types);
|
||||
// Add 1 more field in F1
|
||||
await addOneFieldAndDescriptionAndSaveForm(form1Id, page, {
|
||||
@@ -126,7 +126,7 @@ test.describe("Routing Forms", () => {
|
||||
await page.goto(`/routing-forms/form-edit/${form2Id}`);
|
||||
//FIXME: Figure out why this delay is required. Without it field count comes out to be 1 only
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
expect(await page.locator('[data-testid="field"]').count()).toBe(3);
|
||||
await expect(page.locator('[data-testid="field"]')).toHaveCount(3);
|
||||
await expectCurrentFormToHaveFields(page, { 2: { label: "F1 Field2", typeIndex: 1 } }, types);
|
||||
});
|
||||
todo("Create relationship by using duplicate with live connect");
|
||||
@@ -158,15 +158,15 @@ test.describe("Routing Forms", () => {
|
||||
|
||||
await page.fill('[data-testid="form-field-Test Field Long Text"]', "manual-fill");
|
||||
|
||||
expect(await page.locator(`[data-testid="form-field-firstField"]`).inputValue()).toBe("456");
|
||||
expect(await page.locator(`[data-testid="form-field-Test Field Number"]`).inputValue()).toBe("456");
|
||||
await expect(page.locator('[data-testid="form-field-firstField"]')).toHaveValue("456");
|
||||
await expect(page.locator('[data-testid="form-field-Test Field Number"]')).toHaveValue("456");
|
||||
|
||||
// TODO: Verify select and multiselect has prefilled values.
|
||||
// expect(await page.locator(`[data-testid="form-field-Test Field Select"]`).inputValue()).toBe("456");
|
||||
// expect(await page.locator(`[data-testid="form-field-Test Field MultiSelect"]`).inputValue()).toBe("456");
|
||||
|
||||
expect(await page.locator(`[data-testid="form-field-Test Field Phone"]`).inputValue()).toBe("456");
|
||||
expect(await page.locator(`[data-testid="form-field-Test Field Email"]`).inputValue()).toBe(
|
||||
await expect(page.locator('[data-testid="form-field-Test Field Phone"]')).toHaveValue("456");
|
||||
await expect(page.locator('[data-testid="form-field-Test Field Email"]')).toHaveValue(
|
||||
"456@example.com"
|
||||
);
|
||||
|
||||
@@ -324,12 +324,12 @@ test.describe("Routing Forms", () => {
|
||||
|
||||
// Router should be publicly accessible
|
||||
await users.logout();
|
||||
page.goto(`/router?form=${routingForm.id}&Test field=event-routing`);
|
||||
await page.goto(`/router?form=${routingForm.id}&Test field=event-routing`);
|
||||
await page.waitForURL((url) => {
|
||||
return url.pathname.endsWith("/pro/30min") && url.searchParams.get("Test field") === "event-routing";
|
||||
});
|
||||
|
||||
page.goto(`/router?form=${routingForm.id}&Test field=external-redirect`);
|
||||
await page.goto(`/router?form=${routingForm.id}&Test field=external-redirect`);
|
||||
await page.waitForURL((url) => {
|
||||
return (
|
||||
url.hostname.includes("google.com") && url.searchParams.get("Test field") === "external-redirect"
|
||||
@@ -357,17 +357,16 @@ test.describe("Routing Forms", () => {
|
||||
return document.querySelectorAll("input")[0].validity.valueMissing;
|
||||
});
|
||||
expect(firstInputMissingValue).toBe(true);
|
||||
expect(await page.locator('button[type="submit"][disabled]').count()).toBe(0);
|
||||
await expect(page.locator('button[type="submit"][disabled]')).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("Test preview should return correct route", async ({ page, users }) => {
|
||||
const user = await createUserAndLogin({ users, page });
|
||||
const routingForm = user.routingForms[0];
|
||||
page.goto(`apps/routing-forms/form-edit/${routingForm.id}`);
|
||||
await page.goto(`apps/routing-forms/form-edit/${routingForm.id}`);
|
||||
await page.click('[data-testid="test-preview"]');
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// //event redirect
|
||||
//event redirect
|
||||
await page.fill('[data-testid="form-field-Test field"]', "event-routing");
|
||||
await page.click('[data-testid="test-routing"]');
|
||||
let routingType = await page.locator('[data-testid="test-routing-result-type"]').innerText();
|
||||
|
||||
@@ -38,65 +38,19 @@ export const getEmbedIframe = async ({
|
||||
page: Page;
|
||||
pathname: string;
|
||||
}) => {
|
||||
const handleFrameErrors = (frame: Frame) => {
|
||||
frame.on("pageerror", (error) => {
|
||||
console.error(`Iframe error (${frame.url()}): ${error.message}`);
|
||||
});
|
||||
frame.on("requestfailed", (request) => {
|
||||
console.error(
|
||||
`Iframe failed request (${frame.url()}): ${request.url()}, ${request.failure()?.errorText}`
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// We can't seem to access page.frame till contentWindow is available. So wait for that.
|
||||
const iframeReady = await page.evaluate(
|
||||
(hardTimeout) => {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
const iframe = document.querySelector<HTMLIFrameElement>(".cal-embed");
|
||||
if (iframe) {
|
||||
console.log("Iframe found");
|
||||
}
|
||||
if (iframe?.contentWindow) {
|
||||
console.log("Iframe contentWindow found");
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (iframe && iframe.contentWindow && window.iframeReady) {
|
||||
clearInterval(interval);
|
||||
resolve(true);
|
||||
} else {
|
||||
console.log("Waiting for all three to be true:", {
|
||||
iframeElement: iframe,
|
||||
contentWindow: iframe?.contentWindow,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
iframeReady: window.iframeReady,
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// A hard timeout if iframe isn't ready in that time. Avoids infinite wait
|
||||
setTimeout(() => {
|
||||
clearInterval(interval);
|
||||
resolve(false);
|
||||
// This is the time embed-iframe.ts loads in the iframe and fires atleast one event. Also, it is a load of entire React Application so it can sometime take more time even on CI.
|
||||
}, hardTimeout);
|
||||
});
|
||||
await page.waitForFunction(
|
||||
() => {
|
||||
const iframe = document.querySelector<HTMLIFrameElement>(".cal-embed");
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return iframe && iframe.contentWindow && window.iframeReady;
|
||||
},
|
||||
!process.env.CI ? 15000 : 15000
|
||||
{ polling: 500 }
|
||||
);
|
||||
if (!iframeReady) {
|
||||
const embedIframe = page.frame(`cal-embed=${calNamespace}`);
|
||||
if (!embedIframe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
page.on("frameattached", handleFrameErrors);
|
||||
|
||||
// We just verified that iframeReady is true here, so obviously embedIframe is not null
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const embedIframe = page.frame(`cal-embed=${calNamespace}`)!;
|
||||
handleFrameErrors(embedIframe);
|
||||
const u = new URL(embedIframe.url());
|
||||
if (u.pathname === `${pathname}/embed`) {
|
||||
return embedIframe;
|
||||
@@ -151,12 +105,8 @@ export async function bookFirstEvent(username: string, frame: Frame, page: Page)
|
||||
await frame.press('[name="email"]', "Enter");
|
||||
const response = await page.waitForResponse("**/api/book/event");
|
||||
const booking = (await response.json()) as { uid: string; eventSlug: string };
|
||||
expect(response.status()).toBe(200);
|
||||
booking.eventSlug = eventSlug;
|
||||
|
||||
// Make sure we're navigated to the success page
|
||||
await expect(frame.locator("[data-testid=success-page]")).toBeVisible();
|
||||
// expect(await page.screenshot()).toMatchSnapshot("success-page.png");
|
||||
|
||||
return booking;
|
||||
}
|
||||
|
||||
@@ -166,13 +116,11 @@ export async function rescheduleEvent(username: string, frame: Frame, page: Page
|
||||
await frame.press('[name="email"]', "Enter");
|
||||
await frame.click("[data-testid=confirm-reschedule-button]");
|
||||
const response = await page.waitForResponse("**/api/book/event");
|
||||
expect(response.status()).toBe(200);
|
||||
const responseObj = await response.json();
|
||||
const booking = responseObj.uid;
|
||||
// Make sure we're navigated to the success page
|
||||
await expect(frame.locator("[data-testid=success-page]")).toBeVisible();
|
||||
return booking;
|
||||
}
|
||||
|
||||
export async function installAppleCalendar(page: Page) {
|
||||
await page.goto("/apps/categories/calendar");
|
||||
await page.click('[data-testid="app-store-app-card-apple-calendar"]');
|
||||
|
||||
@@ -113,16 +113,10 @@ test.describe("Popup Tests", () => {
|
||||
const calNamespace = "routingFormAuto";
|
||||
await addEmbedListeners(calNamespace);
|
||||
await page.goto("/?only=prerender-test");
|
||||
let embedIframe = await getEmbedIframe({
|
||||
calNamespace,
|
||||
page,
|
||||
pathname: "/forms/948ae412-d995-4865-875a-48302588de03",
|
||||
});
|
||||
expect(embedIframe).toBeFalsy();
|
||||
await page.click(
|
||||
`[data-cal-namespace=${calNamespace}][data-cal-link="forms/948ae412-d995-4865-875a-48302588de03"]`
|
||||
);
|
||||
embedIframe = await getEmbedIframe({
|
||||
const embedIframe = await getEmbedIframe({
|
||||
calNamespace,
|
||||
page,
|
||||
pathname: "/forms/948ae412-d995-4865-875a-48302588de03",
|
||||
|
||||
@@ -31,7 +31,7 @@ test.describe("Namespacing", () => {
|
||||
case: "doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace",
|
||||
},
|
||||
});
|
||||
expect(await page.locator("iframe").count()).toBe(1);
|
||||
await expect(page.locator("iframe")).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("Double install Embed Snippet with inline embed without a namespace(i.e. default namespace)", async ({
|
||||
@@ -48,7 +48,7 @@ test.describe("Namespacing", () => {
|
||||
case: "doubleInstallSnippetWithInlineEmbed",
|
||||
},
|
||||
});
|
||||
expect(await page.locator("iframe").count()).toBe(1);
|
||||
await expect(page.locator("iframe")).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
test("Different namespaces can have different init configs", async ({ page, embeds }) => {
|
||||
|
||||
@@ -59,7 +59,13 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
|
||||
|
||||
const { hasTeamPlan } = useHasTeamPlan();
|
||||
|
||||
const { handleSubmit, setValue, control, register } = useForm<BookingRedirectForm>({
|
||||
const {
|
||||
handleSubmit,
|
||||
setValue,
|
||||
control,
|
||||
register,
|
||||
formState: { isSubmitting },
|
||||
} = useForm<BookingRedirectForm>({
|
||||
defaultValues: currentlyEditingOutOfOfficeEntry
|
||||
? currentlyEditingOutOfOfficeEntry
|
||||
: {
|
||||
@@ -72,6 +78,7 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
|
||||
reasonId: 1,
|
||||
},
|
||||
});
|
||||
console.log(isSubmitting);
|
||||
|
||||
const createOrEditOutOfOfficeEntry = trpc.viewer.outOfOfficeCreateOrUpdate.useMutation({
|
||||
onSuccess: () => {
|
||||
@@ -97,11 +104,10 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
|
||||
}}>
|
||||
<form
|
||||
id="create-or-edit-ooo-form"
|
||||
className="h-full"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
createOrEditOutOfOfficeEntry.mutate(data);
|
||||
})}>
|
||||
<div className="px-1">
|
||||
<div className="h-full px-1">
|
||||
<DialogHeader
|
||||
title={
|
||||
currentlyEditingOutOfOfficeEntry ? t("edit_an_out_of_office") : t("create_an_out_of_office")
|
||||
@@ -215,28 +221,28 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter showDivider noSticky>
|
||||
<div className="flex">
|
||||
<Button
|
||||
color="minimal"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
closeModal();
|
||||
}}
|
||||
className="mr-1">
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
form="create-or-edit-ooo-form"
|
||||
color="primary"
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
data-testid="create-or-edit-entry-ooo-redirect">
|
||||
{currentlyEditingOutOfOfficeEntry ? t("save") : t("create")}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
<DialogFooter showDivider noSticky>
|
||||
<div className="flex">
|
||||
<Button
|
||||
color="minimal"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
closeModal();
|
||||
}}
|
||||
className="mr-1">
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
form="create-or-edit-ooo-form"
|
||||
color="primary"
|
||||
type="submit"
|
||||
disabled={createOrEditOutOfOfficeEntry.isPending}
|
||||
data-testid="create-or-edit-entry-ooo-redirect">
|
||||
{currentlyEditingOutOfOfficeEntry ? t("save") : t("create")}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user