Unit testing a helper inside a custom provider in angularjs - angularjs

I have this provider:
angular.module('app').provider('appProvider', function() {
this.$get = Helper;
function Helper() {
function method() {
return true;
};
return {
method: method
};
});
When unit testing it, I can reach appProvider, but not the Helper in unit tests. I've been trying this:
describe('test', function() {
var prov;
beforeEach(angular.mock.module('app', function(appProvider) {
prov = appProvider;
}));
it('provider', inject(function() {
expect(prov.Helper.method()).toEqual(true);
}));
});
And getting this error:
TypeError: 'undefined' is not an object (evaluating 'prov.Helper.method()')
Question is: How do I reach method() in order to evaluate is correct behaviour?

You are trying to test a method of the service that your provider provides, so it seems a bit roundabout to test the provider. Why not just test the service instead?

Related

How to mock angular.element.injector().get;

I have controller code like this in an angularjs file...
function sendAnalytics(searchParams) {
var analyticServiceCall = angular.element(document.body).injector().get('SomeElement');
};
When I run test cases attached with the above controller I get the following error
* TypeError: Cannot call method "get" of undefined in http://localhost:46309/src/soemFolder/someController.js (line XYZ)
What I am understanding is, I need to mock angular.element(document.body).injector().get function but how to do it?
beforeEach(inject(function($injector) {
angular.element.fn.extend({ injector: function() { return $injector } });
});
You can find more information here

How can I Unit Test Rest Angular Service and Controller?

Rest-angular for Api Calling .
My Aim to Write a Unit test Case by calling Controller and Test all the Scope are assigned,the Code blocks of with REST API Response But not MOCK RESPONSE.
Rest Angular Service :-
(function () {
angular.module('movieApp').service('movieApiService', callMoviesApi);
function callMoviesApi(Restangular) {
this.getMyMovie= function (Id) {
return Restangular.one('movies/' + movieId).get().then(function(result){
return result.plain();
});
};
this.getMoviesList = function () {
return Restangular.all('movies').getList().then(function(result){
return result.plain();
});
};
}
}());
Where I am Injecting this Service to Controller as a Dependency
Controller Code Follows :-
angular.module('movieApp').controller('MoviesController', ['$scope','movieApiService',
function ($scope, MovieService) {
$scope.movie = $stateParams.movieId;
MovieService.getMovieDetails($scope.movie).then(function (result) {
$scope.movieDetails = result;
$scope.movieId = result._id;
$scope.movieName = result.displayName;
});
}
]);
I did tried to Write a Unit test for the Above Controller not Going good :-(
Test Code Follows:-
'use strict';
(function() {
describe('MoviesController', function() {
//Initialize global variables
var scope,stateParams={},
MoviesController;
// Load the main application module
beforeEach(module('movieApp'));
beforeEach(inject(function($controller, $rootScope,$stateParams) {
scope = $rootScope.$new();
stateParams.movieId='Baahubali';
HomeController = $controller('MoviesController', {
$scope: scope,
$stateParams:stateParams
});
}));
it('Should call movieApi and Assign Scopes', function() {
var Api="http://testsite.com/moives/thor";
var myScope=$httpBackend.expectGET(Api).passthrough();
expect(scope.movie).toBeDefined();
console.log('****'+scope.movie.displayName);
});
});
})();
Error is Raising :-
Error: Unexpected request: GET http://testsite.com/movies/undefined
Expected GET http://testsite.com/movies/undefined?
at $httpBackend (C:/wrokingdir2015/public/lib/angular-mocks/angular-mocks.js:1245)
at sendReq (C:/wrokingdir2015/public/lib/angular-mocks/public/lib/angular/angular.js:9695)
Could Any One help me to Write a Unit test case Which can Initialize controller and Assing Scopes like in real controller for testing .
Honestly iam New Guy for Unit testing .
I suggest Selenium with Cucumber for having the scenarios that you test in a nice and readable format
but for testing only a REST api you just need an implementation of javax.ws.rs.client.Client, I use org.glassfish.jersey.client.JerseyClient.
private final Client client = ClientBuilder.newClient();
e.g.
#When("^I want to retrieve all cells for the report with id \"([^\"]*)\".$")
public void accessCellReport(String id) {
response = client.target(URL).path(PathConstants.PATH_ID)
.resolveTemplate(PathConstants.PARAM_ID, reportId).request(MediaType.APPLICATION_JSON).get();
RestAssertions.assertResponseOk(response);
}
First of all i would use Restangulars one method as it supposed to be used.
Read more about it here: https://github.com/mgonto/restangular#creating-main-restangular-object
Restangular.one('movies', movieId);
In my service test i would do something like this to test that the correct endpoint has been called.
it('should call /movies/{movieId}', function() {
var spy = sinon.spy(Restangular, 'one');
var movieId = 1;
movieApiService.getMyMovie(movieId);
expect(spy).to.have.been.calledWith('movies', movieId);
});
Then I would make a sinon stub to mock the reponse from the service in another test for the controller.
it('should set my movies variabel after calling movie service', function() {
var mockResponse = [
{
id: 1,
title: 'Titanic'
},
{
id: 2,
title: 'American History X'
}
];
sinon.stub(movieApiService, 'getMyMovie')
.returns(
$q.when(
[
{
id: 1,
title: 'Titanic'
},
{
id: 2,
title: 'American History X'
}
]
);
);
expect($scope.movieList).to.equal(mockResponse);
});
And another test for checking that the controller catch function is called.
it('should call error handling if service rejects promise', function() {
sinon.stub(movieApiService, 'getMyMovie')
.returns(
$q.reject('an error occured when fetching movie');
);
});
I suggest using Selenium:
http://www.seleniumhq.org/.
Easy to write unit tests and can be automatized with jenkins build.

Mocking a service used in a filter

I'm writing a unit test for a very simple filter:
app.filter('htmlsafe', ['$sce', function($sce) {
return function(message) {
return $sce.trustAsHtml(message);
};
}]);
I want to mock the $sce service and verify that the trustAsHtml method is being called. Checking the docs has not lead me to much success and after much googling this is the best I can come up with (still not working):
(function (describe, it, expect, inject, beforeEach, module) {
describe('htmlsafe filter', function () {
var htmlsafe, $sce, untrustedString;
beforeEach(module('ComstackPmApp'));
beforeEach(function() {
module(function ($provide) {
$provide.service('$sce', $sce);
});
});
beforeEach(inject(function(htmlsafeFilter) {
htmlsafe = htmlsafeFilter;
untrustedString = '<p>Untrusted</p>';
$sce = {
trustAsHtml: function() {
// stub method to spy on.
}
};
}));
it('Should mark a string as HTML safe', function () {
spyOn($sce, 'trustAsHtml');
htmlsafe(untrustedString);
expect($sce.trustAsHtml.calls.count()).toEqual(1);
});
});
})(describe, it, expect, inject, beforeEach, angular.mock.module);
However this leaves me with the following error message:
PhantomJS 1.9.8 (Mac OS X 0.0.0) htmlsafe filter Should mark a string as HTML safe FAILED
TypeError: 'undefined' is not an object (evaluating '(isArray(Type) ? Type[Type.length - 1] : Type).prototype')
undefined
at instantiate (bower_components/angular/angular.js:4480)
at bower_components/angular/angular.js:4341
at invoke (bower_components/angular/angular.js:4473)
at enforcedReturnValue (bower_components/angular/angular.js:4325)
at invoke (bower_components/angular/angular.js:4473)
at bower_components/angular/angular.js:4290
at getService (bower_components/angular/angular.js:4432)
at invoke (bower_components/angular/angular.js:4464)
at enforcedReturnValue (bower_components/angular/angular.js:4325)
at invoke (bower_components/angular/angular.js:4473)
at bower_components/angular/angular.js:4290
at getService (bower_components/angular/angular.js:4432)
at invoke (bower_components/angular/angular.js:4464)
at workFn (bower_components/angular-mocks/angular-mocks.js:2426)
Error: spyOn could not find an object to spy upon for trustAsHtml()
at specs/filters/HtmlSafeFilter.js:26
Not sure what you're trying to do with all that stuff. You don't need to provide the $sce service: Angular provides it. You don't have to create a fake one either: just spy on the angular-provided service:
describe('htmlsafe filter', function() {
var htmlsafe, $sce, untrustedString;
beforeEach(module('ComstackPmApp'));
beforeEach(inject(function(_$sce_, htmlsafeFilter) {
htmlsafe = htmlsafeFilter;
untrustedString = '<p>Untrusted</p>';
$sce = _$sce_;
}));
it('Should mark a string as HTML safe', function () {
spyOn($sce, 'trustAsHtml');
htmlsafe(untrustedString);
expect($sce.trustAsHtml.calls.count()).toEqual(1);
});
});

Unit Testing Factories with nested promises in AngularJS

I'm building an app heavy on JavaScript. I want to unit test my app using Jasmine. At this time, I'm trying to figure out how to write some code that another developer wrote. This code is a factory with some promise action in it. The code looks like the following:
.factory('myFactory', function ($injector, someOtherFactory) {
return function(promise) {
return promise.then(null, function(res) {
if(res.result === -1) {
promise = someOtherFactory.tryAgain('key', function another() {
return $injector.get('$http')(response.config);
});
}
return promise;
});
};
})
It's like a testing turducken. I have no idea how to test this thing. Currently, I have the following setup:
describe('Factory: myFactory', function () {
it('should contain the service', inject(function (myFactory) {
expect(myFactory).toBeDefined();
}));
});
I know this isn't anything. However, I really have no idea how to test a nested promise as shown above. Any pointers?
Thanks

Not able to write Jasmine test case for Controller in ANgularJS

I have following code in my controller and I want to write Jasmine test case for this part.
I tried to write one, but its throwing following error
TypeError: Object [object Array] has no method 'then'
Controller Code ::
$scope.doGetList = function() {
var queryString = {......sending some query parameters};
searchResource.getList(queryString).then(
function (data) {
$scope.sugesstions = data;
}
);
};
Jasmine Test Case ::
it("should return provided list", angular.mock.inject(function($rootScope, $controller) {
var scope = $rootScope.$new();
var searchResource = {
getList: function() {
return ['suggestions1', 'suggestions2', 'suggestions3'];
}
};
$controller(
headerController,
{
$scope: scope,
cartsService: null,
currentUser: null,
searchResource: searchResource
}
);
expect(scope.sugesstions).toBeDefined();
expect(scope.sugesstions.length).toBe(0);
//this method will call mock method instead of actual server call
scope.doGetAutocomplete();
expect(scope.sugesstions.length).toBe(3);
expect(scope.sugesstions[0]).toEqual('suggestions1');
expect(scope.sugesstions[1]).toEqual('suggestions2');
expect(scope.sugesstions[2]).toEqual('suggestions3');
}));
How should I write it.
You'd have to wrap async call in runs(). From jasmine doc: http://pivotal.github.io/jasmine/#section-Asynchronous_Support
Or, I use jasmine-as-promised with better support: https://github.com/ThomasBurleson/jasmine-as-promised

Resources