Summary Table

Categories Total Count
PII 0
URL 0
DNS 0
EKL 0
IP 0
PORT 0
VsID 0
CF 0
AI 0
VPD 0
PL 0
Other 0

File Content

define(['angular', 'ScrollIndicator'], function (angular) {
'use strict';

describe('Scroll Indicator Directive', function () {
var directive,
scope,
jQueryMock,
elementMock,
innerMock,
parentMock,
contentHeight,
innerHeight,
scrollCallback = function () {},
hasClass = false,
position = {
top: 0
},
scrollPos;

beforeEach(function () {
module('angularTemplateApp');

jQueryMock = jasmine.createSpyObj('$', ['scroll']);
innerMock = jasmine.createSpyObj('element', ['outerHeight']);
elementMock = jasmine.createSpyObj('element', ['find', 'outerHeight', 'hasClass', 'position', 'scrollTop', 'parent']);
parentMock = jasmine.createSpyObj('element', ['prepend', 'find']);

jQueryMock.scroll.and.callFake(function (callback) {
scrollCallback = callback;
});

spyOn(window, '$').and.returnValue(jQueryMock);

innerMock.outerHeight.and.callFake(function () {
return innerHeight;
});

elementMock.find.and.callFake(function () {
return innerMock;
});

elementMock.outerHeight.and.callFake(function () {
return contentHeight;
});

elementMock.hasClass.and.callFake(function () {
return hasClass;
});

elementMock.position.and.callFake(function () {
return position;
});

elementMock.scrollTop.and.callFake(function () {
return scrollPos;
});

elementMock.parent.and.callFake(function () {
return parentMock;
});

spyOn(angular, 'element').and.callFake(function (selector) {
return selector;
});

inject(function ($rootScope, scrollIndicatorDirective) {
scope = $rootScope.$new();

directive = scrollIndicatorDirective;

spyOn(scope, '$on');
});
});

afterEach(function () {
angular.element.and.callThrough();
});

describe("initial state", function () {
beforeEach(function () {
elementMock.find.and.callFake(function (selector) {
return selector;
});

parentMock.find.and.callFake(function (selector) {
return selector;
});
});

it("should prepend the scroll indicator elements to the parent", function () {
directive[0].link(scope, elementMock);

expect(parentMock.prepend).toHaveBeenCalledWith('<div class="arrow-indicator glyphicon glyphicon-chevron-down" aria-hidden="true"></div>\n\<div class="scroll-progress" aria-hidden="true">\n <div class="scroll-progress-bar"></div>\n</div>');
});

it("should correctly set initial values", function () {
directive[0].link(scope, elementMock);

expect(scope.innerElem).toEqual('> div');
expect(scope.arrow).toEqual('> .arrow-indicator');
expect(scope.scrollProgress).toEqual('> .scroll-progress');
expect(scope.scrollProgressBar).toEqual('> .scroll-progress .scroll-progress-bar');
});

describe("isIE11", function () {
it("should be true if MSInputMethodContext on the window and documentMode on the document are set", function () {
window.MSInputMethodContext = true;
document.documentMode = true;

directive[0].link(scope, elementMock);

expect(scope.isIE11).toEqual(true);
});

it("should be false if MSInputMethodContext on the window is not set but documentMode on the document is set", function () {
window.MSInputMethodContext = false;
document.documentMode = true;

directive[0].link(scope, elementMock);

expect(scope.isIE11).toEqual(false);
});

it("should be false if MSInputMethodContext on the window is set but documentMode on the document is not", function () {
window.MSInputMethodContext = true;
document.documentMode = false;

directive[0].link(scope, elementMock);

expect(scope.isIE11).toEqual(false);
});

it("should be false if neither MSInputMethodContext on the window nor documentMode on the document are set", function () {
window.MSInputMethodContext = false;
document.documentMode = false;

directive[0].link(scope, elementMock);

expect(scope.isIE11).toEqual(false);
});
});
});

describe("scroll event", function () {
beforeEach(function () {
directive[0].link(scope, elementMock);

spyOn(scope, 'onScroll');
});

it("should call onScroll if showIndicators is true", function () {
scope.showIndicators = true;

scrollCallback();

expect(scope.onScroll).toHaveBeenCalled();
});

it("should not call onScroll if showIndicators is false", function () {
scope.showIndicators = false;

scrollCallback();

expect(scope.onScroll).not.toHaveBeenCalled();
});
});

describe("watch statements", function () {
var watchFunctions,
callWatchFunctions = function () {
angular.forEach(watchFunctions, function (watchFunction) {
watchFunction();
});
};

beforeEach(function () {
watchFunctions = [];

spyOn(scope, '$watch').and.callFake(function (condition, callback) {
watchFunctions[watchFunctions.length] = function () {
if (condition()) {
callback();
}
}
});

directive[0].link(scope, elementMock);

spyOn(scope, 'init');
});

it("should call init twice when both watch statements are executed", function () {
contentHeight = 100;
innerHeight = 150;

callWatchFunctions();

expect(scope.init.calls.count()).toEqual(2);
});

it("should call init once if only the elem outerHeight statement is executed", function () {
contentHeight = 100;
innerHeight = false;

callWatchFunctions();

expect(scope.init.calls.count()).toEqual(1);
});

it("should call init once if only the innerElem outerHeight statement is executed", function () {
contentHeight = false;
innerHeight = 150;

callWatchFunctions();

expect(scope.init.calls.count()).toEqual(1);
});

it("should not call init if neither statement is executed", function () {
contentHeight = false;
innerHeight = false;

callWatchFunctions();

expect(scope.init).not.toHaveBeenCalled();
});
});

describe('init function', function () {
beforeEach(function () {
directive[0].link(scope, elementMock);

spyOn(scope, 'initStyles');
});

it("should call initStyles", function () {
scope.init();

expect(scope.initStyles).toHaveBeenCalled();
});

it("should set showIndicators to true if the elem height is less than the inner height and elem does not have the inner-scroll class", function () {
contentHeight = 100;
innerHeight = 150;
hasClass = false;

scope.init();

expect(scope.showIndicators).toEqual(true);
expect(elementMock.hasClass).toHaveBeenCalledWith('inner-scroll');
});

it("should set showIndicators to false if the elem height is greater than the inner height and elem does not have the inner-scroll class", function () {
contentHeight = 200;
innerHeight = 150;
hasClass = false;

scope.init();

expect(scope.showIndicators).toEqual(false);
});

it("should set showIndicators to false if the elem height is equal to the inner height and elem does not have the inner-scroll class", function () {
contentHeight = 150;
innerHeight = 150;
hasClass = false;

scope.init();

expect(scope.showIndicators).toEqual(false);
});

it("should set showIndicators to false if the elem height is less than the inner height and elem has the inner-scroll class", function () {
contentHeight = 100;
innerHeight = 150;
hasClass = true;

scope.init();

expect(scope.showIndicators).toEqual(false);
expect(elementMock.hasClass).toHaveBeenCalledWith('inner-scroll');
});

it("should set showIndicators to false if the elem height is greater than the inner height and elem has the inner-scroll class", function () {
contentHeight = 200;
innerHeight = 150;
hasClass = true;

scope.init();

expect(scope.showIndicators).toEqual(false);
});

it("should set showIndicators to false if the elem height is equal to the inner height and elem has the inner-scroll class", function () {
contentHeight = 150;
innerHeight = 150;
hasClass = true;

scope.init();

expect(scope.showIndicators).toEqual(false);
});
});

describe("initStyles function", function () {
beforeEach(function () {
directive[0].link(scope, elementMock);

scope.arrow = jasmine.createSpyObj('scope.arrow', ['css']);
scope.scrollProgress = jasmine.createSpyObj('scope.scrollProgress', ['css']);
scope.scrollProgressBar = jasmine.createSpyObj('scope.scrollProgressBar', ['css']);

contentHeight = 100;
position.top = 60;
});

it("should set initial styles on the arrow and scroll progress bar if showIndicators is true", function () {
scope.showIndicators = true;

scope.initStyles();

expect(scope.arrow.css).toHaveBeenCalledWith({
display: 'block',
opacity: 1,
top: '110px'
});

expect(scope.scrollProgressBar.css).toHaveBeenCalledWith('height', 0);
});

it("should set initial styles on the scroll progress element for non IE11 browsers if showIndicators is true", function () {
scope.isIE11 = false;
scope.showIndicators = true;

scope.initStyles();

expect(scope.scrollProgress.css).toHaveBeenCalledWith({
height: '99px',
top: '60px'
});
});

it("should set initial styles on the scroll progress element for IE11 if showIndicators is true", function () {
scope.isIE11 = true;
scope.showIndicators = true;

scope.initStyles();

expect(scope.scrollProgress.css).toHaveBeenCalledWith({
height: 0,
top: '60px'
});
});

it("should hide the arrow and scroll progress elements if showIndicators is false", function () {
hasClass = false;
scope.showIndicators = false;

scope.initStyles();

expect(scope.arrow.css).toHaveBeenCalledWith('display', 'none');
expect(scope.scrollProgress.css).toHaveBeenCalledWith('height', 0);
});

it("should not update the styles on the scroll progress bar if showIndicators is false", function () {
scope.showIndicators = false;

scope.initStyles();

expect(scope.scrollProgressBar.css).not.toHaveBeenCalled();
});
});

describe("onScroll function", function () {
beforeEach(function () {
directive[0].link(scope, elementMock);

scope.arrow = jasmine.createSpyObj('scope.arrow', ['css']);
scope.scrollProgressBar = jasmine.createSpyObj('scope.scrollProgressBar', ['css']);

contentHeight = 100;
innerHeight = 200;
});

it("should update the styles on the arrow element as the user scrolls", function () {
scrollPos = 50;

scope.onScroll();

expect(scope.arrow.css).toHaveBeenCalledWith({
'opacity': 0.5,
'display': 'block'
});

scrollPos = 40;

scope.onScroll();

expect(scope.arrow.css).toHaveBeenCalledWith({
'opacity': 0.6,
'display': 'block'
});
});

it("should hide the arrow element when the scroll is at 99%", function () {
scrollPos = 99;

scope.onScroll();

var cssObj = scope.arrow.css.calls.argsFor(0)[0];

expect(cssObj.display).toEqual('none');
});

it("should hide the arrow element when the scroll is at 100%", function () {
scrollPos = 100;

scope.onScroll();

var cssObj = scope.arrow.css.calls.argsFor(0)[0];

expect(cssObj.display).toEqual('none');
});

it("should update the scroll progress bar on non IE11 browsers", function () {
scrollPos = 50;

scope.isIE11 = false;

scope.onScroll();

expect(scope.scrollProgressBar.css).toHaveBeenCalledWith('height', '50%');
});

it("should not update the scroll progress bar on IE11", function () {
scrollPos = 50;

scope.isIE11 = true;

scope.onScroll();

expect(scope.scrollProgressBar.css).not.toHaveBeenCalled();
});
});

describe("on destroy", function () {
var findResult = {
remove: function () {}
};

beforeEach(function () {
parentMock.find.and.returnValue(findResult);

spyOn(findResult, 'remove');

scope.$on.and.callFake(function (eventType, callback) {
callback();
});

directive[0].link(scope, elementMock);
});

it("should listen for a destroy event", function () {
expect(scope.$on.calls.argsFor(0)[0]).toEqual('$destroy');
});

it("should remove the scroll indicator elements", function () {
expect(parentMock.find).toHaveBeenCalledWith('> .arrow-indicator, > .scroll-progress');
expect(findResult.remove).toHaveBeenCalled();
});
});
});
});