Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate window scrolling in a Angular Unit Test?

How can you simulate or mock window scrolling in a Jasmine Unit Test and or set a window.pageYOffset property?

I am using Angular 1.3, Jasmine 2.1 + Karma 0.12.28 and PhantomJS 1.9.12

This is my directive:

'use strict';
(function () {
angular
  .module('myApp')
  .directive('scrollNews', scrollNews);

  function scrollNews(){

    var directive = {
      restrict: 'A',
      scope: false,
      link: link
    };

    return directive;

    function link(scope, element) {
      scope.limit = 2;
      //add one to the limit
      scope.loadMore = function() {
        scope.limit += 1;
      };

      var raw = element[0];
      angular.element(window).on('scroll', function () {
        var scrollFrontier = this.pageYOffset + 800;
        // when scrollFrontier has reached raw.scrollHeight, run loadMore()
        if (scrollFrontier >= raw.scrollHeight) {
          scope.loadMore(); // run the function
          scope.$digest(); // update the HTML
        }
      });
    }
  }
})();

And this is my testSpec:

describe('Directive: scroll news', function(){

  var element, $scope, $window;

  beforeEach(module('myApp'));

  beforeEach(inject(function($compile, $rootScope, _$window_){
    $scope = $rootScope;
    $window = _$window_;

    element = angular.element('<div scroll-news></div>');
    $compile(element)($scope);
    $scope.$digest();
  }));

  it('should have a limit of 2 when no scrolling have occurred', function(){
    expect($scope.limit).toBe(2);
  });

  it('should add one to the limit with loadMore function', function(){
    $scope.loadMore();
    expect($scope.limit).toBe(3);
  });

  it('should run loadMore() when scrolling has reached a specific height', function(){
    element.scrollHeight = 1400;

    var spy = spyOn($window, 'scrollTo');
    $window.scrollTo(0, 1400);
    expect(spy).toHaveBeenCalled();

   expect($scope.limit).toBe(3); // Logs: Expected 2 to be 3. - so loadMore() have not called
 });
});

I want to simulate or mock a window scroll event to the element.scrollHeight, because if these two reaches the same height my directive runs the loadMore() function. But how can I make unit test of that?

Btw the directive works fine in production :)

like image 717
user1906437 Avatar asked Mar 17 '23 16:03

user1906437


1 Answers

Had the same issue recently. For the scrolling to work, you will need to set some dimensions on the body tag, so the window can be scrolled.

var scrollEvent = document.createEvent( 'CustomEvent' ); // MUST be 'CustomEvent'
scrollEvent.initCustomEvent( 'scroll', false, false, null );

var expectedLeft = 123;
var expectedTop = 456;

mockWindow.document.body.style.minHeight = '9000px';
mockWindow.document.body.style.minWidth = '9000px';
mockWindow.scrollTo( expectedLeft, expectedTop );
mockWindow.dispatchEvent( scrollEvent );

Unfortunately this does not work in PhantomJS.

If you are running your tests on Travis CI, you can also use Chrome by adding the following to your .travis.yml

before_install:
   - export CHROME_BIN=chromium-browser
   - export DISPLAY=:99.0
   - sh -e /etc/init.d/xvfb start

And a custom Chrome launcher in your karma config:

module.exports = function(config) {
    var configuration = {

        // ... your default content

        // This is the new content for your travis-ci configuration test
        //  Custom launcher for Travis-CI
        customLaunchers: {
            Chrome_travis_ci: {
                base: 'Chrome',
                flags: ['--no-sandbox']
            }
        },

        // Continuous Integration mode
        // if true, it capture browsers, run tests and exit
        singleRun: true 
    };

    if(process.env.TRAVIS){
        configuration.browsers = ['Chrome_travis_ci'];
    }

    config.set( configuration );

};
like image 180
Stefan Avatar answered Mar 20 '23 05:03

Stefan