@@ -17,10 +17,15 @@ import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, Fil
17
17
import { DIRECTORY_DRAG_TYPE } from '@react-aria/dnd' ;
18
18
import { DragBetweenListsComplex , DragBetweenListsExample , DragBetweenListsRootOnlyExample , DragExample , DragIntoItemExample , ReorderExample } from '../stories/ListView.stories' ;
19
19
import { Droppable } from '@react-aria/dnd/test/examples' ;
20
+ import { Flex } from '@react-spectrum/layout' ;
20
21
import { globalDndState } from '@react-aria/dnd/src/utils' ;
22
+ import { Item , ListView } from '../' ;
21
23
import { Provider } from '@react-spectrum/provider' ;
22
24
import React from 'react' ;
25
+ import { Text } from '@react-spectrum/text' ;
23
26
import { theme } from '@react-spectrum/theme-default' ;
27
+ import { useDragAndDrop } from '@react-spectrum/dnd' ;
28
+ import { useListData } from '@react-stately/data' ;
24
29
import userEvent from '@testing-library/user-event' ;
25
30
26
31
let isReact18 = parseInt ( React . version , 10 ) >= 18 ;
@@ -920,6 +925,109 @@ describe('ListView', function () {
920
925
} ) ;
921
926
} ) ;
922
927
928
+ it ( 'should call onRootDrop when dropping on a empty list' , async function ( ) {
929
+ function Example ( ) {
930
+ let list1 = useListData ( {
931
+ initialItems : [ ]
932
+ } ) ;
933
+
934
+ let list2 = useListData ( {
935
+ initialItems : [
936
+ { id : '7' , type : 'folder' , name : 'Pictures' } ,
937
+ { id : '8' , type : 'file' , name : 'Adobe Fresco' } ,
938
+ { id : '9' , type : 'folder' , name : 'Apps' } ,
939
+ { id : '10' , type : 'file' , name : 'Adobe Illustrator' } ,
940
+ { id : '11' , type : 'file' , name : 'Adobe Lightroom' } ,
941
+ { id : '12' , type : 'file' , name : 'Adobe Dreamweaver' }
942
+ ]
943
+ } ) ;
944
+
945
+ let { dragAndDropHooks : list1Hooks } = useDragAndDrop ( {
946
+ ...mockUtilityOptions ,
947
+ acceptedDragTypes : 'all'
948
+ } ) ;
949
+
950
+ let { dragAndDropHooks : list2Hooks } = useDragAndDrop ( {
951
+ getItems : ( keys ) => [ ...keys ] . map ( key => {
952
+ let item = list2 . getItem ( key ) ;
953
+ return {
954
+ [ `${ item . type } ` ] : JSON . stringify ( item ) ,
955
+ 'text/plain' : JSON . stringify ( item )
956
+ } ;
957
+ } )
958
+ } ) ;
959
+
960
+ return (
961
+ < Flex wrap gap = "size-300" >
962
+ < ListView
963
+ aria-label = "Droppable listview"
964
+ width = "size-3600"
965
+ height = "size-3600"
966
+ items = { list1 . items }
967
+ dragAndDropHooks = { list1Hooks } >
968
+ { ( item ) => (
969
+ < Item textValue = { item . name } >
970
+ < Text > { item . name } </ Text >
971
+ </ Item >
972
+ ) }
973
+ </ ListView >
974
+ < ListView
975
+ aria-label = "Draggable ListView"
976
+ selectionMode = "multiple"
977
+ width = "size-3600"
978
+ height = "size-3600"
979
+ items = { list2 . items }
980
+ dragAndDropHooks = { list2Hooks } >
981
+ { ( item ) => (
982
+ < Item textValue = { item . name } >
983
+ < Text > { item . name } </ Text >
984
+ </ Item >
985
+ ) }
986
+ </ ListView >
987
+ </ Flex >
988
+ ) ;
989
+ }
990
+
991
+ let { getAllByRole} = render (
992
+ < Example />
993
+ ) ;
994
+ let grids = getAllByRole ( 'grid' ) ;
995
+ expect ( grids ) . toHaveLength ( 2 ) ;
996
+
997
+ let dropTarget = grids [ 0 ] ;
998
+ let list2Rows = within ( grids [ 1 ] ) . getAllByRole ( 'row' ) ;
999
+ dragBetweenLists ( list2Rows , dropTarget ) ;
1000
+ expect ( onReorder ) . toHaveBeenCalledTimes ( 0 ) ;
1001
+ expect ( onItemDrop ) . toHaveBeenCalledTimes ( 0 ) ;
1002
+ expect ( onRootDrop ) . toHaveBeenCalledTimes ( 1 ) ;
1003
+ expect ( onRootDrop ) . toHaveBeenCalledWith ( {
1004
+ dropOperation : 'move' ,
1005
+ items : [
1006
+ {
1007
+ kind : 'text' ,
1008
+ types : new Set ( [ 'text/plain' , 'folder' ] ) ,
1009
+ getText : expect . any ( Function )
1010
+ } ,
1011
+ {
1012
+ kind : 'text' ,
1013
+ types : new Set ( [ 'text/plain' , 'file' ] ) ,
1014
+ getText : expect . any ( Function )
1015
+ }
1016
+ ]
1017
+ } ) ;
1018
+ let items = await Promise . all ( onRootDrop . mock . calls [ 0 ] [ 0 ] . items . map ( async ( item ) => JSON . parse ( await item . getText ( 'text/plain' ) ) ) ) ;
1019
+ expect ( items ) . toContainObject ( {
1020
+ id : '7' ,
1021
+ type : 'folder' ,
1022
+ name : 'Pictures'
1023
+ } ) ;
1024
+ expect ( items ) . toContainObject ( {
1025
+ id : '8' ,
1026
+ type : 'file' ,
1027
+ name : 'Adobe Fresco'
1028
+ } ) ;
1029
+ } ) ;
1030
+
923
1031
it ( 'should call onItemDrop when dropping on a folder in the list' , async function ( ) {
924
1032
let { getAllByRole} = render (
925
1033
< DragBetweenListsComplex firstListDnDOptions = { mockUtilityOptions } secondListDnDOptions = { { onDragEnd} } />
0 commit comments