Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

google maps unit testing

Have the following directive.

import { Directive, ElementRef, EventEmitter, Output } from '@angular/core';
import { NgModel } from '@angular/forms';
import {} from 'googlemaps';
@Directive({
  selector: '[gmap]'
})
export class GmapDirective {

  @Output() addressFromGoogle: EventEmitter<any> = new EventEmitter();
  autocomplete: any;

  constructor(el: ElementRef) {
    this.autocomplete = new google.maps.places.Autocomplete(el.nativeElement, { componentRestrictions: { country: "us" } });
    google.maps.event.addListener(this.autocomplete, 'place_changed', () => {
      this.addressFromGoogle.emit(this.autocomplete.getPlace());
    });
  }
}

Trying to unit test and get google is not defined How do i provide a global variable to the TestBed ?

describe('GmapDirective', () => {
  let directive: GmapDirective;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [],
      providers: [
        GmapDirective,
        { provide: ElementRef, useClass: MockElementRef },
        {
          provide: google, useValue: {
            google: {
              maps: {
                Animation: {},
                BicyclingLayer: function () { },
                Circle: function () { },
                ControlPosition: {},
                Data: function () { },
                DirectionsRenderer: function () { },
                DirectionsService: function () { },
                DirectionsStatus: {},
                DirectionsTravelMode: {},
                DirectionsUnitSystem: {},
                DistanceMatrixElementStatus: {},
                DistanceMatrixService: function () { },
                DistanceMatrixStatus: {},
                ElevationService: function () { },
                ElevationStatus: {},
                FusionTablesLayer: function () { },
                Geocoder: function () { },
                GeocoderLocationType: {},
                GeocoderStatus: {},
                GroundOverlay: function () { },
                ImageMapType: function () { },
                InfoWindow: function () { },
                KmlLayer: function () { },
                KmlLayerStatus: {},
                LatLng: function () { },
                LatLngBounds: function () { },
                MVCArray: function () { },
                MVCObject: function () { },
                Map: function () {
                  return {
                    setTilt: function () { },
                    mapTypes: {
                      set: function () { }
                    },
                    overlayMapTypes: {
                      insertAt: function () { },
                      removeAt: function () { }
                    }
                  };
                },
                MapTypeControlStyle: {},
                MapTypeId: {
                  HYBRID: '',
                  ROADMAP: '',
                  SATELLITE: '',
                  TERRAIN: ''
                },
                MapTypeRegistry: function () { },
                Marker: function () { },
                MarkerImage: function () { },
                MaxZoomService: function () {
                  return {
                    getMaxZoomAtLatLng: function () { }
                  };
                },
                MaxZoomStatus: {},
                NavigationControlStyle: {},
                OverlayView: function () { },
                Point: function () { },
                Polygon: function () { },
                Polyline: function () { },
                Rectangle: function () { },
                SaveWidget: function () { },
                ScaleControlStyle: {},
                Size: function () { },
                StreetViewCoverageLayer: function () { },
                StreetViewPanorama: function () { },
                StreetViewService: function () { },
                StreetViewStatus: {},
                StrokePosition: {},
                StyledMapType: function () { },
                SymbolPath: {},
                TrafficLayer: function () { },
                TransitLayer: function () { },
                TransitMode: {},
                TransitRoutePreference: {},
                TravelMode: {},
                UnitSystem: {},
                ZoomControlStyle: {},
                __gjsload__: function () { },
                event: {
                  addListener: function () { }
                },
                places: {
                  AutocompleteService: function () {
                    return {
                      getPlacePredictions: function () { }
                    };
                  }
                }
              }
            }
          }
        }
      ],
      declarations: []
    }).compileComponents();
    directive = TestBed.get(GmapDirective);
  }));
  it('should create an instance', () => {
    expect(directive).toBeTruthy();
  });
});

Tried the above and it doesn't work since google is not injected (expected to be in the global namespace)

like image 578
Anand Rockzz Avatar asked May 04 '26 03:05

Anand Rockzz


1 Answers

One of the problems that DI is intended to solve is testability. Globals can be mocked on window, but a cleaner approach is to provide them as providers:

export const GOOGLE = new InjectionToken('google');
export const googleFactory = () => google;

...
providers: [{ provide: GOOGLE, useFactory: googleFactory}, ...]
...

...
constructor(el: ElementRef, @Inject(GOOGLE) google) {
  ...
}
...

Then it can be mocked in test bed:

...
providers: [{ provide: GOOGLE, useValue: mockedGoogle }]
...
like image 186
Estus Flask Avatar answered May 06 '26 16:05

Estus Flask



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!