@@ -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 : [ ] ,
@@ -256,3 +263,179 @@ describe("CalendarPropsBuilder validation", () => {
256263 expect ( result . timeslots ) . toBe ( 2 ) ;
257264 } ) ;
258265} ) ;
266+
267+ describe ( "CalendarPropsBuilder showMultiDayTimes" , ( ) => {
268+ const mockLocalizer = {
269+ format : jest . fn ( ) ,
270+ parse : jest . fn ( ) ,
271+ startOfWeek : jest . fn ( ) ,
272+ getDay : jest . fn ( ) ,
273+ messages : { }
274+ } as any ;
275+
276+ it ( "passes showMultiDayTimes=true to calendar props" , ( ) => {
277+ const props = { ...customViewProps , showMultiDayTimes : true } ;
278+ const builder = new CalendarPropsBuilder ( props ) ;
279+ const result = builder . build ( mockLocalizer , "en" ) ;
280+ expect ( result . showMultiDayTimes ) . toBe ( true ) ;
281+ } ) ;
282+
283+ it ( "passes showMultiDayTimes=false to calendar props" , ( ) => {
284+ const props = { ...customViewProps , showMultiDayTimes : false } ;
285+ const builder = new CalendarPropsBuilder ( props ) ;
286+ const result = builder . build ( mockLocalizer , "en" ) ;
287+ expect ( result . showMultiDayTimes ) . toBe ( false ) ;
288+ } ) ;
289+ } ) ;
290+
291+ describe ( "CalendarPropsBuilder multi-day time formats" , ( ) => {
292+ const mockLocalizer = {
293+ format : jest . fn ( ( date : Date , pattern : string , _culture : string ) => {
294+ // Simulate locale-aware formatting using the pattern
295+ const hours = date . getHours ( ) ;
296+ const minutes = date . getMinutes ( ) . toString ( ) . padStart ( 2 , "0" ) ;
297+ return `${ hours } :${ minutes } (${ pattern } )` ;
298+ } ) ,
299+ parse : jest . fn ( ) ,
300+ startOfWeek : jest . fn ( ) ,
301+ getDay : jest . fn ( ) ,
302+ messages : { }
303+ } as any ;
304+
305+ const buildWithTimeFormat = ( timeFormatValue : string ) => {
306+ const props = {
307+ ...customViewProps ,
308+ timeFormat : dynamic ( timeFormatValue )
309+ } ;
310+ const builder = new CalendarPropsBuilder ( props ) ;
311+ return builder . build ( mockLocalizer , "en" ) ;
312+ } ;
313+
314+ it ( "sets eventTimeRangeStartFormat using the configured time pattern" , ( ) => {
315+ const result = buildWithTimeFormat ( "HH:mm" ) ;
316+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
317+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
318+
319+ expect ( result . formats ! . eventTimeRangeStartFormat ) . toBeDefined ( ) ;
320+ const label = ( result . formats ! . eventTimeRangeStartFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
321+ expect ( label ) . toContain ( "HH:mm" ) ;
322+ expect ( label ) . toMatch ( / – $ / ) ;
323+ } ) ;
324+
325+ it ( "sets eventTimeRangeEndFormat using the configured time pattern" , ( ) => {
326+ const result = buildWithTimeFormat ( "HH:mm" ) ;
327+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
328+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
329+
330+ expect ( result . formats ! . eventTimeRangeEndFormat ) . toBeDefined ( ) ;
331+ const label = ( result . formats ! . eventTimeRangeEndFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
332+ expect ( label ) . toContain ( "HH:mm" ) ;
333+ expect ( label ) . toMatch ( / ^ – / ) ;
334+ } ) ;
335+
336+ it ( "uses the same pattern for eventTimeRangeFormat, start, and end formats" , ( ) => {
337+ const result = buildWithTimeFormat ( "h:mm a" ) ;
338+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
339+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
340+
341+ const rangeLabel = ( result . formats ! . eventTimeRangeFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
342+ const startLabel = ( result . formats ! . eventTimeRangeStartFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
343+ const endLabel = ( result . formats ! . eventTimeRangeEndFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
344+
345+ // All three should use the same "h:mm a" pattern passed to localizer.format
346+ expect ( rangeLabel ) . toContain ( "h:mm a" ) ;
347+ expect ( startLabel ) . toContain ( "h:mm a" ) ;
348+ expect ( endLabel ) . toContain ( "h:mm a" ) ;
349+ } ) ;
350+
351+ it ( "does not set start/end formats when no timeFormat is configured" , ( ) => {
352+ const props = { ...customViewProps , timeFormat : undefined } ;
353+ const builder = new CalendarPropsBuilder ( props ) ;
354+ const result = builder . build ( mockLocalizer , "en" ) ;
355+
356+ expect ( result . formats ! . eventTimeRangeStartFormat ) . toBeUndefined ( ) ;
357+ expect ( result . formats ! . eventTimeRangeEndFormat ) . toBeUndefined ( ) ;
358+ } ) ;
359+ } ) ;
360+
361+ describe ( "CalendarPropsBuilder showEventDate hides multi-day formats" , ( ) => {
362+ const mockLocalizer = {
363+ format : jest . fn ( ( _date : Date , pattern : string ) => `formatted(${ pattern } )` ) ,
364+ parse : jest . fn ( ) ,
365+ startOfWeek : jest . fn ( ) ,
366+ getDay : jest . fn ( ) ,
367+ messages : { }
368+ } as any ;
369+
370+ it ( "blanks eventTimeRangeStartFormat when showEventDate=false" , ( ) => {
371+ const props = {
372+ ...customViewProps ,
373+ showEventDate : dynamic ( false ) ,
374+ timeFormat : dynamic ( "HH:mm" )
375+ } ;
376+ const builder = new CalendarPropsBuilder ( props ) ;
377+ const result = builder . build ( mockLocalizer , "en" ) ;
378+
379+ const label = ( result . formats ! . eventTimeRangeStartFormat as Function ) (
380+ { start : new Date ( ) , end : new Date ( ) } ,
381+ "en" ,
382+ mockLocalizer
383+ ) ;
384+ expect ( label ) . toBe ( "" ) ;
385+ } ) ;
386+
387+ it ( "blanks eventTimeRangeEndFormat when showEventDate=false" , ( ) => {
388+ const props = {
389+ ...customViewProps ,
390+ showEventDate : dynamic ( false ) ,
391+ timeFormat : dynamic ( "HH:mm" )
392+ } ;
393+ const builder = new CalendarPropsBuilder ( props ) ;
394+ const result = builder . build ( mockLocalizer , "en" ) ;
395+
396+ const label = ( result . formats ! . eventTimeRangeEndFormat as Function ) (
397+ { start : new Date ( ) , end : new Date ( ) } ,
398+ "en" ,
399+ mockLocalizer
400+ ) ;
401+ expect ( label ) . toBe ( "" ) ;
402+ } ) ;
403+
404+ it ( "blanks eventTimeRangeFormat when showEventDate=false" , ( ) => {
405+ const props = {
406+ ...customViewProps ,
407+ showEventDate : dynamic ( false ) ,
408+ timeFormat : dynamic ( "HH:mm" )
409+ } ;
410+ const builder = new CalendarPropsBuilder ( props ) ;
411+ const result = builder . build ( mockLocalizer , "en" ) ;
412+
413+ const label = ( result . formats ! . eventTimeRangeFormat as Function ) (
414+ { start : new Date ( ) , end : new Date ( ) } ,
415+ "en" ,
416+ mockLocalizer
417+ ) ;
418+ expect ( label ) . toBe ( "" ) ;
419+ } ) ;
420+
421+ it ( "preserves all time range formats when showEventDate=true" , ( ) => {
422+ const props = {
423+ ...customViewProps ,
424+ showEventDate : dynamic ( true ) ,
425+ timeFormat : dynamic ( "p" )
426+ } ;
427+ const builder = new CalendarPropsBuilder ( props ) ;
428+ const result = builder . build ( mockLocalizer , "en" ) ;
429+
430+ const start = new Date ( "2025-04-28T22:00:00Z" ) ;
431+ const end = new Date ( "2025-04-29T02:00:00Z" ) ;
432+
433+ const rangeLabel = ( result . formats ! . eventTimeRangeFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
434+ const startLabel = ( result . formats ! . eventTimeRangeStartFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
435+ const endLabel = ( result . formats ! . eventTimeRangeEndFormat as Function ) ( { start, end } , "en" , mockLocalizer ) ;
436+
437+ expect ( rangeLabel ) . not . toBe ( "" ) ;
438+ expect ( startLabel ) . not . toBe ( "" ) ;
439+ expect ( endLabel ) . not . toBe ( "" ) ;
440+ } ) ;
441+ } ) ;
0 commit comments