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

Angular.js unit test does not call $animate.enter callback

本文关键字:animate enter 回调 调用 js 单元测试 Angular      更新时间:2023-09-26

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

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

您可以在此处查看代码,只需取消对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());
              });
            });
          }
        });
      }
    }
  };
}]);

addWrapperInfoSpec.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>
  });
});

所以我想好了你必须做什么。我深入研究了代码,发现在ngAnimate内部,它将回调函数推送到$$asyncCallback$$asyncCallback有一个flush函数,它将调用推到它上面的任何函数。要让$animate.enter触发回调,你必须将$$asyncCallback注入到单元测试中,然后调用$$asyncCallback.flush()。这将运行您的回调函数。

你可以在这个Plunker中看到这一点。