angularjs - 如何在 Angular 单元测试中模拟窗口滚动?

标签 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() 函数。但是我怎样才能对它进行单元测试呢?

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

最佳答案

最近有同样的问题。为了使滚动起作用,您需要在 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 上运行测试,您也可以通过将以下内容添加到 .travis.yml 来使用 Chrome
before_install:
   - export CHROME_BIN=chromium-browser
   - export DISPLAY=:99.0
   - sh -e /etc/init.d/xvfb start

以及您的 karma 配置中的自定义 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 );

};

关于angularjs - 如何在 Angular 单元测试中模拟窗口滚动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27385262/

相关文章:

javascript - ng-重复表中 3 列的值? -AngularJS

unit-testing - TFS 尽管构建是绿色的,但并非所有测试都运行

javascript - 有哪些代码质量/代码覆盖率工具可用于检查 Jasmine 中的 Javascript 测试?

Angular Testing 如何防止 ngOnInit 调用直接测试方法

javascript - 将 Angular 代码与外部代码混合的正确范例

javascript - 用 AngularJS 中 $http 的响应替换整个 DOM(页面)

ruby - 突变测试 : does anybody know mutant?

unit-testing - 单元测试?集成测试?回归测试?验收测试?

angular - 构造函数中的 SpyOn 服务函数调用

JavaScript | Angular | Controller 作为语法 : Cannot Use `this`