当指令是属性时单元测试失败

Unit test failing when directive is an Attribute

我有一个声明为属性的指令:

app.directive('myDirective', function() {
    return {
        restrict: 'A',
        replace: true,
        transclude: true,
        scope: {
            data: "="
        },
        template:
            '<p class="my-paragrapgh">' +
                '<label>Hello</label>' +
            '</p>'
    }
});

我有一个单元测试失败了:

describe('myDirective test', function () {
var scope, compile, element;

beforeEach(module('myModule'));

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

    element = angular.element("<div my-directive></div>");
    $compile(element);
    scope.$digest();
}));

it('should have a my-paragrapgh class', function () {
    expect($(element).find('p')[0]).toHaveClass('my-paragrapgh');
});

});

但是,如果我将指令转换为元素,并删除替换和嵌入:

app.directive('myDirective', function() {
    return {
        restrict: 'E',
        //replace: true,
        //transclude: true,
        scope: {
            data: "="
        },
        template:
            '<p class="my-paragrapgh">' +
                '<label>Hello</label>' +
            '</p>'
    }
});

我的单元测试通过了:

describe('myDirective test', function () {
var scope, compile, element;

beforeEach(module('myModule'));

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

    element = angular.element("<my-directive></my-directive>");
    $compile(element);
    scope.$digest();
}));

it('should have a my-paragrapgh class', function () {
    expect($(element).find('p')[0]).toHaveClass('my-paragrapgh');
});

});

如何成功测试声明为属性的指令?我正在使用 Karma、Jasmine 和 PhantomJS

当您有 transclude: true 时,您需要在模板中的某个地方有一个 ng-transclude,以便 angular 知道在哪里注入您的 HTML。尝试:

app.directive('myDirective', function() {
    return {
        restrict: 'A',
        replace: true,
        transclude: true,

        scope: {
            data: "="
        },

        template:
            '<div ng-transclude><p class="my-paragrapgh">' +
                '<label>Hello</label>' +
            '</p></div>'
    }
});

更新

看起来可能是 replace 选项导致了问题。

app.directive('myDirective', function() {
    return {
        restrict: 'A',

        scope: {
            data: "="
        },

        template:
            '<p class="my-paragrapgh">' +
                '<label>Hello</label>' +
            '</p>'
    }
});

replace: true 你内心 HTML 是:

失败

<label>Hello</label>

replace 未定义的情况下,您有

通过

<p class="my-paragrapgh"><label>Hello</label></p>

适用于 replacetransclude,即使没有 ng-trasclude

angular.module('myModule', [])
  .directive('myDirective', function() {
    return {
      restrict: 'A',
      replace: true,
      transclude: true,
      scope: {
        data: "="
      },
      template: '<p class="my-paragrapgh">' +
        '<label>Hello</label>' +
        '</p>'
    }
  });

describe('myDirective test', function() {
  var scope, compile, element;

  // Even we can introduce our Jasmine custom matcher
  beforeEach(function() {
    jasmine.addMatchers({
      toHaveCSSClass: function(util, customEqualityTesters) {
        return {
          compare: function(actual, expected) {
            debugger;
            var result = {};
            result.pass = util.equals(actual.hasClass(expected), true, customEqualityTesters);
            if (result.pass) {
              result.message = "Expected " + actual + " to not have CSS class '" + expected + "'";
            } else {
              result.message = "Expected " + actual + " to have CSS class '" + expected + "'";
            }
            return result;
          }
        }
      }
    });
  });

  beforeEach(module('myModule'));


  beforeEach(inject(function($rootScope, $compile) {
    scope = $rootScope.$new();
    element = angular.element("<div my-directive></div>");
    $compile(element);
    scope.$digest();
  }));

  it('has a my-paragrapgh class', function() {
    expect(element.hasClass('my-paragrapgh')).toBeTruthy();
  });
  
  it('has a my-paragrapgh class - tested by custom matcher', function() {
    expect(element).toHaveCSSClass('my-paragrapgh')
  });

});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>