Angular JS 中 focus-next 自定义指令的测试用例

Test case for focus-next custom directive in Angular JS

我创建了一个自定义指令来解决我的应用程序中一些与焦点相关的问题。

指令代码:

(function() {
    angular.module("FocusNextModule", []).directive("focusNext", function() {
        return {
            restrict: "A",
            link: function($scope, elem, attrs) {
                elem.bind("focus", function(e) {
                    var code = e.which || e.keyCode;

                    var nextElem = document.getElementById(attrs.focusNext);
                    if (nextElem === null || nextElem === undefined) {
                        var altElem = document.getElementById(attrs.focusNextAlt);
                        if (angular.element(altElem).hasClass('ng-hide') === false) {
                            altElem.focus();
                        } else {
                            var selfElem = document.getElementById(attrs.focusSelf);
                            selfElem.focus();
                        }
                        e.preventDefault();
                    } else {
                        nextElem.focus();
                        e.preventDefault();
                    }
                });
            }
        };
    });
})();

如何在模板中使用使用InT emplate

<md-button id="idOfElementC">MyButton</md-button>    
<div tabindex="0" focus-next="idOfElementA" focus-next-alt="idOfElementB" focus-self="idOfElementC"></div>

注: 使用 focus-next 指令,具有 "idOfElementC" id 的元素将位于 div 之上。

指令是如何工作的?

当我们在 ID 为 "idOfElementC" 的元素(此处为按钮)上按 Tab 键时,焦点将使用 focus-next 指令转到 div。 div 将使用以下情况将焦点重定向到其他元素:

a) 首先它会检查是否有id为"idOfElementA"的元素。如果元素存在,则该元素将获得焦点。

b) 如果 ID 为 "idOfElementA" 的元素不存在,则 "idOfElementB" 将获得焦点。

c) 如果 ID 为 "idOfElementB" 的元素也不存在,那么最终 "idOfElementA"(按下的选项卡)将获得焦点。

该指令工作正常并解决了我所有的问题。但是,我需要为此指令编写 jasmine 测试用例。

谁能指导我如何编写 Jasmine 焦点测试用例?

更新: 根据@PetrAveryanov 的评论,该指令看起来很糟糕,我完全同意。

更新指令:

(function() {
    angular.module("FocusNextModule", []).directive("focusNext", function() {
        return {
            restrict: "A",
            link: function($scope, elem, attrs) {
                elem.bind("focus", function(e) {
                    var elemToFocus = document.getElementById(attrs.focusNext) || document.getElementById(attrs.focusNextAlt);
                    /*jshint -W030 */
                    angular.element(elemToFocus).hasClass('ng-hide') === false ? elemToFocus.focus() : document.getElementById(attrs.focusSelf).focus();
                    e.preventDefault();
                });
            }
        };
    });
})();

终于知道如何为指令编写测试用例了。

describe('focus-next-directive test', function() {
    var compile, scope;

    beforeEach(module(FocusNextModule));

    beforeEach(inject(function($compile, $rootScope) {
        compile = $compile;
        scope = $rootScope.$new();
    }));

    it('should focus the next element', function() {
        var div = compile('<div tabindex="0" focus-next="idTestNext"/>')(scope);
        var nextElem = compile('<input id="idTestNext" type="text" />')(scope);
        angular.element(document.body).append(div);
        angular.element(document.body).append(nextElem);
        div.focus();
        expect(nextElem).toEqual(angular.element(document.activeElement));
        div.remove();
        nextElem.remove();
    });

    it('should focus the next alternative element', function() {
        var div = compile('<div tabindex="0" focus-next="idTestNext" focus-next-alt="idTestNextAlt"/>')(scope);
        var nextAltElem = compile('<input id="idTestNextAlt" type="text" />')(scope);
        angular.element(document.body).append(div);
        angular.element(document.body).append(nextAltElem);
        div.focus();
        expect(nextAltElem).toEqual(angular.element(document.activeElement));
        div.remove();
        nextAltElem.remove();
    });

    it('should focus the Self element', function() {
        var selfElem = compile('<input id="idTestSelf" type="text" ng-class="ng-hide"/>')(scope);
        var div = compile('<div tabindex="0" focus-next="idTestNext" focus-next-alt="idTestNextAlt" focus-self="idTestSelf"/>')(scope);
        var nextAltElem = compile('<input id="idTestNextAlt" type="text" class="ng-hide"/>')(scope);
        angular.element(document.body).append(selfElem);
        angular.element(document.body).append(div);
        angular.element(document.body).append(nextAltElem);
        div.focus();
        expect(selfElem).toEqual(angular.element(document.activeElement));
        div.remove();
        selfElem.remove();
        nextAltElem.remove();
    });
});