test: check all advanced options in a managed event-type (teste2e-managedOptions) (#12294)

* check all advanced options in a managed event-type

* Delete apps/web/playwright/booking/managedBookingAllQuestion.e2e.ts

* Delete apps/web/playwright/managedBooking/allQuestions.e2e.ts

* Refactor

* Refactor

* check all advanced options in a managed event-type

* check all advanced options in a managed event-type

* Update regularBookings.ts

* Update regularBookings.ts

---------

Co-authored-by: gitstart-calcom <gitstart-calcom@users.noreply.github.com>
Co-authored-by: GitStart-Cal.com <121884634+gitstart-calcom@users.noreply.github.com>
Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
This commit is contained in:
gitstart-app[bot]
2024-01-27 07:50:38 -03:00
committed by GitHub
co-authored by gitstart-calcom GitStart-Cal.com gitstart-calcom Keith Williams
parent d804b3947d
commit 9422e28598
10 changed files with 174 additions and 15 deletions
@@ -215,6 +215,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
toggleSwitchAtTheEnd={true}
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
title={t("requires_booker_email_verification")}
data-testid="requires-booker-email-verification"
{...shouldLockDisableProps("requiresBookerEmailVerification")}
description={t("description_requires_booker_email_verification")}
checked={value}
@@ -231,6 +232,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
toggleSwitchAtTheEnd={true}
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
title={t("disable_notes")}
data-testid="disable-notes"
{...shouldLockDisableProps("hideCalendarNotes")}
description={t("disable_notes_description")}
checked={value}
@@ -252,6 +254,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
)}
childrenClassName="lg:ml-0"
title={t("redirect_success_booking")}
data-testid="redirect-success-booking"
{...successRedirectUrlLocked}
description={t("redirect_url_description")}
checked={redirectUrlVisible}
@@ -266,6 +269,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
labelSrOnly
disabled={successRedirectUrlLocked.disabled}
placeholder={t("external_redirect_url")}
data-testid="external-redirect-url"
required={redirectUrlVisible}
type="text"
{...formMethods.register("successRedirectUrl")}
@@ -274,7 +278,8 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
className={classNames(
"p-1 text-sm text-orange-600",
formMethods.getValues("successRedirectUrl") ? "block" : "hidden"
)}>
)}
data-testid="redirect-url-warning">
{t("redirect_url_warning")}
</div>
</div>
@@ -295,6 +300,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
title={t("enable_private_url")}
Badge={
<a
data-testid="hashedLinkCheck-info"
target="_blank"
rel="noreferrer"
href="https://cal.com/docs/core-features/event-types/single-use-private-links">
@@ -398,12 +404,14 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
onChange={(e) => {
onChange(Math.abs(Number(e.target.value)));
}}
data-testid="seats-per-time-slot"
/>
<div className="mt-4">
<Controller
name="seatsShowAttendees"
render={({ field: { value, onChange } }) => (
<CheckboxField
data-testid="show-attendees"
description={t("show_attendees")}
disabled={seatsLocked.disabled}
onChange={(e) => onChange(e)}
@@ -446,6 +454,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
description={t("description_lock_timezone_toggle_on_booking_page")}
checked={value}
onCheckedChange={(e) => onChange(e)}
data-testid="lock-timezone-toggle"
/>
)}
/>
@@ -75,6 +75,7 @@ export default function RequiresConfirmationController({
)}
childrenClassName="lg:ml-0"
title={t("requires_confirmation")}
data-testid="requires-confirmation"
disabled={seatsEnabled || requiresConfirmationLockedProps.disabled}
tooltip={seatsEnabled ? t("seat_options_doesnt_support_confirmation") : undefined}
description={t("requires_confirmation_description")}
@@ -91,7 +91,7 @@ test.describe("Booking With All Questions", () => {
} else {
await bookingPage.addQuestion(question, `${question}-test`, `${question} test`, false);
}
await bookingPage.checkField(question);
await bookingPage.checkField(question, { isOptional: true });
}
await bookingPage.updateEventType();
+103 -8
View File
@@ -205,9 +205,15 @@ export function createBookingPageFixture(page: Page) {
goToEventType: async (eventType: string) => {
await page.getByRole("link", { name: eventType }).click();
},
goToTab: async (tabName: string) => {
await page.getByTestId(`vertical-tab-${tabName}`).click();
},
goToEventTypesPage: async () => {
await page.goto("/event-types");
},
setResolution: async (width: number, height: number) => {
await page.setViewportSize({ width: width, height: height });
},
@@ -253,16 +259,21 @@ export function createBookingPageFixture(page: Page) {
},
updateEventType: async () => {
await page.getByTestId("update-eventtype").click();
const toast = await page.waitForSelector('[data-testid="toast-success"]');
expect(toast).toBeTruthy();
},
previewEventType: async () => {
const eventtypePromise = page.waitForEvent("popup");
await page.getByTestId("preview-button").click();
return eventtypePromise;
},
selectTimeSlot: async (eventTypePage: Page) => {
await goToNextMonthIfNoAvailabilities(eventTypePage);
await eventTypePage.getByTestId("time").first().click();
},
clickReschedule: async () => {
await page.getByText("Reschedule").click();
},
@@ -290,6 +301,7 @@ export function createBookingPageFixture(page: Page) {
await page.getByTestId("cancel_reason").fill("Test cancel");
await page.getByTestId("confirm_cancel").click();
},
assertBookingCanceled: async (page: Page) => {
await expect(page.getByTestId("cancelled-headline")).toBeVisible();
},
@@ -330,11 +342,9 @@ export function createBookingPageFixture(page: Page) {
},
confirmBooking: async (eventTypePage: Page) => {
const confirmButton = "confirm-book-button";
await eventTypePage.getByTestId(confirmButton).click();
const scheduleSuccessfullyPage = eventTypePage.getByText(scheduleSuccessfullyText);
await scheduleSuccessfullyPage.waitFor({ state: "visible" });
await expect(scheduleSuccessfullyPage).toBeVisible();
await eventTypePage.getByTestId("confirm-book-button").click();
await eventTypePage.waitForURL("booking/**");
await expect(eventTypePage.getByText(scheduleSuccessfullyText)).toBeVisible();
},
fillAndConfirmBooking: async ({
@@ -390,9 +400,7 @@ export function createBookingPageFixture(page: Page) {
await scheduleSuccessfullyPage.waitFor({ state: "visible" });
await expect(scheduleSuccessfullyPage).toBeVisible();
},
checkField: async (question: string) => {
await expect(page.getByTestId(`field-${question}-test`)).toBeVisible();
},
fillAllQuestions: async (eventTypePage: Page, questions: string[], options: BookingOptions) => {
const confirmButton = options.isReschedule ? "confirm-reschedule-button" : "confirm-book-button";
await fillAllQuestions(eventTypePage, questions, options);
@@ -409,6 +417,93 @@ export function createBookingPageFixture(page: Page) {
await expect(scheduleSuccessfullyPage).toBeVisible();
},
checkField: async (question: string, options?: { isOptional: boolean }) => {
if (options?.isOptional) {
await expect(page.getByTestId(`field-${question}-test`).getByTestId("optional")).toBeVisible();
} else {
await expect(page.getByTestId(`field-${question}-test`).getByTestId("required")).toBeVisible();
}
await expect(page.getByTestId(`field-${question}-test`)).toBeVisible();
},
checkRequiresConfirmation: async () => {
// Check existence of the icon
await expect(page.getByTestId("requires-confirmation-title").locator("svg")).toBeVisible();
const confirmationSwitch = page.getByTestId("requires-confirmation");
await expect(confirmationSwitch).toBeVisible();
await confirmationSwitch.click();
},
checkRequiresBookerEmailVerification: async () => {
await expect(page.getByTestId("requires-booker-email-verification-title").locator("svg")).toBeVisible();
const emailSwitch = page.getByTestId("requires-booker-email-verification");
await expect(emailSwitch).toBeVisible();
await emailSwitch.click();
},
checkHideNotes: async () => {
await expect(page.getByTestId("disable-notes-title").locator("svg")).toBeVisible();
const hideNotesSwitch = page.getByTestId("disable-notes");
await expect(hideNotesSwitch).toBeVisible();
await hideNotesSwitch.click();
},
checkRedirectOnBooking: async () => {
await expect(page.getByTestId("redirect-success-booking-title").locator("svg")).toBeVisible();
const redirectSwitch = page.getByTestId("redirect-success-booking");
await expect(redirectSwitch).toBeVisible();
await redirectSwitch.click();
await expect(page.getByTestId("external-redirect-url")).toBeVisible();
await page.getByTestId("external-redirect-url").fill("https://cal.com");
await expect(page.getByTestId("redirect-url-warning")).toBeVisible();
},
checkEnablePrivateUrl: async () => {
await expect(page.getByTestId("hashedLinkCheck-title").locator("label div")).toBeVisible();
await expect(page.getByTestId("hashedLinkCheck-info")).toBeVisible();
await expect(page.getByTestId("hashedLinkCheck")).toBeVisible();
await page.getByTestId("hashedLinkCheck").click();
await expect(page.getByTestId("generated-hash-url")).toBeVisible();
},
toggleOfferSeats: async () => {
await expect(page.getByTestId("offer-seats-toggle-title").locator("svg")).toBeVisible();
await page.getByTestId("offer-seats-toggle").click();
const seatSwitchField = page.getByTestId("seats-per-time-slot");
await seatSwitchField.fill("3");
await expect(seatSwitchField).toHaveValue("3");
await expect(page.getByTestId("show-attendees")).toBeVisible();
},
checkLockTimezone: async () => {
await expect(page.getByTestId("lock-timezone-toggle-title").locator("svg")).toBeVisible();
const lockSwitch = page.getByTestId("lock-timezone-toggle");
await expect(lockSwitch).toBeVisible();
await lockSwitch.click();
},
checkEventType: async () => {
await expect(page.getByTestId("requires-confirmation-badge").last()).toBeVisible();
},
assertBookingIsVisible: async (name: string) => {
await expect(
page.getByRole("link", {
name,
})
).toBeVisible();
},
checkBufferTime: async () => {
const minutes = (await localize("en"))("minutes");
const fieldPlaceholder = page.getByPlaceholder("0");
@@ -0,0 +1,43 @@
import { test } from "../lib/fixtures";
test.beforeEach(async ({ page, users, bookingPage }) => {
const teamEventTitle = "Test Managed Event Type";
const userFixture = await users.create(
{ name: "testuser" },
{ hasTeam: true, schedulingType: "MANAGED", teamEventTitle }
);
await userFixture.apiLogin();
await page.goto("/event-types");
await bookingPage.goToEventType(teamEventTitle);
await bookingPage.goToTab("event_advanced_tab_title");
});
test.describe("Check advanced options in a managed team event type", () => {
test("Check advanced options in a managed team event type without offer seats", async ({ bookingPage }) => {
await bookingPage.checkRequiresConfirmation();
await bookingPage.checkRequiresBookerEmailVerification();
await bookingPage.checkHideNotes();
await bookingPage.checkRedirectOnBooking();
await bookingPage.checkEnablePrivateUrl();
await bookingPage.checkLockTimezone();
await bookingPage.updateEventType();
await bookingPage.goToEventTypesPage();
await bookingPage.checkEventType();
});
test("Check advanced options in a managed team event type with offer seats", async ({ bookingPage }) => {
await bookingPage.checkRequiresConfirmation();
await bookingPage.checkRequiresBookerEmailVerification();
await bookingPage.checkHideNotes();
await bookingPage.checkRedirectOnBooking();
await bookingPage.checkEnablePrivateUrl();
await bookingPage.toggleOfferSeats();
await bookingPage.checkLockTimezone();
await bookingPage.updateEventType();
await bookingPage.goToEventTypesPage();
await bookingPage.checkEventType();
});
});
@@ -109,6 +109,7 @@ export const CreateANewTeamForm = () => {
}
}}
autoComplete="off"
data-testid="team-name"
/>
</>
)}
@@ -183,6 +183,7 @@ export default function CreateEventTypeDialog({
<TextField
label={t("title")}
placeholder={t("quick_chat")}
data-testid="event-type-quick-chat"
{...register("title")}
onChange={(e) => {
form.setValue("title", e?.target.value);
@@ -293,7 +294,8 @@ export default function CreateEventTypeDialog({
{...register("schedulingType")}
value={SchedulingType.MANAGED}
className={classNames("text-sm", !isAdmin && "w-1/2")}
classNames={{ container: classNames(isAdmin && "w-full") }}>
classNames={{ container: classNames(isAdmin && "w-full") }}
data-testid="managed-event-type">
<strong className="mb-1 block">{t("managed_event")}</strong>
<p>{t("managed_event_description")}</p>
</RadioArea.Item>
@@ -106,7 +106,7 @@ export const EventTypeDescription = ({
</li>
)}
{eventType.requiresConfirmation && (
<li className="hidden xl:block">
<li className="hidden xl:block" data-testid="requires-confirmation-badge">
<Badge variant="gray" startIcon={Clipboard}>
{eventType.metadata?.requiresConfirmationThreshold
? t("may_require_confirmation")
@@ -181,7 +181,9 @@ export const FormBuilder = function FormBuilder({
// Hidden field can't be required, so we don't need to show the Optional badge
<Badge variant="grayWithoutHover">{t("hidden")}</Badge>
) : (
<Badge variant="grayWithoutHover">{isRequired ? t("required") : t("optional")}</Badge>
<Badge variant="grayWithoutHover" data-testid={isRequired ? "required" : "optional"}>
{isRequired ? t("required") : t("optional")}
</Badge>
)}
{Object.entries(groupedBySourceLabel).map(([sourceLabel, sources], key) => (
// We don't know how to pluralize `sourceLabel` because it can be anything
@@ -53,7 +53,7 @@ function SettingsToggle({
switchContainerClassName
)}>
<div>
<div className="flex items-center">
<div className="flex items-center" data-testid={`${rest["data-testid"]}-title`}>
<Label
className={classNames("mt-0.5 text-base font-semibold leading-none", labelClassName)}>
{title}
@@ -61,7 +61,13 @@ function SettingsToggle({
</Label>
{Badge && <div className="mb-2">{Badge}</div>}
</div>
{description && <p className="text-default -mt-1.5 text-sm leading-normal">{description}</p>}
{description && (
<p
className="text-default -mt-1.5 text-sm leading-normal"
data-testid={`${rest["data-testid"]}-description`}>
{description}
</p>
)}
</div>
<div className="my-auto h-full">
<Switch