Короткая версия: У меня есть директива, которая использует «новую область» (то есть, scope:true
; не изолят сфера), которая, как представляется, прекрасно работать, когда я взаимодействовать с приложением, но не появляются, чтобы обновить scope
наблюдаемым способом в модульных тестах. Зачем вносить изменения в field
по направлению директивы не, наблюдаемый в модульном тесте?Единичное тестирование AngularJS Директивы: не обновляемые области?
Пример в Plunker: http://plnkr.co/edit/gpzHsX?p=preview
Вот директива:
angular.module('app').directive('ngxBlurry', [
function() {
return {
restrict:'C',
replace:false,
scope:true,
link: function(scope, element, attrs) {
element.bind('blur', function() {
var val = element.val();
scope.$apply(function(scope) {
scope.field = val;
});
});
scope.$watch('field', function(n, o) {
if (n !== o) {
scope.fields[n] = scope.fields[o];
delete scope.fields[o];
}
});
}
};
}
]);
Он привыкает примерно следующим образом:
<div ng-controller="FooContoller">
<div ng-repeat="(field, value) in fields">
<input value="{{field}}" type="text" class="ngx-blurry"/>
<strong>"field" is «{{field}}»</strong>
</div>
</div>
Предполагая, что fields
выглядит примерно так:
$scope.fields = {
'foo':true,
'bar':true,
'baz':true,
'':true
};
А вот тестовый модуль:
describe('ngxBlurry', function() {
var scope,
element,
template = '<input value="{{field}}" type="text" class="ngx-blurry"/>';
beforeEach(module('app'));
beforeEach(inject(function($rootScope, $compile) {
scope = $rootScope.$new();
scope.fields = {'foo':true, '':true};
scope.field = '';
element = $compile(template)(scope);
}));
it('defers update until after blur', function() {
spyOn(scope, '$apply');
element.val('baz');
element.triggerHandler('blur');
// true:
expect(scope.$apply).toHaveBeenCalled();
// false!?
expect(scope.field).toBe('baz');
scope.$digest();
// still false:
expect(scope.field).toBe('baz');
element.scope().$digest();
// *still* false:
expect(scope.field).toBe('baz');
// also false:
expect(element.scope().field).toBe('baz');
});
});
Теперь при взаимодействии с приложением:
- Я могу ввести в
input
и любые обновления ключей в$scope.fields
не откладывается до размытия событие в этом поле. - В тесте шпион жасмин сообщает, что призыв к
$apply
происходит но ... - ... функция, которая должна быть выполнена в контексте этого
$apply
является (видимо) не вызывался , - ... и не вызывается выражение
$watch
.
Сама директива в контексте запущенного приложения работает нормально, но я не могу найти причин, по которым я не могу наблюдать за изменениями с помощью единичного теста.
Запрет на редизайн директивы (например, использование области изоляции и событий $emit
): есть ли что-нибудь, что я пропустил здесь? Что-то мне нужно изменить по поводу директивы? или какой-то трюк, чтобы сделать эти изменения наблюдаемыми в модульном тесте?