11import { bootstrap } from "@/app" ;
22import { AppModule } from "@/app.module" ;
33import { CreateBookingInput_2024_04_15 } from "@/ee/bookings/2024-04-15/inputs/create-booking.input" ;
4+ import { CreateRecurringBookingInput_2024_04_15 } from "@/ee/bookings/2024-04-15/inputs/create-recurring-booking.input" ;
45import { GetBookingOutput_2024_04_15 } from "@/ee/bookings/2024-04-15/outputs/get-booking.output" ;
56import { GetBookingsOutput_2024_04_15 } from "@/ee/bookings/2024-04-15/outputs/get-bookings.output" ;
67import { CreateScheduleInput_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/inputs/create-schedule.input" ;
@@ -21,6 +22,7 @@ import { randomString } from "test/utils/randomString";
2122import { withApiAuth } from "test/utils/withApiAuth" ;
2223
2324import { SUCCESS_STATUS } from "@calcom/platform-constants" ;
25+ import { BookingResponse } from "@calcom/platform-libraries" ;
2426import { type RegularBookingCreateResult } from "@calcom/platform-libraries/bookings" ;
2527import type { ApiSuccessResponse , ApiErrorResponse } from "@calcom/platform-types" ;
2628import type { User } from "@calcom/prisma/client" ;
@@ -40,6 +42,7 @@ describe("Bookings Endpoints 2024-04-15", () => {
4042 let user : User ;
4143
4244 let eventTypeId : number ;
45+ let recEventTypeId : number ;
4346
4447 let createdBooking : RegularBookingCreateResult ;
4548
@@ -81,6 +84,18 @@ describe("Bookings Endpoints 2024-04-15", () => {
8184 } ,
8285 user . id
8386 ) ;
87+
88+ const recEventType = await eventTypesRepositoryFixture . create (
89+ {
90+ title : `rec-bookings-2024-04-15-event-type-${ randomString ( ) } -${ describe . name } ` ,
91+ slug : `rec-bookings-2024-04-15-event-type-${ randomString ( ) } -${ describe . name } ` ,
92+ length : 60 ,
93+ recurringEvent : { freq : 2 , count : 4 , interval : 1 } ,
94+ } ,
95+ user . id
96+ ) ;
97+ recEventTypeId = recEventType . id ;
98+
8499 eventTypeId = event . id ;
85100
86101 app = moduleRef . createNestApplication ( ) ;
@@ -404,6 +419,94 @@ describe("Bookings Endpoints 2024-04-15", () => {
404419 } ) ;
405420 } ) ;
406421
422+ it ( "should create recurring bookings" , async ( ) => {
423+ const bookingEventTypeId = recEventTypeId ;
424+ const bookingTimeZone = "Europe/London" ;
425+ const bookingLanguage = "en" ;
426+ const bookingHashedLink = "" ;
427+ const bookingMetadata = {
428+ timeFormat : "12" ,
429+ meetingType : "organizer-phone" ,
430+ } ;
431+ const bookingResponses = {
432+ name : "tester" ,
433+ email : "tester@example.com" ,
434+ location : {
435+ value : "link" ,
436+ optionValue : "" ,
437+ } ,
438+ notes : "test" ,
439+ } ;
440+
441+ const body : CreateRecurringBookingInput_2024_04_15 [ ] = [
442+ {
443+ start : "2040-06-21T09:30:00.000Z" ,
444+ end : "2040-06-21T10:30:00.000Z" ,
445+ eventTypeId : bookingEventTypeId ,
446+ timeZone : bookingTimeZone ,
447+ language : bookingLanguage ,
448+ metadata : bookingMetadata ,
449+ hashedLink : bookingHashedLink ,
450+ responses : bookingResponses ,
451+ recurringEventId : "test-recurring-event-id" ,
452+ } ,
453+ {
454+ start : "2040-06-27T09:30:00.000Z" ,
455+ end : "2040-06-27T10:30:00.000Z" ,
456+ eventTypeId : bookingEventTypeId ,
457+ timeZone : bookingTimeZone ,
458+ language : bookingLanguage ,
459+ metadata : bookingMetadata ,
460+ hashedLink : bookingHashedLink ,
461+ responses : bookingResponses ,
462+ recurringEventId : "test-recurring-event-id-2" ,
463+ } ,
464+ {
465+ start : "2040-06-04T09:30:00.000Z" ,
466+ end : "2040-06-04T10:30:00.000Z" ,
467+ eventTypeId : bookingEventTypeId ,
468+ timeZone : bookingTimeZone ,
469+ language : bookingLanguage ,
470+ metadata : bookingMetadata ,
471+ hashedLink : bookingHashedLink ,
472+ responses : bookingResponses ,
473+ recurringEventId : "test-recurring-event-id-3" ,
474+ } ,
475+ {
476+ start : "2040-06-11T09:30:00.000Z" ,
477+ end : "2040-06-11T10:30:00.000Z" ,
478+ eventTypeId : bookingEventTypeId ,
479+ timeZone : bookingTimeZone ,
480+ language : bookingLanguage ,
481+ metadata : bookingMetadata ,
482+ hashedLink : bookingHashedLink ,
483+ responses : bookingResponses ,
484+ recurringEventId : "test-recurring-event-id-4" ,
485+ } ,
486+ ] ;
487+
488+ return request ( app . getHttpServer ( ) )
489+ . post ( "/v2/bookings/recurring" )
490+ . send ( body )
491+ . expect ( 201 )
492+ . then ( async ( response ) => {
493+ const responseBody : ApiSuccessResponse < BookingResponse [ ] > = response . body ;
494+ expect ( responseBody . status ) . toEqual ( SUCCESS_STATUS ) ;
495+ expect ( responseBody . data ) . toBeDefined ( ) ;
496+ responseBody . data . forEach ( ( booking ) => {
497+ expect ( booking . userPrimaryEmail ) . toBeDefined ( ) ;
498+ expect ( booking . userPrimaryEmail ) . toEqual ( userEmail ) ;
499+ expect ( booking . id ) . toBeDefined ( ) ;
500+ expect ( booking . uid ) . toBeDefined ( ) ;
501+ expect ( booking . eventTypeId ) . toEqual ( bookingEventTypeId ) ;
502+ expect ( booking . user . timeZone ) . toEqual ( bookingTimeZone ) ;
503+ expect ( booking . metadata ) . toEqual ( bookingMetadata ) ;
504+ expect ( booking . responses ) . toEqual ( bookingResponses ) ;
505+ expect ( booking . creationSource ) . toEqual ( "API_V2" ) ;
506+ } ) ;
507+ } ) ;
508+ } ) ;
509+
407510 afterAll ( async ( ) => {
408511 await userRepositoryFixture . deleteByEmail ( user . email ) ;
409512 await bookingsRepositoryFixture . deleteAllBookings ( user . id , user . email ) ;
0 commit comments