OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 suite('drag and drop', function() { |
| 6 var app; |
| 7 var list; |
| 8 var sidebar; |
| 9 var store; |
| 10 var dndManager; |
| 11 var draggedIds; |
| 12 |
| 13 var DRAG_STYLE = { |
| 14 NONE: 0, |
| 15 ON: 1, |
| 16 ABOVE: 2, |
| 17 BELOW: 3, |
| 18 }; |
| 19 |
| 20 function getFolderNode(id) { |
| 21 var nodes = [sidebar]; |
| 22 var node; |
| 23 while (nodes.length) { |
| 24 node = nodes.pop(); |
| 25 if (node.itemId == id) |
| 26 return node; |
| 27 |
| 28 node.root.querySelectorAll('bookmarks-folder-node') |
| 29 .forEach((x) => {nodes.unshift(x)}); |
| 30 } |
| 31 } |
| 32 |
| 33 function getListItem(id) { |
| 34 var items = list.root.querySelectorAll('bookmarks-item'); |
| 35 for (var i = 0; i < items.length; i++) { |
| 36 if (items[i].itemId == id) |
| 37 return items[i]; |
| 38 } |
| 39 } |
| 40 |
| 41 function dispatchDragEvent(type, node, xy) { |
| 42 xy = xy || MockInteractions.middleOfNode(node); |
| 43 var props = { |
| 44 bubbles: true, |
| 45 cancelable: true, |
| 46 clientX: xy.x, |
| 47 clientY: xy.y, |
| 48 // Make this a primary input. |
| 49 buttons: 1, |
| 50 }; |
| 51 var e = new DragEvent(type, props); |
| 52 node.dispatchEvent(e); |
| 53 } |
| 54 |
| 55 function assertDragStyle(bookmarkElement, style) { |
| 56 var dragStyles = {}; |
| 57 dragStyles[DRAG_STYLE.ON] = 'drag-on'; |
| 58 dragStyles[DRAG_STYLE.ABOVE] = 'drag-above'; |
| 59 dragStyles[DRAG_STYLE.BELOW] = 'drag-below'; |
| 60 |
| 61 var classList = bookmarkElement.getDropTarget().classList; |
| 62 Object.keys(dragStyles).forEach(dragStyle => { |
| 63 assertEquals( |
| 64 dragStyle == style, classList.contains(dragStyles[dragStyle]), |
| 65 dragStyles[dragStyle] + (dragStyle == style ? ' missing' : ' found') + |
| 66 ' in classList ' + classList); |
| 67 }); |
| 68 } |
| 69 |
| 70 function createDragData(ids, sameProfile) { |
| 71 return { |
| 72 elements: ids.map(id => store.data.nodes[id]), |
| 73 sameProfile: sameProfile == undefined ? true : sameProfile, |
| 74 }; |
| 75 } |
| 76 |
| 77 setup(function() { |
| 78 store = new bookmarks.TestStore({ |
| 79 nodes: testTree( |
| 80 createFolder( |
| 81 '1', |
| 82 [ |
| 83 createFolder( |
| 84 '11', |
| 85 [ |
| 86 createFolder( |
| 87 '111', |
| 88 [ |
| 89 createItem('1111'), |
| 90 ]), |
| 91 createFolder('112', []), |
| 92 ]), |
| 93 createItem('12'), |
| 94 createItem('13'), |
| 95 createFolder('14', []), |
| 96 createFolder('15', []), |
| 97 ]), |
| 98 createFolder('2', [])), |
| 99 selectedFolder: '1', |
| 100 }); |
| 101 bookmarks.Store.instance_ = store; |
| 102 |
| 103 chrome.bookmarkManagerPrivate.startDrag = function(nodes, isTouch) { |
| 104 draggedIds = nodes; |
| 105 }; |
| 106 |
| 107 app = document.createElement('bookmarks-app'); |
| 108 replaceBody(app); |
| 109 list = app.$$('bookmarks-list'); |
| 110 sidebar = app.$$('bookmarks-sidebar'); |
| 111 dndManager = app.dndManager_; |
| 112 dndManager.dropIndicator_.disableTimeoutForTesting(); |
| 113 Polymer.dom.flush(); |
| 114 }); |
| 115 |
| 116 test('dragInfo isDraggingFolderToDescendant', function() { |
| 117 var dragInfo = new bookmarks.DragInfo(); |
| 118 var nodes = store.data.nodes; |
| 119 dragInfo.handleChromeDragEnter(createDragData(['11'])); |
| 120 assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes)); |
| 121 assertFalse(dragInfo.isDraggingFolderToDescendant('1', nodes)); |
| 122 assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes)); |
| 123 |
| 124 dragInfo.handleChromeDragEnter(createDragData(['1'])); |
| 125 assertTrue(dragInfo.isDraggingFolderToDescendant('14', nodes)); |
| 126 assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes)); |
| 127 assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes)); |
| 128 }); |
| 129 |
| 130 test('drag in list', function() { |
| 131 var dragElement = getListItem('13'); |
| 132 var dragTarget = getListItem('12'); |
| 133 |
| 134 dispatchDragEvent('dragstart', dragElement); |
| 135 assertDeepEquals(['13'], draggedIds); |
| 136 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 137 |
| 138 // Bookmark items cannot be dragged onto other items. |
| 139 dispatchDragEvent( |
| 140 'dragover', dragTarget, MockInteractions.topLeftOfNode(dragTarget)); |
| 141 assertEquals( |
| 142 DropPosition.ABOVE, |
| 143 dndManager.calculateValidDropPositions_(dragTarget)); |
| 144 assertDragStyle(dragTarget, DRAG_STYLE.ABOVE); |
| 145 |
| 146 dispatchDragEvent('dragleave', dragTarget); |
| 147 assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| 148 |
| 149 // Bookmark items can be dragged onto folders. |
| 150 dragTarget = getListItem('11'); |
| 151 dispatchDragEvent('dragover', dragTarget); |
| 152 assertEquals( |
| 153 DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| 154 dndManager.calculateValidDropPositions_(dragTarget)); |
| 155 assertDragStyle(dragTarget, DRAG_STYLE.ON); |
| 156 |
| 157 // There are no valid drop locations for dragging an item onto itself. |
| 158 assertEquals( |
| 159 DropPosition.NONE, |
| 160 dndManager.calculateValidDropPositions_(dragElement)); |
| 161 dispatchDragEvent('dragleave', dragTarget); |
| 162 dispatchDragEvent('dragover', dragElement); |
| 163 |
| 164 assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| 165 assertDragStyle(dragElement, DRAG_STYLE.NONE); |
| 166 }); |
| 167 |
| 168 test('reorder folder nodes', function() { |
| 169 var dragElement = getFolderNode('112'); |
| 170 var dragTarget = getFolderNode('111'); |
| 171 dispatchDragEvent('dragstart', dragElement); |
| 172 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 173 |
| 174 assertEquals( |
| 175 DropPosition.ON | DropPosition.ABOVE, |
| 176 dndManager.calculateValidDropPositions_(dragTarget)); |
| 177 |
| 178 dispatchDragEvent( |
| 179 'dragover', dragTarget, MockInteractions.topLeftOfNode(dragTarget)); |
| 180 assertDragStyle(dragTarget, DRAG_STYLE.ABOVE); |
| 181 }); |
| 182 |
| 183 test('drag an item into a sidebar folder', function() { |
| 184 var dragElement = getListItem('13'); |
| 185 var dragTarget = getFolderNode('2'); |
| 186 dispatchDragEvent('dragstart', dragElement); |
| 187 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 188 |
| 189 // Items can only be dragged onto sidebar folders, not above or below. |
| 190 assertEquals( |
| 191 DropPosition.ON, dndManager.calculateValidDropPositions_(dragTarget)); |
| 192 |
| 193 dispatchDragEvent('dragover', dragTarget); |
| 194 assertDragStyle(dragTarget, DRAG_STYLE.ON); |
| 195 |
| 196 // Items cannot be dragged onto their parent folders. |
| 197 dragTarget = getFolderNode('1'); |
| 198 dispatchDragEvent('dragover', dragTarget); |
| 199 assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| 200 }); |
| 201 |
| 202 test('drag a folder into a descendant', function() { |
| 203 var dragElement = getFolderNode('11'); |
| 204 var dragTarget = getFolderNode('112'); |
| 205 |
| 206 // Folders cannot be dragged into their descendants. |
| 207 dispatchDragEvent('dragstart', dragElement); |
| 208 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 209 assertEquals( |
| 210 DropPosition.NONE, |
| 211 dndManager.calculateValidDropPositions_(dragTarget)); |
| 212 |
| 213 dispatchDragEvent('dragover', dragTarget); |
| 214 |
| 215 assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| 216 }); |
| 217 |
| 218 test('drag item into sidebar folder with descendants', function() { |
| 219 var dragElement = getFolderNode('15'); |
| 220 var dragTarget = getFolderNode('11'); |
| 221 dispatchDragEvent('dragstart', dragElement); |
| 222 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 223 |
| 224 // Drags below an open folder are not allowed. |
| 225 assertEquals( |
| 226 DropPosition.ON | DropPosition.ABOVE, |
| 227 dndManager.calculateValidDropPositions_(dragTarget)); |
| 228 |
| 229 dispatchDragEvent('dragover', dragTarget); |
| 230 |
| 231 assertDragStyle(dragTarget, DRAG_STYLE.ON); |
| 232 |
| 233 dispatchDragEvent('dragend', dragElement); |
| 234 assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| 235 |
| 236 store.data.closedFolders['11'] = true; |
| 237 |
| 238 dispatchDragEvent('dragstart', dragElement); |
| 239 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 240 |
| 241 // Drags below a closed folder are allowed. |
| 242 assertEquals( |
| 243 DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| 244 dndManager.calculateValidDropPositions_(dragTarget)); |
| 245 }); |
| 246 |
| 247 test('drag multiple list items', function() { |
| 248 // Dragging multiple items. |
| 249 store.data.selection.items = {'13': true, '15': true}; |
| 250 dispatchDragEvent('dragstart', getListItem('13')); |
| 251 assertDeepEquals(['13', '15'], draggedIds); |
| 252 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 253 |
| 254 // The dragged items should not be allowed to be dragged around any selected |
| 255 // item. |
| 256 assertEquals( |
| 257 DropPosition.NONE, |
| 258 dndManager.calculateValidDropPositions_(getListItem('13'))); |
| 259 assertEquals( |
| 260 DropPosition.ON, |
| 261 dndManager.calculateValidDropPositions_(getListItem('14'))); |
| 262 assertEquals( |
| 263 DropPosition.NONE, |
| 264 dndManager.calculateValidDropPositions_(getListItem('15'))); |
| 265 |
| 266 // Dragging an unselected item should only drag the unselected item. |
| 267 dispatchDragEvent('dragstart', getListItem('14')); |
| 268 assertDeepEquals(['14'], draggedIds); |
| 269 |
| 270 // Dragging a folder node should only drag the node. |
| 271 dispatchDragEvent('dragstart', getListItem('11')); |
| 272 assertDeepEquals(['11'], draggedIds); |
| 273 }); |
| 274 |
| 275 test('bookmarks from different profiles', function() { |
| 276 dndManager.dragInfo_.handleChromeDragEnter(createDragData(['11'], false)); |
| 277 |
| 278 // All positions should be allowed even with the same bookmark id if the |
| 279 // drag element is from a different profile. |
| 280 assertEquals( |
| 281 DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| 282 dndManager.calculateValidDropPositions_(getListItem('11'))); |
| 283 |
| 284 // Folders from other profiles should be able to be dragged into |
| 285 // descendants in this profile. |
| 286 assertEquals( |
| 287 DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| 288 dndManager.calculateValidDropPositions_(getFolderNode('112'))); |
| 289 }); |
| 290 |
| 291 test('drag from sidebar to list', function() { |
| 292 var dragElement = getFolderNode('112'); |
| 293 var dragTarget = getListItem('13'); |
| 294 |
| 295 // Drag a folder onto the list. |
| 296 dispatchDragEvent('dragstart', dragElement); |
| 297 assertDeepEquals(['112'], draggedIds); |
| 298 dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| 299 |
| 300 dispatchDragEvent( |
| 301 'dragover', dragTarget, MockInteractions.topLeftOfNode(dragTarget)); |
| 302 assertDragStyle(dragTarget, DRAG_STYLE.ABOVE); |
| 303 |
| 304 dispatchDragEvent('dragend', dragTarget); |
| 305 |
| 306 // Folders should not be able to dragged onto themselves in the list. |
| 307 dndManager.dragInfo_.handleChromeDragEnter(createDragData(['11'])); |
| 308 assertEquals( |
| 309 DropPosition.NONE, |
| 310 dndManager.calculateValidDropPositions_(getListItem('11'))); |
| 311 |
| 312 // Ancestors should not be able to be dragged onto descendant |
| 313 // displayed lists. |
| 314 store.data.selectedFolder = '111'; |
| 315 store.notifyObservers(); |
| 316 Polymer.dom.flush(); |
| 317 |
| 318 dndManager.dragInfo_.handleChromeDragEnter(createDragData(['11'])); |
| 319 assertEquals( |
| 320 DropPosition.NONE, |
| 321 dndManager.calculateValidDropPositions_(getListItem('1111'))); |
| 322 }); |
| 323 |
| 324 test('drags with search', function() { |
| 325 store.data.search.term = 'Asgore'; |
| 326 store.data.search.results = ['11', '13', '2']; |
| 327 store.data.selectedFolder = null; |
| 328 store.notifyObservers(); |
| 329 |
| 330 // Search results should not be able to be dragged onto, but can be dragged |
| 331 // from. |
| 332 dndManager.dragInfo_.handleChromeDragEnter(createDragData(['2'])); |
| 333 assertEquals( |
| 334 DropPosition.NONE, |
| 335 dndManager.calculateValidDropPositions_(getListItem('13'))); |
| 336 |
| 337 // Drags onto folders should work as per usual. |
| 338 assertEquals( |
| 339 DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| 340 dndManager.calculateValidDropPositions_(getFolderNode('112'))); |
| 341 }); |
| 342 }); |
OLD | NEW |