Angular.js单元测试不会调用$ animate.enter回调

时间:2014-09-10 23:26:26

标签: javascript angularjs unit-testing

我编写了一个指令,它将有条件地添加一个我在Angular< ngIf指令之后建模的包装元素。该指令在生产中运行时效果很好,但在尝试添加单元测试时,$ animate.enter函数从不调用我的回调函数。这会导致我的所有单元测试失败,因为它假定包装器不在那里。

我使用Angular.js版本1.2.16并加载ngMock和ngAnimate进行单元测试。该代码触发ngAnimate enter函数,但它从不触发回调。

您可以查看代码here,只需取消注释appSpec.js脚本标记,该指令就不再有效。

现在有人如何触发$ animate.enter在单元测试中调用我的回调函数?

addWrapperIf.js

angular.module('myModule', ['ngAnimate'])

.directive('addWrapperIf', ['$animate', function($animate) {
  return {
    transclude: 'element',
    priority: 1000,
    restrict: 'A',
    compile: function (element, attr, transclude) {
      return function ($scope, $element, $attr) {
        var childElement, childScope;
        $scope.$watch($attr.addWrapperIf, function addWrapperIfWatchAction(value) {
          if (childElement) {
            $animate.leave(childElement);
            childElement = undefined;
          }
          if (childScope) {
            childScope.$destroy();
            childScope = undefined;
          }

          // add the wrapper
          if (value) {
            childScope = $scope.$new();
            transclude(childScope, function (clone) {
              childElement = clone
              $animate.enter(clone, $element.parent(), $element);
            });
          }
          // remove the wrapper
          else {
            childScope = $scope.$new();
            transclude(childScope, function (clone) {
              $animate.enter(clone, $element.parent(), $element, function() {
                childElement = clone.contents();
                clone.replaceWith(clone.contents());
              });
            });
          }
        });
      }
    }
  };
}]);

addWrapperIfSpec.js

var expect = chai.expect;

describe('addWrapperIf', function () {
  var $template;
  var $compile;
  var $scope;

  beforeEach(window.module('myModule'));

  beforeEach(inject(function(_$compile_, $rootScope){
    $compile = _$compile_;
    $scope = $rootScope.$new();
  }));

  function compileDirective(template) {
    $template = $compile(template)($scope)[0];
    $scope.$apply();
  }

  it('should output the correct values with default options', function() {

    compileDirective('<div add-wrapper-if="false"><span>child</span></div>');

    console.log($template); // <div add-wrapper-if="false"><span>child</span></div>
  });

});

1 个答案:

答案 0 :(得分:2)

所以我弄清楚你要做什么。我挖掘代码并发现在ngAnimate中它将回调函数推送到$$asyncCallback$$asyncCallback有一个flush函数,可以调用任何推送到它上面的函数。要让$animate.enter触发回调,您必须将$$asyncCallback注入单元测试,然后调用$$asyncCallback.flush()。然后,这将运行您的回调函数。

您可以在此Plunker中看到这一点。