如何在角度单元测试中模拟窗口滚动?

时间:2014-12-09 17:38:22

标签: angularjs unit-testing jasmine phantomjs karma-runner

如何在Jasmine单元测试中模拟或模拟窗口滚动并设置window.pageYOffset属性?

我使用的是Angular 1.3,Jasmine 2.1 + Karma 0.12.28和PhantomJS 1.9.12

这是我的指示:

'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
        }
      });
    }
  }
})();

这是我的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
 });
});

我想模拟或模拟一个窗口滚动事件到element.scrollHeight,因为如果这两个达到相同的高度,我的指令运行loadMore()函数。但是我该如何对其进行单元测试呢?

顺便说一句,该指令在生产中运行良好:)

1 个答案:

答案 0 :(得分:5)

最近有同样的问题。要使滚动起作用,您需要在body标签上设置一些尺寸,以便可以滚动窗口。

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

不幸的是,这在PhantomJS中不起作用

如果您在 Travis CI 上运行测试,您还可以使用Chrome ,将以下内容添加到.travis.yml

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

在您的业力配置中自定义Chrome启动器:

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

};