From 7feda49ef2e094dea102b64a2fdcac337fccca8b Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Mon, 26 Oct 2020 10:36:36 -0700 Subject: [PATCH] fix: event listeners handling adding and removing map multiple times (#27) --- src/marker.test.ts | 84 ++++++++++++++++++++++++++++++++++++++++++++++ src/marker.ts | 1 + 2 files changed, 85 insertions(+) create mode 100644 src/marker.test.ts diff --git a/src/marker.test.ts b/src/marker.test.ts new file mode 100644 index 0000000..159b527 --- /dev/null +++ b/src/marker.test.ts @@ -0,0 +1,84 @@ +/** + * Copyright 2020 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Label } from "./label"; +import { MarkerWithLabel } from "./marker"; +import { initialize } from "@googlemaps/jest-mocks"; + +class OverlayView {} +beforeAll(() => { + jest.useFakeTimers(); + initialize(); + google.maps.OverlayView = OverlayView as any; + Label.prototype.getProjection = (): google.maps.MapCanvasProjection => { + return ({ + fromPointToLatLng: () => {}, + fromLatLngToPoint: () => {}, + fromLatLngToDivPixel: (position: google.maps.LatLng) => { + return { x: 1, y: 3 }; + }, + } as unknown) as google.maps.MapCanvasProjection; + }; +}); + +beforeEach(() => { + // avoid type error without new + google.maps.Marker = jest.fn() as any; + google.maps.Marker.prototype.setMap = jest.fn(); + google.maps.Marker.prototype.getMap = jest.fn(); + + Label.prototype.setMap = jest.fn(); + + google.maps.event.addDomListener = jest.fn(); +}); + +test("should have listeners after multiple calls to setMap", () => { + const map = jest.fn() as any; + const marker = new MarkerWithLabel({ labelContent: "foo" }); + + marker.setMap(map); + jest.advanceTimersByTime(1); + expect(marker["interactiveListeners"].length).toBeGreaterThan(0); + + marker.setMap(null); + jest.advanceTimersByTime(1); + expect(marker["interactiveListeners"]).toBe(null); + + marker.setMap(map); + jest.advanceTimersByTime(1); + expect(marker["interactiveListeners"].length).toBeGreaterThan(0); +}); + +test("should have interactive listeners", () => { + const marker = new MarkerWithLabel({ labelContent: "foo" }); + marker["addInteractiveListeners"](); + + expect( + (google.maps.event.addDomListener as any).mock.calls.map((c: any[]) => c[1]) + ).toMatchInlineSnapshot(` + Array [ + "mouseover", + "mouseout", + "mousedown", + "mouseup", + "click", + "dblclick", + "touchstart", + "touchmove", + "touchend", + ] + `); +}); diff --git a/src/marker.ts b/src/marker.ts index 252bb07..f9f9ff9 100644 --- a/src/marker.ts +++ b/src/marker.ts @@ -116,6 +116,7 @@ export class MarkerWithLabel extends MarkerSafe { this.interactiveListeners.forEach((l) => google.maps.event.removeListener(l) ); + this.interactiveListeners = null; } }