@@ -25,7 +25,12 @@ import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.
2525import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture" ;
2626import { randomString } from "test/utils/randomString" ;
2727
28- import { CAL_API_VERSION_HEADER , SUCCESS_STATUS , VERSION_2024_09_04 } from "@calcom/platform-constants" ;
28+ import {
29+ CAL_API_VERSION_HEADER ,
30+ SUCCESS_STATUS ,
31+ VERSION_2024_09_04 ,
32+ ERROR_STATUS ,
33+ } from "@calcom/platform-constants" ;
2934import type {
3035 CreateScheduleInput_2024_06_11 ,
3136 ReserveSlotOutput_2024_09_04 as ReserveSlotOutputData_2024_09_04 ,
@@ -48,6 +53,7 @@ describe("Slots 2024-09-04 Endpoints", () => {
4853 const teammateEmailOne = `slots-2024-09-04-user-1-team-slots-${ randomString ( ) } ` ;
4954 let teammateApiKeyString : string ;
5055 const teammateEmailTwo = `slots-2024-09-04-user-2-team-slots-${ randomString ( ) } ` ;
56+ let teammateTwoApiKeyString : string ;
5157
5258 const outsiderEmail = `slots-2024-09-04-unrelated-team-slots-${ randomString ( ) } ` ;
5359 let outsider : User ;
@@ -61,6 +67,8 @@ describe("Slots 2024-09-04 Endpoints", () => {
6167 let collectiveEventTypeSlug : string ;
6268 let collectiveEventTypeWithoutHostsId : number ;
6369 let roundRobinEventTypeId : number ;
70+ let roundRobinEventTypeWithoutFixedHostsId : number ;
71+ let roundRobinEventTypeWithFixedAndNonFixedHostsId : number ;
6472 let collectiveBookingId : number ;
6573 let roundRobinBookingId : number ;
6674 let fullyBookedRoundRobinBookingIdOne : number ;
@@ -115,6 +123,12 @@ describe("Slots 2024-09-04 Endpoints", () => {
115123 const { keyString } = await apiKeysRepositoryFixture . createApiKey ( teammateOne . id , null ) ;
116124 teammateApiKeyString = keyString ;
117125
126+ const { keyString : keyStringForTeammateTwo } = await apiKeysRepositoryFixture . createApiKey (
127+ teammateTwo . id ,
128+ null
129+ ) ;
130+ teammateTwoApiKeyString = keyStringForTeammateTwo ;
131+
118132 const { keyString : unrelatedUserKeyString } = await apiKeysRepositoryFixture . createApiKey (
119133 outsider . id ,
120134 null
@@ -217,6 +231,67 @@ describe("Slots 2024-09-04 Endpoints", () => {
217231 } ) ;
218232 roundRobinEventTypeId = roundRobinEventType . id ;
219233
234+ const roundRobinEventTypeWithoutFixedHosts = await eventTypesRepositoryFixture . createTeamEventType ( {
235+ schedulingType : "ROUND_ROBIN" ,
236+ team : {
237+ connect : { id : team . id } ,
238+ } ,
239+ title : "RR Event Type Without Fixed Hosts" ,
240+ slug : `slots-2024-09-04-round-robin-event-type-${ randomString ( ) } ` ,
241+ length : 60 ,
242+ assignAllTeamMembers : true ,
243+ bookingFields : [ ] ,
244+ locations : [ ] ,
245+ users : {
246+ connect : [ { id : teammateOne . id } , { id : teammateTwo . id } ] ,
247+ } ,
248+ hosts : {
249+ create : [
250+ {
251+ userId : teammateOne . id ,
252+ isFixed : false ,
253+ } ,
254+ {
255+ userId : teammateTwo . id ,
256+ isFixed : false ,
257+ } ,
258+ ] ,
259+ } ,
260+ } ) ;
261+
262+ roundRobinEventTypeWithoutFixedHostsId = roundRobinEventTypeWithoutFixedHosts . id ;
263+
264+ const roundRobinEventTypeWithFixedAndNonFixedHosts =
265+ await eventTypesRepositoryFixture . createTeamEventType ( {
266+ schedulingType : "ROUND_ROBIN" ,
267+ team : {
268+ connect : { id : team . id } ,
269+ } ,
270+ title : "RR Event Type With Fixed and Non-Fixed Hosts" ,
271+ slug : `slots-2024-09-04-round-robin-event-type-${ randomString ( ) } ` ,
272+ length : 60 ,
273+ assignAllTeamMembers : true ,
274+ bookingFields : [ ] ,
275+ locations : [ ] ,
276+ users : {
277+ connect : [ { id : teammateOne . id } , { id : teammateTwo . id } ] ,
278+ } ,
279+ hosts : {
280+ create : [
281+ {
282+ userId : teammateOne . id ,
283+ isFixed : true ,
284+ } ,
285+ {
286+ userId : teammateTwo . id ,
287+ isFixed : false ,
288+ } ,
289+ ] ,
290+ } ,
291+ } ) ;
292+
293+ roundRobinEventTypeWithFixedAndNonFixedHostsId = roundRobinEventTypeWithFixedAndNonFixedHosts . id ;
294+
220295 const userSchedule : CreateScheduleInput_2024_06_11 = {
221296 name : "working time" ,
222297 timeZone : "Europe/Rome" ,
@@ -541,6 +616,135 @@ describe("Slots 2024-09-04 Endpoints", () => {
541616 bookingsRepositoryFixture . deleteById ( bookingTwo . id ) ;
542617 } ) ;
543618
619+ it ( "should reserve all available slots for round robin event type with non-fixed hosts" , async ( ) => {
620+ const now = "2049-09-05T12:00:00.000Z" ;
621+ const newDate = DateTime . fromISO ( now , { zone : "UTC" } ) . toJSDate ( ) ;
622+ advanceTo ( newDate ) ;
623+
624+ const slotStartTime = "2050-09-05T10:00:00.000Z" ;
625+
626+ const reserveResponseOne = await request ( app . getHttpServer ( ) )
627+ . post ( `/v2/slots/reservations` )
628+ . set ( { Authorization : `Bearer cal_test_${ teammateApiKeyString } ` } )
629+ . send ( {
630+ eventTypeId : roundRobinEventTypeWithoutFixedHostsId ,
631+ slotStart : slotStartTime ,
632+ reservationDuration : 10 ,
633+ } )
634+ . set ( CAL_API_VERSION_HEADER , VERSION_2024_09_04 )
635+ . expect ( 201 ) ;
636+
637+ const reserveResponseOneBody : ReserveSlotOutputResponse_2024_09_04 = reserveResponseOne . body ;
638+ expect ( reserveResponseOneBody . status ) . toEqual ( SUCCESS_STATUS ) ;
639+ const responseReservedSlotOne : ReserveSlotOutputData_2024_09_04 = reserveResponseOneBody . data ;
640+ expect ( responseReservedSlotOne . reservationUid ) . toBeDefined ( ) ;
641+ if ( ! responseReservedSlotOne . reservationUid ) {
642+ throw new Error ( "Reserved slot one uid is undefined" ) ;
643+ }
644+
645+ const dbSlotOne = await selectedSlotRepositoryFixture . getByUid ( responseReservedSlotOne . reservationUid ) ;
646+ expect ( dbSlotOne ) . toBeDefined ( ) ;
647+ if ( dbSlotOne ) {
648+ const dbReleaseAt = DateTime . fromJSDate ( dbSlotOne . releaseAt , { zone : "UTC" } ) . toISO ( ) ;
649+ const expectedReleaseAt = DateTime . fromISO ( now , { zone : "UTC" } ) . plus ( { minutes : 10 } ) . toISO ( ) ;
650+ expect ( dbReleaseAt ) . toEqual ( expectedReleaseAt ) ;
651+ }
652+
653+ const reserveResponseTwo = await request ( app . getHttpServer ( ) )
654+ . post ( `/v2/slots/reservations` )
655+ . set ( { Authorization : `Bearer cal_test_${ teammateTwoApiKeyString } ` } )
656+ . send ( {
657+ eventTypeId : roundRobinEventTypeWithoutFixedHostsId ,
658+ slotStart : slotStartTime ,
659+ reservationDuration : 10 ,
660+ } )
661+ . set ( CAL_API_VERSION_HEADER , VERSION_2024_09_04 )
662+ . expect ( 201 ) ;
663+
664+ const reserveResponseTwoBody : ReserveSlotOutputResponse_2024_09_04 = reserveResponseTwo . body ;
665+ expect ( reserveResponseTwoBody . status ) . toEqual ( SUCCESS_STATUS ) ;
666+ const responseReservedSlotTwo : ReserveSlotOutputData_2024_09_04 = reserveResponseTwoBody . data ;
667+ expect ( responseReservedSlotTwo . reservationUid ) . toBeDefined ( ) ;
668+ if ( ! responseReservedSlotTwo . reservationUid ) {
669+ throw new Error ( "Reserved slot two uid is undefined" ) ;
670+ }
671+
672+ const dbSlotTwo = await selectedSlotRepositoryFixture . getByUid ( responseReservedSlotTwo . reservationUid ) ;
673+ expect ( dbSlotTwo ) . toBeDefined ( ) ;
674+ if ( dbSlotTwo ) {
675+ const dbReleaseAt = DateTime . fromJSDate ( dbSlotTwo . releaseAt , { zone : "UTC" } ) . toISO ( ) ;
676+ const expectedReleaseAt = DateTime . fromISO ( now , { zone : "UTC" } ) . plus ( { minutes : 10 } ) . toISO ( ) ;
677+ expect ( dbReleaseAt ) . toEqual ( expectedReleaseAt ) ;
678+ }
679+
680+ const reserveResponseThree = await request ( app . getHttpServer ( ) )
681+ . post ( `/v2/slots/reservations` )
682+ . set ( { Authorization : `Bearer cal_test_${ outsiderApiKeyString } ` } )
683+ . send ( {
684+ eventTypeId : roundRobinEventTypeWithoutFixedHostsId ,
685+ slotStart : slotStartTime ,
686+ reservationDuration : 10 ,
687+ } )
688+ . set ( CAL_API_VERSION_HEADER , VERSION_2024_09_04 ) ;
689+
690+ expect ( reserveResponseThree . status ) . toEqual ( 403 ) ;
691+ expect ( reserveResponseThree . body . status ) . toEqual ( ERROR_STATUS ) ;
692+
693+ await selectedSlotRepositoryFixture . deleteByUId ( responseReservedSlotOne . reservationUid ) ;
694+ await selectedSlotRepositoryFixture . deleteByUId ( responseReservedSlotTwo . reservationUid ) ;
695+ clear ( ) ;
696+ } ) ;
697+
698+ it ( "should reserve available slot for round robin event type with fixed and non-fixed hosts and should not be able to reserve another slot" , async ( ) => {
699+ const now = "2049-09-05T12:00:00.000Z" ;
700+ const newDate = DateTime . fromISO ( now , { zone : "UTC" } ) . toJSDate ( ) ;
701+ advanceTo ( newDate ) ;
702+
703+ const slotStartTime = "2050-09-05T10:00:00.000Z" ;
704+
705+ const reserveResponseOne = await request ( app . getHttpServer ( ) )
706+ . post ( `/v2/slots/reservations` )
707+ . set ( { Authorization : `Bearer cal_test_${ teammateApiKeyString } ` } )
708+ . send ( {
709+ eventTypeId : roundRobinEventTypeWithFixedAndNonFixedHostsId ,
710+ slotStart : slotStartTime ,
711+ reservationDuration : 10 ,
712+ } )
713+ . set ( CAL_API_VERSION_HEADER , VERSION_2024_09_04 )
714+ . expect ( 201 ) ;
715+
716+ const reserveResponseBodyOne : ReserveSlotOutputResponse_2024_09_04 = reserveResponseOne . body ;
717+ expect ( reserveResponseBodyOne . status ) . toEqual ( SUCCESS_STATUS ) ;
718+ const responseReservedSlotOne : ReserveSlotOutputData_2024_09_04 = reserveResponseBodyOne . data ;
719+ expect ( responseReservedSlotOne . reservationUid ) . toBeDefined ( ) ;
720+ if ( ! responseReservedSlotOne . reservationUid ) {
721+ throw new Error ( "Reserved slot uid is undefined" ) ;
722+ }
723+
724+ const dbSlotOne = await selectedSlotRepositoryFixture . getByUid ( responseReservedSlotOne . reservationUid ) ;
725+ expect ( dbSlotOne ) . toBeDefined ( ) ;
726+ if ( dbSlotOne ) {
727+ const dbReleaseAt = DateTime . fromJSDate ( dbSlotOne . releaseAt , { zone : "UTC" } ) . toISO ( ) ;
728+ const expectedReleaseAt = DateTime . fromISO ( now , { zone : "UTC" } ) . plus ( { minutes : 10 } ) . toISO ( ) ;
729+ expect ( dbReleaseAt ) . toEqual ( expectedReleaseAt ) ;
730+ }
731+
732+ const reserveResponseTwo = await request ( app . getHttpServer ( ) )
733+ . post ( `/v2/slots/reservations` )
734+ . send ( {
735+ eventTypeId : roundRobinEventTypeWithFixedAndNonFixedHostsId ,
736+ slotStart : slotStartTime ,
737+ } )
738+ . set ( { Authorization : `Bearer cal_test_${ teammateTwoApiKeyString } ` } )
739+ . set ( CAL_API_VERSION_HEADER , VERSION_2024_09_04 ) ;
740+
741+ expect ( reserveResponseTwo . status ) . toEqual ( 422 ) ;
742+ expect ( reserveResponseTwo . body . status ) . toEqual ( ERROR_STATUS ) ;
743+
744+ await selectedSlotRepositoryFixture . deleteByUId ( responseReservedSlotOne . reservationUid ) ;
745+ clear ( ) ;
746+ } ) ;
747+
544748 afterAll ( async ( ) => {
545749 await userRepositoryFixture . deleteByEmail ( teammateOne . email ) ;
546750 await userRepositoryFixture . deleteByEmail ( teammateTwo . email ) ;
0 commit comments