@@ -104,7 +104,7 @@ const mockEvent = {
104104function makeProps ( obj = { } ) {
105105 return {
106106 ToolbarComponent : ( { elementTypes } ) => < div data-testid = "test-toolbar" data-elementtypes = { elementTypes . map ( type => type . class ) . join ( ',' ) } /> ,
107- ListComponent : ( { elements, onDragEnd } ) => < div className = "test-list" >
107+ ListComponent : ( { elements, onDragEnd, isLoading } ) => < div className = "test-list" data-is-loading = { isLoading } >
108108 { elements . map ( element => < div id = { `Element${ element . id } ` } key = { element . id } onClick = { ( ) => onDragEnd ( mockEvent ) } > { element . title } </ div > ) }
109109 </ div > ,
110110 areaId : 8 ,
@@ -550,3 +550,60 @@ test('ElementEditor preserves dragging state during sort request', async () => {
550550 await screen . findByTestId ( 'test-toolbar' ) ;
551551 expect ( timesReloaded ) . toBe ( 2 ) ;
552552} ) ;
553+
554+ test ( 'ElementEditor does not show loading indicator for fast operations (< 300ms)' , async ( ) => {
555+ const { container } = render ( < ElementEditor { ...makeProps ( ) } /> ) ;
556+ // Immediately resolve - operation completes in < 300ms
557+ resolveBackendGet ( createJsonResponse ( ) ) ;
558+ await screen . findByTestId ( 'test-toolbar' ) ;
559+ const listComponent = container . querySelector ( '.test-list' ) ;
560+ expect ( listComponent . getAttribute ( 'data-is-loading' ) ) . toBe ( 'false' ) ;
561+ } ) ;
562+
563+ test ( 'ElementEditor shows loading indicator for slow operations (> 300ms)' , async ( ) => {
564+ jest . useFakeTimers ( ) ;
565+ const { container } = render ( < ElementEditor { ...makeProps ( ) } /> ) ;
566+ // Wait for 300ms
567+ jest . advanceTimersByTime ( 300 ) ;
568+ const listComponent = container . querySelector ( '.test-list' ) ;
569+ // Should show loading after 300ms
570+ expect ( listComponent ) . toBeNull ( ) ; // Still returning null since elements is null
571+ // Resolve the backend call
572+ resolveBackendGet ( createJsonResponse ( ) ) ;
573+ await screen . findByTestId ( 'test-toolbar' ) ;
574+ jest . useRealTimers ( ) ;
575+ } ) ;
576+
577+ test ( 'ElementEditor clears loading indicator timeout on fast completion' , async ( ) => {
578+ jest . useFakeTimers ( ) ;
579+ const { container } = render ( < ElementEditor { ...makeProps ( ) } /> ) ;
580+ // Advance time by 100ms (less than 300ms debounce)
581+ jest . advanceTimersByTime ( 100 ) ;
582+ // Resolve quickly
583+ resolveBackendGet ( createJsonResponse ( ) ) ;
584+ // Advance past debounce time
585+ jest . advanceTimersByTime ( 250 ) ;
586+ await screen . findByTestId ( 'test-toolbar' ) ;
587+ const listComponent = container . querySelector ( '.test-list' ) ;
588+ // Should not show loading since it completed before 300ms
589+ expect ( listComponent . getAttribute ( 'data-is-loading' ) ) . toBe ( 'false' ) ;
590+ jest . useRealTimers ( ) ;
591+ } ) ;
592+
593+ test ( 'ElementEditor debounced loading works on refetch' , async ( ) => {
594+ jest . useFakeTimers ( ) ;
595+ const { rerender, container } = render ( < ElementEditor { ...makeProps ( ) } /> ) ;
596+ resolveBackendGet ( createJsonResponse ( ) ) ;
597+ jest . advanceTimersByTime ( 300 ) ;
598+ await screen . findByTestId ( 'test-toolbar' ) ;
599+ expect ( timesReloaded ) . toBe ( 1 ) ;
600+ // Trigger refetch
601+ rerender ( < ElementEditor { ...makeProps ( { forceRefetchElements : true } ) } /> ) ;
602+ // Complete quickly
603+ resolveBackendGet ( createJsonResponse ( ) ) ;
604+ jest . advanceTimersByTime ( 100 ) ;
605+ await screen . findByTestId ( 'test-toolbar' ) ;
606+ const listComponent = container . querySelector ( '.test-list' ) ;
607+ expect ( listComponent . getAttribute ( 'data-is-loading' ) ) . toBe ( 'false' ) ;
608+ jest . useRealTimers ( ) ;
609+ } ) ;
0 commit comments