Chromium Code Reviews| Index: chrome/test/data/webui/md_bookmarks/dnd_manager_test.js |
| diff --git a/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js b/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2984f47e9cd14ed1aafb78f28163609bac50b6b2 |
| --- /dev/null |
| +++ b/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js |
| @@ -0,0 +1,342 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +suite('drag and drop', function() { |
| + var app; |
| + var list; |
| + var sidebar; |
| + var store; |
| + var dndManager; |
| + var draggedIds; |
| + |
| + var DRAG_STYLE = { |
| + NONE: 0, |
| + ON: 1, |
| + ABOVE: 2, |
| + BELOW: 3, |
| + }; |
| + |
| + function getFolderNode(id) { |
| + var nodes = [sidebar]; |
| + var node; |
| + while (nodes.length) { |
| + node = nodes.pop(); |
| + if (node.itemId == id) |
| + return node; |
| + |
| + node.root.querySelectorAll('bookmarks-folder-node') |
| + .forEach((x) => {nodes.unshift(x)}); |
| + } |
| + } |
| + |
| + function getListItem(id) { |
| + var items = list.root.querySelectorAll('bookmarks-item'); |
| + for (var i = 0; i < items.length; i++) { |
| + if (items[i].itemId == id) |
| + return items[i]; |
| + } |
| + } |
| + |
| + function dispatchDragEvent(type, node, xy) { |
| + xy = xy || MockInteractions.middleOfNode(node); |
| + var props = { |
| + bubbles: true, |
| + cancelable: true, |
| + clientX: xy.x, |
| + clientY: xy.y, |
| + // Make this a primary input. |
| + buttons: 1, |
| + }; |
| + var e = new DragEvent(type, props); |
| + node.dispatchEvent(e); |
| + } |
| + |
| + function assertDragStyle(bookmarkElement, style) { |
| + var dragStyles = {}; |
| + dragStyles[DRAG_STYLE.ON] = 'drag-on'; |
| + dragStyles[DRAG_STYLE.ABOVE] = 'drag-above'; |
| + dragStyles[DRAG_STYLE.BELOW] = 'drag-below'; |
| + |
| + var classList = bookmarkElement.getDropTarget().classList; |
| + Object.keys(dragStyles).forEach(dragStyle => { |
| + assertEquals( |
| + dragStyle == style, classList.contains(dragStyles[dragStyle]), |
| + dragStyles[dragStyle] + (dragStyle == style ? ' missing' : ' found') + |
| + ' in classList ' + classList); |
| + }); |
| + } |
| + |
| + function createDragData(ids, sameProfile) { |
| + return { |
| + elements: ids.map(id => store.data.nodes[id]), |
| + 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.
|
| + } |
| + } |
| + |
| + setup(function() { |
| + store = new bookmarks.TestStore({ |
| + nodes: testTree( |
| + createFolder( |
| + '1', |
| + [ |
| + createFolder( |
| + '11', |
| + [ |
| + createFolder( |
| + '111', |
| + [ |
| + createItem('1111'), |
| + ]), |
| + createFolder('112', []), |
| + ]), |
| + createItem('12'), |
| + createItem('13'), |
| + createFolder('14', []), |
| + createFolder('15', []), |
| + ]), |
| + createFolder('2', [])), |
| + selectedFolder: '1', |
| + }); |
| + bookmarks.Store.instance_ = store; |
| + |
| + chrome.bookmarkManagerPrivate.startDrag = function(nodes, isTouch) { |
| + draggedIds = nodes; |
| + }; |
| + |
| + app = document.createElement('bookmarks-app'); |
| + replaceBody(app); |
| + list = app.$$('bookmarks-list'); |
| + sidebar = app.$$('bookmarks-sidebar'); |
| + dndManager = app.dndManager_; |
| + dndManager.dropIndicator_.disableTimeoutForTesting(); |
| + Polymer.dom.flush(); |
| + }); |
| + |
| + test('dragInfo isDraggingFolderToDescendant', function() { |
| + var dragInfo = new bookmarks.DragInfo(); |
| + var nodes = store.data.nodes; |
| + dragInfo.handleChromeDragEnter(createDragData(['11'])); |
| + assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes)); |
| + assertFalse(dragInfo.isDraggingFolderToDescendant('1', nodes)); |
| + assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes)); |
| + |
| + dragInfo.handleChromeDragEnter(createDragData(['1'])); |
| + assertTrue(dragInfo.isDraggingFolderToDescendant('14', nodes)); |
| + assertTrue(dragInfo.isDraggingFolderToDescendant('111', nodes)); |
| + assertFalse(dragInfo.isDraggingFolderToDescendant('2', nodes)); |
| + }); |
| + |
| + test('drag in list', function() { |
| + var dragElement = getListItem('13'); |
| + var dragTarget = getListItem('12'); |
| + |
| + dispatchDragEvent('dragstart', dragElement); |
| + assertDeepEquals(['13'], draggedIds); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + // Bookmark items cannot be dragged onto other items. |
| + dispatchDragEvent( |
| + 'dragover', dragTarget, MockInteractions.topLeftOfNode(dragTarget)); |
| + assertEquals( |
| + DropPosition.ABOVE, |
| + dndManager.calculateValidDropPositions_(dragTarget)); |
| + assertDragStyle(dragTarget, DRAG_STYLE.ABOVE); |
| + |
| + dispatchDragEvent('dragleave', dragTarget); |
| + assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| + |
| + // Bookmark items can be dragged onto folders. |
| + dragTarget = getListItem('11'); |
| + dispatchDragEvent('dragover', dragTarget); |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| + dndManager.calculateValidDropPositions_(dragTarget)); |
| + assertDragStyle(dragTarget, DRAG_STYLE.ON); |
| + |
| + // There are no valid drop locations for dragging an item onto itself. |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(dragElement)); |
| + dispatchDragEvent('dragleave', dragTarget); |
| + dispatchDragEvent('dragover', dragElement); |
| + |
| + assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| + assertDragStyle(dragElement, DRAG_STYLE.NONE); |
| + }); |
| + |
| + test('reorder folder nodes', function() { |
| + var dragElement = getFolderNode('112'); |
| + var dragTarget = getFolderNode('111'); |
| + dispatchDragEvent('dragstart', dragElement); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE, |
| + dndManager.calculateValidDropPositions_(dragTarget)); |
| + |
| + dispatchDragEvent( |
| + 'dragover', dragTarget, MockInteractions.topLeftOfNode(dragTarget)); |
| + assertDragStyle(dragTarget, DRAG_STYLE.ABOVE); |
| + }); |
| + |
| + test('drag an item into a sidebar folder', function() { |
| + var dragElement = getListItem('13'); |
| + var dragTarget = getFolderNode('2'); |
| + dispatchDragEvent('dragstart', dragElement); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + // Items can only be dragged onto sidebar folders, not above or below. |
| + assertEquals( |
| + DropPosition.ON, dndManager.calculateValidDropPositions_(dragTarget)); |
| + |
| + dispatchDragEvent('dragover', dragTarget); |
| + assertDragStyle(dragTarget, DRAG_STYLE.ON); |
| + |
| + // Items cannot be dragged onto their parent folders. |
| + dragTarget = getFolderNode('1'); |
| + dispatchDragEvent('dragover', dragTarget); |
| + assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| + }); |
| + |
| + test('drag a folder into a descendant', function() { |
| + var dragElement = getFolderNode('11'); |
| + var dragTarget = getFolderNode('112'); |
| + |
| + // Folders cannot be dragged into their descendants. |
| + dispatchDragEvent('dragstart', dragElement); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(dragTarget)); |
| + |
| + dispatchDragEvent('dragover', dragTarget); |
| + |
| + assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| + }); |
| + |
| + test('drag item into sidebar folder with descendants', function() { |
| + var dragElement = getFolderNode('15'); |
| + var dragTarget = getFolderNode('11'); |
| + dispatchDragEvent('dragstart', dragElement); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + // Drags below an open folder are not allowed. |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE, |
| + dndManager.calculateValidDropPositions_(dragTarget)); |
| + |
| + dispatchDragEvent('dragover', dragTarget); |
| + |
| + assertDragStyle(dragTarget, DRAG_STYLE.ON); |
| + |
| + dispatchDragEvent('dragend', dragElement); |
| + assertDragStyle(dragTarget, DRAG_STYLE.NONE); |
| + |
| + store.data.closedFolders['11'] = true; |
| + |
| + dispatchDragEvent('dragstart', dragElement); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + // Drags below a closed folder are allowed. |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| + dndManager.calculateValidDropPositions_(dragTarget)); |
| + }); |
| + |
| + test('drag multiple list items', function() { |
| + // Dragging multiple items. |
| + store.data.selection.items = {'13': true, '15': true}; |
| + dispatchDragEvent('dragstart', getListItem('13')); |
| + assertDeepEquals(['13', '15'], draggedIds); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + // The dragged items should not be allowed to be dragged around any selected |
| + // item. |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(getListItem('13'))); |
| + assertEquals( |
| + DropPosition.ON, |
| + dndManager.calculateValidDropPositions_(getListItem('14'))); |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(getListItem('15'))); |
| + |
| + // Dragging an unselected item should only drag the unselected item. |
| + dispatchDragEvent('dragstart', getListItem('14')); |
| + assertDeepEquals(['14'], draggedIds); |
| + |
| + // Dragging a folder node should only drag the node. |
| + dispatchDragEvent('dragstart', getListItem('11')); |
| + assertDeepEquals(['11'], draggedIds); |
| + }); |
| + |
| + test('bookmarks from different profiles', function() { |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(['11'], false)); |
| + |
| + // All positions should be allowed even with the same bookmark id if the |
| + // drag element is from a different profile. |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| + dndManager.calculateValidDropPositions_(getListItem('11'))); |
| + |
| + // Folders from other profiles should be able to be dragged into |
| + // descendants in this profile. |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| + dndManager.calculateValidDropPositions_(getFolderNode('112'))); |
| + }); |
| + |
| + test('drag from sidebar to list', function() { |
| + var dragElement = getFolderNode('112'); |
| + var dragTarget = getListItem('13'); |
| + |
| + // Drag a folder onto the list. |
| + dispatchDragEvent('dragstart', dragElement); |
| + assertDeepEquals(['112'], draggedIds); |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(draggedIds)); |
| + |
| + dispatchDragEvent( |
| + 'dragover', dragTarget, MockInteractions.topLeftOfNode(dragTarget)); |
| + assertDragStyle(dragTarget, DRAG_STYLE.ABOVE); |
| + |
| + dispatchDragEvent('dragend', dragTarget); |
| + |
| + // Folders should not be able to dragged onto themselves in the list. |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(['11'])); |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(getListItem('11'))); |
| + |
| + // Ancestors should not be able to be dragged onto descendant |
| + // displayed lists. |
| + store.data.selectedFolder = '111'; |
| + store.notifyObservers(); |
| + Polymer.dom.flush(); |
| + |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(['11'])); |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(getListItem('1111'))); |
| + }); |
| + |
| + test('drags with search', function() { |
| + store.data.search.term = 'Asgore'; |
| + store.data.search.results = ['11', '13', '2']; |
| + store.data.selectedFolder = null; |
| + store.notifyObservers(); |
| + |
| + // Search results should not be able to be dragged onto, but can be dragged |
| + // from. |
| + dndManager.dragInfo_.handleChromeDragEnter(createDragData(['2'])); |
| + assertEquals( |
| + DropPosition.NONE, |
| + dndManager.calculateValidDropPositions_(getListItem('13'))); |
| + |
| + // Drags onto folders should work as per usual. |
| + assertEquals( |
| + DropPosition.ON | DropPosition.ABOVE | DropPosition.BELOW, |
| + dndManager.calculateValidDropPositions_(getFolderNode('112'))); |
| + }); |
| +}); |