import { render, screen } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import React from 'react'; vi.doMock('../google-maps-loader', () => ({ useGoogleMapsLoader: () => ({ isLoaded: true, loadError: undefined, load: async () => {} }), })); const POA = { lat: -30.03, lng: -51.22 }; describe('Map — previously unwired behaviour', () => { let Map: any; let setOptions: ReturnType; let idleHandler: (() => void) | null; let mapInstance: any; beforeEach(async () => { vi.clearAllMocks(); idleHandler = null; setOptions = vi.fn(); mapInstance = { setOptions, getZoom: vi.fn(() => 12), getCenter: vi.fn(() => ({ lat: () => -30, lng: () => -51 })), addListener: vi.fn((event: string, handler: () => void) => { if (event === 'idle') idleHandler = handler; return { remove: vi.fn() }; }), }; Map = (await import('./map')).Map; Object.defineProperty(HTMLElement.prototype, 'innerMap', { configurable: true, get() { return this.tagName === 'GMP-MAP' ? mapInstance : undefined; }, }); global.google = { maps: { Map: vi.fn(function () { return mapInstance; }), Circle: vi.fn(function () { return { setMap: vi.fn(), setOptions: vi.fn(), addListener: vi.fn(() => ({ remove: vi.fn() })), }; }), Polygon: vi.fn(function () { return { setMap: vi.fn(), setOptions: vi.fn(), addListener: vi.fn(() => ({ remove: vi.fn() })), }; }), Polyline: vi.fn(function () { return { setMap: vi.fn(), setOptions: vi.fn(), addListener: vi.fn(() => ({ remove: vi.fn() })), }; }), InfoWindow: vi.fn(function () { return { open: vi.fn(), close: vi.fn(), setContent: vi.fn() }; }), LatLng: vi.fn(function (lat: number, lng: number) { return { lat, lng }; }), LatLngBounds: vi.fn(function () { return { extend: vi.fn() }; }), Data: vi.fn(function () { return { setMap: vi.fn(), addGeoJson: vi.fn(), setStyle: vi.fn(), forEach: vi.fn(), remove: vi.fn(), revertStyle: vi.fn(), overrideStyle: vi.fn(), addListener: vi.fn(() => ({ remove: vi.fn() })), }; }), event: { addListener: vi.fn(() => ({ remove: vi.fn() })), addListenerOnce: vi.fn(() => ({ remove: vi.fn() })), }, marker: { AdvancedMarkerElement: vi.fn() }, }, } as any; }); afterEach(() => { delete (HTMLElement.prototype as any).innerMap; delete (global as any).google; vi.resetModules(); }); /* --- Control booleans reached the map ---------------------------------- */ describe('map control options', () => { it('applies the documented defaults to the map instance', () => { render(); // These were public, documented props that reached nothing. expect(setOptions).toHaveBeenCalledWith( expect.objectContaining({ disableDefaultUI: false, zoomControl: true, streetViewControl: false, mapTypeControl: false, fullscreenControl: true, gestureHandling: 'cooperative', }) ); }); it('forwards overrides', () => { render( ); expect(setOptions).toHaveBeenCalledWith( expect.objectContaining({ disableDefaultUI: true, zoomControl: false, gestureHandling: 'greedy', streetViewControl: true, }) ); }); it('re-applies when a control prop changes', () => { const { rerender } = render(); setOptions.mockClear(); rerender(); expect(setOptions).toHaveBeenCalledWith(expect.objectContaining({ zoomControl: false })); }); }); /* --- One writer for mapTypeId ------------------------------------------ */ describe('mapTypeId precedence', () => { it('uses the raw prop when no basemap is set', () => { render(); expect((document.querySelector('gmp-map') as any).mapTypeId).toBe('terrain'); }); it('lets basemap win over the raw prop', () => { // Two effects used to write this field and raced. render(); expect((document.querySelector('gmp-map') as any).mapTypeId).toBe('satellite'); }); it('keeps the raw prop for a basemap with no native type', () => { render(); expect((document.querySelector('gmp-map') as any).mapTypeId).toBe('terrain'); }); }); /* --- Caption collision follows the camera ------------------------------ */ it('re-resolves caption collisions when the camera comes to rest', () => { render( ); // A pan or zoom moves captions without resizing the container, so a // ResizeObserver alone never fired. expect(idleHandler).toBeTypeOf('function'); expect(() => idleHandler?.()).not.toThrow(); }); });