我正在尝试使用jasmine测试角度指令。
以下是受测试指令的简化示例:
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');
});
虽然此指令在生产中使用时按预期工作,但在测试中似乎更新属性的值不会导致相应的范围值更新,这导致手表永远不会触发。为什么范围上的值不会更新,为什么这只会在测试中发生?
这是一个展示问题http://plnkr.co/edit/MmS1X2zrPZyGSUIVUsDg?p=preview
的傻瓜有什么想法吗?
答案 0 :(得分:2)
您需要在使用新文本更新元素的属性后编译元素。在你的情况下,你根本不需要scope.digest
(因为你并没有真正用{{modelvalue}}
绑定文本)。原因是您没有附加绑定变量,而是将计划文本分配给属性,因此您需要重新编译该元素。
所以你只需要这样做: -
template.attr('data-my-attr', 'newValue');
compile(template)(scope);
<强> Demo 强>
如果您的测试是这样的(使用指令时使用角度绑定): -
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来实现。
<强> Demo 强>