如何在 angularjs 中测试指令加载与否
How to test directive loaded or not in angularjs
我已经编写了指令,该指令在参数中采用指令名称并将该指令动态加载为休闲:
.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。
您的 dailyIntervalDirective
似乎有 templateUrl
.
现在,如果指令有效,那么在测试中,您可以期望 GET
调用 "/flat-ui/tpls/daily-interval.html"
使用 httpBackend
服务。因为一旦编译了 dailyIntervalDirective
指令,就应该加载该模板。希望能帮助到你。 :)
[编辑]
我也怀疑 elm.find('div[daily-interval-directive]');
是否会起作用,正如 angular docs. 中提到的 find() - Limited to lookups by tag name
根据要求,请在下面找到示例代码片段:
// -----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();
});
});
如果此测试用例通过,则表示指令已加载。
问题分为两部分。第一个问题是 指令定义对象 中的 templateUrl
。正如@r_goyal 所回答的那样,只要通过 URL 加载模板,它就会通过 GET
调用加载。因此,您需要使用 httpBackend
.
来模拟它
第二部分是$timeout
的用法。 $timeout 异步执行,但测试同步执行。这就是您测试失败的原因。为了测试 $timeout
中的代码,我们使用 $timeout service found in angular.mock module 模拟它。我们需要在 mock $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
希望对您有所帮助
我已经编写了指令,该指令在参数中采用指令名称并将该指令动态加载为休闲:
.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。
您的 dailyIntervalDirective
似乎有 templateUrl
.
现在,如果指令有效,那么在测试中,您可以期望 GET
调用 "/flat-ui/tpls/daily-interval.html"
使用 httpBackend
服务。因为一旦编译了 dailyIntervalDirective
指令,就应该加载该模板。希望能帮助到你。 :)
[编辑]
我也怀疑 elm.find('div[daily-interval-directive]');
是否会起作用,正如 angular docs. 中提到的 find() - Limited to lookups by tag name
根据要求,请在下面找到示例代码片段:
// -----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();
});
});
如果此测试用例通过,则表示指令已加载。
问题分为两部分。第一个问题是 指令定义对象 中的 templateUrl
。正如@r_goyal GET
调用加载。因此,您需要使用 httpBackend
.
第二部分是$timeout
的用法。 $timeout 异步执行,但测试同步执行。这就是您测试失败的原因。为了测试 $timeout
中的代码,我们使用 $timeout service found in angular.mock module 模拟它。我们需要在 mock $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
希望对您有所帮助