1

为了轻松创建模态,我想要一个指令,它只需要一个模板,然后创建一个按钮,该按钮以模板作为内容打开一个模态。

<script type="text/ng-template" id="myTemplate.html">
<h1>hello world</h1>
</script>
<div my-modal="myTemplate.html"></div>

现在,我在我的模块中创建了一个新的 angularJS 指令,它只返回一个模板,该模板具有ng-click然后打开模式:

angular.module('myApp.directives').directive('myModal', ['$modal',
  function($modal) {
    return {
      link: function(scope, elem, attrs) {
        scope.modalController = function ($scope, $modalInstance) {
        };

        scope.openModal = function() {
          var modalInstance = $modal.open({
          templateUrl: attrs.myModal,
          controller: scope.modalController
        });

        modalInstance.result.then(function () {}, function () {});

        return modalInstance;
      };
    },

    restrict: 'A',
    scope: {
      myModal: '='
    },
    transclude: false,
    template: '<button ng-click="openModal()">open</button>'
  };
}]);

这适用于我的应用程序。你可以在这里看到 plunkr

问题是我无法进行测试。它尝试了 jasmine.clock 和 $timeout 方法,但它似乎仍然不起作用。

这是我的测试:

(function () {
  "use strict";

  describe('my-modal', function() {
    var element,
        scope,
    apply,
    triggerClick,
    $timeout;

        beforeEach(module('myApp.services'));
        beforeEach(module('myApp.directives'));
        beforeEach(module('pascalprecht.translate'));
        beforeEach(module('ui.bootstrap'));

        describe('directive', function() {

          beforeEach(function(){
            jasmine.Clock.useMock();
          });

          beforeEach(inject(function($injector,$compile) {
            var $rootScope = $injector.get('$rootScope');
            scope = $rootScope.$new();
            $timeout = $injector.get('$timeout');
            apply = function () {
              /* This is a workaround because. Read up on it here: http://tinyurl.com/ng8zzub */
            if(!scope.$$phase) {
              scope.$apply();
            }
          };

          triggerClick = function(element){
            $(element).trigger('click');
            apply();
          };

          var html =
            '<html><body>' +
              '<h1>PETER?</h1>' +
              '<script type="text/ng-template" id="myModalTemplate.html">' +
               '<h1>Hallo Peter</h1>' +
                '<p>Was geht?</p>' +
              '</script>' +
              '<div my-modal="myModalTemplate.html"></div>'
            '</body></html>';

          element = $compile(html)(scope);
          scope.$digest();
        }));

        it('should open uppon click on directive element', function() {
          triggerClick($(element).find('button'));
          jasmine.Clock.tick(9000);
          $timeout.flush();
          apply();
          expect($(element).find('.modal').length > 0).toBeTruthy();
        });
      });
    });
  }());

不幸的是,测试失败了。

在ui-bootstrap 本身用来证明它的模态组件正在工作的单元测试中,他们直接检查 $document 这对我来说不是一个选项。

所以一件奇怪的事情是,当我console.log()用来查看是否element发生了变化时,我看到htmlandbody标记已被剥离。但是 modal 使用主体向其附加元素。

4

1 回答 1

2

所以问题是 ui-bootstrap.modal 使用 $document 来附加它的 html,而不是使用调用它作为引用的指令。

因此,要测试天气是否由指令调用模态,我们必须在 $document 中搜索它。我在 beforeEach 的测试中注入了它:

var $document;
beforeEach(inject(function(_$document_) {
  $document = _$document_;
}));

然后在我的实际测试中,我用它来找到这样的模态元素:

it('should open uppon click on directive element', function() {
  expect($document.find('.modal-open').length > 0).toBeFalsy();
  expect($document.find('.modal').length > 0).toBeFalsy();
  triggerClick(element.find('button'));
  expect($document.find('.modal-open').length > 0).toBeTruthy();
  expect($document.find('.modal').length > 0).toBeTruthy();
}

有用!

于 2014-04-08T12:07:08.853 回答