From e61be783d12091ea8de8cdf96c351706acc772bd Mon Sep 17 00:00:00 2001 From: "gitstart-app[bot]" <57568882+gitstart-app[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:56:48 +0000 Subject: [PATCH 1/4] test: Check the recurring event tab and your funtionalities (teste2e-recurring) (#12331) Co-authored-by: gitstart-calcom Co-authored-by: GitStart-Cal.com <121884634+gitstart-calcom@users.noreply.github.com> Co-authored-by: Keith Williams --- .../booking/recurringBooking.e2e.ts | 28 +++++++++++++++++ .../playwright/fixtures/regularBookings.ts | 30 +++++++++++++++++++ .../components/event-meta/Occurences.tsx | 5 ++-- .../components/EventTypeDescription.tsx | 2 +- 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 apps/web/playwright/booking/recurringBooking.e2e.ts diff --git a/apps/web/playwright/booking/recurringBooking.e2e.ts b/apps/web/playwright/booking/recurringBooking.e2e.ts new file mode 100644 index 00000000000000..5f89ef9849567b --- /dev/null +++ b/apps/web/playwright/booking/recurringBooking.e2e.ts @@ -0,0 +1,28 @@ +/* eslint-disable playwright/no-conditional-in-test */ +import { loginUser } from "../fixtures/regularBookings"; +import { test } from "../lib/fixtures"; + +test.describe.configure({ mode: "serial" }); + +test.describe("Booking with recurring checked", () => { + test.beforeEach(async ({ page, users, bookingPage }) => { + await loginUser(users); + await page.goto("/event-types"); + await bookingPage.goToEventType("30 min"); + await bookingPage.goToTab("recurring"); + }); + + test("Updates event type with recurring events", async ({ page, bookingPage }) => { + await bookingPage.updateRecurringTab("2", "3"); + await bookingPage.updateEventType(); + await page.getByRole("link", { name: "Event Types" }).click(); + await bookingPage.assertRepeatEventType(); + }); + + test("Updates and shows recurring schedule correctly in booking page", async ({ bookingPage }) => { + await bookingPage.updateRecurringTab("2", "3"); + await bookingPage.updateEventType(); + const eventTypePage = await bookingPage.previewEventType(); + await bookingPage.fillRecurringFieldAndConfirm(eventTypePage); + }); +}); diff --git a/apps/web/playwright/fixtures/regularBookings.ts b/apps/web/playwright/fixtures/regularBookings.ts index 93671b0a59f72a..18f2f0a5d5f2bf 100644 --- a/apps/web/playwright/fixtures/regularBookings.ts +++ b/apps/web/playwright/fixtures/regularBookings.ts @@ -2,6 +2,7 @@ import { expect, type Page } from "@playwright/test"; import dayjs from "@calcom/dayjs"; +import { localize } from "../lib/testUtils"; import type { createUsersFixture } from "./users"; const reschedulePlaceholderText = "Let others know why you need to reschedule"; @@ -220,6 +221,23 @@ export function createBookingPageFixture(page: Page) { } await page.getByTestId("field-add-save").click(); }, + updateRecurringTab: async (repeatWeek: string, maxEvents: string) => { + const repeatText = (await localize("en"))("repeats_every"); + const maximumOf = (await localize("en"))("for_a_maximum_of"); + await page.getByTestId("recurring-event-check").click(); + await page + .getByTestId("recurring-event-collapsible") + .locator("div") + .filter({ hasText: repeatText }) + .getByRole("spinbutton") + .fill(repeatWeek); + await page + .getByTestId("recurring-event-collapsible") + .locator("div") + .filter({ hasText: maximumOf }) + .getByRole("spinbutton") + .fill(maxEvents); + }, updateEventType: async () => { await page.getByTestId("update-eventtype").click(); }, @@ -246,6 +264,14 @@ export function createBookingPageFixture(page: Page) { await page.getByTestId("confirm-reschedule-button").click(); }, + fillRecurringFieldAndConfirm: async (eventTypePage: Page) => { + await eventTypePage.getByTestId("occurrence-input").click(); + await eventTypePage.getByTestId("occurrence-input").fill("2"); + await goToNextMonthIfNoAvailabilities(eventTypePage); + await eventTypePage.getByTestId("time").first().click(); + await expect(eventTypePage.getByTestId("recurring-dates")).toBeVisible(); + }, + cancelBookingWithReason: async (page: Page) => { await page.getByTestId("cancel").click(); await page.getByTestId("cancel_reason").fill("Test cancel"); @@ -279,6 +305,10 @@ export function createBookingPageFixture(page: Page) { await expect(page.getByText(scheduleSuccessfullyText)).toBeVisible(); }, + assertRepeatEventType: async () => { + await expect(page.getByTestId("repeat-eventtype")).toBeVisible(); + }, + cancelBooking: async (eventTypePage: Page) => { await eventTypePage.getByTestId("cancel").click(); await eventTypePage.getByTestId("cancel_reason").fill("Test cancel"); diff --git a/packages/features/bookings/components/event-meta/Occurences.tsx b/packages/features/bookings/components/event-meta/Occurences.tsx index fbed0add185b9f..38cbdadcdd4ce9 100644 --- a/packages/features/bookings/components/event-meta/Occurences.tsx +++ b/packages/features/bookings/components/event-meta/Occurences.tsx @@ -47,7 +47,7 @@ export const EventOccurences = ({ event }: { event: PublicEvent }) => { i18n.language ); return ( - <> +
{recurringStrings.slice(0, 5).map((timeFormatted, key) => (

{timeFormatted}

))} @@ -59,7 +59,7 @@ export const EventOccurences = ({ event }: { event: PublicEvent }) => {

+ {t("plus_more", { count: recurringStrings.length - 5 })}

)} - +
); } @@ -73,6 +73,7 @@ export const EventOccurences = ({ event }: { event: PublicEvent }) => { min="1" max={event.recurringEvent.count} defaultValue={occurenceCount || event.recurringEvent.count} + data-testid="occurrence-input" onChange={(event) => { const pattern = /^(?=.*[0-9])\S+$/; const inputValue = parseInt(event.target.value); diff --git a/packages/features/eventtypes/components/EventTypeDescription.tsx b/packages/features/eventtypes/components/EventTypeDescription.tsx index ec8f15cd4c5a16..437e425f1d643b 100644 --- a/packages/features/eventtypes/components/EventTypeDescription.tsx +++ b/packages/features/eventtypes/components/EventTypeDescription.tsx @@ -86,7 +86,7 @@ export const EventTypeDescription = ({ )} {recurringEvent?.count && recurringEvent.count > 0 && ( -
  • +
  • {t("repeats_up_to", { count: recurringEvent.count, From 4dba72fecbbcdf5d18c4dde131bfead8be0cc16a Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 2 Jan 2024 17:39:39 -0500 Subject: [PATCH 2/4] fix: Permissions issue with team labeler (#12992) * fix: Permissions issue with team labeler * Made the job runnable --- .github/workflows/labeler.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0ed17ef62afb87..44978d72d6e11d 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,6 +1,7 @@ name: "Pull Request Labeler" on: - pull_request_target + - workflow_call concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true @@ -25,7 +26,7 @@ jobs: - uses: actions/checkout@v2 - uses: equitybee/team-label-action@main with: - repo-token: ${{ secrets.GITHUB_TOKEN }} + repo-token: ${{ secrets.EQUITY_BEE_TEAM_LABELER_ACTION_TOKEN }} organization-name: calcom ignore-labels: "app-store, ai, authentication, automated-testing, platform, billing, bookings, caldav, calendar-apps, ci, console, crm-apps, docs, documentation, emails, embeds, event-types, i18n, impersonation, manual-testing, ui, performance, ops-stack, organizations, public-api, routing-forms, seats, teams, webhooks, workflows, zapier" apply-labels-from-issue: From c7b62950de2ccaf8ce339ceba5afc768327a4a69 Mon Sep 17 00:00:00 2001 From: Kartik Saini <41051387+kart1ka@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:05:46 +0530 Subject: [PATCH 3/4] fix: cal video link on booking confirmation (#12944) * fix: Ensure generated Cal Video link matches expected pattern on booking confirmation * fix: missing Google Meet videoCallUrl in webhooks on booking confirmation --------- Co-authored-by: Peer Richelsen Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> --- .../features/bookings/lib/handleConfirmation.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/features/bookings/lib/handleConfirmation.ts b/packages/features/bookings/lib/handleConfirmation.ts index fd23e806994376..14bc68817d487d 100644 --- a/packages/features/bookings/lib/handleConfirmation.ts +++ b/packages/features/bookings/lib/handleConfirmation.ts @@ -9,6 +9,7 @@ import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; import { scheduleTrigger } from "@calcom/features/webhooks/lib/scheduleTrigger"; import type { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload"; import sendPayload from "@calcom/features/webhooks/lib/sendPayload"; +import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser"; import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; @@ -138,6 +139,7 @@ export async function handleConfirmation(args: { }[] = []; const videoCallUrl = metadata.hangoutLink ? metadata.hangoutLink : evt.videoCallData?.url || ""; + const meetingUrl = getVideoCallUrlFromCalEvent(evt) || videoCallUrl; if (recurringEventId) { // The booking to confirm is a recurring event and comes from /booking/recurring, proceeding to mark all related @@ -162,7 +164,7 @@ export async function handleConfirmation(args: { paid, metadata: { ...(typeof recurringBooking.metadata === "object" ? recurringBooking.metadata : {}), - videoCallUrl, + videoCallUrl: meetingUrl, }, }, select: { @@ -215,7 +217,10 @@ export async function handleConfirmation(args: { references: { create: scheduleResult.referencesToCreate, }, - metadata: { ...(typeof booking.metadata === "object" ? booking.metadata : {}), videoCallUrl }, + metadata: { + ...(typeof booking.metadata === "object" ? booking.metadata : {}), + videoCallUrl: meetingUrl, + }, }, select: { eventType: { @@ -258,7 +263,11 @@ export async function handleConfirmation(args: { try { for (let index = 0; index < updatedBookings.length; index++) { const eventTypeSlug = updatedBookings[index].eventType?.slug || ""; - const evtOfBooking = { ...evt, metadata: { videoCallUrl }, eventType: { slug: eventTypeSlug } }; + const evtOfBooking = { + ...evt, + metadata: { videoCallUrl: meetingUrl }, + eventType: { slug: eventTypeSlug }, + }; evtOfBooking.startTime = updatedBookings[index].startTime.toISOString(); evtOfBooking.endTime = updatedBookings[index].endTime.toISOString(); evtOfBooking.uid = updatedBookings[index].uid; @@ -341,7 +350,7 @@ export async function handleConfirmation(args: { eventTypeId: booking.eventType?.id, status: "ACCEPTED", smsReminderNumber: booking.smsReminderNumber || undefined, - metadata: evt.videoCallData?.url ? { videoCallUrl: evt.videoCallData.url } : undefined, + metadata: meetingUrl ? { videoCallUrl: meetingUrl } : undefined, }).catch((e) => { console.error( `Error executing webhook for event: ${WebhookTriggerEvents.BOOKING_CREATED}, URL: ${sub.subscriberUrl}`, From 6dec98129cd70f985889feb58a482480276dc1c3 Mon Sep 17 00:00:00 2001 From: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:05:29 +0530 Subject: [PATCH 4/4] fix: bad request in webhook route (#13008) --- apps/web/pages/api/recorded-daily-video.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/web/pages/api/recorded-daily-video.ts b/apps/web/pages/api/recorded-daily-video.ts index 9886fc686347fb..412d73bbfca47e 100644 --- a/apps/web/pages/api/recorded-daily-video.ts +++ b/apps/web/pages/api/recorded-daily-video.ts @@ -21,16 +21,16 @@ const schema = z id: z.string(), payload: z.object({ recording_id: z.string(), - end_ts: z.number(), + end_ts: z.number().optional(), room_name: z.string(), - start_ts: z.number(), + start_ts: z.number().optional(), status: z.string(), - max_participants: z.number(), - duration: z.number(), - s3_key: z.string(), + max_participants: z.number().optional(), + duration: z.number().optional(), + s3_key: z.string().optional(), }), - event_ts: z.number(), + event_ts: z.number().optional(), }) .passthrough();