我正在我的指令的链接函数中设置表单的有效性,它在实践中有效。但是,它似乎将验证器放在错误的元素上,我无法在 Jasmine 单元测试中访问它。这是我所做工作的精简版本:
该指令是嵌套表单的一部分,尽管我认为这没有什么区别:
// directive view
<tfoot ng-form="formStep">
<tr>
<td>
<div test-directive ng-model="testDirective.model" ng-change="checkValidity()"></div>
</td>
</tr>
</tfoot>
在链接函数中,我正在获取表单的模型控制器(或者它是指令的控制器?我不清楚这一点。
// directive linking function
(function () {
'use strict';
angular.module('app')
.directive('testDirective', testDirective);
testDirective.$inject = [];
function testDirective() {
return {
restrict : 'A',
require: 'ngModel',
scope : {
},
replace : true,
template: require('./test.directive.partial.html'),
link: function(scope, element, attributes, ngModelController){
scope.checkValidity = checkValidity;
function checkValidity(){
ngModelController.$setValidity('testError', false);
}
}
};
}
})();
在随后的指令部分中,验证器最终在
<div class="testDirective">
而不是
<div ng-form="testDirectiveForm">
因此,当输入更改时,代码的最终结果是
<div class="testDirective ng-scope ng-isolate-scope ng-invalid-test-error ng-dirty ng-valid-parse">
(至少从单元测试记录时。
// test.directive.partial.html
<div class="testDirective">
<div ng-form="testDirectiveForm">
<label class="radio-inline">
<input type="radio" ng-model="testModel.test" ng-value="true" required ng-change="checkValidity()" />
<strong>option 1</strong>
</label>
</div>
</div>
在单元测试中,如果我控制台.log element.isolateScope().testDirectiveForm.$error 如果我没有为输入设置值,它就会包含必需的错误。但是,它不包含 testError 的错误。这似乎被放在它上面的元素上。
// Unit test
describe('testDirective', function () {
var $scope;
beforeEach(angular.mock.module('app'));
beforeEach(inject(function($rootScope){
$scope = $rootScope.$new();
}));
describe('link function', function(){
var createElement, element, isolateScope;
beforeEach(inject(function($compile){
$scope.ngModel;
element = angular.element('<div test-directive></div>');
element.attr('ng-model', 'ngModel');
createElement = function(){
element = $compile(element)($scope);
};
}));
describe('after link', function () {
beforeEach(inject(function () {
createElement();
}));
describe('after initialization', function () {
beforeEach(function () {
$scope.$apply();
isolateScope = element.isolateScope();
});
it('.checkValidity should set the the error to testError', inject(function($rootScope){
isolateScope.checkValidity();
$rootScope.$digest();
console.log(isolateScope.testDirectiveForm.$error.testError);
expect(isolateScope.testDirectiveForm.$error.testError).toBeDefined();
}));
});
});
});
});
这是怎么回事?我认为我在链接函数中获得的控制器属于该指令,但是如果我在测试中记录"element.scope()",我将无法看到验证器或看到任何检查它的方法。有没有更好的方法呢?
我通过在测试中从 element.data() 获取模型控制器来解决这个问题,如下所示:
// Unit test
describe('testDirective', function () {
var $scope, modelController;
beforeEach(angular.mock.module('app'));
beforeEach(inject(function($rootScope){
$scope = $rootScope.$new();
}));
describe('link function', function(){
var createElement, element, isolateScope;
beforeEach(inject(function($compile){
$scope.ngModel;
element = angular.element('<div test-directive></div>');
element.attr('ng-model', 'ngModel');
createElement = function(){
element = $compile(element)($scope);
};
}));
describe('after link', function () {
beforeEach(inject(function () {
createElement();
}));
describe('after initialization', function () {
beforeEach(function () {
$scope.$apply();
isolateScope = element.isolateScope();
modelController = element.data().$ngModelController;
});
it('.checkValidity should set the the error to testError', inject(function(){
isolateScope.checkValidity();
expect(modelController.$error.testError).toBeDefined();
}));
});
});
});
});
我尝试使用 $validators它适用于我正在处理的组件之一(相同的单元测试有效)。但是,我正在处理的另一个组件每次更新视图时都无法运行验证器。也许与嵌套表单控制器有关?代码是这样的:
ngModelController.$validators.testError = function(modelValue, viewValue) {
if (!(viewValue && viewValue.length)) {
return false;
} else {
return true;
}
};
我还能够通过在链接函数中使用范围将验证器放在testDirectiveForm上来访问隔离作用域上的表单,如下所示:
function checkValidity(){
scope.testDirectiveForm.$setValidity('testError', false);
}
这很容易用我最初所做的进行单元测试:
it('.checkValidity should set the the error to testError', inject(function($rootScope){
isolateScope.checkValidity();
$rootScope.$digest();
console.log(isolateScope.testDirectiveForm.$error.testError);
expect(isolateScope.testDirectiveForm.$error.testError).toBeDefined();
}));
但是,它与项目中其余工作的完成方式不一致。
希望其中一些对某人有所帮助。谢谢大家的回答。