diff --git a/test/spec/ol/pointer/mousesource.test.js b/test/spec/ol/pointer/mousesource.test.js new file mode 100644 index 0000000000..9c12038585 --- /dev/null +++ b/test/spec/ol/pointer/mousesource.test.js @@ -0,0 +1,101 @@ +goog.provide('ol.test.pointer.MouseSource'); + +describe('ol.pointer.MouseSource', function() { + var handler; + var target; + var eventSpy; + var clock; + + beforeEach(function() { + clock = sinon.useFakeTimers(); + target = goog.dom.createElement(goog.dom.TagName.DIV); + + // make sure that a mouse and touch event source is used + ol.BrowserFeature.HAS_POINTER = false; + ol.BrowserFeature.HAS_MSPOINTER = false; + ol.BrowserFeature.HAS_TOUCH = true; + + handler = new ol.pointer.PointerEventHandler(target); + eventSpy = sinon.spy(); + }); + + afterEach(function() { + handler.dispose(); + }); + + describe('simulated mouse events', function() { + it('prevents simulated mouse events', function() { + goog.events.listen(handler, 'pointerdown', eventSpy); + + // simulates that a mouse event is triggered from a touch + simulateTouchEvent('touchstart', 10, 20); + simulateEvent('mousedown', 10, 20); + + expect(eventSpy.calledOnce).to.be.ok(); + + }); + + it('dispatches real mouse events', function() { + goog.events.listen(handler, 'pointerdown', eventSpy); + + // the two events are at different positions + simulateTouchEvent('touchstart', 10, 20); + simulateEvent('mousedown', 10, 40); + + expect(eventSpy.calledTwice).to.be.ok(); + }); + + it('dispatches real mouse events after timeout', function() { + // set the timeout to a lower value, to speed up the tests + var touchSource = handler.eventSourceList_[1]; + touchSource.DEDUP_TIMEOUT = 100; + + goog.events.listen(handler, 'pointerdown', eventSpy); + + // first simulate a touch event, then a mouse event + // at the same position after a timeout + simulateTouchEvent('touchstart', 10, 20); + clock.tick(150); + simulateEvent('mousedown', 10, 20); + + expect(eventSpy.calledTwice).to.be.ok(); + }); + }); + + function simulateTouchEvent(type, x, y) { + var touches = [ + { + identifier: 4, + clientX: x, + clientX: y, + target: target + } + ]; + + var event = new goog.events.BrowserEvent({ + type: type, + touches: touches, + changedTouches: touches + }); + goog.events.fireListeners(target, type, false, event); + } + + function simulateEvent(type, x, y) { + var event = new goog.events.BrowserEvent({ + type: type, + clientX: x, + clientY: y, + target: target + }); + goog.events.fireListeners(target, type, false, event); + } +}); + +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.events.BrowserEvent'); +goog.require('ol.BrowserFeature'); +goog.require('ol.pointer.MouseSource'); +goog.require('ol.pointer.PointerEvent'); +goog.require('ol.pointer.PointerEventHandler'); diff --git a/test/spec/ol/pointer/touchsource.test.js b/test/spec/ol/pointer/touchsource.test.js new file mode 100644 index 0000000000..580fc1cbd9 --- /dev/null +++ b/test/spec/ol/pointer/touchsource.test.js @@ -0,0 +1,138 @@ +goog.provide('ol.test.pointer.TouchSource'); + +describe('ol.pointer.TouchSource', function() { + var handler; + var target; + var eventSpy; + + beforeEach(function() { + target = goog.dom.createElement(goog.dom.TagName.DIV); + + // make sure that a mouse and touch event source is used + ol.BrowserFeature.HAS_POINTER = false; + ol.BrowserFeature.HAS_MSPOINTER = false; + ol.BrowserFeature.HAS_TOUCH = true; + + handler = new ol.pointer.PointerEventHandler(target); + eventSpy = sinon.spy(); + }); + + afterEach(function() { + handler.dispose(); + }); + + describe('pointer event creation', function() { + it('generates pointer events for each touch contact', function() { + goog.events.listen(handler, 'pointerdown', eventSpy); + + simulateTouchEvent('touchstart', [ + {identifier: 3, clientX: 10, clientY: 11}, + {identifier: 4, clientX: 30, clientY: 45} + ]); + + expect(eventSpy.calledTwice).to.be.ok(); + + // pointer event for the first touch contact + var pointerEvent1 = eventSpy.firstCall.args[0]; + expect(pointerEvent1.pointerId).to.be(5); + expect(pointerEvent1.pointerType).to.be('touch'); + expect(pointerEvent1.clientX).to.be(10); + expect(pointerEvent1.clientY).to.be(11); + + // pointer event for the second touch contact + var pointerEvent2 = eventSpy.secondCall.args[0]; + expect(pointerEvent2.pointerId).to.be(6); + expect(pointerEvent2.pointerType).to.be('touch'); + expect(pointerEvent2.clientX).to.be(30); + expect(pointerEvent2.clientY).to.be(45); + + expect(handler.pointerMap.getCount()).to.be(2); + }); + + it('creates the right pointer events', function() { + goog.events.listen(handler, 'pointerdown', eventSpy); + + // first touch + simulateTouchEvent('touchstart', [ + {identifier: 3, clientX: 10, clientY: 11} + ]); + expect(eventSpy.calledOnce).to.be.ok(); + expect(handler.pointerMap.getCount()).to.be(1); + + // second touch (first touch still down) + simulateTouchEvent('touchstart', [ + {identifier: 4, clientX: 30, clientY: 45} + ], [{identifier: 3}, {identifier: 4}] + ); + expect(eventSpy.calledTwice).to.be.ok(); + expect(handler.pointerMap.getCount()).to.be(2); + + // first touch moves + var moveEventSpy = sinon.spy(); + goog.events.listen(handler, 'pointermove', moveEventSpy); + + simulateTouchEvent('touchmove', [ + {identifier: 3, clientX: 15, clientY: 16} + ], [{identifier: 3}, {identifier: 4}] + ); + expect(moveEventSpy.calledOnce).to.be.ok(); + + // and then both touches go up + var upEventSpy = sinon.spy(); + goog.events.listen(handler, 'pointerup', upEventSpy); + + simulateTouchEvent('touchend', [ + {identifier: 3, clientX: 15, clientY: 16}, + {identifier: 4, clientX: 30, clientY: 45} + ], [{identifier: 3}, {identifier: 4}] + ); + expect(upEventSpy.calledTwice).to.be.ok(); + expect(handler.pointerMap.getCount()).to.be(0); + }); + + it('handles flawed touches', function() { + goog.events.listen(handler, 'pointerdown', eventSpy); + + // first touch + simulateTouchEvent('touchstart', [ + {identifier: 3, clientX: 10, clientY: 11} + ]); + expect(eventSpy.calledOnce).to.be.ok(); + expect(handler.pointerMap.getCount()).to.be(1); + + // second touch, but the first touch has disappeared + var cancelEventSpy = sinon.spy(); + goog.events.listen(handler, 'pointercancel', cancelEventSpy); + simulateTouchEvent('touchstart', [ + {identifier: 4, clientX: 30, clientY: 45} + ], [{identifier: 4}] + ); + expect(eventSpy.calledTwice).to.be.ok(); + + // the first (broken) touch is canceled + expect(cancelEventSpy.calledOnce).to.be.ok(); + expect(handler.pointerMap.getCount()).to.be(1); + }); + }); + + function simulateTouchEvent(type, changedTouches, touches) { + var touches = goog.isDef(touches) ? + touches : changedTouches; + + var event = new goog.events.BrowserEvent({ + type: type, + touches: touches, + changedTouches: changedTouches + }); + goog.events.fireListeners(target, type, false, event); + } +}); + +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.events.BrowserEvent'); +goog.require('ol.BrowserFeature'); +goog.require('ol.pointer.PointerEvent'); +goog.require('ol.pointer.PointerEventHandler'); +goog.require('ol.pointer.TouchSource');