angular-snapscroll
Version:
Vertical scroll-and-snap functionality in angular
1,487 lines (1,414 loc) • 169 kB
JavaScript
describe('Directive: snapscroll', function () {
var $compile,
$scope,
scrollMock = {},
defaultSnapscrollScrollEasingMock = jasmine.createSpy('easing');
beforeEach(module('snapscroll'));
beforeEach(module(function ($provide) {
$provide.value('scrollie', scrollMock);
$provide.value('defaultSnapscrollScrollEasing', defaultSnapscrollScrollEasingMock);
}));
beforeEach(inject(function (_$compile_, _$rootScope_) {
$compile = _$compile_;
$scope = _$rootScope_.$new();
}));
afterEach(function () {
angular.element(document).find('body').empty();
});
function compileElement(html, appendToBody) {
var body,
element = angular.element(html);
if (!angular.isDefined(appendToBody)) {
appendToBody = false;
}
if (appendToBody) {
body = angular.element(document).find('body');
body.append(element);
}
element = $compile(element)($scope);
$scope.$digest();
return element;
}
function testBeforeSnap(html) {
var test = 0;
$scope.beforeSnap = function () {
test = 1;
};
compileElement(html, true);
$scope.snapIndex = 1;
$scope.$apply();
expect(test).toBe(1);
}
function testExecutesBeforeSnapOnInitialSnap(html) {
var test = 0;
$scope.beforeSnap = function () {
test = 1;
};
compileElement(html, true);
expect(test).toBe(1);
}
function testCorrectSnapIndexPassedToBeforeSnap(html) {
var spy = jasmine.createSpy('beforeSnap');
$scope.snapIndex = 0;
$scope.beforeSnap = spy;
compileElement(html, true);
$scope.snapIndex = 1;
$scope.$apply();
var calls = spy.calls.all();
expect(calls[0].args).toEqual([0]);
expect(calls[1].args).toEqual([1]);
}
function testAllowsPreventingSnapping(html) {
var prevent,
test = 0;
$scope.beforeSnap = function () {
if (prevent) {
return false;
}
test += 1;
};
expect(test).toBe(0);
compileElement(html, true);
expect(test).toBe(1);
$scope.$apply(function () {
$scope.snapIndex = 1;
});
expect(test).toBe(2);
prevent = true;
$scope.$apply(function () {
$scope.snapIndex = 0;
});
expect($scope.snapIndex).toBe(1);
expect(test).toBe(2);
}
function testAllowsSnappingToADifferentSnapIndex(html) {
var snapIndexOverride;
$scope.beforeSnap = function () {
if (snapIndexOverride) {
return snapIndexOverride;
}
};
compileElement(html, true);
expect($scope.snapIndex).toBe(0);
snapIndexOverride = 2;
$scope.$apply(function () {
$scope.snapIndex = 1;
});
expect($scope.snapIndex).toBe(2);
}
function testIgnoresSnapIndexOverrideIfNotANumber(html) {
var snapIndexOverride;
$scope.beforeSnap = function () {
if (snapIndexOverride !== undefined) {
return snapIndexOverride;
}
};
compileElement(html, true);
expect($scope.snapIndex).toBe(0);
snapIndexOverride = 'meh';
$scope.$apply(function () {
$scope.snapIndex = 1;
});
snapIndexOverride = NaN;
$scope.$apply(function () {
$scope.snapIndex = 0;
});
expect($scope.snapIndex).toBe(0);
}
function testIgnoresInvalidSnapIndexOverride(html) {
var snapIndexOverride;
$scope.beforeSnap = function () {
if (snapIndexOverride) {
return snapIndexOverride;
}
};
compileElement(html, true);
expect($scope.snapIndex).toBe(0);
snapIndexOverride = 10;
$scope.$apply(function () {
$scope.snapIndex = 1;
});
expect($scope.snapIndex).toBe(1);
}
function testResetsSnapIndexIfSnappingPrevented(html) {
var prevent = false;
$scope.beforeSnap = function () {
if (prevent) {
return false;
}
};
compileElement(html, true);
$scope.snapIndex = 1;
$scope.$apply();
expect($scope.snapIndex).toBe(1);
prevent = true;
$scope.snapIndex = 2;
$scope.$apply();
expect($scope.snapIndex).toBe(1);
}
function testAfterSnap(html) {
var test = 0;
$scope.afterSnap = function () {
test = 1;
};
compileElement(html, true);
$scope.snapIndex = 1;
$scope.$apply();
expect(test).toBe(1);
}
function testExecutesAfterSnapOnInitialSnap(html) {
var test = 0;
$scope.afterSnap = function () {
test = 1;
};
compileElement(html, true);
expect(test).toBe(1);
}
function testCorrectSnapIndexPassedToAfterSnap(html) {
var spy = jasmine.createSpy('afterSnap');
$scope.snapIndex = 0;
$scope.afterSnap = spy;
compileElement(html, true);
$scope.snapIndex = 1;
$scope.$apply();
var calls = spy.calls.all();
expect(calls[0].args).toEqual([0]);
expect(calls[1].args).toEqual([1]);
}
function triggerThreeMousewheelEvents(element, preventDefault) {
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120,
preventDefault: preventDefault
}); // mousewheel down
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120,
preventDefault: preventDefault
}); // mousewheel up
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120,
preventDefault: preventDefault
}); // mousewheel down
}
function testPreventsNormalScrollingUsingMousewheel(html) {
var element,
preventDefault = jasmine.createSpy('preventDefault');
element = compileElement(html, true);
triggerThreeMousewheelEvents(element, preventDefault);
expect(preventDefault).toHaveBeenCalled();
expect(preventDefault.calls.count()).toBe(3);
}
function testAllowsNormalScrollingUsingMousewheelWhenDisabled(html) {
var element,
preventDefault = jasmine.createSpy('preventDefault');
element = compileElement(html, true);
triggerThreeMousewheelEvents(element, preventDefault);
expect(preventDefault).not.toHaveBeenCalled();
}
function testPreventsNormalScrollingUsingMousewheelWhenReEnabled(html) {
var element,
preventDefault = jasmine.createSpy('preventDefault');
$scope.enabled = false;
element = compileElement(html, true);
triggerThreeMousewheelEvents(element, preventDefault);
expect(preventDefault).not.toHaveBeenCalled();
$scope.$apply(function () {
$scope.enabled = true;
});
triggerThreeMousewheelEvents(element, preventDefault);
expect(preventDefault).toHaveBeenCalled();
expect(preventDefault.calls.count()).toBe(3);
}
function testPreventsBubblingUpOfMousewheelEventsIfElementIsStillScrollable(html) {
var stopPropagation = jasmine.createSpy('stopPropagation');
var element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120,
stopPropagation: stopPropagation
}); // try to snap up
expect(stopPropagation).not.toHaveBeenCalled();
$scope.$apply(function () {
$scope.index = 2;
});
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120,
stopPropagation: stopPropagation
}); // try to snap down
expect(stopPropagation).not.toHaveBeenCalled();
$scope.$apply(function () {
$scope.index = 1;
});
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120,
stopPropagation: stopPropagation
}); // try to snap up
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120,
stopPropagation: stopPropagation
}); // then down
expect(stopPropagation).toHaveBeenCalled();
expect(stopPropagation.calls.count()).toBe(2);
}
function testSnapsDownOnMousewheelDown(html, $timeout) {
var element;
element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(100);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(3);
expect(element[0].scrollTop).toBe(150);
}
function testDoesntSnapDownIfElementIsNotScrollable(html) {
var element;
element = compileElement(html, true);
expect($scope.index).toBeUndefined();
expect(element[0].scrollTop).toBe(0);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBeUndefined();
expect(element[0].scrollTop).toBe(0);
}
function testSnapsUpOnMousewheelUp(html, $timeout) {
var element;
$scope.index = 3;
element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(100);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
}
function testDoesntSnapUpIfElementIsNotScrollable(html) {
var element;
element = compileElement(html, true);
expect($scope.index).toBeUndefined();
expect(element[0].scrollTop).toBe(0);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBeUndefined();
expect(element[0].scrollTop).toBe(0);
}
function testExecutesBeforeSnapOnMousewheelDown(html, $timeout) {
var spy = jasmine.createSpy('beforeSnap');
$scope.beforeSnap = spy;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(0); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1);
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(2);
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(3);
spy.calls.reset();
}
function testCallsBeforeSnapOnMousewheelDownWithWheelEvent(html, $timeout) {
var spy = jasmine.createSpy('beforeSnap');
$scope.beforeSnap = spy;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(0, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(2, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(3, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
}
function testCallsAfterSnapOnMousewheelDownWithWheelEvent(html, $timeout) {
var spy = jasmine.createSpy('afterSnap');
$scope.afterSnap = spy;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(0, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(2, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(3, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
}
function testCallsBeforeSnapOnMousewheelDownWithWheelEventOnlyWhenAvailable(html, $timeout) {
var spy = jasmine.createSpy('beforeSnap');
$scope.beforeSnap = spy;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(0, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
$scope.$apply(function () {
$scope.index = 2;
});
expect(spy).toHaveBeenCalledWith(2, undefined);
}
function testCallsAfterSnapOnMousewheelDownWithWheelEventOnlyWhenAvailable(html, $timeout) {
var spy = jasmine.createSpy('afterSnap');
$scope.afterSnap = spy;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(0, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1, jasmine.objectContaining({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
$scope.$apply(function () {
$scope.index = 2;
});
expect(spy).toHaveBeenCalledWith(2, undefined);
}
function testExecutesBeforeSnapOnMousewheelUp(html, $timeout) {
var spy = jasmine.createSpy('beforeSnap');
$scope.beforeSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(3); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2);
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(1);
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(0);
spy.calls.reset();
}
function testCallsBeforeSnapOnMousewheelUpWithWheelEvent(html, $timeout) {
var spy = jasmine.createSpy('beforeSnap');
$scope.beforeSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(3, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(1, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(0, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
}
function testCallsAfterSnapOnMousewheelUpWithWheelEvent(html, $timeout) {
var spy = jasmine.createSpy('afterSnap');
$scope.afterSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(3, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(1, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).not.toHaveBeenCalled(); // index still 1
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(0, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
}
function testCallsBeforeSnapOnMousewheelUpWithWheelEventOnlyWhenAvailable(html, $timeout) {
var spy = jasmine.createSpy('beforeSnap');
$scope.beforeSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(3, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
$scope.$apply(function () {
$scope.index = 1;
});
expect(spy).toHaveBeenCalledWith(1, undefined);
}
function testCallsAfterSnapOnMousewheelUpWithWheelEventOnlyWhenAvailable(html, $timeout) {
var spy = jasmine.createSpy('afterSnap');
$scope.afterSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
expect(spy).toHaveBeenCalledWith(3, undefined); // initial snap
spy.calls.reset();
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2, jasmine.objectContaining({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
}));
spy.calls.reset();
$timeout.flush(); // flush the timeout on preventDown
$scope.$apply(function () {
$scope.index = 1;
});
expect(spy).toHaveBeenCalledWith(1, undefined);
}
function testDoesNotSnapDownIfBeforeSnapReturnsFalseOnMousewheelDown(html) {
var spy = jasmine.createSpy('beforeSnap').and.callFake(function (snapIndex) {
if (snapIndex === 1) {
return false;
}
});
$scope.beforeSnap = spy;
var element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1);
expect($scope.index).toBe(0);
}
function testDoesNotSnapUpIfBeforeSnapReturnsFalseOnMousewheelUp(html) {
var spy = jasmine.createSpy('beforeSnap').and.callFake(function (snapIndex) {
if (snapIndex === 2) {
return false;
}
});
$scope.beforeSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2);
expect($scope.index).toBe(3);
}
function testSnapsToADifferentSnapIndexIfBeforeSnapReturnsNumberOnMousewheelDown(html) {
var spy = jasmine.createSpy('beforeSnap').and.callFake(function (snapIndex) {
if (snapIndex === 1) {
return 2;
}
});
$scope.beforeSnap = spy;
var element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect(spy).toHaveBeenCalledWith(1);
expect($scope.index).toBe(2);
}
function testSnapsToADifferentSnapIndexIfBeforeSnapReturnsNumberOnMousewheelUp(html) {
var spy = jasmine.createSpy('beforeSnap').and.callFake(function (snapIndex) {
if (snapIndex === 2) {
return 1;
}
});
$scope.beforeSnap = spy;
$scope.index = 3;
var element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect(spy).toHaveBeenCalledWith(2);
expect($scope.index).toBe(1);
}
function testShowsRestOfBigSnapOnMousewheelDown(html, $timeout) {
var element;
element = compileElement(html, true);
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(100);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(125);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(175);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(3);
expect(element[0].scrollTop).toBe(225);
}
function testShowsRestOfBigSnapOnMousewheelUp(html, $timeout) {
var element;
$scope.index = 3;
element = compileElement(html, true);
expect($scope.index).toBe(3);
expect(element[0].scrollTop).toBe(225);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(175);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(125);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(75);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
}
function testDoesntSnapDownOnNewDownMousewheelIfAlreadyScrolledToBottom(html) {
var element;
$scope.index = 3;
element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(3);
expect(element[0].scrollTop).toBe(150);
// try to wheel up then..
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(100);
}
function testDoesntSnapUpOnNewDownMousewheelIfAlreadyScrolltopIsZero(html) {
var element;
element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
// try to wheel down then..
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
}
function testDoesntSnapDownIfBiggerHeightChildIsScrolledToTheEnd(html, $timeout) {
var element;
element = compileElement(html, true);
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(100);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(125);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(125);
}
function testDoesntSnapDownIfBiggerHeightChildIsScrolledToTheBeginning(html, $timeout) {
var element;
$scope.index = 1;
element = compileElement(html, true);
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(125);
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(75);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(25);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
wheelDelta: 120,
detail: -120,
deltaY: -120
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
}
function testStopsListeningToMousewheelWhenScopeIsDestroyed(html) {
var element;
element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$scope.$destroy();
element.triggerHandler({
type: 'wheel',
wheelDelta: -120,
detail: 120,
deltaY: 120
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
}
function testUsesTheOriginalBrowserMousewheelEvents(html, $timeout) {
var element;
$scope.index = 3;
element = compileElement(html, true);
element.triggerHandler({
type: 'wheel',
originalEvent: {
wheelDelta: 120,
detail: -120,
deltaY: -120,
preventDefault: angular.noop,
stopPropagation: angular.noop
}
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(100);
$timeout.flush(); // flush the timeout on preventDown
element.triggerHandler({
type: 'wheel',
originalEvent: {
wheelDelta: 120,
detail: -120,
deltaY: -120,
preventDefault: angular.noop,
stopPropagation: angular.noop
}
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$timeout.flush(); // flush the timeout on preventUp
element.triggerHandler({
type: 'wheel',
originalEvent: {
wheelDelta: 120,
detail: -120,
deltaY: -120,
preventDefault: angular.noop,
stopPropagation: angular.noop
}
});
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
}
describe('as an attribute', function () {
beforeEach(function () {
var failureCallback;
scrollMock.to = jasmine.createSpy('scroll.to').and.callFake(function (element, top) {
element[0].scrollTop = top;
return {
then: function (success, error) {
failureCallback = error;
if (angular.isFunction(success)) {
success();
}
return this;
}
};
});
scrollMock.stop = jasmine.createSpy('scroll.stop').and.callFake(function () {
if (angular.isFunction(failureCallback)) {
failureCallback();
}
});
});
it('can be declared as an attribute', function () {
expect(function () {
compileElement('<div snapscroll=""></div>');
}).not.toThrow();
});
it('sets overflow-y on the element to auto if it\'s not set', function () {
var element = compileElement('<div snapscroll=""></div>');
expect(element.css('overflowY')).toBe('auto');
});
it('changes overflow-y to auto if it\'s set to visible', function () {
var element = compileElement('<div snapscroll="" style="overflow-y: visible;"></div>');
expect(element.css('overflowY')).toBe('auto');
});
it('changes overflow-y to auto if it\'s set to hidden', function () {
var element = compileElement('<div snapscroll="" style="overflow-y: hidden;"></div>');
expect(element.css('overflowY')).toBe('auto');
});
it('does not change overflow-y if it\'s set to scroll', function () {
var element = compileElement('<div snapscroll="" style="overflow-y: scroll;"></div>');
expect(element.css('overflowY')).toBe('scroll');
});
it('does not set overflow-y to auto if overflow is set to scroll', function () {
var element = compileElement('<div snapscroll="" style="overflow: scroll;"></div>');
expect(element.css('overflowY')).toBe('scroll');
});
it('defaults snapIndex to zero', function () {
var html = [
'<div snapscroll="" snap-index="snapIndex" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
compileElement(html, true);
expect($scope.snapIndex).toBe(0);
});
it('does not update snapIndex if the element\'s height is 0', function () {
var html = [
'<div snapscroll="" snap-index="snapIndex" style="height: 0; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
compileElement(html, true);
expect($scope.snapIndex).toBeUndefined();
});
it('does not update snapIndex if the element has no children', function () {
var html = [
'<div snapscroll="" snap-index="snapIndex" style="height: 50px; overflow: auto">',
'</div>'
].join('');
compileElement(html, true);
expect($scope.snapIndex).toBeUndefined();
});
it('does not update snapIndex if the element\'s children\'s combined height is less than the element\'s height', function () {
var html = [
'<div snapscroll="" snap-index="snapIndex" style="height: 50px; overflow: auto">',
'<div style="height: 10px"></div>',
'<div style="height: 10px"></div>',
'<div style="height: 10px"></div>',
'</div>'
].join('');
compileElement(html, true);
expect($scope.snapIndex).toBeUndefined();
});
it('updates the snapIndex if the element\'s children\'s combined height is greater than the element\'s height', function () {
var html = [
'<div snapscroll="" snap-index="snapIndex" style="height: 50px; overflow: auto">',
'<div style="height: 10px"></div>',
'<div style="height: 60px"></div>',
'</div>'
].join('');
compileElement(html, true);
expect($scope.snapIndex).toBe(0);
});
it('converts a snapIndex to a scrollTop (simple)', function () {
var element = compileElement('<div snapscroll=""></div>');
expect(element[0].scrollTop).toBe(0);
});
it('converts a snapIndex to a scrollTop (functional)', function () {
var element,
html = [
'<div snapscroll="" snap-index="index" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
$scope.index = 1;
element = compileElement(html, true);
expect(element[0].scrollTop).toBe(50);
});
it('doesn\'t snap to a snapIndex less than zero', function () {
var element,
html = [
'<div snapscroll="" snap-index="index" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
$scope.index = 1;
element = compileElement(html, true);
$scope.$apply(function () {
$scope.index = -1;
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
});
it('doesn\'t snap to a snapIndex greater than the number of available snaps (i.e. total - 1 since snapIndex is zero-based)', function () {
var element,
html = [
'<div snapscroll="" snap-index="index" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
$scope.index = 1;
element = compileElement(html, true);
$scope.$apply(function () {
$scope.index = 3;
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
});
it('casts any non-integer snapIndex to its nearest integer value', function () {
var element,
html = [
'<div snapscroll="" snap-index="index" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
$scope.index = 0.0000005;
element = compileElement(html, true);
expect($scope.index).toBe(0);
expect(element[0].scrollTop).toBe(0);
$scope.$apply(function () {
$scope.index = 1.499995;
});
expect($scope.index).toBe(1);
expect(element[0].scrollTop).toBe(50);
$scope.$apply(function () {
$scope.index = 1.5;
});
expect($scope.index).toBe(2);
expect(element[0].scrollTop).toBe(100);
});
it('doesn\'t fire before and afterSnap callbacks while resetting the scrollTop unless snapIndex is changed', inject(function ($timeout) {
var element,
test = 0,
html = [
'<div snapscroll="" snap-index="index" after-snap="afterSnap()" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
$scope.afterSnap = function () {
test += 1;
};
element = compileElement(html, true);
expect($scope.index).toBe(0);
expect(test).toBe(1);
element[0].scrollTop = 24;
element.triggerHandler('scroll');
$timeout.flush();
expect($scope.index).toBe(0);
expect(test).toBe(1);
}));
it('allows setting an initial snapIndex as an integer', function () {
var element,
html = [
'<div snapscroll="" snap-index="1" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
element = compileElement(html, true);
expect(element[0].scrollTop).toBe(50);
});
it('allows setting an initial snapIndex using an expression', function () {
var element,
html = [
'<div snapscroll="" snap-index="1 + 1" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'</div>'
].join('');
element = compileElement(html, true);
expect(element[0].scrollTop).toBe(100);
});
it('allows setting an initial snapIndex using an angular expression', function () {
var element,
html = [
'<div snapscroll="" snap-index="index + 1" style="height: 50px; overflow: auto">',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'<div style="height: 50px"></div>',
'