@@ -19,6 +19,9 @@ jest.mock("react-big-calendar", () => {
1919 resizable,
2020 selectable,
2121 showAllEvents,
22+ showMultiDayTimes,
23+ min,
24+ max,
2225 events,
2326 step,
2427 timeslots,
@@ -34,6 +37,9 @@ jest.mock("react-big-calendar", () => {
3437 data-resizable = { resizable }
3538 data-selectable = { selectable }
3639 data-show-all-events = { showAllEvents }
40+ data-show-multi-day-times = { showMultiDayTimes }
41+ data-min = { min ?. toISOString ( ) }
42+ data-max = { max ?. toISOString ( ) }
3743 data-events-count = { events ?. length ?? 0 }
3844 data-step = { step }
3945 data-timeslots = { timeslots }
@@ -93,6 +99,7 @@ const customViewProps: CalendarContainerProps = {
9399 customViewShowFriday : true ,
94100 customViewShowSaturday : false ,
95101 showAllEvents : true ,
102+ showMultiDayTimes : true ,
96103 step : 60 ,
97104 timeslots : 2 ,
98105 toolbarItems : [ ] ,
@@ -358,3 +365,179 @@ describe("CalendarPropsBuilder column header formats", () => {
358365 expect ( localizer . format ) . toHaveBeenCalledWith ( expect . any ( Date ) , "HH:mm" , "en" ) ;
359366 } ) ;
360367} ) ;
368+
369+ describe ( "CalendarPropsBuilder showMultiDayTimes" , ( ) => {
370+ const mockLocalizer = {
371+ format : jest . fn ( ) ,
372+ parse : jest . fn ( ) ,
373+ startOfWeek : jest . fn ( ) ,
374+ getDay : jest . fn ( ) ,
375+ messages : { }
376+ } as any ;
377+
378+ it ( "passes showMultiDayTimes=true to calendar props" , ( ) => {
379+ const props = { ...customViewProps , showMultiDayTimes : true } ;
380+ const builder = new CalendarPropsBuilder ( props ) ;
381+ const result = builder . build ( mockLocalizer , "en" ) ;
382+ expect ( result . showMultiDayTimes ) . toBe ( true ) ;
383+ } ) ;
384+
385+ it ( "passes showMultiDayTimes=false to calendar props" , ( ) => {
386+ const props = { ...customViewProps , showMultiDayTimes : false } ;
387+ const builder = new CalendarPropsBuilder ( props ) ;
388+ const result = builder . build ( mockLocalizer , "en" ) ;
389+ expect ( result . showMultiDayTimes ) . toBe ( false ) ;
390+ } ) ;
391+ } ) ;
392+
393+ describe ( "CalendarPropsBuilder multi-day time formats" , ( ) => {
394+ const mockLocalizer = {
395+ format : jest . fn ( ( date : Date , pattern : string , _culture : string ) => {
396+ // Simulate locale-aware formatting using the pattern
397+ const hours = date . getHours ( ) ;
398+ const minutes = date . getMinutes ( ) . toString ( ) . padStart ( 2 , "0" ) ;
399+ return `${ hours } :${ minutes } (${ pattern } )` ;
400+ } ) ,
401+ parse : jest . fn ( ) ,
402+ startOfWeek : jest . fn ( ) ,
403+ getDay : jest . fn ( ) ,
404+ messages : { }
405+ } as any ;
406+
407+ const buildWithTimeFormat = ( timeFormatValue : string ) => {
408+ const props = {
409+ ...customViewProps ,
410+ timeFormat : dynamic ( timeFormatValue )
411+ } ;
412+ const builder = new CalendarPropsBuilder ( props ) ;
413+ return builder . build ( mockLocalizer , "en" ) ;
414+ } ;
415+
416+ it ( "sets eventTimeRangeStartFormat using the configured time pattern" , ( ) => {
417+ const result = buildWithTimeFormat ( "HH:mm" ) ;
418+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
419+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
420+
421+ expect ( result . formats ! . eventTimeRangeStartFormat ) . toBeDefined ( ) ;
422+ const label = ( result . formats ! . eventTimeRangeStartFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
423+ expect ( label ) . toContain ( "HH:mm" ) ;
424+ expect ( label ) . toMatch ( / – $ / ) ;
425+ } ) ;
426+
427+ it ( "sets eventTimeRangeEndFormat using the configured time pattern" , ( ) => {
428+ const result = buildWithTimeFormat ( "HH:mm" ) ;
429+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
430+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
431+
432+ expect ( result . formats ! . eventTimeRangeEndFormat ) . toBeDefined ( ) ;
433+ const label = ( result . formats ! . eventTimeRangeEndFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
434+ expect ( label ) . toContain ( "HH:mm" ) ;
435+ expect ( label ) . toMatch ( / ^ – / ) ;
436+ } ) ;
437+
438+ it ( "uses the same pattern for eventTimeRangeFormat, start, and end formats" , ( ) => {
439+ const result = buildWithTimeFormat ( "h:mm a" ) ;
440+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
441+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
442+
443+ const rangeLabel = ( result . formats ! . eventTimeRangeFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
444+ const startLabel = ( result . formats ! . eventTimeRangeStartFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
445+ const endLabel = ( result . formats ! . eventTimeRangeEndFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
446+
447+ // All three should use the same "h:mm a" pattern passed to localizer.format
448+ expect ( rangeLabel ) . toContain ( "h:mm a" ) ;
449+ expect ( startLabel ) . toContain ( "h:mm a" ) ;
450+ expect ( endLabel ) . toContain ( "h:mm a" ) ;
451+ } ) ;
452+
453+ it ( "does not set start/end formats when no timeFormat is configured" , ( ) => {
454+ const props = { ...customViewProps , timeFormat : undefined } ;
455+ const builder = new CalendarPropsBuilder ( props ) ;
456+ const result = builder . build ( mockLocalizer , "en" ) ;
457+
458+ expect ( result . formats ! . eventTimeRangeStartFormat ) . toBeUndefined ( ) ;
459+ expect ( result . formats ! . eventTimeRangeEndFormat ) . toBeUndefined ( ) ;
460+ } ) ;
461+ } ) ;
462+
463+ describe ( "CalendarPropsBuilder showEventDate hides multi-day formats" , ( ) => {
464+ const mockLocalizer = {
465+ format : jest . fn ( ( _date : Date , pattern : string ) => `formatted(${ pattern } )` ) ,
466+ parse : jest . fn ( ) ,
467+ startOfWeek : jest . fn ( ) ,
468+ getDay : jest . fn ( ) ,
469+ messages : { }
470+ } as any ;
471+
472+ it ( "blanks eventTimeRangeStartFormat when showEventDate=false" , ( ) => {
473+ const props = {
474+ ...customViewProps ,
475+ showEventDate : dynamic ( false ) ,
476+ timeFormat : dynamic ( "HH:mm" )
477+ } ;
478+ const builder = new CalendarPropsBuilder ( props ) ;
479+ const result = builder . build ( mockLocalizer , "en" ) ;
480+
481+ const label = ( result . formats ! . eventTimeRangeStartFormat as Function ) (
482+ { start : new Date ( ) , end : new Date ( ) } ,
483+ "en" ,
484+ mockLocalizer
485+ ) ;
486+ expect ( label ) . toBe ( "" ) ;
487+ } ) ;
488+
489+ it ( "blanks eventTimeRangeEndFormat when showEventDate=false" , ( ) => {
490+ const props = {
491+ ...customViewProps ,
492+ showEventDate : dynamic ( false ) ,
493+ timeFormat : dynamic ( "HH:mm" )
494+ } ;
495+ const builder = new CalendarPropsBuilder ( props ) ;
496+ const result = builder . build ( mockLocalizer , "en" ) ;
497+
498+ const label = ( result . formats ! . eventTimeRangeEndFormat as Function ) (
499+ { start : new Date ( ) , end : new Date ( ) } ,
500+ "en" ,
501+ mockLocalizer
502+ ) ;
503+ expect ( label ) . toBe ( "" ) ;
504+ } ) ;
505+
506+ it ( "blanks eventTimeRangeFormat when showEventDate=false" , ( ) => {
507+ const props = {
508+ ...customViewProps ,
509+ showEventDate : dynamic ( false ) ,
510+ timeFormat : dynamic ( "HH:mm" )
511+ } ;
512+ const builder = new CalendarPropsBuilder ( props ) ;
513+ const result = builder . build ( mockLocalizer , "en" ) ;
514+
515+ const label = ( result . formats ! . eventTimeRangeFormat as Function ) (
516+ { start : new Date ( ) , end : new Date ( ) } ,
517+ "en" ,
518+ mockLocalizer
519+ ) ;
520+ expect ( label ) . toBe ( "" ) ;
521+ } ) ;
522+
523+ it ( "preserves all time range formats when showEventDate=true" , ( ) => {
524+ const props = {
525+ ...customViewProps ,
526+ showEventDate : dynamic ( true ) ,
527+ timeFormat : dynamic ( "p" )
528+ } ;
529+ const builder = new CalendarPropsBuilder ( props ) ;
530+ const result = builder . build ( mockLocalizer , "en" ) ;
531+
532+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
533+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
534+
535+ const rangeLabel = ( result . formats ! . eventTimeRangeFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
536+ const startLabel = ( result . formats ! . eventTimeRangeStartFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
537+ const endLabel = ( result . formats ! . eventTimeRangeEndFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
538+
539+ expect ( rangeLabel ) . not . toBe ( "" ) ;
540+ expect ( startLabel ) . not . toBe ( "" ) ;
541+ expect ( endLabel ) . not . toBe ( "" ) ;
542+ } ) ;
543+ } ) ;
0 commit comments