gpt4 book ai didi

angularjs - 更新 ngModel 的单元测试 Angular 指令

转载 作者:行者123 更新时间:2023-12-04 11:51:16 29 4
gpt4 key购买 nike

我正在尝试测试我为验证输入而编写的指令,但遇到了一些麻烦。
指令管理的输入应包含有效的十六进制颜色值,如果用户使用无效值对其进行修改,我想取消此修改。我的指令如下,并且按预期工作:

module.directive('colorValidate', function() {
return {
restrict: 'A',
scope: {
color: '=ngModel'
},
link: function(scope, element) {
var previousValue = '#ffffff';
//pattern that accept #ff0000 or #f00
var colorPattern = new RegExp('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$');
element.on('focus', function() {
previousValue = scope.color;
});
element.on('blur', function() {
if (!colorPattern.test(scope.color)) {
scope.$apply(function() {
scope.color = previousValue;
});
}
else {
scope.$apply(function() {
scope.color = scope.color.toLowerCase();
});
}
});
}
};
});

这是使用此指令的输入示例:
<input color-validate type="text" ng-model="color.color"/>

第一个问题:这种访问和修改元素的ngModel的方式正确吗?

然后我的主要问题是测试部分。这是我编写的两个简单的测试,但它们并没有真正起作用:
describe('colorValidate directive', function() {
var scope,
elem,
compiled,
html;

beforeEach(function() {
html = '<input color-validate type="text" ng-model="color.color"/>';

inject(function($compile, $rootScope) {
scope = $rootScope.$new();
scope.color = {color: '#aaaaaa'};
elem = angular.element(html);
compiled = $compile(elem);
compiled(scope);
scope.$digest();
});
});

it('should permit valid 6-chars color value', function() {
elem.triggerHandler('focus');
elem.val('#FF0000');
elem.triggerHandler('blur');
scope.$digest();
expect(elem.val()).toBe('#FF0000');
});

it('should reject non valid color values', function() {
elem.triggerHandler('focus');
elem.val('#F00F');
scope.$digest();
elem.triggerHandler('blur');
expect(elem.val()).toBe('#aaaaaa');
});
});

第一次测试成功,第二次失败,因为测试的值是“#F00F”而不是“#aaaaaa”。基本上,我的测试都没有真正修改指令处理的 ngModel 值......

最佳答案

调用 elem.val() 实际上不会导致 scope.color 得到更新。换句话说,这个测试将失败:

it("should set scope", function () {
elem.triggerHandler("focus");
elem.val("#FF0000");
scope.$digest();
elem.triggerHandler("blur");

//Will fail: expected #aaaaaa to be #ff0000
expect(scope.color.color).toBe("#ff0000");
});

这是因为 ngModel 绑定(bind)到输入上的关键事件并在该点更新模型(范围)。在元素上调用 val() 或 value 不会触发 angular 认为发生了变化的事件(即使在 $digest 循环中)。因此,您应该通过更改模型值并断言它们被接受或重置来运行测试:
it('should permit valid 6-chars color value', function() {
elem.triggerHandler('focus');
scope.color.color = '#FF0000';
//need to trigger a digest here for the two-way binding
scope.$digest();
elem.triggerHandler('blur');
//Don't need a $digest here because you call scope.$apply() within the blur in both if/else conditions
//scope.$digest();
expect(scope.color.color).toBe('#ff0000');
});

it('should reject non valid color values', function() {
elem.triggerHandler('focus');
scope.color.color = '#F00F';
//need to trigger a digest here for the two-way binding
scope.$digest();
elem.triggerHandler('blur');
expect(scope.color.color).toBe('#aaaaaa');
});

您不需要测试该值是否已更新,因为大概 Angular 已经编写了测试以确保当指令具有双向绑定(bind) (=ngModel) 时,当指令内的范围值更改时 View 会更新。

关于angularjs - 更新 ngModel 的单元测试 Angular 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27150805/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com