angular-material-npfixed
Version:
The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M
692 lines (585 loc) • 21.8 kB
JavaScript
describe('$mdGesture', function() {
beforeEach(module('material.core', function() {
angular.element(document).triggerHandler('$$mdGestureReset');
}));
describe('custom gesture', function() {
var startSpy1, moveSpy1, endSpy1;
var startSpy2, moveSpy2, endSpy2;
var childEl, middleEl, parentEl;
beforeEach(function() {
inject(function($mdGesture) {
startSpy1 = jasmine.createSpy('start1');
moveSpy1 = jasmine.createSpy('move1');
endSpy1 = jasmine.createSpy('end1');
startSpy2 = jasmine.createSpy('start2');
moveSpy2 = jasmine.createSpy('move2');
endSpy2 = jasmine.createSpy('end2');
$mdGesture.handler('gesture1', {
options: {
defaultKey: 'defaultVal'
},
onStart: startSpy1,
onMove: moveSpy1,
onEnd: endSpy1
});
$mdGesture.handler('gesture2', {
onStart: startSpy2,
onMove: moveSpy2,
onEnd: endSpy2
});
childEl = angular.element('<child>');
middleEl = angular.element('<middle>').append(childEl);
parentEl = angular.element('<parent>').append(middleEl);
});
});
it('should pass provided options', inject(function($document, $mdGesture) {
$mdGesture.register(childEl, 'gesture1', { optKey: 'optValue' });
startSpy1.and.callFake(function() {
return {
isRunning: true,
options: {
optKey: 'optValue',
defaultKey: 'defaultVal'
},
registeredParent: childEl[0]
};
});
$document.triggerHandler({
type: 'touchstart',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
expect(startSpy2).toHaveBeenCalled();
}));
it('touch{start,move,end,cancel}', inject(function($document) {
$document.triggerHandler({
type: 'touchstart',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
$document.triggerHandler('touchmove');
expect(moveSpy1).toHaveBeenCalled();
$document.triggerHandler('touchend');
expect(endSpy1).toHaveBeenCalled();
startSpy1.calls.reset();
moveSpy1.calls.reset();
endSpy1.calls.reset();
$document.triggerHandler({
type: 'touchstart',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
$document.triggerHandler('touchmove');
expect(moveSpy1).toHaveBeenCalled();
$document.triggerHandler('touchcancel');
expect(endSpy1).toHaveBeenCalled();
}));
it('gesture{down,move,up,cancel}', inject(function($document) {
$document.triggerHandler({
type: 'pointerdown',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
$document.triggerHandler('pointermove');
expect(moveSpy1).toHaveBeenCalled();
$document.triggerHandler('pointerup');
expect(endSpy1).toHaveBeenCalled();
startSpy1.calls.reset();
moveSpy1.calls.reset();
endSpy1.calls.reset();
$document.triggerHandler({
type: 'pointerdown',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
$document.triggerHandler('pointermove');
expect(moveSpy1).toHaveBeenCalled();
$document.triggerHandler('pointercancel');
expect(endSpy1).toHaveBeenCalled();
}));
it('mouse{down,move,up,leave}', inject(function($document) {
$document.triggerHandler({
type: 'mousedown',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
$document.triggerHandler('mousemove');
expect(moveSpy1).toHaveBeenCalled();
$document.triggerHandler('mouseup');
expect(endSpy1).toHaveBeenCalled();
startSpy1.calls.reset();
moveSpy1.calls.reset();
endSpy1.calls.reset();
$document.triggerHandler({
type: 'mousedown',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
$document.triggerHandler('mousemove');
expect(moveSpy1).toHaveBeenCalled();
$document.triggerHandler('mouseleave');
expect(endSpy1).toHaveBeenCalled();
}));
it('should not call start on an event with different type if <400ms have passed', inject(function($document) {
var now = 0;
spyOn(Date, 'now').and.callFake(function() { return now; });
$document.triggerHandler({
type: 'touchstart',
target: childEl[0]
});
$document.triggerHandler('touchmove');
$document.triggerHandler('touchend');
startSpy1.calls.reset();
$document.triggerHandler({
type: 'mousedown',
target: childEl[0]
});
expect(startSpy1).not.toHaveBeenCalled();
now = 1500;
$document.triggerHandler({
type: 'mousedown',
target: childEl[0]
});
expect(startSpy1).toHaveBeenCalled();
}));
});
describe('click', function() {
// Click tests should only be enabled when `$$hijackClicks == true` (for mobile)
it('should click if distance < options.maxDistance', inject(function($document, $mdGesture) {
if ( $mdGesture.$$hijackClicks ) {
var spy = jasmine.createSpy('click');
var el = angular.element('<div>');
el.on('click', spy);
expect(spy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchstart',
target: el[0],
touches: [{pageX: 100, pageY: 100 }]
});
expect(spy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchend',
target: el[0],
touches: [{pageX: 97, pageY: 102 }]
});
expect(spy).toHaveBeenCalled();
}
}));
it('should not click if distance > options.maxDistance', inject(function($mdGesture, $document) {
if ( $mdGesture.$$hijackClicks ) {
var spy = jasmine.createSpy('click');
var el = angular.element('<div>');
el.on('click', spy);
$document.triggerHandler({
type: 'touchstart',
target: el[0],
touches: [{pageX: 100, pageY: 100 }]
});
expect(spy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchend',
target: el[0],
touches: [{pageX: 90, pageY: 110 }]
});
expect(spy).not.toHaveBeenCalled();
}
}));
});
describe('press', function() {
beforeEach(function() {
// Make sure `unexpected` prototype/inherited methods do not impact gestures
Object.prototype.test123 = function(x) { };
});
afterEach(function() {
delete Object.prototype.test123;
});
it('should pressdown/up on touchstart/end', inject(function($mdGesture, $document) {
var downSpy = jasmine.createSpy('pressdown');
var upSpy = jasmine.createSpy('pressup');
var el = angular.element('<div>');
el.on('$md.pressdown', downSpy)
.on('$md.pressup', upSpy);
$document.triggerHandler({
type: 'touchstart',
target: el[0]
});
expect(downSpy).toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
downSpy.calls.reset();
$document.triggerHandler({
type: 'touchmove',
target: el[0]
});
expect(downSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchend',
target: el[0]
});
expect(downSpy).not.toHaveBeenCalled();
expect(upSpy).toHaveBeenCalled();
}));
});
describe('hold', function() {
it('should call hold after options number of ms', inject(function($mdGesture, $document, $timeout) {
var holdSpy = jasmine.createSpy('hold');
var el = angular.element('<div>');
$mdGesture.register(el, 'hold', {
delay: 333
});
el.on('$md.hold', holdSpy);
$document.triggerHandler({
type: 'touchstart',
target: el[0]
});
// Make sure the timeout was set to exactly 333
$timeout.flush(332);
expect(holdSpy).not.toHaveBeenCalled();
$timeout.flush(1);
expect(holdSpy).toHaveBeenCalled();
$timeout.verifyNoPendingTasks();
}));
it('should reset timeout if moving > options.maxDistance', inject(function($mdGesture, $document, $timeout) {
var holdSpy = jasmine.createSpy('hold');
var el = angular.element('<div>');
$mdGesture.register(el, 'hold', {
delay: 333,
maxDistance: 10
});
// Setup our spies and trigger our first action (touchstart)
el.on('$md.hold', holdSpy);
spyOn($timeout, 'cancel').and.callThrough();
$document.triggerHandler({
type: 'touchstart',
target: el[0],
touches: [{pageX: 100, pageY: 100}]
});
// The $md.hold spy should NOT have been called since the user has not lifted their finger
expect(holdSpy).not.toHaveBeenCalled();
// Reset calls to $timeout.cancel so that we can ensure (below) that it is called and
// trigger our second action (touchmove)
$timeout.cancel.calls.reset();
$document.triggerHandler({
type: 'touchmove',
target: el[0],
touches: [{pageX: 90, pageY: 90}]
});
// Because the user moves their finger instead of lifting, expect cancel to have been called
// and the $md.hold spy NOT to have been called
expect($timeout.cancel).toHaveBeenCalled();
expect(holdSpy).not.toHaveBeenCalled();
// We originally also called `$timeout.verifyNoPendingTasks();` here, however, changes made to
// $timeout.cancel() in 1.6 adds more tasks to the deferredQueue, so this will fail.
}));
it('should not reset timeout if moving < options.maxDistance', inject(function($mdGesture, $document, $timeout) {
var holdSpy = jasmine.createSpy('hold');
var el = angular.element('<div>');
$mdGesture.register(el, 'hold', {
delay: 333,
maxDistance: 10
});
el.on('$md.hold', holdSpy);
$document.triggerHandler({
type: 'touchstart',
target: el[0],
touches: [{pageX: 100, pageY: 100}]
});
spyOn($timeout, 'cancel');
expect(holdSpy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchmove',
target: el[0],
touches: [{pageX: 96, pageY: 96}]
});
expect(holdSpy).not.toHaveBeenCalled();
expect($timeout.cancel).not.toHaveBeenCalled();
$timeout.flush(333);
expect(holdSpy).toHaveBeenCalled();
$timeout.verifyNoPendingTasks();
}));
});
describe('drag', function() {
var startDragSpy, el, dragSpy, endDragSpy, doc;
beforeEach(function() {
inject(function($mdGesture, $document) {
doc = $document;
startDragSpy = jasmine.createSpy('dragstart');
dragSpy = jasmine.createSpy('drag');
endDragSpy = jasmine.createSpy('dragend');
el = angular.element('<div>');
$mdGesture.register(el, 'drag');
el.on('$md.dragstart', startDragSpy)
.on('$md.drag' , dragSpy)
.on('$md.dragend' , endDragSpy);
});
});
it('should only start after distanceX > minDistance', inject(function($mdGesture, $document) {
doc.triggerHandler({
type: 'touchstart',
target: el[0],
touches: [{pageX: 100, pageY: 100}]
});
expect(startDragSpy).not.toHaveBeenCalled();
expect(dragSpy).not.toHaveBeenCalled();
expect(endDragSpy).not.toHaveBeenCalled();
// Move 5 distanceX, no trigger
doc.triggerHandler({
type: 'touchmove',
target: el[0],
touches: [{pageX: 95, pageY: 100}]
});
expect(startDragSpy).not.toHaveBeenCalled();
expect(dragSpy).not.toHaveBeenCalled();
expect(endDragSpy).not.toHaveBeenCalled();
// Move 11 distanceX, trigger
doc.triggerHandler({
type: 'touchmove',
target: el[0],
touches: [{pageX: 89, pageY: 100}]
});
expect(startDragSpy).toHaveBeenCalled();
expect(startDragSpy.calls.mostRecent().args[0].pointer).toHaveFields({
startX: 89,
startY: 100,
x: 89,
y: 100,
distanceX: 0
});
expect(endDragSpy).not.toHaveBeenCalled();
startDragSpy.calls.reset();
doc.triggerHandler({
type: 'touchmove',
target: el[0],
touches: [{pageX: 90, pageY: 99}]
});
expect(startDragSpy).not.toHaveBeenCalled();
expect(dragSpy).toHaveBeenCalled();
expect(endDragSpy).not.toHaveBeenCalled();
dragSpy.calls.reset();
doc.triggerHandler({
type: 'touchend',
target: el[0],
changedTouches: [{pageX: 200, pageY: 0}]
});
expect(startDragSpy).not.toHaveBeenCalled();
expect(dragSpy).not.toHaveBeenCalled();
expect(endDragSpy).toHaveBeenCalled();
var pointer = endDragSpy.calls.mostRecent().args[0].pointer;
expect(pointer).toHaveFields({
distanceX: 111,
distanceY: -100,
x: 200,
y: 0
});
}));
});
describe('swipe', function() {
var now;
var leftSpy;
var rightSpy;
var upSpy;
var downSpy;
var el;
beforeEach(function () {
now = 0;
spyOn(Date, 'now').and.callFake(function() { return now; });
leftSpy = jasmine.createSpy('left');
rightSpy = jasmine.createSpy('right');
upSpy = jasmine.createSpy('up');
downSpy = jasmine.createSpy('down');
el = angular.element('<div>');
el.on('$md.swipeleft', leftSpy)
.on('$md.swiperight', rightSpy)
.on('$md.swipeup', upSpy)
.on('$md.swipedown', downSpy);
});
it('should swipeleft if velocityX > minVelocity and distanceX > maxDistance', inject(function($mdGesture, $document) {
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
now = 1;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: -100, pageY: 0
});
expect(leftSpy).toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
var pointer = leftSpy.calls.mostRecent().args[0].pointer;
expect(pointer.velocityX).toBe(-100);
expect(pointer.distanceX).toBe(-100);
}));
it('should swiperight if velocityX > minVelocity and distanceX > maxDistance', inject(function($mdGesture, $document) {
$document.triggerHandler('$$mdGestureReset');
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
now = 1;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 100, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
var pointer = rightSpy.calls.mostRecent().args[0].pointer;
expect(pointer.velocityX).toBe(100);
expect(pointer.distanceX).toBe(100);
}));
it('should swipeup if velocityY > minVelocity and distanceY > maxDistance', inject(function($mdGesture, $document) {
$document.triggerHandler('$$mdGestureReset');
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
now = 1;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 0, pageY: -100
});
expect(upSpy).toHaveBeenCalled();
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
var pointer = upSpy.calls.mostRecent().args[0].pointer;
expect(pointer.velocityY).toBe(-100);
expect(pointer.distanceY).toBe(-100);
}));
it('should swipedown if velocityY > minVelocity and distanceY > maxDistance', inject(function($mdGesture, $document) {
$document.triggerHandler('$$mdGestureReset');
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
now = 1;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 0, pageY: 100
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).toHaveBeenCalled();
var pointer = downSpy.calls.mostRecent().args[0].pointer;
expect(pointer.velocityY).toBe(100);
expect(pointer.distanceY).toBe(100);
}));
it('should not swipeleft when velocity is too low', inject(function($document) {
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
// 100ms and 50 distance = velocity of 0.5, below the boundary. no swipe.
now = 100;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: -50, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
// 101ms and 100 distance = velocity of 1.0001, just fast enough for a swipe.
now = 101;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: -100, pageY: 0
});
expect(leftSpy).toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
}));
it('should not swiperight when distance is too low', inject(function($document) {
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
now = 1;
//10 distance = boundary. no swipe.
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 10, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
//11 distance = enough. swipe.
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 11, pageY: 0
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
}));
it('should not swipeup when velocity is too low', inject(function($document) {
$document.triggerHandler('$$mdGestureReset');
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
// 100ms and 50 distance = velocity of 0.5, below the boundary. no swipe.
now = 100;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 0, pageY: -50
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
// 101ms and 100 distance = velocity of 1.0001, just fast enough for a swipe.
now = 101;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 0, pageY: -100
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
}));
it('should not swipedown when velocity is too low', inject(function($document) {
$document.triggerHandler('$$mdGestureReset');
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
// 100ms and 50 distance = velocity of 0.5, below the boundary. no swipe.
now = 100;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 0, pageY: 50
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).not.toHaveBeenCalled();
$document.triggerHandler({
type: 'touchstart', target: el[0], pageX: 0, pageY: 0
});
// 101ms and 100 distance = velocity of 1.0001, just fast enough for a swipe.
now = 101;
$document.triggerHandler({
type: 'touchend', target: el[0], pageX: 0, pageY: 100
});
expect(leftSpy).not.toHaveBeenCalled();
expect(rightSpy).not.toHaveBeenCalled();
expect(upSpy).not.toHaveBeenCalled();
expect(downSpy).toHaveBeenCalled();
}));
});
});