@@ -164,4 +164,354 @@ describe("checkForConflicts", () => {
164164 expect ( result ) . toBe ( false ) ;
165165 } ) ;
166166 } ) ;
167+
168+ describe ( "comprehensive edge cases and boundary conditions" , ( ) => {
169+ it ( "should return false for empty busy array" , ( ) => {
170+ const result = checkForConflicts ( {
171+ ...createTestData ( "2023-01-01T09:00:00Z" ) ,
172+ busy : [ ] ,
173+ } ) ;
174+ expect ( result ) . toBe ( false ) ;
175+ } ) ;
176+
177+ it ( "should handle slot that starts exactly when busy period ends" , ( ) => {
178+ const result = checkForConflicts ( {
179+ ...createTestData ( "2023-01-01T09:30:00Z" ) ,
180+ busy : [
181+ {
182+ start : dayjs . utc ( "2023-01-01T09:00:00Z" ) . toDate ( ) ,
183+ end : dayjs . utc ( "2023-01-01T09:30:00Z" ) . toDate ( ) ,
184+ } ,
185+ ] ,
186+ } ) ;
187+ expect ( result ) . toBe ( false ) ;
188+ } ) ;
189+
190+ it ( "should handle slot that ends exactly when busy period starts" , ( ) => {
191+ const result = checkForConflicts ( {
192+ ...createTestData ( "2023-01-01T08:30:00Z" ) ,
193+ busy : [
194+ {
195+ start : dayjs . utc ( "2023-01-01T09:00:00Z" ) . toDate ( ) ,
196+ end : dayjs . utc ( "2023-01-01T09:30:00Z" ) . toDate ( ) ,
197+ } ,
198+ ] ,
199+ } ) ;
200+ expect ( result ) . toBe ( false ) ;
201+ } ) ;
202+
203+ it ( "should handle slot start exactly matching busy period start (inclusive)" , ( ) => {
204+ const result = checkForConflicts ( {
205+ ...createTestData ( "2023-01-01T09:00:00Z" ) ,
206+ busy : [
207+ {
208+ start : dayjs . utc ( "2023-01-01T09:00:00Z" ) . toDate ( ) ,
209+ end : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
210+ } ,
211+ ] ,
212+ } ) ;
213+ expect ( result ) . toBe ( true ) ;
214+ } ) ;
215+
216+ it ( "should handle slot end exactly matching busy period end (inclusive)" , ( ) => {
217+ const result = checkForConflicts ( {
218+ ...createTestData ( "2023-01-01T09:15:00Z" ) ,
219+ busy : [
220+ {
221+ start : dayjs . utc ( "2023-01-01T09:30:00Z" ) . toDate ( ) ,
222+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
223+ } ,
224+ ] ,
225+ } ) ;
226+ expect ( result ) . toBe ( true ) ;
227+ } ) ;
228+
229+ it ( "should handle very short event length (1 minute)" , ( ) => {
230+ const result = checkForConflicts ( {
231+ time : dayjs ( "2023-01-01T09:00:00Z" ) ,
232+ eventLength : 1 ,
233+ busy : [
234+ {
235+ start : dayjs . utc ( "2023-01-01T09:00:30Z" ) . toDate ( ) ,
236+ end : dayjs . utc ( "2023-01-01T09:01:30Z" ) . toDate ( ) ,
237+ } ,
238+ ] ,
239+ } ) ;
240+ expect ( result ) . toBe ( true ) ;
241+ } ) ;
242+
243+ it ( "should handle very long event length (8 hours)" , ( ) => {
244+ const result = checkForConflicts ( {
245+ time : dayjs ( "2023-01-01T09:00:00Z" ) ,
246+ eventLength : 480 , // 8 hours
247+ busy : [
248+ {
249+ start : dayjs . utc ( "2023-01-01T12:00:00Z" ) . toDate ( ) ,
250+ end : dayjs . utc ( "2023-01-01T13:00:00Z" ) . toDate ( ) ,
251+ } ,
252+ ] ,
253+ } ) ;
254+ expect ( result ) . toBe ( true ) ;
255+ } ) ;
256+ } ) ;
257+
258+ describe ( "multiple busy periods scenarios" , ( ) => {
259+ it ( "should return true when first busy period conflicts" , ( ) => {
260+ const result = checkForConflicts ( {
261+ ...createTestData ( "2023-01-01T09:00:00Z" ) ,
262+ busy : [
263+ {
264+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
265+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
266+ } ,
267+ {
268+ start : dayjs . utc ( "2023-01-01T10:00:00Z" ) . toDate ( ) ,
269+ end : dayjs . utc ( "2023-01-01T11:00:00Z" ) . toDate ( ) ,
270+ } ,
271+ ] ,
272+ } ) ;
273+ expect ( result ) . toBe ( true ) ;
274+ } ) ;
275+
276+ it ( "should return true when last busy period conflicts" , ( ) => {
277+ const result = checkForConflicts ( {
278+ ...createTestData ( "2023-01-01T10:30:00Z" ) ,
279+ busy : [
280+ {
281+ start : dayjs . utc ( "2023-01-01T08:00:00Z" ) . toDate ( ) ,
282+ end : dayjs . utc ( "2023-01-01T09:00:00Z" ) . toDate ( ) ,
283+ } ,
284+ {
285+ start : dayjs . utc ( "2023-01-01T10:45:00Z" ) . toDate ( ) ,
286+ end : dayjs . utc ( "2023-01-01T11:15:00Z" ) . toDate ( ) ,
287+ } ,
288+ ] ,
289+ } ) ;
290+ expect ( result ) . toBe ( true ) ;
291+ } ) ;
292+
293+ it ( "should return true when middle busy period conflicts" , ( ) => {
294+ const result = checkForConflicts ( {
295+ ...createTestData ( "2023-01-01T10:00:00Z" ) ,
296+ busy : [
297+ {
298+ start : dayjs . utc ( "2023-01-01T08:00:00Z" ) . toDate ( ) ,
299+ end : dayjs . utc ( "2023-01-01T09:00:00Z" ) . toDate ( ) ,
300+ } ,
301+ {
302+ start : dayjs . utc ( "2023-01-01T10:15:00Z" ) . toDate ( ) ,
303+ end : dayjs . utc ( "2023-01-01T10:45:00Z" ) . toDate ( ) ,
304+ } ,
305+ {
306+ start : dayjs . utc ( "2023-01-01T11:00:00Z" ) . toDate ( ) ,
307+ end : dayjs . utc ( "2023-01-01T12:00:00Z" ) . toDate ( ) ,
308+ } ,
309+ ] ,
310+ } ) ;
311+ expect ( result ) . toBe ( true ) ;
312+ } ) ;
313+
314+ it ( "should handle many non-overlapping busy periods" , ( ) => {
315+ const busyPeriods = [ ] ;
316+ for ( let i = 0 ; i < 10 ; i ++ ) {
317+ const hour = ( 8 + i * 2 ) % 24 ; // Wrap around to prevent invalid hours
318+ busyPeriods . push ( {
319+ start : dayjs . utc ( `2023-01-01T${ hour . toString ( ) . padStart ( 2 , "0" ) } :00:00Z` ) . toDate ( ) ,
320+ end : dayjs . utc ( `2023-01-01T${ hour . toString ( ) . padStart ( 2 , "0" ) } :30:00Z` ) . toDate ( ) ,
321+ } ) ;
322+ }
323+
324+ const result = checkForConflicts ( {
325+ ...createTestData ( "2023-01-01T07:00:00Z" ) ,
326+ busy : busyPeriods ,
327+ } ) ;
328+ expect ( result ) . toBe ( false ) ;
329+ } ) ;
330+
331+ it ( "should handle overlapping busy periods" , ( ) => {
332+ const result = checkForConflicts ( {
333+ ...createTestData ( "2023-01-01T09:00:00Z" ) ,
334+ busy : [
335+ {
336+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
337+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
338+ } ,
339+ {
340+ start : dayjs . utc ( "2023-01-01T09:30:00Z" ) . toDate ( ) ,
341+ end : dayjs . utc ( "2023-01-01T10:00:00Z" ) . toDate ( ) ,
342+ } ,
343+ ] ,
344+ } ) ;
345+ expect ( result ) . toBe ( true ) ;
346+ } ) ;
347+ } ) ;
348+
349+ describe ( "currentSeats comprehensive scenarios" , ( ) => {
350+ it ( "should return false when currentSeats has exact time match" , ( ) => {
351+ const testTime = dayjs . utc ( "2023-01-01T09:00:00Z" ) ;
352+ const currentSeats : CurrentSeats = [
353+ {
354+ uid : "booking-1" ,
355+ startTime : testTime . toDate ( ) ,
356+ _count : { attendees : 2 } ,
357+ } ,
358+ ] ;
359+
360+ const result = checkForConflicts ( {
361+ time : testTime ,
362+ eventLength : 30 ,
363+ busy : [
364+ {
365+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
366+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
367+ } ,
368+ ] ,
369+ currentSeats,
370+ } ) ;
371+ expect ( result ) . toBe ( false ) ;
372+ } ) ;
373+
374+ it ( "should return true when currentSeats has no matching time but busy period conflicts" , ( ) => {
375+ const currentSeats : CurrentSeats = [
376+ {
377+ uid : "booking-1" ,
378+ startTime : dayjs . utc ( "2023-01-01T08:00:00Z" ) . toDate ( ) ,
379+ _count : { attendees : 1 } ,
380+ } ,
381+ ] ;
382+
383+ const result = checkForConflicts ( {
384+ time : dayjs . utc ( "2023-01-01T09:00:00Z" ) ,
385+ eventLength : 30 ,
386+ busy : [
387+ {
388+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
389+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
390+ } ,
391+ ] ,
392+ currentSeats,
393+ } ) ;
394+ expect ( result ) . toBe ( true ) ;
395+ } ) ;
396+
397+ it ( "should handle multiple currentSeats with one matching" , ( ) => {
398+ const testTime = dayjs . utc ( "2023-01-01T09:00:00Z" ) ;
399+ const currentSeats : CurrentSeats = [
400+ {
401+ uid : "booking-1" ,
402+ startTime : dayjs . utc ( "2023-01-01T08:00:00Z" ) . toDate ( ) ,
403+ _count : { attendees : 1 } ,
404+ } ,
405+ {
406+ uid : "booking-2" ,
407+ startTime : testTime . toDate ( ) ,
408+ _count : { attendees : 1 } ,
409+ } ,
410+ ] ;
411+
412+ const result = checkForConflicts ( {
413+ time : testTime ,
414+ eventLength : 30 ,
415+ busy : [
416+ {
417+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
418+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
419+ } ,
420+ ] ,
421+ currentSeats,
422+ } ) ;
423+ expect ( result ) . toBe ( false ) ;
424+ } ) ;
425+
426+ it ( "should handle empty currentSeats array" , ( ) => {
427+ const result = checkForConflicts ( {
428+ time : dayjs . utc ( "2023-01-01T09:00:00Z" ) ,
429+ eventLength : 30 ,
430+ busy : [
431+ {
432+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
433+ end : dayjs . utc ( "2023-01-01T09:45:00Z" ) . toDate ( ) ,
434+ } ,
435+ ] ,
436+ currentSeats : [ ] ,
437+ } ) ;
438+ expect ( result ) . toBe ( true ) ;
439+ } ) ;
440+ } ) ;
441+
442+ describe ( "timezone and date handling" , ( ) => {
443+ it ( "should handle different timezone inputs correctly" , ( ) => {
444+ const result = checkForConflicts ( {
445+ time : dayjs ( "2023-01-01T09:00:00-05:00" ) , // EST
446+ eventLength : 30 ,
447+ busy : [
448+ {
449+ start : dayjs . utc ( "2023-01-01T14:15:00Z" ) . toDate ( ) , // UTC equivalent of 9:15 EST
450+ end : dayjs . utc ( "2023-01-01T14:45:00Z" ) . toDate ( ) ,
451+ } ,
452+ ] ,
453+ } ) ;
454+ expect ( result ) . toBe ( true ) ;
455+ } ) ;
456+
457+ it ( "should handle cross-day boundaries" , ( ) => {
458+ const result = checkForConflicts ( {
459+ time : dayjs . utc ( "2023-01-01T23:45:00Z" ) ,
460+ eventLength : 30 ,
461+ busy : [
462+ {
463+ start : dayjs . utc ( "2023-01-02T00:00:00Z" ) . toDate ( ) ,
464+ end : dayjs . utc ( "2023-01-02T00:30:00Z" ) . toDate ( ) ,
465+ } ,
466+ ] ,
467+ } ) ;
468+ expect ( result ) . toBe ( true ) ;
469+ } ) ;
470+ } ) ;
471+
472+ describe ( "performance and stress scenarios" , ( ) => {
473+ it ( "should handle large number of busy periods efficiently" , ( ) => {
474+ const busyPeriods = [ ] ;
475+ for ( let i = 0 ; i < 1000 ; i ++ ) {
476+ const hour = ( 8 + ( i % 12 ) ) % 24 ; // Wrap around to prevent invalid hours
477+ const minute = i % 60 ;
478+ const endMinute = ( ( i % 60 ) + 15 ) % 60 ;
479+ const endHour = endMinute < minute ? ( hour + 1 ) % 24 : hour ; // Handle minute overflow
480+
481+ busyPeriods . push ( {
482+ start : dayjs
483+ . utc ( `2023-01-01T${ hour . toString ( ) . padStart ( 2 , "0" ) } :${ minute . toString ( ) . padStart ( 2 , "0" ) } :00Z` )
484+ . toDate ( ) ,
485+ end : dayjs
486+ . utc (
487+ `2023-01-01T${ endHour . toString ( ) . padStart ( 2 , "0" ) } :${ endMinute . toString ( ) . padStart ( 2 , "0" ) } :00Z`
488+ )
489+ . toDate ( ) ,
490+ } ) ;
491+ }
492+
493+ const startTime = performance . now ( ) ;
494+ const result = checkForConflicts ( {
495+ ...createTestData ( "2023-01-01T07:00:00Z" ) ,
496+ busy : busyPeriods ,
497+ } ) ;
498+ const endTime = performance . now ( ) ;
499+
500+ expect ( result ) . toBe ( false ) ;
501+ expect ( endTime - startTime ) . toBeLessThan ( 100 ) ; // Should complete in under 100ms
502+ } ) ;
503+
504+ it ( "should handle zero-duration busy periods" , ( ) => {
505+ const result = checkForConflicts ( {
506+ ...createTestData ( "2023-01-01T09:00:00Z" ) ,
507+ busy : [
508+ {
509+ start : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) ,
510+ end : dayjs . utc ( "2023-01-01T09:15:00Z" ) . toDate ( ) , // Zero duration
511+ } ,
512+ ] ,
513+ } ) ;
514+ expect ( result ) . toBe ( true ) ;
515+ } ) ;
516+ } ) ;
167517} ) ;
0 commit comments