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:
co-authored by
gitstart-calcom
GitStart-Cal.com
gitstart-calcom
Keith Williams
parent
d804b3947d
commit
9422e28598
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user