如何检查我的元素是否已集中在单元测试中

时间:2022-05-16 20:37:26

I have the following directive to autofocus a field:

我有以下指令来自动对焦字段:

.directive('ngAutofocus', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, elm) {
                $timeout(function () {
                elm[0].focus();
            });
        }
    };
}

How would I unit test this? I tried several things like the following selector but they all return errors or false:

我该如何对此进行单元测试?我尝试了几个像下面的选择器,但它们都返回错误或错误:

console.log($(elm[0]).is(':focus'));

My unit test is set up like this:

我的单元测试设置如下:

elm = angular.element('<input type="text"  name="textfield1" ng-autofocus>');
$scope.$digest();
$compile(elm)($scope);

4 个解决方案

#1


33  

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. 我没有调用超时刷新功能,因此没有发生超时,并且
  3. 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.
  4. 我试图查看元素的焦点属性,而只是查看focus()函数的调用更像是单元测试。焦点属性实际上属于e2e测试区域。

#2


2  

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.

您可以使用document.activeElement来检查焦点。唯一的缺点是需要将HTML添加到文档正文才能使其正常工作。

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

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

#3


0  

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:

下面是一个更详细的解决方案,它允许测试(监视)立即运行的焦点(即没有$ timeout或其他事件)。关键是在$ compile运行之前首先呈现DOM元素:

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

        }

    }

})();

#4


-3  

You should use the angular.element api - jQuery lite - and use the method triggerHandler().

你应该使用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://docs.angularjs.org/api/ng/function/angular.element

http://api.jquery.com/triggerhandler/

http://api.jquery.com/triggerhandler/

Potential Area for some testing focus knowledge:

某些测试重点知识的潜在领域:

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

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.

你也关注你的单元测试 - 你不需要将元素附加到身体上,没有它可以进行测试。

#1


33  

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. 我没有调用超时刷新功能,因此没有发生超时,并且
  3. 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.
  4. 我试图查看元素的焦点属性,而只是查看focus()函数的调用更像是单元测试。焦点属性实际上属于e2e测试区域。

#2


2  

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.

您可以使用document.activeElement来检查焦点。唯一的缺点是需要将HTML添加到文档正文才能使其正常工作。

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

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

#3


0  

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:

下面是一个更详细的解决方案,它允许测试(监视)立即运行的焦点(即没有$ timeout或其他事件)。关键是在$ compile运行之前首先呈现DOM元素:

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

        }

    }

})();

#4


-3  

You should use the angular.element api - jQuery lite - and use the method triggerHandler().

你应该使用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://docs.angularjs.org/api/ng/function/angular.element

http://api.jquery.com/triggerhandler/

http://api.jquery.com/triggerhandler/

Potential Area for some testing focus knowledge:

某些测试重点知识的潜在领域:

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

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.

你也关注你的单元测试 - 你不需要将元素附加到身体上,没有它可以进行测试。