如何在angularjs中测试是不是加载指令

Posted

技术标签:

【中文标题】如何在angularjs中测试是不是加载指令【英文标题】:How to test directive loaded or not in angularjs如何在angularjs中测试是否加载指令 【发布时间】:2017-04-30 17:05:57 【问题描述】:

我已经编写了指令,该指令在参数中采用指令名称并将该指令动态加载为休闲:

.directive("loadDirective", function($compile, $timeout) 
        return 
            restrict: 'E',
            scope: 
                Dtype: '=type',
                subType: '@',
                data: "=data"
            ,
            link: function(scope, element) 
                scope.$watch('Dtype', function() 
                    $timeout(function() 
                        var generatedTemplate = '<div ' + scope.Dtype + (scope.subType ? '-' + scope.subType + '-directive' : '-directive') + ' data="data" >dd</div>';
                        element.empty().append($compile(generatedTemplate)(scope));
                    )
                )
            ,
        ;
    )

这是我将动态加载的指令之一

.directive("dailyIntervalDirective", function() 
        return 
            scope: 
                data: '='
            ,
            restrict: 'A',
            templateUrl: '/flat-ui/tpls/daily-interval.html'
        ;
    )

现在我正在尝试为 loadDiretive 编写测试用例来测试它是否加载指令,如下所示:

describe("loadDirective directive", function() 
    var elm, scope;
    beforeEach(module('guideApp.directives'));
    beforeEach(module('/flat-ui/tpls/daily-interval.html'));
    beforeEach(angular.mock.inject(function($rootScope, $compile) 
        scope = $rootScope;
        elm = angular.element('<load-directive type="directive" sub-type="interval" data="schedulerData"></load-directive>');
        compile = $compile;
        compile(elm)(scope);
        scope.schedulerData = 
            interval: 1,
        
        scope.$digest();
    ));
    it("should be able to load daily directive", function() 
        scope.directive = "daily";
        var intervaldirective = elm.find('div[daily-interval-directive]');
        expect(intervaldirective.length).toEqual(1);
    );
   );

这对我来说不是很好。我试图记录榆树,但它没有加载dailyInterevalDirective。

【问题讨论】:

嗨 Rhushikesh,指令“loadDirective”和“dailyIntervalDirective”是否按预期工作?? 它工作正常吗?但是当我编写测试用例时,现在可以测试它的加载与否 【参考方案1】:

您的 dailyIntervalDirective 似乎有一个 templateUrl

现在,如果指令有效,那么在测试中,您可以期待使用 httpBackend"/flat-ui/tpls/daily-interval.html" /strong> 服务。因为应该在编译 dailyIntervalDirective 指令后立即加载该模板。希望能帮助到你。 :)

[编辑] 我也怀疑elm.find('div[daily-interval-directive]'); 是否会起作用,正如angular docs. 中提到的那样, find() - Limited to lookups by tag name

根据要求,请在下面找到示例代码sn-p:

// -----in your spec file----  
describe("loadDirective directive", function() 
var elm, scope,$httpBackend;
beforeEach(module('guideApp.directives'));
beforeEach(angular.mock.inject(function($rootScope, $compile,$httpBackend) 
    scope = $rootScope;
    $httpBackend= $httpBackend;
    $httpBackend.whenGET('/flat-ui/tpls/daily-interval.html').respond(200, 'any response you can send here, even a blank string, as it is just to test ');
    elm = angular.element('<load-directive type="directive" sub-type="interval" data="schedulerData"></load-directive>');
    compile = $compile;
    compile(elm)(scope);
    scope.schedulerData = 
        interval: 1,
    
    scope.$digest();
));
it("should try to load daily directive's template", function() 
    scope.directive = "daily";
    $httpBackend.expectGET('/flat-ui/tpls/daily-interval.html');
    $httpBackend.flush();
);
);

如果这个测试用例应该通过,则说明指令已加载。

【讨论】:

还有其他方法,比如不使用匿名函数创建“dailyIntervalDirective”,而是创建一个命名函数,然后在测试用例中监视该函数以检查它是否被调用。 ;) 我之前做过Each(module('/flat-ui/tpls/daily-interval.html'));获取模板 不...抱歉,这不是获取模板的方式...您也不需要获取模板..您只需检查是否有http调用来获取所需的模板,如果有模板调用,则确认指令已加载【参考方案2】:

这个问题有两个部分。第一个问题是指令定义对象中的templateUrl。正如@r_goyal here 所回答的那样,每当通过URL 加载模板时,它都会通过GET 调用加载。因此,您需要使用 httpBackend 模拟它。

第二部分是$timeout的用法。 $timeout 异步执行,但测试同步执行。这就是你测试失败的原因。为了测试$timeout 中的代码,我们使用$timeout service found in angular.mock module 模拟它。我们需要在模拟$timeout 服务上使用$timeout.flush 方法来强制原始$timeout 中的代码同步执行。这是一个完全更正的示例:

describe("loadDirective directive", function() 
    var elm, scope, timeout, httpBackend;
    beforeEach(module('guideApp.directives'));
    beforeEach(module('/flat-ui/tpls/daily-interval.html'));
    beforeEach(angular.mock.inject(function($rootScope, $compile, $timeout, $httpBackend) 
        scope = $rootScope;
        timeout = $timeout;
        httpBackend = $httpBackend;

        elm = angular.element('<load-directive type="directive" sub-type="interval" data="schedulerData"></load-directive>');
        compile = $compile;
        compile(elm)(scope);
        scope.schedulerData = 
            interval: 1,
        
        scope.$digest();
    ));
    it("should be able to load daily directive", function() 
        scope.directive = "daily";
        httpBackend.when('GET','/flat-ui/tpls/daily-interval.html').respond("<div> Any mock template or the original template loaded as a fixture </div>");

        scope.$apply();
        timeout.flush();
        httpBackend.flush();
        var intervaldirective = elm.find('div[daily-interval-directive]');
        expect(intervaldirective.length).toEqual(1);
    );
   );

有几点需要注意:

这里我们调用scope.$apply()作为加载指令的代码 动态地在 watch 内。即使您将Dtype 变量设置为 范围为新值,watch 函数 将不会执行 直到一个消化循环开始。

然后我们调用timeout.flush()强制$timeout中的代码 同步执行

You can read more about testing $timeout here

希望对你有帮助

【讨论】:

以上是关于如何在angularjs中测试是不是加载指令的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS – 如何在 Jasmine 中为输入事件指令编写单元测试

如何在 AngularJS 中对隔离范围指令进行单元测试

在AngularJS指令中为$ http.get加载模板属性

如何修复 AngularJS 指令中的“jQuery 可拖动不是函数”

angularJs如何实现不同页面引入不同的js文件?

如何在AngularJS中重新加载md-icon?