For your first error screen, you are correct that it is due to the jasmine test runner not containing a reference to the google maps js file.
For the second error you do not have a div element with map-canvas-add-location. Your view does contain the div element, but it isn't being loaded within your jasmine test suite. This is correct behavior, unit tests should not depend on a specific dom structure as it makes them far more brittle.
I know of 2 ways to handle the second error:
- Utilizing services to wrap specific calls to google map dependencies. This is how my current angular maps project works.
- Converting all map level tests to E2E tests instead of unit tests.
I recommend number 1 as E2E testing only is not a step to be taken lightly. E2E tests are generally more brittle and harder to maintain.
Here is a sample of how a wrapper service might look:
.factory('GoogleMap', function(){
return {
createMap: function(element, options){
return new google.maps.Map(element, options);
},
mapOptions: {
animation: google.maps.MapTypeId.DROP,
maxZoom: 15,
mapTypeControlOptions: {
position: google.maps.ControlPosition.LEFT_BOTTOM,
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
},
markerOptions:{
animation: google.maps.Animation.DROP,
clickable: true
},
position: function(location){
return new google.maps.LatLng(location.latitude, location.longitude);
},
geocode: function(search, successFun){
var geocoder = new google.maps.Geocoder();
geocoder.geocode(search, successFun);
},
bounds: function(){
return new google.maps.LatLngBounds();
}
};
});
and used within code:
var mapOptions = angular.extend({
zoom: 15,
center: GoogleMap.position({latitude: 51.142036, longitude: 4.440966})
}, GoogleMap.mapOptions);
map = GoogleMap.createMap(document.getElementById('map-canvas-add-location'), mapOptions);
Then in your tests you'll need to create a mock GoogleMap service and setups spies on that mock to assert your map is being correctly generated.
Here is a sample mock GoogleMap service:
.factory('mockGoogleMap', function(){
var mapResult = {
formatted_address: 'mock formatted address',
geometry: {
location: {
lat: function(){
return 1;
},
lng: function(){
return 2;
}
}
}
};
return {
createMap: function(element, options){
return {
//add functions called by your controller on the map here
};
},
mapOptions: {},
markerOptions: {},
position: function(location){
return {latitude: location.latitude, longitude: location.longitude};
},
geocode: function(params, success){
success([mapResult], null);
},
geocodeResult: mapResult,
bounds: function(){
return {
extend: function(position){},
getCenter: function(){ return {}; }
};
},
};
});