describe('Ionic ScrollDelegate Service', function() { var $ionicScrollDelegate, rootScope, compile, timeout, document; beforeEach(module('ionic')); beforeEach(inject(function(_$ionicScrollDelegate_, $rootScope, $timeout, $compile, $document) { $ionicScrollDelegate = _$ionicScrollDelegate_; document = $document; rootScope = $rootScope; timeout = $timeout; compile = $compile; })); it('should just return rootScope if no scrollCtrl', inject(function($rootScope) { expect(function() { $ionicScrollDelegate($rootScope); }).not.toThrow(); expect($ionicScrollDelegate($rootScope).getScrollView()).toBeFalsy(); })); it('Should get scroll view', function() { var scope = rootScope.$new(); var el = compile('')(scope); var sv = $ionicScrollDelegate(scope).getScrollView(); expect(sv).not.toBe(undefined); }); it('should resize', function() { var scope = rootScope.$new(); var el = compile('')(scope); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'resize'); spyOn(sv, 'scrollTo'); del.resize(); timeout.flush(); expect(sv.resize).toHaveBeenCalled(); }); it('scroll event', function() { var scope = rootScope.$new(); var el = compile('')(scope); scope = el.scope(); scope.$apply(); var top, left; scope.$onScroll = jasmine.createSpy('scroll').andCallFake(function(data) { top = data.scrollTop; left = data.scrollLeft; }); ionic.trigger('scroll', {target: el[0]}); expect(scope.$onScroll).toHaveBeenCalled(); expect(top).toBe(0); expect(left).toBe(0); ionic.trigger('scroll', {target: el[0], scrollTop: 3, scrollLeft: 4}); expect(top).toBe(3); expect(left).toBe(4); }); testWithAnimate(true); testWithAnimate(false); function testWithAnimate(animate) { describe('with animate='+animate, function() { it('should tapScrollToTop', function() { var scope = rootScope.$new(); var el = angular.element('
' + '
' + '
' + '
'); //ionic.trigger() REALLY doesnt want to work with tap, //so we just mock on to catch the callback and use that... var callback; var del = $ionicScrollDelegate(scope); spyOn(ionic, 'on').andCallFake(function(eventName, cb) { callback = cb; }); del.tapScrollToTop(el, animate); spyOn(del, 'scrollTop'); //Don't test the rectContains part, too much to mock spyOn(ionic.DomUtil, 'rectContains').andCallFake(function() { return true; }); callback({ target: el[0].querySelector('.not-button'), gesture:{ touches:[{}] } }); expect(del.scrollTop).toHaveBeenCalledWith(animate); del.scrollTop.reset(); callback({ target: el[0].querySelector('.button') }); expect(del.scrollTop).not.toHaveBeenCalled(); }); it('should resize & scroll top', function() { var scope = rootScope.$new(); var el = compile('')(scope); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'resize'); spyOn(sv, 'scrollTo'); del.scrollTop(animate); timeout.flush(); expect(sv.resize).toHaveBeenCalled(); expect(sv.scrollTo.mostRecentCall.args).toEqual([0, 0, animate]); }); it('should resize & scroll bottom', function() { var scope = rootScope.$new(); var el = compile('

')(scope); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'getScrollMax').andCallFake(function() { return { left: 10, top: 11 }; }); spyOn(sv, 'resize'); spyOn(sv, 'scrollTo'); var max = sv.getScrollMax(); del.scrollBottom(animate); timeout.flush(); expect(sv.resize).toHaveBeenCalled(); expect(sv.scrollTo.mostRecentCall.args).toEqual([max.left, max.top, animate]); }); it('should resize & scrollTo', function() { var scope = rootScope.$new(); var el = compile('

')(scope); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'scrollTo'); spyOn(sv, 'resize'); del.scrollTo(2, 3, animate); timeout.flush(); expect(sv.resize).toHaveBeenCalled(); expect(sv.scrollTo.mostRecentCall.args).toEqual([2, 3, animate]); }); it('should throw error on rememberScroll if no id', function() { var scope = rootScope.$new(); var el = compile(''); var del = $ionicScrollDelegate(scope); expect(del.rememberScrollPosition).toThrow(); }); it('scrollToRememberedPosition should scroll if exists', function() { var scope = rootScope.$new(); var el = compile('')(scope); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); scope.$apply(); $ionicScrollDelegate._rememberedScrollValues['1'] = { left: 3, top: 4 }; del.scrollToRememberedPosition('1', animate); spyOn(sv, 'scrollTo'); timeout.flush(); expect(sv.scrollTo).toHaveBeenCalledWith(3, 4, animate); }); it('should save on destroy for rememberScrollPosition', function() { var scope = rootScope.$new(); var el = compile('')(scope); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); scope.$apply(); $ionicScrollDelegate._rememberedScrollValues['1'] = { left: -1, top: -1 }; del.rememberScrollPosition('1', animate); spyOn(sv, 'getValues').andCallFake(function() { return { foo: 'bar' }; }); scope.$destroy(); expect(sv.getValues).toHaveBeenCalled(); expect($ionicScrollDelegate._rememberedScrollValues['1']).toEqual({ foo: 'bar' }); }); }); } }); describe('anchorScroll', function() { function setLocationHash(hash) { inject(function($location) { $location.hash = function() { return hash; }; }); } beforeEach(module('ionic')); testWithAnimate(true); testWithAnimate(false); function testWithAnimate(animate) { describe('with animate=' + animate, function() { var contentEl, scope, $ionicScrollDelegate, timeout; beforeEach(inject(function($rootScope, $compile, $timeout, $document, _$ionicScrollDelegate_) { scope = $rootScope.$new(); contentEl = $compile('')(scope); document.body.appendChild(contentEl[0]); $ionicScrollDelegate = _$ionicScrollDelegate_; timeout = $timeout; $rootScope.$apply(); })); it('should anchorScroll to an element with id', function() { var anchorMe = angular.element('
'); var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'scrollTo'); spyOn(ionic.DomUtil, 'getPositionInParent').andCallFake(function() { return { left: 2, top: 1 }; }); setLocationHash('anchorMe'); contentEl.append(anchorMe); del.anchorScroll(animate); timeout.flush(); expect(sv.scrollTo).toHaveBeenCalledWith(2, 1, animate); }); it('should anchorScroll to top if !$location.hash()', function() { var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'scrollTo'); spyOn(ionic.DomUtil, 'getPositionInParent'); del.anchorScroll(animate); timeout.flush(); expect(sv.scrollTo).toHaveBeenCalledWith(0, 0, animate); expect(ionic.DomUtil.getPositionInParent).not.toHaveBeenCalled(); }); it('should anchorScroll to top if element with hash id doesnt exist', function() { var del = $ionicScrollDelegate(scope); var sv = del.getScrollView(); spyOn(sv, 'scrollTo'); spyOn(ionic.DomUtil, 'getPositionInParent'); setLocationHash('doesnotexist'); del.anchorScroll(animate); timeout.flush(); expect(sv.scrollTo).toHaveBeenCalledWith(0, 0, animate); expect(ionic.DomUtil.getPositionInParent).not.toHaveBeenCalled(); }); }); } });