mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
* fis: pass the missing `platformClientId` to `handleNewBooking` in api/v2 * Update formatCalendarEvent.ts * only add the externald in case of same calendar, otherwise add if from the .ics file sent in email * Revert "fis: pass the missing `platformClientId` to `handleNewBooking` in api/v2" This reverts commit 030ac0f0981c1135d4973fbdafa62d58e8985831. * fix: alow the host change logic to run for collective envets as well * fix: run the changedOrganizer logic for both collective and round-robin events * Update handleNewBooking.ts * fix: failing unit test --------- Co-authored-by: Lauris Skraucis <[email protected]>
239 lines
8.7 KiB
TypeScript
239 lines
8.7 KiB
TypeScript
import {
|
|
createBookingScenario,
|
|
getGoogleCalendarCredential,
|
|
TestData,
|
|
getOrganizer,
|
|
getBooker,
|
|
getScenarioData,
|
|
mockSuccessfulVideoMeetingCreation,
|
|
mockCalendarToHaveNoBusySlots,
|
|
getDate,
|
|
BookingLocations,
|
|
} from "@calcom/web/test/utils/bookingScenario/bookingScenario";
|
|
import { expectBookingToBeInDatabase } from "@calcom/web/test/utils/bookingScenario/expects";
|
|
import { getMockRequestDataForBooking } from "@calcom/web/test/utils/bookingScenario/getMockRequestDataForBooking";
|
|
import { setupAndTeardown } from "@calcom/web/test/utils/bookingScenario/setupAndTeardown";
|
|
|
|
import type { Request, Response } from "express";
|
|
import type { NextApiRequest, NextApiResponse } from "next";
|
|
import { describe, expect, beforeEach } from "vitest";
|
|
|
|
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
|
|
import { resetTestEmails } from "@calcom/lib/testEmails";
|
|
import { SchedulingType } from "@calcom/prisma/enums";
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
|
import { test } from "@calcom/web/test/fixtures/fixtures";
|
|
|
|
import { getNewBookingHandler } from "../getNewBookingHandler";
|
|
|
|
export type CustomNextApiRequest = NextApiRequest & Request;
|
|
|
|
export type CustomNextApiResponse = NextApiResponse & Response;
|
|
|
|
const timeout = process.env.CI ? 5000 : 20000;
|
|
|
|
describe("handleNewBooking", () => {
|
|
setupAndTeardown();
|
|
|
|
beforeEach(() => {
|
|
resetTestEmails();
|
|
});
|
|
|
|
describe("Collective Event Reschedule with Destination Calendar Bug", () => {
|
|
test(
|
|
`should reschedule a collective event booking and ensure both hosts have the booking in their calendars when a second host is added
|
|
1. Create a collective event with 1 host and book it
|
|
2. Add a second host to the event type
|
|
3. Reschedule the booking
|
|
4. Verify both hosts have the booking in their calendars
|
|
`,
|
|
async ({ emails }) => {
|
|
const handleNewBooking = getNewBookingHandler();
|
|
|
|
const booker = getBooker({
|
|
email: "[email protected]",
|
|
name: "Booker",
|
|
});
|
|
|
|
const organizer = getOrganizer({
|
|
name: "Organizer",
|
|
email: "[email protected]",
|
|
id: 101,
|
|
schedules: [TestData.schedules.IstWorkHours],
|
|
credentials: [getGoogleCalendarCredential()],
|
|
selectedCalendars: [TestData.selectedCalendars.google],
|
|
destinationCalendar: {
|
|
integration: "google_calendar",
|
|
externalId: "[email protected]",
|
|
primaryEmail: "[email protected]",
|
|
},
|
|
});
|
|
|
|
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
|
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
|
const uidOfBookingToBeRescheduled = "n5Wv3eHgconAED2j4gcVhP";
|
|
const iCalUID = `${uidOfBookingToBeRescheduled}@Cal.com`;
|
|
|
|
await createBookingScenario(
|
|
getScenarioData({
|
|
eventTypes: [
|
|
{
|
|
id: 1,
|
|
slotInterval: 15,
|
|
length: 30,
|
|
schedulingType: SchedulingType.COLLECTIVE,
|
|
users: [
|
|
{
|
|
id: 101, // organizer
|
|
},
|
|
{
|
|
id: 102, // second host (will be added to event type)
|
|
},
|
|
],
|
|
destinationCalendar: {
|
|
integration: "google_calendar",
|
|
externalId: "[email protected]",
|
|
primaryEmail: "[email protected]",
|
|
},
|
|
},
|
|
],
|
|
users: [
|
|
{
|
|
id: 101,
|
|
name: "Organizer",
|
|
email: "[email protected]",
|
|
username: "organizer",
|
|
timeZone: "Asia/Kolkata",
|
|
defaultScheduleId: null,
|
|
schedules: [TestData.schedules.IstWorkHours],
|
|
credentials: [getGoogleCalendarCredential()],
|
|
selectedCalendars: [TestData.selectedCalendars.google],
|
|
destinationCalendar: {
|
|
integration: "google_calendar",
|
|
externalId: "[email protected]",
|
|
primaryEmail: "[email protected]",
|
|
},
|
|
},
|
|
{
|
|
id: 102,
|
|
name: "Second Host",
|
|
email: "[email protected]",
|
|
username: "second-host",
|
|
timeZone: "Asia/Kolkata",
|
|
defaultScheduleId: null,
|
|
schedules: [TestData.schedules.IstWorkHours],
|
|
credentials: [getGoogleCalendarCredential()],
|
|
selectedCalendars: [TestData.selectedCalendars.google],
|
|
destinationCalendar: {
|
|
integration: "google_calendar",
|
|
externalId: "[email protected]",
|
|
primaryEmail: "[email protected]",
|
|
},
|
|
},
|
|
],
|
|
bookings: [
|
|
{
|
|
uid: uidOfBookingToBeRescheduled,
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
startTime: `${plus1DateString}T05:00:00.000Z`,
|
|
endTime: `${plus1DateString}T05:30:00.000Z`,
|
|
userId: 101,
|
|
references: [
|
|
{
|
|
type: appStoreMetadata.dailyvideo.type,
|
|
uid: "MOCK_ID_1",
|
|
meetingId: "MOCK_ID_1",
|
|
meetingPassword: "MOCK_PASS_1",
|
|
meetingUrl: "http://mock-dailyvideo.example.com/meeting-1",
|
|
credentialId: null,
|
|
},
|
|
{
|
|
type: appStoreMetadata.googlecalendar.type,
|
|
uid: "MOCKED_GOOGLE_CALENDAR_EVENT_ID_1",
|
|
meetingId: "MOCKED_GOOGLE_CALENDAR_EVENT_ID_1",
|
|
meetingPassword: "MOCK_PASSWORD",
|
|
meetingUrl: "https://UNUSED_URL",
|
|
externalCalendarId: "[email protected]",
|
|
credentialId: undefined,
|
|
},
|
|
],
|
|
iCalUID,
|
|
},
|
|
],
|
|
apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]],
|
|
})
|
|
);
|
|
|
|
mockSuccessfulVideoMeetingCreation({
|
|
metadataLookupKey: appStoreMetadata.dailyvideo.dirName,
|
|
videoMeetingData: {
|
|
id: "MOCK_ID_1", // Video meeting ID is not updated during reschedule
|
|
password: "MOCK_PASS_1",
|
|
url: `http://mock-dailyvideo.example.com/meeting-1`,
|
|
},
|
|
});
|
|
|
|
const organizerCalendarMock = await mockCalendarToHaveNoBusySlots("googlecalendar", {
|
|
update: {
|
|
id: "MOCKED_GOOGLE_CALENDAR_EVENT_ID_2",
|
|
iCalUID: "MOCKED_GOOGLE_CALENDAR_ICS_ID_2",
|
|
},
|
|
});
|
|
|
|
const rescheduleBookingData = getMockRequestDataForBooking({
|
|
data: {
|
|
start: `${plus2DateString}T11:00:00.000Z`,
|
|
end: `${plus2DateString}T11:30:00.000Z`,
|
|
eventTypeId: 1,
|
|
rescheduleUid: uidOfBookingToBeRescheduled,
|
|
responses: {
|
|
email: booker.email,
|
|
name: booker.name,
|
|
location: { optionValue: "", value: BookingLocations.CalVideo },
|
|
},
|
|
rescheduledBy: organizer.email,
|
|
},
|
|
});
|
|
|
|
const rescheduledBooking = await handleNewBooking({
|
|
bookingData: rescheduleBookingData,
|
|
});
|
|
|
|
await expectBookingToBeInDatabase({
|
|
description: "",
|
|
location: BookingLocations.CalVideo,
|
|
responses: expect.objectContaining({
|
|
email: booker.email,
|
|
name: booker.name,
|
|
}),
|
|
uid: rescheduledBooking.uid!,
|
|
eventTypeId: rescheduleBookingData.eventTypeId,
|
|
status: BookingStatus.ACCEPTED,
|
|
references: [
|
|
{
|
|
type: appStoreMetadata.dailyvideo.type,
|
|
uid: "MOCK_ID_1",
|
|
meetingId: "MOCK_ID_1",
|
|
meetingPassword: "MOCK_PASS_1",
|
|
meetingUrl: "http://mock-dailyvideo.example.com/meeting-1",
|
|
},
|
|
{
|
|
type: appStoreMetadata.googlecalendar.type,
|
|
uid: "MOCKED_GOOGLE_CALENDAR_EVENT_ID_1",
|
|
externalCalendarId: "[email protected]",
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(organizerCalendarMock.updateEventCalls.length).toBe(1);
|
|
expect(organizerCalendarMock.createEventCalls.length).toBe(0);
|
|
|
|
// Check availability calls for both hosts
|
|
expect(organizerCalendarMock.getAvailabilityCalls.length).toBe(2);
|
|
},
|
|
timeout
|
|
);
|
|
});
|
|
});
|