// Copyright 2008 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.DraggerTest');
goog.setTestOnly('goog.fx.DraggerTest');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.Event');
goog.require('goog.events.EventType');
goog.require('goog.fx.Dragger');
goog.require('goog.math.Rect');
goog.require('goog.style.bidi');
goog.require('goog.testing.StrictMock');
goog.require('goog.testing.events');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent');
var HAS_SET_CAPTURE = goog.fx.Dragger.HAS_SET_CAPTURE_;
var target;
var targetRtl;
function setUp() {
var sandbox = goog.dom.getElement('sandbox');
target = goog.dom.createDom(goog.dom.TagName.DIV, {
'id': 'target',
'style': 'display:none;position:absolute;top:15px;left:10px'
});
sandbox.appendChild(target);
sandbox.appendChild(goog.dom.createDom(goog.dom.TagName.DIV, {id: 'handle'}));
var sandboxRtl = goog.dom.getElement('sandbox_rtl');
targetRtl = goog.dom.createDom(goog.dom.TagName.DIV, {
'id': 'target_rtl',
'style': 'position:absolute; top:15px; right:10px; width:10px; ' +
'height: 10px; background: green;'
});
sandboxRtl.appendChild(targetRtl);
sandboxRtl.appendChild(goog.dom.createDom(goog.dom.TagName.DIV, {
'id': 'background_rtl',
'style': 'width: 10000px;height:50px;position:absolute;color:blue;'
}));
sandboxRtl.appendChild(
goog.dom.createDom(goog.dom.TagName.DIV, {id: 'handle_rtl'}));
}
function tearDown() {
goog.dom.removeChildren(goog.dom.getElement('sandbox'));
goog.dom.removeChildren(goog.dom.getElement('sandbox_rtl'));
goog.events.removeAll(document);
}
function testStartDrag() {
runStartDragTest('handle', target);
}
function testStartDrag_rtl() {
runStartDragTest('handle_rtl', targetRtl);
}
function runStartDragTest(handleId, targetElement) {
var dragger =
new goog.fx.Dragger(targetElement, goog.dom.getElement(handleId));
if (handleId == 'handle_rtl') {
dragger.enableRightPositioningForRtl(true);
}
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEDOWN;
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(true);
e.preventDefault();
e.isMouseActionButton().$returns(true);
e.preventDefault();
e.$replay();
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function() {
targetElement.style.display = 'block';
});
dragger.startDrag(e);
assertTrue(
'Start drag with no hysteresis must actually start the drag.',
dragger.isDragging());
if (handleId == 'handle_rtl') {
assertEquals(10, goog.style.bidi.getOffsetStart(targetElement));
}
assertEquals(
'Dragger startX must match event\'s clientX.', 1, dragger.startX);
assertEquals(
'Dragger clientX must match event\'s clientX', 1, dragger.clientX);
assertEquals(
'Dragger startY must match event\'s clientY.', 2, dragger.startY);
assertEquals(
'Dragger clientY must match event\'s clientY', 2, dragger.clientY);
assertEquals(
'Dragger deltaX must match target\'s offsetLeft', 10, dragger.deltaX);
assertEquals(
'Dragger deltaY must match target\'s offsetTop', 15, dragger.deltaY);
dragger = new goog.fx.Dragger(targetElement, goog.dom.getElement(handleId));
dragger.setHysteresis(1);
dragger.startDrag(e);
assertFalse(
'Start drag with a valid non-zero hysteresis should not start ' +
'the drag.',
dragger.isDragging());
e.$verify();
}
/**
* @bug 1381317 Cancelling start drag didn't end the attempt to drag.
*/
function testStartDrag_Cancel() {
var dragger = new goog.fx.Dragger(target);
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEDOWN;
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(true);
e.$replay();
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
// Cancel drag.
e.preventDefault();
});
dragger.startDrag(e);
assertFalse('Start drag must have been cancelled.', dragger.isDragging());
assertFalse(
'Dragger must not have registered mousemove handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEMOVE,
!HAS_SET_CAPTURE));
assertFalse(
'Dragger must not have registered mouseup handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEUP, !HAS_SET_CAPTURE));
e.$verify();
}
/**
* Tests that start drag happens on left mousedown.
*/
function testStartDrag_LeftMouseDownOnly() {
var dragger = new goog.fx.Dragger(target);
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEDOWN;
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(false);
e.$replay();
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
fail('No drag START event should have been dispatched');
});
dragger.startDrag(e);
assertFalse('Start drag must have been cancelled.', dragger.isDragging());
assertFalse(
'Dragger must not have registered mousemove handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEMOVE, true));
assertFalse(
'Dragger must not have registered mouseup handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEUP, true));
e.$verify();
}
/**
* Tests that start drag happens on other event type than MOUSEDOWN.
*/
function testStartDrag_MouseMove() {
var dragger = new goog.fx.Dragger(target);
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEMOVE;
e.clientX = 1;
e.clientY = 2;
// preventDefault is not called.
e.$replay();
var startDragFired = false;
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
startDragFired = true;
});
dragger.startDrag(e);
assertTrue('Dragging should be in progress.', dragger.isDragging());
assertTrue('Start drag event should have fired.', startDragFired);
assertTrue(
'Dragger must have registered mousemove handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEMOVE,
!HAS_SET_CAPTURE));
assertTrue(
'Dragger must have registered mouseup handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEUP, !HAS_SET_CAPTURE));
e.$verify();
}
/**
* Tests that preventDefault is not called for TOUCHSTART event.
*/
function testStartDrag_TouchStart() {
var dragger = new goog.fx.Dragger(target);
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.TOUCHSTART;
// preventDefault is not called.
e.$replay();
var startDragFired = false;
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
startDragFired = true;
});
dragger.startDrag(e);
assertTrue('Dragging should be in progress.', dragger.isDragging());
assertTrue('Start drag event should have fired.', startDragFired);
assertTrue(
'Dragger must have registered touchstart listener.',
goog.events.hasListener(
dragger.handle, goog.events.EventType.TOUCHSTART, false /*opt_cap*/));
e.$verify();
}
/**
* Tests that preventDefault is not called for TOUCHSTART event when hysteresis
* is set to be greater than zero.
*/
function testStartDrag_TouchStart_NonZeroHysteresis() {
var dragger = new goog.fx.Dragger(target);
dragger.setHysteresis(5);
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.TOUCHSTART;
// preventDefault is not called.
e.$replay();
var startDragFired = false;
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
startDragFired = true;
});
dragger.startDrag(e);
assertFalse(
'Start drag must not start drag because of hysterisis.',
dragger.isDragging());
assertTrue(
'Dragger must have registered touchstart listener.',
goog.events.hasListener(
dragger.handle, goog.events.EventType.TOUCHSTART, false /*opt_cap*/));
e.$verify();
}
/**
* @bug 1381317 Cancelling start drag didn't end the attempt to drag.
*/
function testHandleMove_Cancel() {
var dragger = new goog.fx.Dragger(target);
dragger.setHysteresis(5);
goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
// Cancel drag.
e.preventDefault();
});
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(true).$anyTimes();
// preventDefault is not called.
e.$replay();
dragger.startDrag(e);
assertFalse(
'Start drag must not start drag because of hysterisis.',
dragger.isDragging());
assertTrue(
'Dragger must have registered mousemove handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEMOVE,
!HAS_SET_CAPTURE));
assertTrue(
'Dragger must have registered mouseup handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEUP, !HAS_SET_CAPTURE));
e.clientX = 10;
e.clientY = 10;
dragger.handleMove_(e);
assertFalse('Drag must be cancelled.', dragger.isDragging());
assertFalse(
'Dragger must unregistered mousemove handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEMOVE, true));
assertFalse(
'Dragger must unregistered mouseup handlers.',
goog.events.hasListener(
dragger.document_, goog.events.EventType.MOUSEUP, true));
e.$verify();
}
/**
* @bug 1714667 IE<9 built in drag and drop handling stops dragging.
*/
function testIeDragStartCancelling() {
// Testing only IE<9.
if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(9)) {
return;
}
// Built in 'dragstart' cancelling not enabled.
var dragger = new goog.fx.Dragger(target);
var e = new goog.events.Event(goog.events.EventType.MOUSEDOWN);
e.clientX = 1;
e.clientY = 2;
e.button = 1; // IE only constant for left button.
var be = new goog.events.BrowserEvent(e);
dragger.startDrag(be);
assertTrue('The drag should have started.', dragger.isDragging());
e = new goog.events.Event(goog.events.EventType.DRAGSTART);
e.target = dragger.document_.documentElement;
assertTrue(
'The event should not be canceled.',
goog.testing.events.fireBrowserEvent(e));
dragger.dispose();
// Built in 'dragstart' cancelling enabled.
dragger = new goog.fx.Dragger(target);
dragger.setCancelIeDragStart(true);
e = new goog.events.Event(goog.events.EventType.MOUSEDOWN);
e.clientX = 1;
e.clientY = 2;
e.button = 1; // IE only constant for left button.
be = new goog.events.BrowserEvent(e);
dragger.startDrag(be);
assertTrue('The drag should have started.', dragger.isDragging());
e = new goog.events.Event(goog.events.EventType.DRAGSTART);
e.target = dragger.document_.documentElement;
assertFalse(
'The event should be canceled.', goog.testing.events.fireBrowserEvent(e));
dragger.dispose();
}
function testPreventMouseDown() {
var dragger = new goog.fx.Dragger(target);
dragger.setPreventMouseDown(false);
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEDOWN;
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(true);
// preventDefault is not called.
e.$replay();
dragger.startDrag(e);
assertTrue('Dragging should be in progess.', dragger.isDragging());
e.$verify();
}
function testLimits() {
var dragger = new goog.fx.Dragger(target);
assertEquals(100, dragger.limitX(100));
assertEquals(100, dragger.limitY(100));
dragger.setLimits(new goog.math.Rect(10, 20, 30, 40));
assertEquals(10, dragger.limitX(0));
assertEquals(40, dragger.limitX(100));
assertEquals(20, dragger.limitY(0));
assertEquals(60, dragger.limitY(100));
}
function testWindowBlur() {
if (!goog.fx.Dragger.HAS_SET_CAPTURE_) {
var dragger = new goog.fx.Dragger(target);
var dragEnded = false;
goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
dragEnded = true;
});
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEDOWN;
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(true);
e.preventDefault();
e.$replay();
dragger.startDrag(e);
e.$verify();
assertTrue(dragger.isDragging());
e = new goog.events.BrowserEvent();
e.type = goog.events.EventType.BLUR;
e.target = window;
e.currentTarget = window;
goog.testing.events.fireBrowserEvent(e);
assertTrue(dragEnded);
}
}
function testBlur() {
if (!goog.fx.Dragger.HAS_SET_CAPTURE_) {
var dragger = new goog.fx.Dragger(target);
var dragEnded = false;
goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
dragEnded = true;
});
var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
e.type = goog.events.EventType.MOUSEDOWN;
e.clientX = 1;
e.clientY = 2;
e.isMouseActionButton().$returns(true);
e.preventDefault();
e.$replay();
dragger.startDrag(e);
e.$verify();
assertTrue(dragger.isDragging());
e = new goog.events.BrowserEvent();
e.type = goog.events.EventType.BLUR;
e.target = document.body;
e.currentTarget = document.body;
// Blur events do not bubble but the test event system does not emulate that
// part so we add a capturing listener on the target and stops the
// propagation at the target, preventing any event from bubbling.
goog.events.listen(document.body, goog.events.EventType.BLUR, function(e) {
e.propagationStopped_ = true;
}, true);
goog.testing.events.fireBrowserEvent(e);
assertFalse(dragEnded);
}
}
function testCloneNode() {
var element = goog.dom.createDom(goog.dom.TagName.DIV);
element.innerHTML = '' +
'' +
'';
element.childNodes[0].value = '\'new\'\n"value"';
element.childNodes[1].value = '<' +
'/textarea><3';
element.childNodes[2].value = '