Skip to content

Commit

Permalink
react_maps: write js tests for react leaflet map
Browse files Browse the repository at this point in the history
  • Loading branch information
vellip authored and goapunk committed Jan 3, 2024
1 parent 13d8783 commit 087bb8e
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function checkPointInsidePolygon (marker, polygons) {

const markerProps = { icon: makeIcon(), draggable: true }

class AddMarkerControlClass extends L.Control {
export class AddMarkerControlClass extends L.Control {
constructor ({ input, point }) {
super()
this.marker = null
Expand Down
4 changes: 3 additions & 1 deletion adhocracy4/maps_react/static/a4maps_react/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const polygonStyle = {
fillOpacity: 0.2
}

export const Map = React.forwardRef(function Map (
const Map = React.forwardRef(function Map (
{ attribution, baseUrl, polygon, omtToken, children, ...rest }, ref
) {
const map = useRef()
Expand Down Expand Up @@ -41,3 +41,5 @@ export const Map = React.forwardRef(function Map (
</MapContainer>
)
})

export default Map
2 changes: 1 addition & 1 deletion adhocracy4/maps_react/static/a4maps_react/ZoomControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createControlComponent } from '@react-leaflet/core'
import L from 'leaflet'

// Create a Leaflet Control
const createLeafletElement = (props) => {
export const createLeafletElement = (props) => {
const zoomControl = L.control.zoom(props)

const updateDisabled = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import L from 'leaflet'
import { AddMarkerControlClass } from '../AddMarkerControl'
import { polygonData } from './Map.jest'
import { jest } from '@jest/globals'

describe('AddMarkerControlClass', () => {
const polygonGeoJSON = L.geoJSON(polygonData)
const map = { on: jest.fn(), off: jest.fn(), addLayer: jest.fn(), constraints: polygonGeoJSON }
const point = JSON.stringify({
type: 'Feature',
properties: {},
geometry: {
type: 'Point',
coordinates: [5, 5]
}
})

it('sets a marker', () => {
const input = document.createElement('input')
const instance = new AddMarkerControlClass({ input })
instance.map = map

const latlng = { lat: 5, lng: 5 }

expect(instance.marker).toBe(null)
instance.updateMarker(latlng)
expect(instance.marker).toBeDefined()
expect(input.value).toEqual(expect.stringContaining('5,5'))
instance.updateMarker({ lat: 2, lng: 2 })
expect(input.value).toEqual(expect.stringContaining('2,2'))
})

it('does not set a marker when outside', () => {
const input = document.createElement('input')
const instance = new AddMarkerControlClass({ input })
instance.map = map
const latlng = { lat: 15, lng: 15 }
expect(instance.marker).toBe(null)
instance.updateMarker(latlng)
expect(instance.marker).toBe(null)
expect(input.value).toEqual('')
})

it('updates on drag', () => {
const input = document.createElement('input')
const instance = new AddMarkerControlClass({ input, point })
instance.map = map
expect(instance.oldCoords).toStrictEqual([5, 5])
const newCoords = { lat: 10, lng: 10 }

const e = { target: { getLatLng: () => newCoords, setLatLng: jest.fn() } }
instance.onDragend(e)
expect(instance.oldCoords).toStrictEqual(newCoords)

const e2 = { target: { getLatLng: () => ({ lat: 15, lng: 15 }), setLatLng: jest.fn() } }
instance.onDragend(e2)
expect(e2.target.setLatLng).toHaveBeenCalledWith(newCoords)
expect(instance.oldCoords).toStrictEqual(newCoords)
})
})
66 changes: 66 additions & 0 deletions adhocracy4/maps_react/static/a4maps_react/__tests__/Map.jest.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import Map from '../Map'

export const polygonData = {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [
[
[0, 0],
[10, 0],
[10, 10],
[0, 10]
]
]
}
}

jest.mock('react-leaflet', () => {
const ActualReactLeaflet = jest.requireActual('react-leaflet')
const React = require('react')

const MapContainer = React.forwardRef((props, ref) => (
<div data-testid="map">
<ActualReactLeaflet.MapContainer ref={ref} {...props} />
</div>
))
MapContainer.displayName = 'MapContainer'

const GeoJSON = React.forwardRef((props, ref) => (
<div data-testid="geojson"><ActualReactLeaflet.GeoJSON ref={ref} props={props} /></div>
))
GeoJSON.displayName = 'GeoJSON'

return {
__esModule: true,
...ActualReactLeaflet,
GeoJSON,
MapContainer
}
})

describe('Map component tests', () => {
test('component renders', () => {
render(<Map />)
const mapNode = screen.getByTestId('map')

expect(mapNode).toBeTruthy()
})

test('renders map with GeoJSON when polygon prop is provided', () => {
render(<Map polygon={polygonData} />)
const geoJsonNode = screen.getByTestId('geojson')

expect(geoJsonNode).toBeTruthy()
})

test('does not render GeoJSON when polygon prop is not provided', () => {
render(<Map />)
const geoJsonNode = screen.queryByTestId('geojson')

expect(geoJsonNode).toBeFalsy()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createLeafletElement } from '../ZoomControl'
import L from 'leaflet'

describe('ZoomControl', () => {
it('createLeafletElement should return a zoom control', () => {
const zoomControl = createLeafletElement({})
expect(zoomControl).toBeInstanceOf(L.Control.Zoom)

const map = {
_zoom: 5,
getMinZoom: jest.fn(() => 3),
getMaxZoom: jest.fn(() => 10),
getZoom: jest.fn(),
on: jest.fn(),
off: jest.fn()
}
L.DomUtil.addClass = jest.fn()
L.DomUtil.removeClass = jest.fn()
zoomControl._map = map

const onAdd = jest.spyOn(L.Control.Zoom.prototype, 'onAdd')
const onRemove = jest.spyOn(L.Control.Zoom.prototype, 'onRemove')

zoomControl.onAdd(map)

expect(map.on).toHaveBeenCalledWith('zoom', expect.any(Function))
expect(onAdd).toHaveBeenCalledWith(map)
expect(map.getMinZoom).toHaveBeenCalled()
expect(map.getMaxZoom).toHaveBeenCalled()
expect(L.DomUtil.addClass).toHaveBeenCalledTimes(0)
expect(L.DomUtil.removeClass).toHaveBeenCalledTimes(2)

zoomControl.onRemove(map)

expect(map.off).toHaveBeenCalledWith('zoom', expect.any(Function))
expect(onRemove).toHaveBeenCalledWith(map)
})
})
8 changes: 7 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ const config = {
],
transform: {
'^.+\\.[t|j]sx?$': 'babel-jest'
}
},
transformIgnorePatterns: [
'node_modules/(?!(@?react-leaflet)/)'
],
setupFiles: [
'<rootDir>/setupTests.js'
]
}

module.exports = config
3 changes: 3 additions & 0 deletions setupTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (typeof window.URL.createObjectURL === 'undefined') {
window.URL.createObjectURL = () => {}
}

0 comments on commit 087bb8e

Please sign in to comment.