diff --git a/packages/core/EventManager.ts b/packages/core/EventManager.ts index 1803c58b09..700b1c52d2 100644 --- a/packages/core/EventManager.ts +++ b/packages/core/EventManager.ts @@ -186,9 +186,12 @@ export default class EventManager { result.type = result.createdEvent.type; //responses data is later sent to webhook if (evt.location && evt.responses) { - evt.responses["location"].value = { - optionValue: "", - value: evt.location, + evt.responses["location"] = { + ...(evt.responses["location"] ?? {}), + value: { + optionValue: "", + value: evt.location, + }, }; } } @@ -256,9 +259,12 @@ export default class EventManager { result.type = result.createdEvent.type; //responses data is later sent to webhook if (evt.location && evt.responses) { - evt.responses["location"].value = { - optionValue: "", - value: evt.location, + evt.responses["location"] = { + ...(evt.responses["location"] ?? {}), + value: { + optionValue: "", + value: evt.location, + }, }; } } diff --git a/packages/emails/lib/generateIcsFile.ts b/packages/emails/lib/generateIcsFile.ts index cb63bbadfa..6f3a99fcef 100644 --- a/packages/emails/lib/generateIcsFile.ts +++ b/packages/emails/lib/generateIcsFile.ts @@ -31,7 +31,7 @@ export default function generateIcsFile({ if ( role !== GenerateIcsRole.ATTENDEE && calEvent.destinationCalendar && - calEvent.destinationCalendar[0].integration === "office365_calendar" + calEvent.destinationCalendar[0]?.integration === "office365_calendar" ) return null; diff --git a/packages/trpc/server/routers/viewer/bookings/confirm.handler.test.ts b/packages/trpc/server/routers/viewer/bookings/confirm.handler.test.ts new file mode 100644 index 0000000000..5fcba1c5d6 --- /dev/null +++ b/packages/trpc/server/routers/viewer/bookings/confirm.handler.test.ts @@ -0,0 +1,110 @@ +import { + createBookingScenario, + TestData, + getOrganizer, + getScenarioData, + mockSuccessfulVideoMeetingCreation, + getDate, +} from "@calcom/web/test/utils/bookingScenario/bookingScenario"; +import { setupAndTeardown } from "@calcom/web/test/utils/bookingScenario/setupAndTeardown"; + +import { describe, it, beforeEach, vi, expect } from "vitest"; + +import { BookingStatus } from "@calcom/prisma/enums"; + +import type { TrpcSessionUser } from "../../../trpc"; +import { confirmHandler } from "./confirm.handler"; + +describe("confirmHandler", () => { + setupAndTeardown(); + beforeEach(() => { + // Reset all mocks before each test + vi.clearAllMocks(); + }); + + it("should successfully confirm booking when event type doesn't have any default location", async () => { + const attendeeUser = getOrganizer({ + email: "test@example.com", + name: "test name", + id: 102, + schedules: [TestData.schedules.IstWorkHours], + }); + + const organizer = getOrganizer({ + name: "Organizer", + email: "organizer@example.com", + id: 101, + schedules: [TestData.schedules.IstWorkHours], + }); + + const uidOfBooking = "n5Wv3eHgconAED2j4gcVhP"; + const iCalUID = `${uidOfBooking}@Cal.com`; + + const { dateString: plus1DateString } = getDate({ dateIncrement: 1 }); + + await createBookingScenario( + getScenarioData({ + webhooks: [ + { + userId: organizer.id, + eventTriggers: ["BOOKING_CREATED"], + subscriberUrl: "http://my-webhook.example.com", + active: true, + eventTypeId: 1, + appId: null, + }, + ], + eventTypes: [ + { + id: 1, + slotInterval: 15, + length: 15, + locations: [], + users: [ + { + id: 101, + }, + ], + }, + ], + bookings: [ + { + id: 101, + uid: uidOfBooking, + eventTypeId: 1, + status: BookingStatus.PENDING, + startTime: `${plus1DateString}T05:00:00.000Z`, + endTime: `${plus1DateString}T05:15:00.000Z`, + references: [], + iCalUID, + location: "integrations:daily", + attendees: [attendeeUser], + responses: { name: attendeeUser.name, email: attendeeUser.email, guests: [] }, + }, + ], + organizer, + apps: [TestData.apps["daily-video"]], + }) + ); + + mockSuccessfulVideoMeetingCreation({ + metadataLookupKey: "dailyvideo", + }); + + const ctx = { + user: { + id: organizer.id, + name: organizer.name, + timeZone: organizer.timeZone, + username: organizer.username, + } as NonNullable, + }; + + const res = await confirmHandler({ + ctx, + input: { bookingId: 101, confirmed: true, reason: "" }, + }); + + expect(res?.status).toBe(BookingStatus.ACCEPTED); + }); +});