@@ -17,10 +17,15 @@ import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, Fil
1717import { DIRECTORY_DRAG_TYPE } from '@react-aria/dnd' ;
1818import { DragBetweenListsComplex , DragBetweenListsExample , DragBetweenListsRootOnlyExample , DragExample , DragIntoItemExample , ReorderExample } from '../stories/ListView.stories' ;
1919import { Droppable } from '@react-aria/dnd/test/examples' ;
20+ import { Flex } from '@react-spectrum/layout' ;
2021import { globalDndState } from '@react-aria/dnd/src/utils' ;
22+ import { Item , ListView } from '../' ;
2123import { Provider } from '@react-spectrum/provider' ;
2224import React from 'react' ;
25+ import { Text } from '@react-spectrum/text' ;
2326import { theme } from '@react-spectrum/theme-default' ;
27+ import { useDragAndDrop } from '@react-spectrum/dnd' ;
28+ import { useListData } from '@react-stately/data' ;
2429import userEvent from '@testing-library/user-event' ;
2530
2631let isReact18 = parseInt ( React . version , 10 ) >= 18 ;
@@ -920,6 +925,109 @@ describe('ListView', function () {
920925 } ) ;
921926 } ) ;
922927
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+
9231031 it ( 'should call onItemDrop when dropping on a folder in the list' , async function ( ) {
9241032 let { getAllByRole} = render (
9251033 < DragBetweenListsComplex firstListDnDOptions = { mockUtilityOptions } secondListDnDOptions = { { onDragEnd} } />
0 commit comments