jasmine 是否可以访问 angular 指令控制器中定义的范围方法?
Is it possible for jasmine to access the scope methods defined in an angular directive controller?
我正在尝试对如下指令进行单元测试。我希望能够调用指令控制器 ($scope.save
) 中定义的函数,但我的测试似乎根本无法访问该范围。
我也尝试了 isolateScope()
,但是没有像我预期的那样 return 内部 $scope 对象。也许我做错了。
如何在下面的示例中获取 myDir
的 $scope? (或者如果您愿意,可以在 fiddle 处:http://jsfiddle.net/lalanl/8fkdsme3/)
angular.module('app', []).directive([
function(myService) {
return {
restrict: 'E',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function($scope) {
$scope.someVal = 'porcupine';
$scope.save = function() { /* ... */ };
}
}
}
]);
describe('myDir', function() {
var $compile, $http, $httpBackend, $scope, $rootScope, $q;
var element;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
$compile = _$compile_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$q = _$q_;
});
$scope.data = "some data";
element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
$rootScope.$digest();
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
});
it('should let me see its guts', function() {
expect($scope.save).toBeTruthy();
expect(typeof $scope.save).toBe("function");
});
});
<html>
<head>
<style type="text/css">
@charset "UTF-8";
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak,
.ng-hide:not(.ng-hide-animate) {
display: none !important;
}
ng\:form {
display: block;
}
</style>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>SO question - jsFiddle demo</title>
<script type="text/javascript" src="/js/lib/dummy.js"></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine.js"></script>
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine-html.js"></script>
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/boot.js"></script>
<link rel="stylesheet" type="text/css" href="http://jasmine.github.io/2.0/lib/jasmine.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-mocks.js"></script>
<style type="text/css">
</style>
<script type="text/javascript">
//<![CDATA[
angular.module('app', []).directive([
function(myService) {
return {
restrict: 'E',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function($scope) {
$scope.someVal = 'porcupine';
$scope.save = function() { /* ... */ };
}
}
}
]);
describe('myDir', function() {
var $compile, $http, $httpBackend, $scope, $rootScope, $q;
var element;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
$compile = _$compile_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$q = _$q_;
});
$scope.data = "some data";
element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
});
it('should let me see its guts', function() {
expect($scope.save).toBeTruthy();
expect(typeof $scope.save).toBe("function");
});
});
//]]>
</script>
</head>
<body>
</body>
</html>
这是更新后的 jsfiddle,您的测试使用内联指令模板。
编辑:设法让它与外部模板一起工作。我忘了刷新我的 http 请求。我已经更新了完整的答案,你可以看到更新后的 jsfiddle here
您的测试存在一些问题:-
- 在指令定义中,您没有给出指令名称。服务 myService 没有注入到你的指令中,但由于你没有正确定义你的指令,你没有得到那个错误。
- 此外,您在尝试使用之前删除的 element.isolateScope() 来获取元素的范围时是正确的。这是因为该指令将创建一个新的隔离范围。
- 您需要执行 $httpBackEnd.flush() 来刷新外部模板的待处理请求。由于您没有这样做,您测试中的 $compile 没有看到模板并且没有正确编译它。
我还做了一些其他小改动以使其正常工作。
P.S。如果您在项目中使用 karma,我会使用 karma-ng-html2js-preprocessor 来使用外部模板测试指令。看看here.
angular.module('app', []).directive('myDir', function () {
return {
restrict: 'E',
//template: '<div>test:{{someVal}}</div>',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function ($scope) {
$scope.someVal = 'porcupine';
$scope.save = function () { /* ... */
};
}
}
});
describe('myDir', function () {
var $compile, $scope, $rootScope;
var element, isolatedScope;
beforeEach(module('app'));
beforeEach(inject(function (_$compile_, _$rootScope_, $httpBackend) {
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
$compile = _$compile_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
element = $compile('<my-dir info="data"></my-dir>')($scope);
$httpBackend.flush();
isolatedScope = element.isolateScope();
}));
it('should let me see its guts', function () {
expect(isolatedScope.save).toBeTruthy();
expect(typeof isolatedScope.save).toBe("function");
});
});
我正在尝试对如下指令进行单元测试。我希望能够调用指令控制器 ($scope.save
) 中定义的函数,但我的测试似乎根本无法访问该范围。
我也尝试了 isolateScope()
,但是没有像我预期的那样 return 内部 $scope 对象。也许我做错了。
如何在下面的示例中获取 myDir
的 $scope? (或者如果您愿意,可以在 fiddle 处:http://jsfiddle.net/lalanl/8fkdsme3/)
angular.module('app', []).directive([
function(myService) {
return {
restrict: 'E',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function($scope) {
$scope.someVal = 'porcupine';
$scope.save = function() { /* ... */ };
}
}
}
]);
describe('myDir', function() {
var $compile, $http, $httpBackend, $scope, $rootScope, $q;
var element;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
$compile = _$compile_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$q = _$q_;
});
$scope.data = "some data";
element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
$rootScope.$digest();
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
});
it('should let me see its guts', function() {
expect($scope.save).toBeTruthy();
expect(typeof $scope.save).toBe("function");
});
});
<html>
<head>
<style type="text/css">
@charset "UTF-8";
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak,
.ng-hide:not(.ng-hide-animate) {
display: none !important;
}
ng\:form {
display: block;
}
</style>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>SO question - jsFiddle demo</title>
<script type="text/javascript" src="/js/lib/dummy.js"></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine.js"></script>
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/jasmine-html.js"></script>
<script type="text/javascript" src="http://jasmine.github.io/2.0/lib/boot.js"></script>
<link rel="stylesheet" type="text/css" href="http://jasmine.github.io/2.0/lib/jasmine.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-mocks.js"></script>
<style type="text/css">
</style>
<script type="text/javascript">
//<![CDATA[
angular.module('app', []).directive([
function(myService) {
return {
restrict: 'E',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function($scope) {
$scope.someVal = 'porcupine';
$scope.save = function() { /* ... */ };
}
}
}
]);
describe('myDir', function() {
var $compile, $http, $httpBackend, $scope, $rootScope, $q;
var element;
beforeEach(module('app'));
beforeEach(function() {
inject(function(_$compile_, _$http_, _$httpBackend_, _$rootScope_, _$q_) {
$compile = _$compile_;
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$q = _$q_;
});
$scope.data = "some data";
element = $compile(angular.element('<my-dir info="data"></my-dir>'), $scope);
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
});
it('should let me see its guts', function() {
expect($scope.save).toBeTruthy();
expect(typeof $scope.save).toBe("function");
});
});
//]]>
</script>
</head>
<body>
</body>
</html>
这是更新后的 jsfiddle,您的测试使用内联指令模板。
编辑:设法让它与外部模板一起工作。我忘了刷新我的 http 请求。我已经更新了完整的答案,你可以看到更新后的 jsfiddle here
您的测试存在一些问题:-
- 在指令定义中,您没有给出指令名称。服务 myService 没有注入到你的指令中,但由于你没有正确定义你的指令,你没有得到那个错误。
- 此外,您在尝试使用之前删除的 element.isolateScope() 来获取元素的范围时是正确的。这是因为该指令将创建一个新的隔离范围。
- 您需要执行 $httpBackEnd.flush() 来刷新外部模板的待处理请求。由于您没有这样做,您测试中的 $compile 没有看到模板并且没有正确编译它。
我还做了一些其他小改动以使其正常工作。
P.S。如果您在项目中使用 karma,我会使用 karma-ng-html2js-preprocessor 来使用外部模板测试指令。看看here.
angular.module('app', []).directive('myDir', function () {
return {
restrict: 'E',
//template: '<div>test:{{someVal}}</div>',
templateUrl: 'path/to/template.html',
scope: {
info: "=info"
},
controller: function ($scope) {
$scope.someVal = 'porcupine';
$scope.save = function () { /* ... */
};
}
}
});
describe('myDir', function () {
var $compile, $scope, $rootScope;
var element, isolatedScope;
beforeEach(module('app'));
beforeEach(inject(function (_$compile_, _$rootScope_, $httpBackend) {
$httpBackend.whenGET('path/to/template.html').respond('<div>test:{{someVal}}</div>');
$compile = _$compile_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
element = $compile('<my-dir info="data"></my-dir>')($scope);
$httpBackend.flush();
isolatedScope = element.isolateScope();
}));
it('should let me see its guts', function () {
expect(isolatedScope.save).toBeTruthy();
expect(typeof isolatedScope.save).toBe("function");
});
});