From 339a2810cd7df738dba93172682dd5b32c62a66c Mon Sep 17 00:00:00 2001 From: Martin Schuhfuss Date: Tue, 17 Oct 2023 22:43:28 +0200 Subject: [PATCH] feat: implement mock for importLibrary (#538) Implemented a mock for importLibrary that returns the correct collection of api-objects in their mocked versions. --- src/import-library.test.ts | 40 ++++++++ src/import-library.ts | 202 +++++++++++++++++++++++++++++++++++++ src/index.ts | 9 ++ 3 files changed, 251 insertions(+) create mode 100644 src/import-library.test.ts create mode 100644 src/import-library.ts diff --git a/src/import-library.test.ts b/src/import-library.test.ts new file mode 100644 index 00000000..3a715dc0 --- /dev/null +++ b/src/import-library.test.ts @@ -0,0 +1,40 @@ +import { initialize, importLibrary } from "./index"; + +beforeEach(() => { + initialize(); +}); + +test("google.maps.importLibrary is a mock", async () => { + expect(google.maps.importLibrary).toBeDefined(); + expect((google.maps.importLibrary as any).mock).toBeDefined(); +}); + +const libraries = [ + "core", + "maps", + "places", + "geocoding", + "routes", + "marker", + "geometry", + "elevation", + "streetView", + "journeySharing", + "drawing", + "visualization", +]; + +test.each(libraries)("library %s is returned", async (name) => { + const libraryPromise = google.maps.importLibrary(name); + expect(libraryPromise).toBeInstanceOf(Promise); + await expect(libraryPromise).resolves.toBeDefined(); +}); + +test("throws an error for unknown libraries", async () => { + await expect(google.maps.importLibrary("unknown")).rejects.toThrowError(); +}); + +test("importLibrary is exported as mock", async () => { + await google.maps.importLibrary("core"); + expect(importLibrary.mock.calls).toHaveLength(1); +}); diff --git a/src/import-library.ts b/src/import-library.ts new file mode 100644 index 00000000..0a3f545a --- /dev/null +++ b/src/import-library.ts @@ -0,0 +1,202 @@ +export const importLibrary = jest.fn(async (name: string) => { + switch (name) { + case "core": { + const { + ControlPosition, + event, + LatLng, + LatLngAltitude, + LatLngBounds, + MapsNetworkError, + MapsNetworkErrorEndpoint, + MapsRequestError, + MapsServerError, + MVCArray, + MVCObject, + Point, + Settings, + Size, + SymbolPath, + UnitSystem, + } = google.maps; + + return { + ControlPosition, + event, + LatLng, + LatLngAltitude, + LatLngBounds, + MapsNetworkError, + MapsNetworkErrorEndpoint, + MapsRequestError, + MapsServerError, + MVCArray, + MVCObject, + Point, + Settings, + Size, + SymbolPath, + UnitSystem, + } as google.maps.CoreLibrary; + } + + case "maps": { + const { + BicyclingLayer, + Circle, + Data, + FeatureType, + GroundOverlay, + ImageMapType, + InfoWindow, + KmlLayer, + KmlLayerStatus, + Map, + MapTypeControlStyle, + MapTypeId, + MapTypeRegistry, + MaxZoomService, + MaxZoomStatus, + OverlayView, + Polygon, + Polyline, + Rectangle, + RenderingType, + StrokePosition, + StyledMapType, + TrafficLayer, + TransitLayer, + WebGLOverlayView, + } = google.maps; + + return { + BicyclingLayer, + Circle, + Data, + FeatureType, + GroundOverlay, + ImageMapType, + InfoWindow, + KmlLayer, + KmlLayerStatus, + Map, + MapTypeControlStyle, + MapTypeId, + MapTypeRegistry, + MaxZoomService, + MaxZoomStatus, + OverlayView, + Polygon, + Polyline, + Rectangle, + RenderingType, + StrokePosition, + StyledMapType, + TrafficLayer, + TransitLayer, + WebGLOverlayView, + } as google.maps.MapsLibrary; + } + case "places": + return google.maps.places as google.maps.PlacesLibrary; + case "geocoding": { + const { Geocoder, GeocoderLocationType, GeocoderStatus } = google.maps; + return { + Geocoder, + GeocoderLocationType, + GeocoderStatus, + } as google.maps.GeocodingLibrary; + } + case "routes": { + const { + DirectionsRenderer, + DirectionsService, + DirectionsStatus, + DistanceMatrixElementStatus, + DistanceMatrixService, + DistanceMatrixStatus, + TrafficModel, + TransitMode, + TransitRoutePreference, + TravelMode, + VehicleType, + } = google.maps; + + return { + DirectionsRenderer, + DirectionsService, + DirectionsStatus, + DistanceMatrixElementStatus, + DistanceMatrixService, + DistanceMatrixStatus, + TrafficModel, + TransitMode, + TransitRoutePreference, + TravelMode, + VehicleType, + } as google.maps.RoutesLibrary; + } + case "marker": { + const { + Animation, + CollisionBehavior, + Marker, + marker: { AdvancedMarkerClickEvent, AdvancedMarkerElement, PinElement }, + } = google.maps; + + return { + AdvancedMarkerClickEvent, + AdvancedMarkerElement, + Animation, + CollisionBehavior, + Marker, + PinElement, + } as google.maps.MarkerLibrary; + } + case "geometry": { + return google.maps.geometry as google.maps.GeometryLibrary; + } + case "elevation": { + const { ElevationService, ElevationStatus } = google.maps; + + return { + ElevationService, + ElevationStatus, + } as google.maps.ElevationLibrary; + } + case "streetView": { + const { + InfoWindow, + OverlayView, + StreetViewCoverageLayer, + StreetViewPanorama, + StreetViewPreference, + StreetViewService, + StreetViewSource, + StreetViewStatus, + } = google.maps; + + return { + InfoWindow, + OverlayView, + StreetViewCoverageLayer, + StreetViewPanorama, + StreetViewPreference, + StreetViewService, + StreetViewSource, + StreetViewStatus, + } as google.maps.StreetViewLibrary; + } + case "journeySharing": { + return google.maps.journeySharing as google.maps.JourneySharingLibrary; + } + case "drawing": { + return google.maps.drawing as google.maps.DrawingLibrary; + } + case "visualization": { + return google.maps.visualization as google.maps.VisualizationLibrary; + } + } + + throw new TypeError(`unknown library name: ${name}`); +}); diff --git a/src/index.ts b/src/index.ts index d91c6992..e499614d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { importLibrary } from "./import-library"; import { LatLng, LatLngBounds } from "./maps/coordinates/latlng"; import { LatLngAltitude } from "./maps/coordinates/latlngaltitude"; import { PlacesService } from "./places/places-service/places-service"; @@ -65,8 +66,11 @@ import { mockInstances } from "./registry"; const initialize = function (): void { mockInstances.clearAll(); + importLibrary.mockClear(); + (global as any).google = { maps: { + importLibrary, ImageMapType: jest.fn(), Marker: Marker, Map: Map_, @@ -114,6 +118,10 @@ const initialize = function (): void { AdvancedMarkerElement, }, FeatureLayer, + drawing: {}, // FIXME: missing implementation (#521) + geometry: {}, // FIXME: missing implementation (#299) + journeySharing: {}, // FIXME: missing implementation + visualization: {}, // FIXME: missing implementation }, }; }; @@ -158,6 +166,7 @@ export { AdvancedMarkerElement, PinElement, FeatureLayer, + importLibrary, mockInstances, initialize, };