更新模板和调用 $digest 不会触发带有正确参数的 $watch - 单元测试 angularjs
Updating template and calling $digest does not trigger $watch with correct parameters - unit tests angularjs
我有一个简单的指令,它根据指令的 scope
属性 添加或删除 focus
class 到元素。
我想写 2 个测试。
首先测试验证,当 scope.addFocus
属性 设置为 'true'
时,focus
class 在元素上。此测试通过。
然后我更新指令的编译模板,将 scope.addFocus
属性 更改为 'false'
,触发 $digest()
并期望,该指令将更新元素的 classes 并删除 focus
class。这个测试失败了。
这里是一个 link plunkr: http://plnkr.co/edit/k4PBcCwfivsJsbIEUwGd?p=preview
想知道为什么 $compiledTemplate.attr('add-focus', 'false'); $directiveScope.$digest();
不更新
按预期更新 classes?
指令代码
myApp.directive('myDirective', function() {
return {
scope: {
addFocus: '@'
},
restrict: 'A',
link: function (scope, element, attr) {
scope.$watch(
function() { return scope.addFocus; },
function (newValue, oldValue) {
if (newValue === 'true') {
element.addClass('focus');
} else {
element.removeClass('focus');
}
},
false
);
}
};
});
测试
describe('myApp', function () {
var $compile, $timeout, $rootScope;
var $directiveScope;
var template = '<div my-Directive add-focus="true"></div>';
var $compiledTemplate;
beforeEach(function () {
module('myApp');
});
beforeEach(angular.mock.inject(function(_$compile_, _$timeout_, _$rootScope_) {
$compile = _$compile_;
$timeout = _$timeout_;
$rootScope = _$rootScope_;
}
));
beforeEach(function() {
$directiveScope = $rootScope.$new();
$compiledTemplate = $compile(template)($directiveScope);
$directiveScope.$digest();
});
// Test 1
it('directive is compiled and has focus class', function() {
console.log('test1', $compiledTemplate[0]);
expect($compiledTemplate.hasClass('focus')).toBe(true);
});
// Test 2
it('focus class is removed', function() {
$compiledTemplate.attr('add-focus', 'false');
$directiveScope.$digest();
$timeout(function() {
console.log('test2', $compiledTemplate[0]);
expect($compiledTemplate.hasClass('focus')).toBe(false);
}, 0);
$timeout.flush();
});
});
更新了 Plunker
问题是 watcher 没有被调用。我们需要同样使用 isolateScope。我创建了如下的 isolateScope :
isolateScope = $compiledTemplate.isolateScope();
并切换规范中的 addFocus 值以触发观察器
isolateScope.addFocus = false;
答案已给出并被接受,尽管它不好:当您使用输入测试指令时 - 测试输入,不要直接更改指令范围。
最短的例子是:
beforeEach(function() {
$upperScope = $rootScope.$new();
$upperScope.param = true;
$compiledTemplate = $compile('<div my-Directive add-focus="{{param}}"></div>')($upperScope);
$upperScope.$digest();
});
// Test 1
it('directive is compiled and has focus class', function() {
expect($compiledTemplate.hasClass('focus')).toBe(true);
});
// Test 2
it('focus class is removed', function() {
$upperScope.param = false;
$upperScope.$digest();
expect($compiledTemplate.hasClass('focus')).toBe(false);
});
我有一个简单的指令,它根据指令的 scope
属性 添加或删除 focus
class 到元素。
我想写 2 个测试。
首先测试验证,当 scope.addFocus
属性 设置为 'true'
时,focus
class 在元素上。此测试通过。
然后我更新指令的编译模板,将 scope.addFocus
属性 更改为 'false'
,触发 $digest()
并期望,该指令将更新元素的 classes 并删除 focus
class。这个测试失败了。
这里是一个 link plunkr: http://plnkr.co/edit/k4PBcCwfivsJsbIEUwGd?p=preview
想知道为什么 $compiledTemplate.attr('add-focus', 'false'); $directiveScope.$digest();
不更新
按预期更新 classes?
指令代码
myApp.directive('myDirective', function() {
return {
scope: {
addFocus: '@'
},
restrict: 'A',
link: function (scope, element, attr) {
scope.$watch(
function() { return scope.addFocus; },
function (newValue, oldValue) {
if (newValue === 'true') {
element.addClass('focus');
} else {
element.removeClass('focus');
}
},
false
);
}
};
});
测试
describe('myApp', function () {
var $compile, $timeout, $rootScope;
var $directiveScope;
var template = '<div my-Directive add-focus="true"></div>';
var $compiledTemplate;
beforeEach(function () {
module('myApp');
});
beforeEach(angular.mock.inject(function(_$compile_, _$timeout_, _$rootScope_) {
$compile = _$compile_;
$timeout = _$timeout_;
$rootScope = _$rootScope_;
}
));
beforeEach(function() {
$directiveScope = $rootScope.$new();
$compiledTemplate = $compile(template)($directiveScope);
$directiveScope.$digest();
});
// Test 1
it('directive is compiled and has focus class', function() {
console.log('test1', $compiledTemplate[0]);
expect($compiledTemplate.hasClass('focus')).toBe(true);
});
// Test 2
it('focus class is removed', function() {
$compiledTemplate.attr('add-focus', 'false');
$directiveScope.$digest();
$timeout(function() {
console.log('test2', $compiledTemplate[0]);
expect($compiledTemplate.hasClass('focus')).toBe(false);
}, 0);
$timeout.flush();
});
});
更新了 Plunker
问题是 watcher 没有被调用。我们需要同样使用 isolateScope。我创建了如下的 isolateScope :
isolateScope = $compiledTemplate.isolateScope();
并切换规范中的 addFocus 值以触发观察器
isolateScope.addFocus = false;
答案已给出并被接受,尽管它不好:当您使用输入测试指令时 - 测试输入,不要直接更改指令范围。
最短的例子是:
beforeEach(function() {
$upperScope = $rootScope.$new();
$upperScope.param = true;
$compiledTemplate = $compile('<div my-Directive add-focus="{{param}}"></div>')($upperScope);
$upperScope.$digest();
});
// Test 1
it('directive is compiled and has focus class', function() {
expect($compiledTemplate.hasClass('focus')).toBe(true);
});
// Test 2
it('focus class is removed', function() {
$upperScope.param = false;
$upperScope.$digest();
expect($compiledTemplate.hasClass('focus')).toBe(false);
});