Reputation: 848
I followed this tutorial to make unit test for a service that return aPromise
but could not get it worked.
My service returns a Promise
that will retrives HTML5
geolocation.
app.factory('getGeo', function() {
return function(){
return new Promise(function (resolve, reject) {
navigator.geolocation.getCurrentPosition(resolve, reject, options);
});
}
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
});
And my controller has a function that resolve the Promise
to set some states in the app.
getGeo().then((position) => {
//perform logic when geo is received
$scope.weatherInfo.la = position.coords.latitude;//new properties
$scope.weatherInfo.lo = position.coords.longitude;//new properties
$scope.weatherInfo.url = `http://api.openweathermap.org/data/2.5/weather?lat=${$scope.weatherInfo.la}&lon=${$scope.weatherInfo.lo}&appid=0d00180d180f48b832ffe7d9179d40c4`;
})
And my test:
beforeEach(inject(function(_$rootScope_, _getGeo_){
$rootScope = _$rootScope_;
$getGeo = _getGeo_;
}));
describe('getGeo method', function() {
it('getGeo should return a promise', function() {
var $scope = $rootScope.$new();
var position = {coords:{coords:{latitude:'1',latitude:'3'}}};
$getGeo().then(function(position) {
expect($scope.weatherInfo.url).not.toBeNull();
done();
});
$scope.$digest();
});
});
I got this SPEC HAS NO EXPECTATIONS getGeo should return a promise
. Seems the code inside the mock service never gets called. But if I move out the expect($scope.weatherInfo.url).not.toBeNull()
and put it under $scope.$digest()
I'd get a Cannot read property 'url' of undefined
error.
Upvotes: 0
Views: 310
Reputation: 361
var position = {coords:{coords:{latitude:'1',latitude:'3'}}};
$getGeo().then(function(position) {
expect($scope.weatherInfo.url).not.toBeNull();
}
Variable in callback - it is the data which promise will return. It is not your var position = {coords:{coords:{latitude:'1',latitude:'3'}}};
I think you shouldn't call the factory in the test. The factory will call constructor only one time when you inject its first. So you just need to make next
$getGeo.then(function(position) {...})
Your factory takes data from outside navigator.geolocation.getCurrentPosition()
. So you need to make stub for it.
spyOn(navigator.geolocation, 'getCurrentPosition').andReturn(/* here is the data which you expected */)
It is hard to show you the full example. However, I tried to describe critical things.
Upvotes: 1