Files
calendar/packages/embeds/embed-core/playwright/lib/testUtils.ts
T
Hariom BalharaandGitHub e57f734e79 Test/Embed/Reschedule (#6056)
* Add reschedule embed test

* Add comments
2022-12-18 19:24:44 +00:00

152 lines
5.6 KiB
TypeScript

import { Page, Frame, test, expect } from "@playwright/test";
import prisma from "@calcom/prisma";
export function todo(title: string) {
// eslint-disable-next-line @typescript-eslint/no-empty-function, playwright/no-skipped-test
test.skip(title, () => {});
}
export const deleteAllBookingsByEmail = async (email: string) =>
await prisma.booking.deleteMany({
where: {
attendees: {
some: {
email: email,
},
},
},
});
export const getBooking = async (bookingId: string) => {
const booking = await prisma.booking.findUnique({
where: {
uid: bookingId,
},
include: {
attendees: true,
},
});
if (!booking) {
throw new Error("Booking not found");
}
return booking;
};
export const getEmbedIframe = async ({ page, pathname }: { page: Page; pathname: string }) => {
// We can't seem to access page.frame till contentWindow is available. So wait for that.
const iframeReady = await page.evaluate(() => {
return new Promise((resolve) => {
const interval = setInterval(() => {
const iframe = document.querySelector(".cal-embed") as HTMLIFrameElement | null;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (iframe && iframe.contentWindow && window.iframeReady) {
clearInterval(interval);
resolve(true);
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
console.log("Iframe Status:", !!iframe, !!iframe?.contentWindow, window.iframeReady);
}
}, 500);
// A hard timeout if iframe isn't ready in that time. Avoids infinite wait
setTimeout(() => {
clearInterval(interval);
resolve(false);
}, 5000);
});
});
if (!iframeReady) {
return null;
}
// 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")!;
const u = new URL(embedIframe.url());
if (u.pathname === pathname + "/embed") {
return embedIframe;
}
console.log('Embed iframe url pathname match. Expected: "' + pathname + '/embed"', "Actual: " + u.pathname);
return null;
};
async function selectFirstAvailableTimeSlotNextMonth(frame: Frame, page: Page) {
await frame.click('[data-testid="incrementMonth"]');
// @TODO: Find a better way to make test wait for full month change render to end
// so it can click up on the right day, also when done, resolve other todos as well
// The problem is that the Month Text changes instantly but we don't know when the corresponding dates are visible
// Waiting for full month increment
await frame.waitForTimeout(1000);
expect(await page.screenshot()).toMatchSnapshot("availability-page-2.png");
// TODO: Find out why the first day is always booked on tests
await frame.locator('[data-testid="day"][data-disabled="false"]').nth(1).click();
await frame.click('[data-testid="time"]');
}
export async function bookFirstEvent(username: string, frame: Frame, page: Page) {
// Click first event type
await frame.click('[data-testid="event-type-link"]');
await frame.waitForNavigation({
url(url) {
return !!url.pathname.match(new RegExp(`/${username}/.*$`));
},
});
// Let current month dates fully render.
// There is a bug where if we don't let current month fully render and quickly click go to next month, current month get's rendered
// This doesn't seem to be replicable with the speed of a person, only during automation.
// It would also allow correct snapshot to be taken for current month.
await frame.waitForTimeout(1000);
expect(await page.screenshot()).toMatchSnapshot("availability-page-1.png");
const eventSlug = new URL(frame.url()).pathname;
await selectFirstAvailableTimeSlotNextMonth(frame, page);
await frame.waitForNavigation({
url(url) {
return url.pathname.includes(`/${username}/book`);
},
});
expect(await page.screenshot()).toMatchSnapshot("booking-page.png");
// --- fill form
await frame.fill('[name="name"]', "Embed User");
await frame.fill('[name="email"]', "embed-user@example.com");
await frame.press('[name="email"]', "Enter");
const response = await page.waitForResponse("**/api/book/event");
const booking = (await response.json()) as { uid: string; eventSlug: string };
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");
//NOTE: frame.click('body') won't work here. Because the way it works, it clicks on the center of the body tag which is an element inside the popup view and that won't close the popup
await frame.evaluate(() => {
// Closes popup - if it is a popup. If not a popup, it will just do nothing
document.body.click();
});
return booking;
}
export async function rescheduleEvent(username, frame, page) {
await selectFirstAvailableTimeSlotNextMonth(frame, page);
await frame.waitForNavigation({
url(url) {
return url.pathname.includes(`/${username}/book`);
},
});
// --- fill form
await frame.press('[name="email"]', "Enter");
await frame.click("[data-testid=confirm-reschedule-button]");
const response = await page.waitForResponse("**/api/book/event");
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;
}