Как проверить, был ли мой элемент сосредоточен в unit test
У меня есть следующая директива для автофокусировки поля:
.directive('ngAutofocus', function ($timeout) {
return {
restrict: 'A',
link: function (scope, elm) {
$timeout(function () {
elm[0].focus();
});
}
};
}
Как я мог бы unit test это? Я пробовал несколько вещей, таких как следующий селектор, но все они возвращают ошибки или false:
console.log($(elm[0]).is(':focus'));
Мой unit test настроен следующим образом:
elm = angular.element('<input type="text" name="textfield1" ng-autofocus>');
$scope.$digest();
$compile(elm)($scope);
Ответы
Ответ 1
Я понял это, и это было довольно очевидно на самом деле;
it('should set the focus on timeout', function () {
spyOn(elm[0],'focus');
$timeout.flush();
expect(elm[0].focus).toHaveBeenCalled();
})
Моя проблема была в два раза:
- Я не вызывал функцию тайм-аута, поэтому тайм-аут не происходил, а
- Я пытался посмотреть на атрибут фокуса элемента, тогда как просто смотреть на вызов функции focus() гораздо больше похоже на модульное тестирование. Атрибут focus - это то, что действительно принадлежит территории тестирования e2e.
Ответ 2
Вы можете использовать document.activeElement
для проверки фокуса. Единственным недостатком является то, что HTML необходимо добавить в тело документа для работы.
https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
Ответ 3
Ниже приведено более подробное решение, которое позволяет проверить (шпионить) фокус, который выполняется немедленно (т.е. no $timeout
или другое событие). Ключ должен сначала выполнить DOM element
перед $compile
:
'use strict';
describe('Testing the focus call from the link function', function () {
var $compile;
var $rootScope;
beforeEach(angular.mock.module('auto-focus-module'));
beforeEach(inject(function (_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
it('should automatically focus when calling the link function', function () {
var $scope = $rootScope.$new();
// create an uncompiled DOM element so we can bind the focus spy
var rawEl = angular.element('<input auto-focus-directive>');
// set the spy
spyOn(rawEl[0], 'focus');
// compile the rawEl so that compile and link functions run
$compile(rawEl)($scope);
expect(rawEl[0].focus).toHaveBeenCalled();
});
});
С функцией directive
и link
, которая может выглядеть так:
(function () {
'use strict';
angular.module('auto-focus-module')
.directive('autoFocusDirective', autoFocusDirective);
function autoFocusDirective () {
return {
link: link
};
function link (scope, elem) {
elem[0].focus();
}
}
})();
Ответ 4
Вы должны использовать angular.element api - jQuery lite - и использовать метод triggerHandler().
it('should have focus', function() {
elm.triggerHandler('focus');
expect(elm).toBeInFocus() //PSEUDO CODE - you will need to see how this can be tested
}
http://docs.angularjs.org/api/ng/function/angular.element
http://api.jquery.com/triggerhandler/
Потенциальная область для тестирования знаний по тестированию:
https://shanetomlinson.com/2014/test-element-focus-javascript
Также вы относительно своего unit test - вам не нужно добавлять элемент в тело, его можно протестировать без этого.