Chromium Code Reviews| 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, | |
|
tsergeant
2017/03/27 06:49:24
nit: these should align
calamity
2017/03/28 04:15:03
Obviously, it's because I forgot the semicolon on
tsergeant
2017/03/28 23:52:22
That's... interesting behavior.
| |
| 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 |