diff --git a/src/features/flights-map/components/MapCanvas.test.tsx b/src/features/flights-map/components/MapCanvas.test.tsx index cee61dc6..17519a3d 100644 --- a/src/features/flights-map/components/MapCanvas.test.tsx +++ b/src/features/flights-map/components/MapCanvas.test.tsx @@ -507,6 +507,50 @@ describe("MapCanvas — polylines (C.3)", () => { expect(createdPolylines.length).toBe(afterInitialRender); }); + it("keeps drawn route endpoints visible even when their zoom tier is hidden", () => { + render( + , + ); + const map = createdMaps[0]!; + map.setZoom(3); + map.fireZoomend(); + + const endpoint = createdMarkers.find((m) => m.options.title === "B")!; + const owningLayer = createdLayerGroups.find((l) => l._markers.includes(endpoint)); + + expect(owningLayer).toBeDefined(); + const addedToMap = + map.addLayer.mock.calls.map((c) => c[0]).includes(owningLayer!) || + owningLayer!.addTo.mock.calls.length > 0; + expect(addedToMap).toBe(true); + }); + + it("force-opens drawn route endpoint tooltips at zoom <= 3", () => { + render( + , + ); + const map = createdMaps[0]!; + map.setZoom(3); + map.fireZoomend(); + + const endpoint = createdMarkers.find((m) => m.options.title === "B")!; + expect(endpoint.openTooltip).toHaveBeenCalled(); + }); + it("silently skips polylines with unknown city codes", () => { render( = ({ const markerIndexRef = useRef>(new Map()); const highlightedIdsRef = useRef>(new Set()); const intermediateIdsRef = useRef>(new Set()); + const routeEndpointIdsRef = useRef>(new Set()); // Track latest toggles so the zoomend handler sees current values const domesticRef = useRef(domestic); @@ -247,8 +248,13 @@ export const MapCanvas: FC = ({ } }); - // Pass 2: force-open intermediate route tooltips (Angular parity). - for (const id of intermediateIdsRef.current) { + // Pass 2: force-open visible route labels. Intermediate cities and + // currently drawn endpoints must stay readable even when LOD hides labels. + const forcedTooltipIds = new Set([ + ...intermediateIdsRef.current, + ...routeEndpointIdsRef.current, + ]); + for (const id of forcedTooltipIds) { const m = markerIndexRef.current.get(id); if (m) m.openTooltip(); } @@ -351,6 +357,7 @@ export const MapCanvas: FC = ({ markerIndexRef.current = new Map(); highlightedIdsRef.current = new Set(); intermediateIdsRef.current = new Set(); + routeEndpointIdsRef.current = new Set(); }; }, []); @@ -371,10 +378,14 @@ export const MapCanvas: FC = ({ } markerIndexRef.current = new Map(); highlightedIdsRef.current = new Set(); + routeEndpointIdsRef.current = new Set( + polylines.flatMap((pl) => pl.cityIds), + ); for (const m of markers) { const isCategorized = m.zoomLevel !== undefined && m.countryType !== undefined; + const isRouteEndpoint = routeEndpointIdsRef.current.has(m.id); const iconStyle: MarkerStyle = m.highlighted ? "orange" : m.style; const marker = L.marker([m.lat, m.lng], { @@ -399,6 +410,8 @@ export const MapCanvas: FC = ({ if (m.highlighted) { highlightedIdsRef.current.add(m.id); marker.addTo(highlightLayer); + } else if (isRouteEndpoint) { + marker.addTo(highlightLayer); } else if (isCategorized) { const countryIdx = m.countryType === "ru" ? 0 : 1; const rawTier = m.zoomLevel ?? 6; @@ -413,7 +426,7 @@ export const MapCanvas: FC = ({ syncVisibility(); syncTooltips(); - }, [markers]); + }, [markers, polylines]); useEffect(() => { syncMarkers();