After upgrading an Angular project from version 8 to 11 and updating the dependencies, I encountered an issue with compatibility. The project previously used the @agm/core
package, which is not compatible with Angular 11. I replaced it with @angular/google-maps
as suggested, and although everything works fine, the tests are failing.
The map is a part of a component where the Google API is loaded, ensuring it is not loaded multiple times:
import { Component, OnInit, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { GoogleMap } from '@angular/google-maps';
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit {
@ViewChild(GoogleMap, { static: false }) map: GoogleMap;
apiLoaded: Observable<boolean>;
constructor(httpClient: HttpClient) {
if (window.google === undefined) {
this.apiLoaded = httpClient.jsonp(`https://maps.googleapis.com/maps/api/js?key=${environment.googleAPIKey}`, 'callback')
.pipe(
// Doing preparation stuff
);
}
else {
this.apiLoaded = of(true);
}
}
}
While everything works as intended when running ng serve
, running ng test
presents issues:
Unhandled promise rejection: InvalidValueError: ng_jsonp_callback_0 is not a function
error properties: null({ constructor: Function })
Error:
at new ge (https://maps.googleapis.com/maps/api/js?key=<api-key>&callback=ng_jsonp_callback_0:70:72)
at Object._.he (https://maps.googleapis.com/maps/api/js?key=<api-key>&callback=ng_jsonp_callback_0:70:182)
at Nj (https://maps.googleapis.com/maps/api/js?key=<api-key>&callback=ng_jsonp_callback_0:146:233)
at https://maps.googleapis.com/maps/api/js?key=<api-key>&callback=ng_jsonp_callback_0:146:118
at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:364:1)
at Zone.run (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:123:1)
at http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:857:1
at ZoneDelegate.invokeTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:399:1)
at Zone.runTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:167:1)
at drainMicroTaskQueue (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:569:1)
It seems that the Google API is not present during testing. Various attempts were made to solve this issue, including:
- Adding the Google API loading in the index.html:
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
- Adding the link to the Karma config file in the
files
section:
files: [
'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY'
],
- Downloading the link's content, putting it into a file, and adding the referenced file in the Karma config under the files section. Although this works initially, it soon throws errors, making it unsuitable for automated testing on Jenkins.
- Trying online mocks, but the existing tests heavily utilize functions that don't work with a mocked API.
- Attempting to load the API in the test file before running the tests, but this also did not yield the expected results:
beforeEach(waitForAsync(() => {
httpClient.jsonp(`https://maps.googleapis.com/maps/api/js?key=${environment.googleAPIKey}`, 'callback');
While considering moving the API loading into a service or pre-loading the API in the Karma config file before testing, it seems like there isn't an elegant solution yet.
How can I ensure the current Google Maps API is present for testing in a more seamless manner?