How do I check if my element has been focussed in a unit test

后端 未结 4 1729
梦毁少年i
梦毁少年i 2020-12-14 18:43

I have the following directive to autofocus a field:

.directive(\'ngAutofocus\', function ($timeout) {
    return {
        restrict: \'A\',
        link: fu         


        
相关标签:
4条回答
  • 2020-12-14 18:58

    A more verbose solution below, which allows testing (spying on) the focus that runs immediately (i.e. no $timeout or other event). The key is to first render a DOM element before $compile runs:

    '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();
    
        });
    
    });
    

    With a directive and link function that could look like:

    (function () {
    
        'use strict';
    
        angular.module('auto-focus-module')
            .directive('autoFocusDirective', autoFocusDirective);
    
        function autoFocusDirective () {
    
            return {
                link: link
            };
    
            function link (scope, elem) {
    
                elem[0].focus();
    
            }
    
        }
    
    })();
    
    0 讨论(0)
  • 2020-12-14 18:59

    You can use document.activeElement to check focus. The only downside being that the HTML needs to be added to the document body for this to work.

    https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement

    0 讨论(0)
  • 2020-12-14 19:08

    You should use the angular.element api - jQuery lite - and use the method 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/

    Potential Area for some testing focus knowledge:

    https://shanetomlinson.com/2014/test-element-focus-javascript

    Also you concerning your unit test - you don't need to append the element to the body, it's possible to test without that.

    0 讨论(0)
  • 2020-12-14 19:19

    I figured it out, and it was pretty obvious actually;

    it('should set the focus on timeout', function () {
        spyOn(elm[0],'focus');
        $timeout.flush();
        expect(elm[0].focus).toHaveBeenCalled();
    })
    

    My problem was two-fold:

    1. I wasn't calling the timeout flush function so timeout wasn't occuring, and
    2. I was trying to look at the focus attribute of the element whereas just looking at the call of the focus() function is much more like unit-testing. The focus attribute is something that really belongs to the e2e testing territory.
    0 讨论(0)
提交回复
热议问题