diff --git a/apps/web/modules/bookings/views/bookings-single-view.tsx b/apps/web/modules/bookings/views/bookings-single-view.tsx
index b9298c8c1b..94347610b1 100644
--- a/apps/web/modules/bookings/views/bookings-single-view.tsx
+++ b/apps/web/modules/bookings/views/bookings-single-view.tsx
@@ -321,6 +321,7 @@ export default function Success(props: PageProps) {
{t("back_to_bookings")}
diff --git a/apps/web/playwright/booking/collectiveEventType/collectiveEventType.e2e.ts b/apps/web/playwright/booking/collectiveEventType/collectiveEventType.e2e.ts
new file mode 100644
index 0000000000..cc01cb280c
--- /dev/null
+++ b/apps/web/playwright/booking/collectiveEventType/collectiveEventType.e2e.ts
@@ -0,0 +1,54 @@
+import { test } from "../../lib/fixtures";
+
+test.describe("Collective event type", () => {
+ const teamEventTitle = "Test Managed Event Type";
+ let userId: number;
+ test.beforeEach(async ({ page, users, bookingPage }) => {
+ const userFixture = await users.create(
+ { name: "testuser" },
+ { hasTeam: true, schedulingType: "COLLECTIVE", teamEventTitle }
+ );
+ await userFixture.apiLogin();
+ userId = userFixture.id;
+ await page.goto("/event-types");
+ await bookingPage.goToEventType(teamEventTitle);
+ });
+ test("Book a Collective event type", async ({ bookingPage }) => {
+ const eventTypePage = await bookingPage.previewEventType();
+ await bookingPage.selectTimeSlot(eventTypePage);
+ await bookingPage.fillEmailAndName(eventTypePage);
+ await bookingPage.confirmBooking(eventTypePage);
+ await bookingPage.backToBookings(eventTypePage);
+ await bookingPage.assertLabelWithCorrectTeamName(eventTypePage, teamEventTitle);
+ await bookingPage.assertBookingWithCorrectTitleAndDescription(eventTypePage, {
+ profileName: "testuser",
+ bookingName: teamEventTitle,
+ teamName: `user-id-${userId}'s Team`,
+ });
+ await bookingPage.clickOnBooking(eventTypePage, teamEventTitle);
+ await bookingPage.rescheduleBooking(eventTypePage);
+ await bookingPage.assertBookingRescheduled(eventTypePage);
+ await bookingPage.cancelBookingWithReason(eventTypePage);
+ await bookingPage.assertBookingCanceled(eventTypePage);
+ });
+ test("Book a Collective event type (with added guest)", async ({ bookingPage }) => {
+ const eventTypePage = await bookingPage.previewEventType();
+ await bookingPage.selectTimeSlot(eventTypePage);
+ await bookingPage.fillEmailAndName(eventTypePage);
+ await bookingPage.addGuests(eventTypePage, { guests: ["test@example.com"] });
+ await bookingPage.confirmBooking(eventTypePage);
+ await bookingPage.backToBookings(eventTypePage);
+ await bookingPage.assertLabelWithCorrectTeamName(eventTypePage, teamEventTitle);
+ await bookingPage.assertBookingWithCorrectTitleAndDescription(eventTypePage, {
+ profileName: "testuser",
+ bookingName: teamEventTitle,
+ teamName: `user-id-${userId}'s Team`,
+ aditionalGuestEmail: "test@example.com",
+ });
+ await bookingPage.clickOnBooking(eventTypePage, teamEventTitle);
+ await bookingPage.rescheduleBooking(eventTypePage);
+ await bookingPage.assertBookingRescheduled(eventTypePage);
+ await bookingPage.cancelBookingWithReason(eventTypePage);
+ await bookingPage.assertBookingCanceled(eventTypePage);
+ });
+});
diff --git a/apps/web/playwright/fixtures/regularBookings.ts b/apps/web/playwright/fixtures/regularBookings.ts
index 565340ccc7..9b0baab023 100644
--- a/apps/web/playwright/fixtures/regularBookings.ts
+++ b/apps/web/playwright/fixtures/regularBookings.ts
@@ -26,6 +26,8 @@ interface QuestionActions {
[key: string]: () => Promise;
}
+type teamBookingtypes = { isManagedType?: boolean; isRoundRobinType?: boolean; isCollectiveType?: boolean };
+
type customLocators = {
shouldChangeSelectLocator: boolean;
shouldUseLastRadioGroupLocator: boolean;
@@ -205,7 +207,12 @@ export function createBookingPageFixture(page: Page) {
goToEventType: async (eventType: string) => {
await page.getByRole("link", { name: eventType }).click();
},
-
+ goToPage: async (pageName: string, page: Page) => {
+ await page.getByRole("link", { name: pageName }).click();
+ },
+ backToBookings: async (page: Page) => {
+ await page.getByTestId("back-to-bookings").click();
+ },
goToTab: async (tabName: string) => {
await page.getByTestId(`vertical-tab-${tabName}`).click();
},
@@ -405,17 +412,102 @@ export function createBookingPageFixture(page: Page) {
const confirmButton = options.isReschedule ? "confirm-reschedule-button" : "confirm-book-button";
await fillAllQuestions(eventTypePage, questions, options);
await eventTypePage.getByTestId(confirmButton).click();
- await eventTypePage.waitForTimeout(400);
- if (await eventTypePage.getByRole("heading", { name: "Could not book the meeting." }).isVisible()) {
- await eventTypePage.getByTestId("back").click();
- await eventTypePage.getByTestId("time").last().click();
- await fillAllQuestions(eventTypePage, questions, options);
- await eventTypePage.getByTestId(confirmButton).click();
- }
const scheduleSuccessfullyPage = eventTypePage.getByText(scheduleSuccessfullyText);
await scheduleSuccessfullyPage.waitFor({ state: "visible" });
await expect(scheduleSuccessfullyPage).toBeVisible();
},
+ addGuests: async (eventTypePage: Page, options: { guests: string[] }) => {
+ await eventTypePage.getByTestId("add-guests").click();
+ for (const guest of options.guests) {
+ await eventTypePage.getByPlaceholder("Email").fill(guest);
+ }
+ },
+ createTeam: async (name: string) => {
+ await page.getByTestId("teams-test").click();
+ await page.getByTestId("new-team-btn").click();
+ await page.getByPlaceholder("Acme Inc.").click();
+ await page.getByPlaceholder("Acme Inc.").fill(name);
+ await page.getByTestId("continue-button").click();
+ await page.getByTestId("publish-button").click();
+
+ await page.getByTestId("vertical-tab-Back").click();
+ },
+
+ createTeamEventType: async (name: string, options: teamBookingtypes) => {
+ await page.getByTestId("new-event-type").click();
+ await page.getByTestId("option-0").click();
+
+ // We first simulate to create a default event type to check if managed option is not available
+
+ const managedEventDescription = (await localize("en"))("managed_event_description");
+ const roundRobinEventDescription = (await localize("en"))("round_robin_description");
+ const collectiveEventDescription = (await localize("en"))("collective_description");
+ const quickChatText = (await localize("en"))("quick_chat");
+ await expect(page.locator("div").filter({ hasText: managedEventDescription })).toBeHidden();
+ await page.getByTestId("dialog-rejection").click();
+
+ await page.getByTestId("new-event-type").click();
+ await page.getByTestId("option-team-1").click();
+ await page.getByPlaceholder(quickChatText).fill(name);
+ if (options.isCollectiveType) {
+ await page
+ .locator("div")
+ .filter({ hasText: `Collective${collectiveEventDescription}` })
+ .getByRole("radio")
+ .first()
+ .click();
+ }
+
+ if (options.isRoundRobinType) {
+ await page
+ .locator("div")
+ .filter({ hasText: `Round Robin${roundRobinEventDescription}` })
+ .getByRole("radio")
+ .nth(1)
+ .click();
+ }
+
+ if (options.isManagedType) {
+ await page
+ .locator("div")
+ .filter({ hasText: `Managed Event${managedEventDescription}` })
+ .getByRole("radio")
+ .last()
+ .click();
+
+ const managedEventClarification = (await localize("en"))("managed_event_url_clarification");
+ await expect(page.getByText(managedEventClarification)).toBeVisible();
+ }
+
+ const continueText = (await localize("en"))("continue");
+ const toast = page.getByTestId("toast-success");
+
+ await page.getByRole("button", { name: continueText }).click();
+ expect(toast).toBeTruthy();
+ await page.getByTestId("update-eventtype").click();
+ },
+ assertLabelWithCorrectTeamName: async (page: Page, teamName: string) => {
+ await expect(page.getByRole("link", { name: teamName }).first()).toBeVisible();
+ },
+ assertBookingWithCorrectTitleAndDescription: async (
+ page: Page,
+ options: { profileName: string; bookingName: string; teamName: string; aditionalGuestEmail?: string }
+ ) => {
+ options.aditionalGuestEmail
+ ? await expect(
+ page.getByRole("link", {
+ name: `${options.bookingName} between ${options.teamName} and ${options.profileName} You , ${options.profileName} and ${options.aditionalGuestEmail}`,
+ })
+ ).toBeVisible()
+ : await expect(
+ page.getByRole("link", {
+ name: `${options.bookingName} between ${options.teamName} and ${options.profileName} You and ${options.profileName}`,
+ })
+ ).toBeVisible();
+ },
+ clickOnBooking: async (page: Page, teamName: string) => {
+ await page.getByRole("link", { name: teamName }).first().click();
+ },
checkField: async (question: string, options?: { isOptional: boolean }) => {
if (options?.isOptional) {
@@ -635,5 +727,12 @@ export function createBookingPageFixture(page: Page) {
await page.getByTestId("booking-item").first().getByText("Reject").click();
await page.getByTestId("rejection-confirm").click();
},
+ fillEmailAndName: async (eventTypePage: Page) => {
+ const emailLabel = (await localize("en"))("email_address");
+ const nameLabel = (await localize("en"))("your_name");
+
+ await eventTypePage.getByLabel(emailLabel).fill(EMAIL);
+ await eventTypePage.getByLabel(nameLabel).fill("testuser");
+ },
};
}
diff --git a/packages/features/ee/teams/components/CreateANewTeamForm.tsx b/packages/features/ee/teams/components/CreateANewTeamForm.tsx
index beabedb1d6..4aa012d88b 100644
--- a/packages/features/ee/teams/components/CreateANewTeamForm.tsx
+++ b/packages/features/ee/teams/components/CreateANewTeamForm.tsx
@@ -158,7 +158,8 @@ export const CreateANewTeamForm = () => {
color="primary"
EndIcon={ArrowRight}
type="submit"
- className="w-full justify-center">
+ className="w-full justify-center"
+ data-testid="continue-button">
{t(flag.submitLabel)}
diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx
index 4511ef8418..538f9e234c 100644
--- a/packages/features/shell/Shell.tsx
+++ b/packages/features/shell/Shell.tsx
@@ -742,7 +742,7 @@ const NavigationItem: React.FC<{
/>
)}
{isLocaleReady ? (
-
+
{t(item.name)}
{item.badge && item.badge}