From 72ecf31f49250f6161d85dfd320540616a5a101a Mon Sep 17 00:00:00 2001 From: Dan Leech Date: Mon, 3 Aug 2026 15:38:03 +0100 Subject: [PATCH] Sonar fixes --- plugins/interact/src/hooks/useMapItemList.js | 4 +- .../openlayers/src/utils/tileLayers.test.js | 2 +- .../maplibre/src/utils/queryFeatures.test.js | 12 ++--- src/App/components/Actions/Actions.jsx | 4 +- src/App/components/Tabs/Tabs.jsx | 1 + src/App/components/Tabs/Tabs.test.jsx | 45 +++++-------------- src/App/hooks/useMarkersAPI.test.js | 2 +- src/App/registry/pluginRegistry.test.js | 4 +- src/App/renderer/mapButtons.test.js | 16 +++---- 9 files changed, 34 insertions(+), 56 deletions(-) diff --git a/plugins/interact/src/hooks/useMapItemList.js b/plugins/interact/src/hooks/useMapItemList.js index 7f95602a3..5b4f1bc06 100644 --- a/plugins/interact/src/hooks/useMapItemList.js +++ b/plugins/interact/src/hooks/useMapItemList.js @@ -111,8 +111,8 @@ function useActiveItemHandler ({ markers, interactionModes, layers, mapProvider, dispatch({ type: 'SET_LISTBOX_ACTIVE', payload: null }) return } - const markerMatch = markers.items.find(m => m.id === id) - if (markerMatch) { + const hasMarkerMatch = markers.items.some(m => m.id === id) + if (hasMarkerMatch) { listboxActiveItemRef.current = { id, isMarker: true } dispatch({ type: 'SET_LISTBOX_ACTIVE', payload: null }) return diff --git a/providers/beta/openlayers/src/utils/tileLayers.test.js b/providers/beta/openlayers/src/utils/tileLayers.test.js index a4f4206b7..5fb94eac8 100644 --- a/providers/beta/openlayers/src/utils/tileLayers.test.js +++ b/providers/beta/openlayers/src/utils/tileLayers.test.js @@ -305,7 +305,7 @@ describe('createVectorTileLayer', () => { it('slices capabilities lods to max 16 resolutions', async () => { await createVectorTileLayer(styleUrl, null) const { resolutions } = TileGrid.mock.calls[0][0] - expect(resolutions.length).toBe(16) + expect(resolutions).toHaveLength(16) }) it('creates VectorTileSource with MVT format and 27700 projection', async () => { diff --git a/providers/maplibre/src/utils/queryFeatures.test.js b/providers/maplibre/src/utils/queryFeatures.test.js index e2caf4105..3f70c8543 100644 --- a/providers/maplibre/src/utils/queryFeatures.test.js +++ b/providers/maplibre/src/utils/queryFeatures.test.js @@ -27,7 +27,7 @@ describe('queryFeatures coverage', () => { cases.forEach(({ type, coords, p }) => { const feat = { id: type, layer: { id: 'L1' }, geometry: { type, coordinates: coords } } const map = { ...mockMap, queryRenderedFeatures: () => [feat, feat] } // Hits deduplication - expect(queryFeatures(map, p).length).toBe(1) + expect(queryFeatures(map, p)).toHaveLength(1) }) // 3. Hits Line 144 (.sort) and property-based ID fallback @@ -46,7 +46,7 @@ describe('queryFeatures coverage', () => { const sortMap = { ...mockMap, queryRenderedFeatures: () => [f1, f2] } const result = queryFeatures(sortMap, { x: 0, y: 0 }) - expect(result.length).toBe(2) + expect(result).toHaveLength(2) expect(result[0].layer.id).toBe('layer-A') // Sorted by layerStack index // 4. Hit ray-casting intersect logic — point inside the polygon @@ -55,16 +55,16 @@ describe('queryFeatures coverage', () => { geometry: { type: 'Polygon', coordinates: [[[0, 0], [10, 10], [0, 10], [0, 0]]] } } const rayMap = { ...mockMap, queryRenderedFeatures: () => [polyFeat] } - expect(queryFeatures(rayMap, { x: 2, y: 8 }).length).toBe(1) + expect(queryFeatures(rayMap, { x: 2, y: 8 })).toHaveLength(1) // 5. Outside polygon is filtered out (tolerance only applies to lines) const outsideMap = { ...mockMap, queryRenderedFeatures: () => [polyFeat] } - expect(queryFeatures(outsideMap, { x: -1, y: 5 }).length).toBe(0) + expect(queryFeatures(outsideMap, { x: -1, y: 5 })).toHaveLength(0) // 6. Symbol under exact click point is included const symbolFeat = { id: 'sym', layer: { id: 'S', source: 'src' }, geometry: { type: 'Point', coordinates: [0, 0] } } const symbolMap = { ...mockMap, queryRenderedFeatures: () => [symbolFeat] } // both calls return it - expect(queryFeatures(symbolMap, { x: 5, y: 5 }).length).toBe(1) + expect(queryFeatures(symbolMap, { x: 5, y: 5 })).toHaveLength(1) // 7. Symbol NOT under exact click point is filtered out let call = 0 @@ -72,6 +72,6 @@ describe('queryFeatures coverage', () => { ...mockMap, queryRenderedFeatures: () => call++ === 0 ? [symbolFeat] : [] // bbox returns it, exact does not } - expect(queryFeatures(symbolMissMap, { x: 5, y: 5 }).length).toBe(0) + expect(queryFeatures(symbolMissMap, { x: 5, y: 5 })).toHaveLength(0) }) }) diff --git a/src/App/components/Actions/Actions.jsx b/src/App/components/Actions/Actions.jsx index 73cb9d43f..3f88cad07 100755 --- a/src/App/components/Actions/Actions.jsx +++ b/src/App/components/Actions/Actions.jsx @@ -7,7 +7,7 @@ export const Actions = ({ children }) => { const { openPanels, panelConfig, breakpoint } = useApp() const childArray = React.Children.toArray(children) - const visibleChild = childArray.find(c => c.props?.isHidden === false && c.props?.variant !== 'touch') + const hasVisibleChild = childArray.some(c => c.props?.isHidden === false && c.props?.variant !== 'touch') // If a panel exists above we need so css adjustment const isBottomSlotUsed = Object.keys(openPanels).some(panelId => { @@ -17,7 +17,7 @@ export const Actions = ({ children }) => { const className = [ 'im-c-panel', 'im-c-actions', - !visibleChild && 'im-c-actions--hidden', + !hasVisibleChild && 'im-c-actions--hidden', isBottomSlotUsed && 'im-c-actions--border-top' ].filter(Boolean).join(' ') diff --git a/src/App/components/Tabs/Tabs.jsx b/src/App/components/Tabs/Tabs.jsx index 61ca293eb..c727c631f 100644 --- a/src/App/components/Tabs/Tabs.jsx +++ b/src/App/components/Tabs/Tabs.jsx @@ -40,6 +40,7 @@ export const Tabs = ({ tabs, defaultTab }) => { // NOSONAR: project does not use
{tabs.map(({ name }) => (