【问题标题】:Jasmine unit test for Angular directiveAngular 指令的 Jasmine 单元测试
【发布时间】:2015-01-18 13:25:12
【问题描述】:

我有以下角度指令,当我将鼠标悬停在跨度上时会添加一个工具提示。

angular.module('mainMod')
    .directive('toolTip', [function() {
        return {
            restrict: 'A',
            scope: {
                theTooltip: '@toolTip'
            },
            link: function(scope, element, attrs){
                element.tooltip({ 
                        delay: 0, 
                        showURL: false, 
                        bodyHandler: function() {
                            return jQuery('<div class="hover">').text(scope.theTooltip);
                        } 
                });
            }
        }
    }])
    ;


<span ng-show="data.tooltip" class="icon" tool-tip="{{data.tooltip}}"></span>

我正在为此指令编写单元测试,atm 我不能使用jasmine-jquery

我对编写单元测试还很陌生,谁能帮帮我?

给我一​​些建议或指向一些有用的资源?

任何意见或建议将不胜感激。

我的atm并不多......

describe('Unit testing tooltip', function() {
    var $compile;
    var $rootScope;

    // Load the myApp module, which contains the directive
    beforeEach(module('mainMod'));

    // Store references to $rootScope and $compile
    // so they are available to all tests in this describe block
    beforeEach(inject(function(_$compile_, _$rootScope_){
      // The injector unwraps the underscores (_) from around the parameter names when matching
      $compile = _$compile_;
      $rootScope = _$rootScope_;
    }));


    it(' ', function() {
        // Compile a piece of HTML containing the directive
        FAILS HERE --> var element = $compile("<span class='icon' tool-tip='{{data.tooltip}}'></span>")($rootScope); 

        $rootScope.$digest();

    });
});

失败并显示

消息
TypeError: undefined is not a function

我认为这是由我上面指定的行末尾的 ($rootScope) 引起的。

【问题讨论】:

    标签: angularjs unit-testing angularjs-directive jasmine


    【解决方案1】:

    在编译之前,你必须先用 angular.element 包装你的 DOM 内容。我不确定您使用的是什么工具提示模块,但我使用了 jQuery UI 工具提示。

        //create a new scope with $rootScope if you want
        $scope  = $rootScope.$new();
    
        var element = angular.element("<span class='icon' tool-tip='This is the tooltip data'></span>");
    
        //use the current scope has just been created above for the directive
        $compile(element)($scope);
    

    还有一件事,因为您在指令中使用了隔离作用域,要从指令中获取当前作用域,您需要调用

       element.isolateScope()
    

    基于此参考:How to Unit Test Isolated Scope Directive in AngularJS

    对于一个工作小提琴,你可以在这里找到它:http://jsfiddle.net/themyth92/4w52wsms/1/

    【讨论】:

    • 根据docs.angularjs.org/api/ng/service/$compile,您不必包装任何东西,字符串模板就可以了。此外,从外部测试单元时,无需担心获得隔离范围。
    • 你有没有试过不使用angular.element,因为当我删除那个部分时,它会导致错误。也许它与角度版本有关。
    • 我使用$compile 来编译所有指令测试中的字符串模板,跨越各种 AngularJS 版本,没有任何问题。
    • 你能用不带角度元素的 $compile 更新我的小提琴吗?会很棒的:)
    • 哇,非常感谢。隔离范围部分怎么样,有什么方法可以得到指令范围?
    【解决方案2】:

    任何单元测试基本上都是一样的——模拟环境,构建单元,检查单元是否以预期的方式与环境交互。在这种情况下,您可能想要模拟工具提示创建者

    spyOn(jQuery.fn, 'tooltip');
    

    然后使用指令编译一些模板(你已经在做),然后在编译的元素上模拟悬停事件,然后检查是否以预期的方式调用了工具提示创建者

    expect(jQuery.fn.tooltip).toHaveBeenCalledWith(jasmine.objectContaining({
        // ... (expected properties)
    }));
    

    如何模拟事件取决于element.tooltip 应该如何工作。如果它真的像你在问题代码中使用的那样工作,你根本不需要模拟任何东西,只需在模板编译后检查预期的交互即可。

    【讨论】:

    • 非常感谢 hon2a。我在问题中描述的方式确实有效。我想我对要采取的步骤有一个很好的了解,但是在我上面强调的那一行中,我的测试失败了,我不知道为什么。
    • @Daft 然后您需要进行一些调试并准确找出失败的原因。从这里开始,在不了解 tooltip 的情况下,我只能看到 3 个可能不存在的东西 - .tooltip 插件、jQuery 函数和 .text 函数。找出是哪一个,然后采取相应的行动。
    • @Daft 在旁注中,你真的不应该使用jQuery('&lt;div class="hover"&gt;') 来创建一个元素。使用jQuery('&lt;div&gt;').addClass('hover')(通过标签名创建元素)或jQuery('&lt;div class="hover"&gt;&lt;/div&gt;')(正确的HTML片段)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 2013-10-18
    • 2018-09-30
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多