10

I have an infinite scroll directive that I am trying to unit test. Currently I have this:

describe('Infinite Scroll', function(){
  var $compile, $scope;

  beforeEach(module('nag.infiniteScroll'));

  beforeEach(inject(function($injector) {
    $scope = $injector.get('$rootScope');
    $compile = $injector.get('$compile');

    $scope.scrolled = false;
    $scope.test = function() {
      $scope.scrolled = true;
    };
  }));

  var setupElement = function(scope) {
    var element = $compile('<div><div id="test" style="height:50px; width: 50px;overflow: auto" nag-infinite-scroll="test()">a<br><br><br>c<br><br><br><br>e<br><br>v<br><br>f<br><br>g<br><br>m<br>f<br><br>y<br></div></div>')(scope);
    scope.$digest();
    return element;
  }

  it('should have proper initial structure', function() {
    var element = setupElement($scope);

    element.find('#test').scrollTop(10000);

    expect($scope.scrolled).toBe(true);
  });
});

However the .scrollTop(10000); does not seem to trigger anything.

Is there anyway to unit test this type of functionality (I am able to unit test other directives with similar interactions like clicking on elements)?

In case it is relative, this is the infinite scroll code:

angular.module('nag.infiniteScroll', [])
.directive('nagInfiniteScroll', [
  function() {
    return function(scope, elm, attr) {
      var raw = elm[0];

      elm.bind('scroll', function() {
        if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
          scope.$apply(attr.nagInfiniteScroll);
        }
      });
    };
  }
]);
ryanzec
  • 27,284
  • 38
  • 112
  • 169

2 Answers2

7

You have to trigger the scroll event on your element manually in your test:

element.find('#test').scrollTop(10000);
element.find('#test').triggerHandler('scroll');
Andreas Köberle
  • 106,652
  • 57
  • 273
  • 297
  • Well that maked the code trigger however it will trigger the code even if the scrollTop() is not apply because raw.scrollTop, raw. offsetHeight, and raw.scrollHeight all evaluate to 0 within the directive's code. Maybe this is something that just can't be unit tested. – ryanzec May 14 '13 at 14:26
  • I have the same issue - it seems that elements can't have an pageYOffset/pageXOffset when they are not added to a document. Adding the element to document does not work also "Cannot read property 'createDocumentFragment' of null" – iRaS Oct 28 '15 at 13:59
0

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 );

};
Stefan
  • 116
  • 1
  • 4