| // Copyright 2011 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| goog.provide('goog.fx.DragListGroupTest'); |
| goog.setTestOnly('goog.fx.DragListGroupTest'); |
| |
| goog.require('goog.array'); |
| goog.require('goog.dom'); |
| goog.require('goog.dom.classlist'); |
| goog.require('goog.events'); |
| goog.require('goog.events.BrowserEvent'); |
| goog.require('goog.events.BrowserFeature'); |
| goog.require('goog.events.Event'); |
| goog.require('goog.events.EventType'); |
| goog.require('goog.fx.DragEvent'); |
| goog.require('goog.fx.DragListDirection'); |
| goog.require('goog.fx.DragListGroup'); |
| goog.require('goog.fx.Dragger'); |
| goog.require('goog.math.Coordinate'); |
| goog.require('goog.object'); |
| goog.require('goog.testing.events'); |
| goog.require('goog.testing.jsunit'); |
| |
| |
| /** @type {goog.fx.DragListGroup} */ |
| var dlg; |
| |
| |
| /** @type {goog.dom.Element} */ |
| var list; |
| |
| |
| /** @type {goog.events.BrowserEvent} */ |
| var event; |
| |
| |
| /** |
| * The number of event listeners registered by the DragListGroup after the |
| * init() call. |
| * @type {number} |
| */ |
| var initialListenerCount; |
| |
| |
| /** |
| * Type of events fired by the DragListGroup. |
| * @type {!Array<string>} |
| */ |
| var firedEventTypes; |
| |
| function setUp() { |
| var sandbox = goog.dom.getElement('sandbox'); |
| list = goog.dom.createDom('div', {'id': 'horiz_div'}); |
| list.appendChild( |
| goog.dom.createDom('div', null, goog.dom.createTextNode('1'))); |
| list.appendChild( |
| goog.dom.createDom('div', null, goog.dom.createTextNode('2'))); |
| list.appendChild( |
| goog.dom.createDom('div', null, goog.dom.createTextNode('3'))); |
| sandbox.appendChild(list); |
| |
| dlg = new goog.fx.DragListGroup(); |
| dlg.setDragItemHoverClass('opacity_40', 'cursor_move'); |
| dlg.setDragItemHandleHoverClass('opacity_40', 'cursor_pointer'); |
| dlg.setCurrDragItemClass('blue_bg', 'opacity_40'); |
| dlg.setDraggerElClass('cursor_move', 'blue_bg'); |
| dlg.addDragList(list, goog.fx.DragListDirection.RIGHT); |
| dlg.init(); |
| |
| initialListenerCount = goog.object.getCount(dlg.eventHandler_.keys_); |
| |
| event = new goog.events.BrowserEvent(); |
| event.currentTarget = list.getElementsByTagName('div')[0]; |
| |
| firedEventTypes = []; |
| goog.events.listen(dlg, |
| goog.object.getValues(goog.fx.DragListGroup.EventType), |
| function(e) { |
| firedEventTypes.push(e.type); |
| }); |
| } |
| |
| function tearDown() { |
| dlg.dispose(); |
| goog.dom.getElement('sandbox').innerHTML = ''; |
| } |
| |
| |
| /** |
| * Test the initial assumptions. |
| * |
| * Verify that the setter methods work properly, i.e., the CSS classes are |
| * stored in the private arrays after init() but are not added yet to target. |
| * (Since initially, we are not yet hovering over any list, in particular, |
| * over this target.) |
| */ |
| function testSettersAfterInit() { |
| assertTrue(goog.array.equals(dlg.dragItemHoverClasses_, |
| ['opacity_40', 'cursor_move'])); |
| assertTrue(goog.array.equals(dlg.dragItemHandleHoverClasses_, |
| ['opacity_40', 'cursor_pointer'])); |
| assertTrue(goog.array.equals(dlg.currDragItemClasses_, |
| ['blue_bg', 'opacity_40'])); |
| |
| assertFalse('Should have no cursor_move class after init', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_move')); |
| assertFalse('Should have no cursor_pointer class after init', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer')); |
| assertFalse('Should have no opacity_40 class after init', |
| goog.dom.classlist.contains(event.currentTarget, 'opacity_40')); |
| assertFalse('Should not have blue_bg class after init', |
| goog.dom.classlist.contains(event.currentTarget, 'blue_bg')); |
| } |
| |
| |
| /** |
| * Test the effect of hovering over a list. |
| * |
| * Check that after the MOUSEOVER browser event these classes are added to |
| * the current target of the event. |
| */ |
| function testAddDragItemHoverClasses() { |
| dlg.handleDragItemMouseover_(event); |
| |
| assertTrue('Should have cursor_move class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_move')); |
| assertTrue('Should have opacity_40 class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'opacity_40')); |
| assertFalse('Should not have cursor_pointer class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer')); |
| assertFalse('Should not have blue_bg class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'blue_bg')); |
| } |
| |
| function testAddDragItemHandleHoverClasses() { |
| dlg.handleDragItemHandleMouseover_(event); |
| |
| assertFalse('Should not have cursor_move class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_move')); |
| assertTrue('Should have opacity_40 class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'opacity_40')); |
| assertTrue('Should have cursor_pointer class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer')); |
| assertFalse('Should not have blue_bg class after MOUSEOVER', |
| goog.dom.classlist.contains(event.currentTarget, 'blue_bg')); |
| } |
| |
| |
| /** |
| * Test the effect of stopping hovering over a list. |
| * |
| * Check that after the MOUSEOUT browser event all CSS classes are removed |
| * from the target (as we are no longer hovering over the it). |
| */ |
| function testRemoveDragItemHoverClasses() { |
| dlg.handleDragItemMouseover_(event); |
| dlg.handleDragItemMouseout_(event); |
| |
| assertFalse('Should have no cursor_move class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_move')); |
| assertFalse('Should have no cursor_pointer class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer')); |
| assertFalse('Should have no opacity_40 class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'opacity_40')); |
| assertFalse('Should have no blue_bg class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'blue_bg')); |
| } |
| |
| function testRemoveDragItemHandleHoverClasses() { |
| dlg.handleDragItemHandleMouseover_(event); |
| dlg.handleDragItemHandleMouseout_(event); |
| |
| assertFalse('Should have no cursor_move class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_move')); |
| assertFalse('Should have no cursor_pointer class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer')); |
| assertFalse('Should have no opacity_40 class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'opacity_40')); |
| assertFalse('Should have no blue_bg class after MOUSEOUT', |
| goog.dom.classlist.contains(event.currentTarget, 'blue_bg')); |
| } |
| |
| |
| /** |
| * Test the effect of dragging an item. (DRAGSTART event.) |
| * |
| * Check that after the MOUSEDOWN browser event is handled by the |
| * handlePotentialDragStart_() method the currDragItem has the CSS classes |
| * set by the setter method. |
| */ |
| function testAddCurrentDragItemClasses() { |
| var be = new goog.events.BrowserEvent({ |
| type: goog.events.EventType.MOUSEDOWN, |
| button: goog.events.BrowserFeature.HAS_W3C_BUTTON ? 0 : 1 |
| }); |
| event.event_ = be; |
| |
| dlg.handlePotentialDragStart_(event); |
| |
| assertFalse('Should have no cursor_move class after MOUSEDOWN', |
| goog.dom.classlist.contains(dlg.currDragItem_, 'cursor_move')); |
| assertFalse('Should have no cursor_pointer class after MOUSEDOWN', |
| goog.dom.classlist.contains(dlg.currDragItem_, 'cursor_pointer')); |
| assertTrue('Should have opacity_40 class after MOUSEDOWN', |
| goog.dom.classlist.contains(dlg.currDragItem_, 'opacity_40')); |
| assertTrue('Should have blue_bg class after MOUSEDOWN', |
| goog.dom.classlist.contains(dlg.currDragItem_, 'blue_bg')); |
| } |
| |
| |
| /** |
| * Test the effect of dragging an item. (DRAGEND event.) |
| * |
| * Check that after the MOUSEUP browser event handled by the handleDragEnd_() |
| * method the currDragItem has no CSS classes set in the dispatched event. |
| */ |
| function testRemoveCurrentDragItemClasses() { |
| var be = new goog.events.BrowserEvent({ |
| type: goog.events.EventType.MOUSEDOWN, |
| button: goog.events.BrowserFeature.HAS_W3C_BUTTON ? 0 : 1 |
| }); |
| event.event_ = be; |
| dlg.handlePotentialDragStart_(event); |
| |
| // Need to catch the dispatched event because the temporary fields |
| // including dlg.currentDragItem_ are cleared after the dragging has ended. |
| var currDragItem = goog.dom.createDom( |
| 'div', ['cursor_move', 'blue_bg'], goog.dom.createTextNode('4')); |
| goog.events.listen(dlg, goog.fx.DragListGroup.EventType.DRAGEND, |
| function(e) {currDragItem = dlg.currDragItem_;}); |
| |
| var dragger = new goog.fx.Dragger(event.currentTarget); |
| be.type = goog.events.EventType.MOUSEUP; |
| be.clientX = 1; |
| be.clientY = 2; |
| var dragEvent = new goog.fx.DragEvent( |
| goog.fx.Dragger.EventType.END, dragger, be.clientX, be.clientY, be); |
| dlg.handleDragEnd_(dragEvent); // this method dispatches the DRAGEND event |
| dragger.dispose(); |
| |
| assertFalse('Should have no cursor_move class after MOUSEUP', |
| goog.dom.classlist.contains(currDragItem, 'cursor_move')); |
| assertFalse('Should have no cursor_pointer class after MOUSEUP', |
| goog.dom.classlist.contains(currDragItem, 'cursor_pointer')); |
| assertFalse('Should have no opacity_40 class after MOUSEUP', |
| goog.dom.classlist.contains(currDragItem, 'opacity_40')); |
| assertFalse('Should have no blue_bg class after MOUSEUP', |
| goog.dom.classlist.contains(currDragItem, 'blue_bg')); |
| } |
| |
| |
| /** |
| * Asserts that the DragListGroup is in idle state. |
| * @param {!goog.fx.DragListGroup} dlg The DragListGroup to examine. |
| */ |
| function assertIdle(dlg) { |
| assertNull('dragger element has been cleaned up', dlg.draggerEl_); |
| assertNull('dragger has been cleaned up', dlg.dragger_); |
| assertEquals('the additional event listeners have been removed', |
| initialListenerCount, goog.object.getCount(dlg.eventHandler_.keys_)); |
| } |
| |
| function testFiredEvents() { |
| goog.testing.events.fireClickSequence(list.firstChild); |
| assertArrayEquals('event types in case of zero distance dragging', [ |
| goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, |
| goog.fx.DragListGroup.EventType.DRAGSTART, |
| goog.fx.DragListGroup.EventType.BEFOREDRAGEND, |
| goog.fx.DragListGroup.EventType.DRAGEND |
| ], firedEventTypes); |
| assertIdle(dlg); |
| } |
| |
| function testFiredEventsWithHysteresis() { |
| dlg.setHysteresis(2); |
| |
| goog.testing.events.fireClickSequence(list.firstChild); |
| assertArrayEquals('no events fired on click if hysteresis is enabled', [], |
| firedEventTypes); |
| assertIdle(dlg); |
| |
| goog.testing.events.fireMouseDownEvent(list.firstChild, null, |
| new goog.math.Coordinate(0, 0)); |
| goog.testing.events.fireMouseMoveEvent(list.firstChild, |
| new goog.math.Coordinate(1, 0)); |
| assertArrayEquals('no events fired below hysteresis distance', [], |
| firedEventTypes); |
| |
| goog.testing.events.fireMouseMoveEvent(list.firstChild, |
| new goog.math.Coordinate(3, 0)); |
| assertArrayEquals('start+move events are fired over hysteresis distance', [ |
| goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, |
| goog.fx.DragListGroup.EventType.DRAGSTART, |
| goog.fx.DragListGroup.EventType.BEFOREDRAGMOVE, |
| goog.fx.DragListGroup.EventType.DRAGMOVE |
| ], firedEventTypes); |
| |
| firedEventTypes.length = 0; |
| goog.testing.events.fireMouseUpEvent(list.firstChild, null, |
| new goog.math.Coordinate(3, 0)); |
| assertArrayEquals('end events are fired on mouseup', [ |
| goog.fx.DragListGroup.EventType.BEFOREDRAGEND, |
| goog.fx.DragListGroup.EventType.DRAGEND |
| ], firedEventTypes); |
| assertIdle(dlg); |
| } |
| |
| function testPreventDefaultBeforeDragStart() { |
| goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, |
| goog.events.Event.preventDefault); |
| |
| goog.testing.events.fireMouseDownEvent(list.firstChild); |
| assertArrayEquals('event types if dragging is prevented', |
| [goog.fx.DragListGroup.EventType.BEFOREDRAGSTART], firedEventTypes); |
| assertIdle(dlg); |
| } |
| |
| function testPreventDefaultBeforeDragStartWithHysteresis() { |
| dlg.setHysteresis(5); |
| goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, |
| goog.events.Event.preventDefault); |
| |
| goog.testing.events.fireMouseDownEvent(list.firstChild, null, |
| new goog.math.Coordinate(0, 0)); |
| goog.testing.events.fireMouseMoveEvent(list.firstChild, |
| new goog.math.Coordinate(10, 0)); |
| assertArrayEquals('event types if dragging is prevented', |
| [goog.fx.DragListGroup.EventType.BEFOREDRAGSTART], firedEventTypes); |
| assertIdle(dlg); |
| } |
| |
| function testRightClick() { |
| goog.testing.events.fireMouseDownEvent(list.firstChild, |
| goog.events.BrowserEvent.MouseButton.RIGHT); |
| goog.testing.events.fireMouseUpEvent(list.firstChild, |
| goog.events.BrowserEvent.MouseButton.RIGHT); |
| |
| assertArrayEquals('no events fired', [], firedEventTypes); |
| assertIdle(dlg); |
| } |
| |
| |
| /** |
| * Tests that a new item can be added to a drag list after the control has |
| * been initialized. |
| */ |
| function testAddItemToDragList() { |
| var item = |
| goog.dom.createDom('div', null, goog.dom.createTextNode('newItem')); |
| |
| dlg.addItemToDragList(list, item); |
| |
| assertEquals(item, list.lastChild); |
| assertEquals(4, goog.dom.getChildren(list).length); |
| |
| goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, |
| goog.events.Event.preventDefault); |
| |
| goog.testing.events.fireMouseDownEvent(item); |
| assertTrue('Should fire beforedragstart event when clicked', |
| goog.array.equals([goog.fx.DragListGroup.EventType.BEFOREDRAGSTART], |
| firedEventTypes)); |
| } |
| |
| |
| /** |
| * Tests that a new item added to a drag list after the control has been |
| * initialized is inserted at the correct position. |
| */ |
| function testInsertItemInDragList() { |
| var item = |
| goog.dom.createDom('div', null, goog.dom.createTextNode('newItem')); |
| |
| dlg.addItemToDragList(list, item, 0); |
| |
| assertEquals(item, list.firstChild); |
| assertEquals(4, goog.dom.getChildren(list).length); |
| |
| goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, |
| goog.events.Event.preventDefault); |
| |
| goog.testing.events.fireMouseDownEvent(item); |
| assertTrue('Should fire beforedragstart event when clicked', |
| goog.array.equals([goog.fx.DragListGroup.EventType.BEFOREDRAGSTART], |
| firedEventTypes)); |
| } |