在测试期间更改了单向绑定指令属性,没有更新指令范围

Change in one-way bound directive attribute during test not updating directive scope

本文关键字:指令 属性 范围 更新 绑定 测试      更新时间:2023-09-26

我正在尝试使用jasmine测试一个angular指令。

下面是一个被测试指令的简化示例:

angular.module('app', []).directive('testDirective', [
  function() {
    return {
      restrict:'A',
      scope: {
        myAttr: '@'
      },
      link: function(scope, element, attrs) {
        element.html(scope.myAttr);
        scope.$watch('myAttr', function(n, o) {
          if(n !== o) {
            element.html(n);
          }
        });
      }
    };
  }
]);

使用隔离作用域,它将属性data-my-attr的值单向绑定到myAttr的作用域值,然后观察myAttr的值是否有任何变化,此时它更新显示的元素。

同样,为了清晰起见,这段代码经过了大量修改,所以请原谅这个高度人为的例子。

该测试正在编译一个包含该指令的元素,验证元素的初始html设置是否正确(它是),然后更改该属性的值,并期望元素中发生相应的更改(它不是)。这是测试代码的简化版本。

it('fires myAttr watch', function() {
    var body = angular.element('body');
    var template = angular.element('<div id="testid" data-test-directive data-my-attr="initialValue"/>');
    body.append([template]);
    compile(template)(scope);
    scope.$digest();
    expect(angular.element('#testid').text()).toEqual('initialValue');
    template.attr('data-my-attr', 'newValue');
    scope.$digest();
    expect(angular.element('#testid').text()).toEqual('newValue');
  });

虽然这个指令在生产中使用时可以按预期工作,但在测试中,似乎更新属性的值不会导致相应的作用域值更新,这导致watch永远不会触发。为什么作用域上的值不更新,为什么这只发生在测试中?

下面是演示问题的plunkr http://plnkr.co/edit/MmS1X2zrPZyGSUIVUsDg?p=preview

任何想法?

您需要在使用新文本更新元素的属性后编译元素。在您的情况下,您根本不需要scope.digest(因为您没有真正将文本与{{modelvalue}}绑定)。原因是您没有附加绑定变量,而是将计划文本分配给该属性,因此需要重新编译该元素。

所以你只需要做:-

template.attr('data-my-attr', 'newValue');
compile(template)(scope);

你的测试是这样的(使用指令时使用角绑定):-

var body = angular.element('body');
rootScope.initialValue ="initialValue";
var template = angular.element('<div id="testid" data-test-directive data-my-attr="{{initialValue}}"/>');
body.append([template]);
compile(template)(scope);
scope.$digest();
expect(angular.element('#testid').text()).toEqual('initialValue');
rootScope.initialValue = "newValue";
scope.$digest();
expect(angular.element('#testid').text()).toEqual('newValue');

调用$digest就可以了。