calcom/apps/web/playwright/booking-pages.test.ts
alannnc 3c6ac395cc
Feature/reschedule bookings (#2351)
* WIP bookings page ui changes, created api endpoint

* Ui changes mobile/desktop

* Added translations

* Fix lib import and common names

* WIP reschedule

* WIP

* Save wip

* [WIP] builder and class for CalendarEvent, email for attende

* update rescheduled emails, booking view and availability page view

* Working version reschedule

* Fix for req.user as array

* Added missing translation and refactor dialog to self component

* Test for reschedule

* update on types

* Update lib no required

* Update type on createBooking

* fix types

* remove preview stripe sub

* remove unused file

* remove unused import

* Fix reschedule test

* Refactor and cleaning up code

* Email reschedule title fixes

* Adding calendar delete and recreate placeholder of cancelled

* Add translation

* Removed logs, notes, fixed types

* Fixes process.env types

* Use strict compare

* Fixes type inference

* Type fixing is my middle name

* Update apps/web/components/booking/BookingListItem.tsx

* Update apps/web/components/dialog/RescheduleDialog.tsx

* Update packages/core/builders/CalendarEvent/director.ts

* Update apps/web/pages/success.tsx

* Updates rescheduling labels

* Update packages/core/builders/CalendarEvent/builder.ts

* Type fixes

* Update packages/core/builders/CalendarEvent/builder.ts

* Only validating input blocked once

* E2E fixes

* Stripe tests fixes

Co-authored-by: Peer Richelsen <peer@cal.com>
Co-authored-by: zomars <zomars@me.com>
2022-04-14 15:25:24 -06:00

149 lines
4.4 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { deleteAllBookingsByEmail } from "./lib/teardown";
import {
bookFirstEvent,
bookTimeSlot,
selectFirstAvailableTimeSlotNextMonth,
selectSecondAvailableTimeSlotNextMonth,
todo,
} from "./lib/testUtils";
test.describe("free user", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/free");
});
test.afterEach(async () => {
// delete test bookings
await deleteAllBookingsByEmail("free@example.com");
});
test("only one visible event", async ({ page }) => {
await expect(page.locator(`[href="/free/30min"]`)).toBeVisible();
await expect(page.locator(`[href="/free/60min"]`)).not.toBeVisible();
});
test("cannot book same slot multiple times", async ({ page }) => {
// Click first event type
await page.click('[data-testid="event-type-link"]');
await selectFirstAvailableTimeSlotNextMonth(page);
// Navigate to book page
await page.waitForNavigation({
url(url) {
return url.pathname.endsWith("/book");
},
});
// save booking url
const bookingUrl: string = page.url();
// book same time spot twice
await bookTimeSlot(page);
// Make sure we're navigated to the success page
await page.waitForNavigation({
url(url) {
return url.pathname.endsWith("/success");
},
});
// return to same time spot booking page
await page.goto(bookingUrl);
// book same time spot again
await bookTimeSlot(page);
// check for error message
await expect(page.locator("[data-testid=booking-fail]")).toBeVisible();
});
// Why do we need this test. The previous test is testing /30min booking only ?
todo("`/free/30min` is bookable");
test("`/free/60min` is not bookable", async ({ page }) => {
// Not available in listing
await expect(page.locator('[href="/free/60min"]')).toHaveCount(0);
await page.goto("/free/60min");
// Not available on a direct visit to event type page
await expect(page.locator('[data-testid="404-page"]')).toBeVisible();
});
});
test.describe("pro user", () => {
test.use({ storageState: "playwright/artifacts/proStorageState.json" });
test.beforeEach(async ({ page }) => {
await deleteAllBookingsByEmail("pro@example.com");
await page.goto("/pro");
});
test.afterEach(async () => {
await deleteAllBookingsByEmail("pro@example.com");
});
test("pro user's page has at least 2 visible events", async ({ page }) => {
// await page.pause();
const $eventTypes = await page.locator("[data-testid=event-types] > *");
expect(await $eventTypes.count()).toBeGreaterThanOrEqual(2);
});
test("book an event first day in next month", async ({ page }) => {
// Click first event type
await page.click('[data-testid="event-type-link"]');
await selectFirstAvailableTimeSlotNextMonth(page);
await bookTimeSlot(page);
// Make sure we're navigated to the success page
await page.waitForNavigation({
url(url) {
return url.pathname.endsWith("/success");
},
});
});
test("can reschedule a booking", async ({ page }) => {
await bookFirstEvent(page);
await page.goto("/bookings/upcoming");
await page.locator('[data-testid="reschedule"]').click();
await page.locator('[data-testid="edit"]').click();
await page.waitForNavigation({
url: (url) => {
const bookingId = url.searchParams.get("rescheduleUid");
return !!bookingId;
},
});
await selectSecondAvailableTimeSlotNextMonth(page);
// --- fill form
await page.locator('[data-testid="confirm-reschedule-button"]').click();
await page.waitForNavigation({
url(url) {
return url.pathname === "/success" && url.searchParams.get("reschedule") === "true";
},
});
});
test("Can cancel the recently created booking and rebook the same timeslot", async ({ page }) => {
await bookFirstEvent(page);
await page.goto("/bookings/upcoming");
await page.locator('[data-testid="cancel"]').first().click();
await page.waitForNavigation({
url: (url) => {
return url.pathname.startsWith("/cancel");
},
});
// --- fill form
await page.locator('[data-testid="cancel"]').click();
await page.waitForNavigation({
url(url) {
return url.pathname === "/cancel/success";
},
});
await page.goto("/pro");
await bookFirstEvent(page);
});
});