Подтвердить что ты не робот

Как проверить, был ли мой элемент сосредоточен в 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);
4b9b3361

Ответ 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 - вам не нужно добавлять элемент в тело, его можно протестировать без этого.