I have some JavaScript written in the context of AngularJS. My relevant JavaScript looks like the following:
.factory('$myFactory', function ($myLibrary, $interpolate) {
return {
myFunction: function ($scope, $attrs, p) {
if (p !== null) {
$attrs.set('myProperty', p);
}
}
};
I am trying to unit test this code. In an attempt to unit test the code, I'm using Jasmine.
it('should set myProperty', inject(function ($scope, $myFactory) {
// $myFactory.myFunction($scope
}));
I can't figure out how to inject some $attrs from my unit test. How do I do that? I can successfully get my $scope setup. However, I don't understand how to inject $attrs. Is there something special about it that I'm not aware of? I'm having a similar issue with $element, though that one is out of the context of this specific test.
Thank you!
Overview. $injector is used to retrieve object instances as defined by provider, instantiate types, invoke methods, and load modules. The following always holds true: var $injector = angular.
The "Application Module" can be injected as a dependency in AngularJS.
Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"> So in this case you will have access to the symbol and readonly attributes.
Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.
Here is a plunker: http://plnkr.co/edit/k1cxSjpAXhhJUEOcx9PG
Maybe there is a better solution but That's what I got.
$scope
is easy to get, you can inject $rootScope
everywhere$attrs
on the other hand is only available through the $compile
variable (it lives in compile.js)My solution is to create a fake controller , to compile it and to hijack it's $attrs
.
var injected = null
function fakeController($scope, $attrs, $element){
injected = {}
injected.$scope = $scope;
injected.$attrs = $attrs;
injected.$element = $element;
}
describe('Testing a Hello World controller', function() {
var $scope = null;
var $attrs = null;
var $element = null;
var ctrl = null;
//you need to indicate your module in a test
beforeEach(module('plunker'));
beforeEach(inject(function($compile, $rootScope, $controller) {
$compile('<span ng-controller="fakeController"></span>')($rootScope);
$scope = injected.$scope;
$attrs = injected.$attrs;
$element = injected.$element;
ctrl = $controller('MainCtrl', {
$scope: $scope,
$attrs: $attrs,
$element: $element
});
}));
it('should say hallo to the World', function() {
expect($scope.name).toEqual('World');
});
});
seems that you can just instantiate the controller with empty object, as well...
ctrl = $controller('MyCtrl', {
$scope: $scope,
$attrs: {}
});
In latest versions of AngularJS a controller needs to be provided to get full $attrs.
See $controllerProvider documentation.
describe('angular-component-controller', function() {
// save injected parameters of controller
var injected = {};
var controller;
// @see $https://docs.angularjs.org/api/ngMock/service/$componentController
// we need to extract those from $compile instead of use as locals
angular.module('locals', []).controller('controller',
['$attrs', function($attrs) {
injected.$attrs = $attrs;
}]
);
beforeEach(module('locals'));
beforeEach(inject(function($rootScope, $compile, $componentController) {
// invoke dummy component to get $attrs
$compile('<span ng-controller="controller">')($rootScope);
var locals = {};
locals.$scope = $rootScope.$new();
locals.$attrs = injected.$attrs;
var bindings = {};
controller = $componentController('component', locals, bindings);
}));
});
See this gist AngularJS $componentController unit test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With