/** * HeatLayers regression test — post-walkthrough fix. * * Bug: the heat layer's `setLatLngs` was called BEFORE the layer was added to the * map. A leaflet.heat layer that is not on a map has a null `_map`, and * `setLatLngs -> redraw` dereferences `_map._animating`, throwing * "Cannot read properties of null (reading '_animating')" and white-screening * the whole SPA right after login. * * This test exercises the REAL HeatLayers code path (not a wholesale RecordsMap * mock) and asserts the layer is added to the map BEFORE setLatLngs is called. * Against the old code (setLatLngs first), the ordering assertion fails. */ import { describe, it, expect, vi, beforeEach } from 'vitest' import { render } from '@testing-library/react' const { callLog, setLatLngsSpy, mapAddLayerSpy } = vi.hoisted(() => { const callLog: string[] = [] const setLatLngsSpy = vi.fn((_pts: unknown) => { callLog.push('setLatLngs') }) const mapAddLayerSpy = vi.fn((_layer: unknown) => { callLog.push('addLayer') }) return { callLog, setLatLngsSpy, mapAddLayerSpy } }) // Mock leaflet. heatLayer returns a fake layer whose setLatLngs logs call order; // Icon/DivIcon/marker exist because RecordsMap.tsx runs icon setup at module load. vi.mock('leaflet', () => { class FakeIcon { constructor(_opts: unknown) {} static Default = { prototype: {}, mergeOptions: vi.fn() } } return { Icon: FakeIcon, DivIcon: vi.fn(function FakeDivIcon(_opts: unknown) { return {} }), heatLayer: vi.fn(() => ({ setLatLngs: setLatLngsSpy, setOptions: vi.fn(), addTo: vi.fn() })), markerClusterGroup: vi.fn(() => ({ addLayer: vi.fn(), addTo: vi.fn(), clearLayers: vi.fn() })), marker: vi.fn(() => ({ bindTooltip: vi.fn().mockReturnThis(), on: vi.fn().mockReturnThis() })), default: {}, } }) vi.mock('leaflet.heat', () => ({})) vi.mock('leaflet.markercluster', () => ({})) vi.mock('leaflet/dist/images/marker-icon-2x.png', () => ({ default: 'marker-icon-2x.png' })) vi.mock('leaflet/dist/images/marker-icon.png', () => ({ default: 'marker-icon.png' })) vi.mock('leaflet/dist/images/marker-shadow.png', () => ({ default: 'marker-shadow.png' })) vi.mock('leaflet/dist/leaflet.css', () => ({})) vi.mock('leaflet.markercluster/dist/MarkerCluster.css', () => ({})) vi.mock('leaflet.markercluster/dist/MarkerCluster.Default.css', () => ({})) // useMap returns a fake map; hasLayer=false so addLayer is exercised. vi.mock('react-leaflet', () => ({ MapContainer: ({ children }: { children: React.ReactNode }) =>