@defra/interactive-map 0.0.9-alpha → 0.0.10-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/DOCS_README.md +39 -0
  2. package/docs/api.md +1 -1
  3. package/docs/architecture/architecture-diagrams.md +1 -3
  4. package/docs/architecture/diagrams-viewer.mdx +12 -0
  5. package/docs/govuk-prototype.md +23 -0
  6. package/docs/index.md +23 -0
  7. package/docusaurus.config.cjs +106 -0
  8. package/mise.toml +2 -0
  9. package/package.json +21 -4
  10. package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -1
  11. package/plugins/beta/draw-es/src/api/newPolygon.js +1 -3
  12. package/plugins/beta/draw-es/src/events.js +2 -2
  13. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
  14. package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
  15. package/plugins/beta/draw-ml/src/api/newLine.js +2 -2
  16. package/plugins/beta/draw-ml/src/api/newPolygon.js +2 -2
  17. package/plugins/beta/draw-ml/src/events.js +18 -10
  18. package/plugins/search/src/Search.test.jsx +170 -0
  19. package/plugins/search/src/components/CloseButton/CloseButton.test.jsx +67 -0
  20. package/plugins/search/src/components/Form/Form.test.jsx +158 -0
  21. package/plugins/search/src/components/OpenButton/OpenButton.test.jsx +47 -0
  22. package/plugins/search/src/components/Suggestions/Suggestions.test.jsx +79 -0
  23. package/plugins/search/src/datasets.test.js +46 -0
  24. package/plugins/search/src/events/fetchSuggestions.test.js +212 -0
  25. package/plugins/search/src/events/formHandlers.test.js +232 -0
  26. package/plugins/search/src/events/index.test.js +118 -0
  27. package/plugins/search/src/events/inputHandlers.test.js +104 -0
  28. package/plugins/search/src/events/suggestionHandlers.test.js +166 -0
  29. package/plugins/search/src/index.test.js +47 -0
  30. package/plugins/search/src/reducer.test.js +80 -0
  31. package/plugins/search/src/utils/parseOsNamesResults.js +2 -1
  32. package/plugins/search/src/utils/parseOsNamesResults.test.js +140 -0
  33. package/plugins/search/src/utils/updateMap.test.js +52 -0
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ import { createSuggestionHandlers } from './suggestionHandlers.js'
5
+ import { updateMap } from '../utils/updateMap.js'
6
+
7
+ jest.mock('../utils/updateMap.js')
8
+
9
+ describe('createSuggestionHandlers', () => {
10
+ let dispatch
11
+ let services
12
+ let handlers
13
+
14
+ beforeEach(() => {
15
+ dispatch = jest.fn()
16
+
17
+ services = {
18
+ eventBus: { emit: jest.fn() },
19
+ announce: jest.fn()
20
+ }
21
+
22
+ handlers = createSuggestionHandlers({
23
+ dispatch,
24
+ services,
25
+ mapProvider: 'map',
26
+ markers: 'markers',
27
+ showMarker: true,
28
+ markerColor: 'blue'
29
+ })
30
+
31
+ jest.clearAllMocks()
32
+ })
33
+
34
+ // ---------- Suggestion click ----------
35
+
36
+ test('handleSuggestionClick (desktop)', () => {
37
+ const suggestion = { text: 'Paris', bounds: 'b', point: 'p' }
38
+
39
+ handlers.handleSuggestionClick(suggestion, { breakpoint: 'desktop' })
40
+
41
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_VALUE', payload: 'Paris' })
42
+ expect(dispatch).toHaveBeenCalledWith({ type: 'HIDE_SUGGESTIONS' })
43
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_SELECTED', payload: -1 })
44
+ expect(updateMap).toHaveBeenCalledWith(expect.objectContaining({ bounds: 'b', point: 'p' }))
45
+ expect(services.eventBus.emit).toHaveBeenCalledWith(
46
+ 'search:match',
47
+ expect.objectContaining({ query: 'Paris' })
48
+ )
49
+ })
50
+
51
+ test('handleSuggestionClick (mobile closes search)', () => {
52
+ const suggestion = { text: 'Berlin', bounds: 'b', point: 'p' }
53
+
54
+ handlers.handleSuggestionClick(suggestion, { breakpoint: 'mobile' })
55
+
56
+ expect(dispatch).toHaveBeenCalledWith({ type: 'TOGGLE_EXPANDED', payload: false })
57
+ expect(services.eventBus.emit).toHaveBeenCalledWith('search:close')
58
+ })
59
+
60
+ // ---------- ArrowDown ----------
61
+
62
+ test('ArrowDown selects next suggestion', () => {
63
+ const e = { key: 'ArrowDown', preventDefault: jest.fn() }
64
+
65
+ handlers.handleInputKeyDown(e, {
66
+ suggestions: [{ text: 'A' }, { text: 'B' }],
67
+ selectedIndex: 0
68
+ })
69
+
70
+ expect(e.preventDefault).toHaveBeenCalled()
71
+ expect(services.announce).toHaveBeenCalledWith('B. 2 of 2 is highlighted')
72
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_SELECTED', payload: 1 })
73
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_KEYBOARD_FOCUS_WITHIN', payload: false })
74
+ })
75
+
76
+ test('ArrowDown does nothing when no suggestions', () => {
77
+ const e = { key: 'ArrowDown', preventDefault: jest.fn() }
78
+
79
+ handlers.handleInputKeyDown(e, { suggestions: [], selectedIndex: 0 })
80
+
81
+ expect(e.preventDefault).not.toHaveBeenCalled()
82
+ expect(dispatch).not.toHaveBeenCalled()
83
+ expect(services.announce).not.toHaveBeenCalled()
84
+ })
85
+
86
+ test('ArrowDown does nothing when at last suggestion', () => {
87
+ const e = { key: 'ArrowDown', preventDefault: jest.fn() }
88
+
89
+ handlers.handleInputKeyDown(e, {
90
+ suggestions: [{ text: 'A' }, { text: 'B' }],
91
+ selectedIndex: 1 // last index
92
+ })
93
+
94
+ expect(e.preventDefault).toHaveBeenCalled()
95
+ expect(dispatch).not.toHaveBeenCalled()
96
+ expect(services.announce).not.toHaveBeenCalled()
97
+ })
98
+
99
+ // ---------- ArrowUp ----------
100
+
101
+ test('ArrowUp moves selection up and resets to -1', () => {
102
+ const e = { key: 'ArrowUp', preventDefault: jest.fn() }
103
+
104
+ handlers.handleInputKeyDown(e, {
105
+ suggestions: [{ text: 'A' }, { text: 'B' }],
106
+ selectedIndex: 0
107
+ })
108
+
109
+ expect(e.preventDefault).toHaveBeenCalled()
110
+ expect(services.announce).toHaveBeenCalledWith('2 suggestions available')
111
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_SELECTED', payload: -1 })
112
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_KEYBOARD_FOCUS_WITHIN', payload: true })
113
+ })
114
+
115
+ test('ArrowUp moves selection up normally when selectedIndex > 0', () => {
116
+ const e = { key: 'ArrowUp', preventDefault: jest.fn() }
117
+
118
+ handlers.handleInputKeyDown(e, {
119
+ suggestions: [{ text: 'A' }, { text: 'B' }, { text: 'C' }],
120
+ selectedIndex: 2
121
+ })
122
+
123
+ expect(e.preventDefault).toHaveBeenCalled()
124
+ expect(services.announce).toHaveBeenCalledWith('B. 2 of 3 is highlighted')
125
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_SELECTED', payload: 1 })
126
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_KEYBOARD_FOCUS_WITHIN', payload: false })
127
+ })
128
+
129
+ test('ArrowUp does nothing when no suggestions', () => {
130
+ const e = { key: 'ArrowUp', preventDefault: jest.fn() }
131
+
132
+ handlers.handleInputKeyDown(e, { suggestions: [], selectedIndex: 0 })
133
+
134
+ expect(e.preventDefault).not.toHaveBeenCalled()
135
+ expect(dispatch).not.toHaveBeenCalled()
136
+ expect(services.announce).not.toHaveBeenCalled()
137
+ })
138
+
139
+ // ---------- Escape & default ----------
140
+
141
+ test('Escape hides suggestions and clears selection', () => {
142
+ const e = { key: 'Escape', preventDefault: jest.fn() }
143
+
144
+ handlers.handleInputKeyDown(e, {
145
+ suggestions: [{ text: 'A' }],
146
+ selectedIndex: 0
147
+ })
148
+
149
+ expect(e.preventDefault).toHaveBeenCalled()
150
+ expect(dispatch).toHaveBeenCalledWith({ type: 'HIDE_SUGGESTIONS' })
151
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_SELECTED', payload: -1 })
152
+ })
153
+
154
+ test('Other keys do nothing', () => {
155
+ const e = { key: 'Enter', preventDefault: jest.fn() }
156
+
157
+ handlers.handleInputKeyDown(e, {
158
+ suggestions: [{ text: 'A' }],
159
+ selectedIndex: 0
160
+ })
161
+
162
+ expect(e.preventDefault).not.toHaveBeenCalled()
163
+ expect(dispatch).not.toHaveBeenCalled()
164
+ expect(services.announce).not.toHaveBeenCalled()
165
+ })
166
+ })
@@ -0,0 +1,47 @@
1
+ // /plugins/search/index.test.js
2
+
3
+ // Mock SCSS import so Jest can run without parsing errors
4
+ jest.mock('./search.scss', () => {})
5
+
6
+ import createPlugin from './index'
7
+
8
+ describe('createPlugin', () => {
9
+ beforeEach(() => {
10
+ jest.resetModules()
11
+ })
12
+
13
+ it('returns default plugin structure with showMarker and id', async () => {
14
+ const plugin = createPlugin()
15
+ expect(plugin.showMarker).toBe(true)
16
+ expect(plugin.id).toBe('search')
17
+ expect(typeof plugin.load).toBe('function')
18
+ })
19
+
20
+ it('overrides manifest when isExpanded is true', () => {
21
+ const plugin = createPlugin({ isExpanded: true })
22
+ expect(plugin.isExpanded).toBe(true)
23
+ expect(plugin.manifest).toEqual({
24
+ controls: [{ id: 'search', mobile: { slot: 'banner' } }]
25
+ })
26
+ })
27
+
28
+ it('spreads custom options correctly', () => {
29
+ const custom = { foo: 'bar', isExpanded: false }
30
+ const plugin = createPlugin(custom)
31
+ expect(plugin.foo).toBe('bar')
32
+ expect(plugin.showMarker).toBe(true)
33
+ expect(plugin.id).toBe('search')
34
+ })
35
+
36
+ it('load function dynamically imports the manifest and returns it', async () => {
37
+ // Mock the dynamic import for './manifest.js'
38
+ const manifestMock = { data: 'test-manifest' }
39
+ jest.mock('./manifest.js', () => ({
40
+ manifest: manifestMock
41
+ }), { virtual: true })
42
+
43
+ const plugin = createPlugin()
44
+ const result = await plugin.load()
45
+ expect(result).toEqual(manifestMock)
46
+ })
47
+ })
@@ -0,0 +1,80 @@
1
+ // /plugins/search/reducer.test.js
2
+
3
+ import { initialState, actions } from './reducer'
4
+
5
+ describe('search state actions', () => {
6
+ it('TOGGLE_EXPANDED sets isExpanded and areSuggestionsVisible', () => {
7
+ const state = { ...initialState }
8
+ const newState = actions.TOGGLE_EXPANDED(state, true)
9
+ expect(newState.isExpanded).toBe(true)
10
+ expect(newState.areSuggestionsVisible).toBe(true)
11
+
12
+ const collapsed = actions.TOGGLE_EXPANDED(state, false)
13
+ expect(collapsed.isExpanded).toBe(false)
14
+ expect(collapsed.areSuggestionsVisible).toBe(false)
15
+ })
16
+
17
+ it('SET_KEYBOARD_FOCUS_WITHIN sets focus and shows suggestions', () => {
18
+ const state = { ...initialState }
19
+ const newState = actions.SET_KEYBOARD_FOCUS_WITHIN(state, true)
20
+ expect(newState.hasKeyboardFocusWithin).toBe(true)
21
+ expect(newState.areSuggestionsVisible).toBe(true)
22
+
23
+ const removedFocus = actions.SET_KEYBOARD_FOCUS_WITHIN(state, false)
24
+ expect(removedFocus.hasKeyboardFocusWithin).toBe(false)
25
+ expect(removedFocus.areSuggestionsVisible).toBe(true) // always true
26
+ })
27
+
28
+ it('INPUT_BLUR removes focus and updates areSuggestionsVisible correctly', () => {
29
+ const state = { ...initialState, areSuggestionsVisible: true, hasKeyboardFocusWithin: true }
30
+
31
+ // Non-keyboard blur
32
+ const newStateMouse = actions.INPUT_BLUR(state, 'mouse')
33
+ expect(newStateMouse.hasKeyboardFocusWithin).toBe(false)
34
+ expect(newStateMouse.areSuggestionsVisible).toBe(true) // still true
35
+ expect(newStateMouse.selectedIndex).toBe(-1)
36
+
37
+ // Keyboard blur hides suggestions
38
+ const newStateKeyboard = actions.INPUT_BLUR(state, 'keyboard')
39
+ expect(newStateKeyboard.hasKeyboardFocusWithin).toBe(false)
40
+ expect(newStateKeyboard.areSuggestionsVisible).toBe(false) // now false
41
+ expect(newStateKeyboard.selectedIndex).toBe(-1)
42
+ })
43
+
44
+ it('SET_VALUE updates the input value', () => {
45
+ const state = { ...initialState }
46
+ const newState = actions.SET_VALUE(state, 'test')
47
+ expect(newState.value).toBe('test')
48
+ })
49
+
50
+ it('UPDATE_SUGGESTIONS updates the suggestions array', () => {
51
+ const state = { ...initialState }
52
+ const suggestions = [{ id: 1 }, { id: 2 }]
53
+ const newState = actions.UPDATE_SUGGESTIONS(state, suggestions)
54
+ expect(newState.suggestions).toEqual(suggestions)
55
+ })
56
+
57
+ it('SHOW_SUGGESTIONS sets areSuggestionsVisible to true', () => {
58
+ const state = { ...initialState, areSuggestionsVisible: false }
59
+ const newState = actions.SHOW_SUGGESTIONS(state)
60
+ expect(newState.areSuggestionsVisible).toBe(true)
61
+ })
62
+
63
+ it('HIDE_SUGGESTIONS sets areSuggestionsVisible to false', () => {
64
+ const state = { ...initialState, areSuggestionsVisible: true }
65
+ const newState = actions.HIDE_SUGGESTIONS(state)
66
+ expect(newState.areSuggestionsVisible).toBe(false)
67
+ })
68
+
69
+ it('SET_SELECTED updates selectedIndex and visibility', () => {
70
+ const state = { ...initialState, areSuggestionsVisible: false }
71
+
72
+ const selected = actions.SET_SELECTED(state, 1)
73
+ expect(selected.selectedIndex).toBe(1)
74
+ expect(selected.areSuggestionsVisible).toBe(true)
75
+
76
+ const deselected = actions.SET_SELECTED(state, -1)
77
+ expect(deselected.selectedIndex).toBe(-1)
78
+ expect(deselected.areSuggestionsVisible).toBe(false)
79
+ })
80
+ })
@@ -105,5 +105,6 @@ const parseOsNamesResults = (json, query, crs) => {
105
105
  }
106
106
 
107
107
  export {
108
- parseOsNamesResults
108
+ parseOsNamesResults,
109
+ point
109
110
  }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ import { parseOsNamesResults, point } from './parseOsNamesResults.js'
5
+ import OsGridRef from 'geodesy/osgridref.js'
6
+
7
+ // Mock OsGridRef so we can control toLatLon outputs
8
+ jest.mock('geodesy/osgridref.js', () => {
9
+ return jest.fn().mockImplementation((x, y) => ({
10
+ x,
11
+ y,
12
+ toLatLon: () => ({ lat: y / 1e5, lon: x / 1e5 }) // deterministic lat/lon
13
+ }))
14
+ })
15
+
16
+ describe('osNamesUtils', () => {
17
+ const sampleEntry = {
18
+ GAZETTEER_ENTRY: {
19
+ ID: 1,
20
+ NAME1: 'London',
21
+ COUNTY_UNITARY: 'Greater London',
22
+ DISTRICT_BOROUGH: 'Camden',
23
+ POSTCODE_DISTRICT: 'WC1',
24
+ LOCAL_TYPE: 'Town',
25
+ MBR_XMIN: 1000,
26
+ MBR_YMIN: 2000,
27
+ MBR_XMAX: 3000,
28
+ MBR_YMAX: 4000,
29
+ GEOMETRY_X: 1500,
30
+ GEOMETRY_Y: 2500
31
+ }
32
+ }
33
+
34
+ test('returns empty array for null/invalid/error results', () => {
35
+ expect(parseOsNamesResults(null, 'x', 'EPSG:27700')).toEqual([])
36
+ expect(parseOsNamesResults({ error: true }, 'x', 'EPSG:27700')).toEqual([])
37
+ expect(parseOsNamesResults({ header: { totalresults: 0 } }, 'x', 'EPSG:27700')).toEqual([])
38
+ })
39
+
40
+ test('removes tenuous results when query does not match', () => {
41
+ const results = [
42
+ { GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY, NAME1: 'Bristol', ID: 2 } }
43
+ ]
44
+ const json = { results }
45
+ const output = parseOsNamesResults(json, 'London', 'EPSG:27700')
46
+ expect(output).toHaveLength(0)
47
+ })
48
+
49
+ test('removes duplicate IDs', () => {
50
+ const dup = { ...sampleEntry, GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY } }
51
+ const json = { results: [sampleEntry, dup] }
52
+ const output = parseOsNamesResults(json, 'London', 'EPSG:27700')
53
+ expect(output).toHaveLength(1)
54
+ })
55
+
56
+ test('limits results to MAX_RESULTS', () => {
57
+ const manyResults = Array.from({ length: 10 }, (_, i) => ({
58
+ GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY, ID: i }
59
+ }))
60
+ const json = { results: manyResults }
61
+ const output = parseOsNamesResults(json, 'London', 'EPSG:27700')
62
+ expect(output).toHaveLength(8)
63
+ })
64
+
65
+ test('bounds returns raw OSGB values for EPSG:27700', () => {
66
+ const json = { results: [sampleEntry] }
67
+ const output = parseOsNamesResults(json, 'London', 'EPSG:27700')
68
+ expect(output[0].bounds).toEqual([
69
+ sampleEntry.GAZETTEER_ENTRY.MBR_XMIN,
70
+ sampleEntry.GAZETTEER_ENTRY.MBR_YMIN,
71
+ sampleEntry.GAZETTEER_ENTRY.MBR_XMAX,
72
+ sampleEntry.GAZETTEER_ENTRY.MBR_YMAX
73
+ ])
74
+ expect(output[0].point).toEqual([
75
+ sampleEntry.GAZETTEER_ENTRY.GEOMETRY_X,
76
+ sampleEntry.GAZETTEER_ENTRY.GEOMETRY_Y
77
+ ])
78
+ })
79
+
80
+ test('bounds converts to WGS84 for EPSG:4326', () => {
81
+ const json = { results: [sampleEntry] }
82
+ const output = parseOsNamesResults(json, 'London', 'EPSG:4326')
83
+ const expectedBounds = [
84
+ Math.round(1000 / 1e5 * 1e6) / 1e6,
85
+ Math.round(2000 / 1e5 * 1e6) / 1e6,
86
+ Math.round(3000 / 1e5 * 1e6) / 1e6,
87
+ Math.round(4000 / 1e5 * 1e6) / 1e6
88
+ ]
89
+ expect(output[0].bounds).toEqual(expectedBounds)
90
+ const expectedPoint = [
91
+ Math.round(1500 / 1e5 * 1e6) / 1e6,
92
+ Math.round(2500 / 1e5 * 1e6) / 1e6
93
+ ]
94
+ expect(output[0].point).toEqual(expectedPoint)
95
+ })
96
+
97
+ test('label generates marked text', () => {
98
+ const json = { results: [sampleEntry] }
99
+ const output = parseOsNamesResults(json, 'London', 'EPSG:27700')
100
+ expect(output[0].text).toContain('London')
101
+ expect(output[0].marked).toContain('<mark>')
102
+ })
103
+
104
+ test('handles MBR_XMIN null by using buffered GEOMETRY_X/Y', () => {
105
+ const entry = {
106
+ GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY, MBR_XMIN: null, MBR_YMIN: null }
107
+ }
108
+ const json = { results: [entry] }
109
+ const output = parseOsNamesResults(json, 'London', 'EPSG:27700')
110
+ expect(output[0].bounds).toEqual([
111
+ entry.GAZETTEER_ENTRY.GEOMETRY_X - 500,
112
+ entry.GAZETTEER_ENTRY.GEOMETRY_Y - 500,
113
+ entry.GAZETTEER_ENTRY.GEOMETRY_X + 500,
114
+ entry.GAZETTEER_ENTRY.GEOMETRY_Y + 500
115
+ ])
116
+ })
117
+
118
+ test('label falls back to DISTRICT_BOROUGH when COUNTY_UNITARY is absent', () => {
119
+ const entry = { GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY, COUNTY_UNITARY: null } }
120
+ const output = parseOsNamesResults({ results: [entry] }, 'London', 'EPSG:27700')
121
+ expect(output[0].text).toContain(sampleEntry.GAZETTEER_ENTRY.DISTRICT_BOROUGH)
122
+ })
123
+
124
+ test('label omits qualifier for City type', () => {
125
+ const entry = { GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY, LOCAL_TYPE: 'City' } }
126
+ const output = parseOsNamesResults({ results: [entry] }, 'London', 'EPSG:27700')
127
+ expect(output[0].text).toBe('London')
128
+ })
129
+
130
+ test('throws error for unsupported CRS', () => {
131
+ const entry = { GAZETTEER_ENTRY: { ...sampleEntry.GAZETTEER_ENTRY } }
132
+ const json = { results: [entry] }
133
+ expect(() => parseOsNamesResults(json, 'London', 'EPSG:9999')).toThrow('Unsupported CRS')
134
+ })
135
+
136
+ test('point function throws error for unsupported CRS', () => {
137
+ const coords = { GEOMETRY_X: 1500, GEOMETRY_Y: 2500 }
138
+ expect(() => point('EPSG:9999', coords)).toThrow('Unsupported CRS: EPSG:9999')
139
+ })
140
+ })
@@ -0,0 +1,52 @@
1
+ // src/plugins/search/utils/updateMap.test.js
2
+
3
+ import { updateMap } from './updateMap.js'
4
+
5
+ describe('updateMap', () => {
6
+ let mapProvider
7
+ let markers
8
+ const bounds = { north: 1, south: 0 }
9
+ const point = { lat: 10, lng: 20 }
10
+
11
+ beforeEach(() => {
12
+ mapProvider = {
13
+ fitToBounds: jest.fn(),
14
+ }
15
+
16
+ markers = {
17
+ add: jest.fn(),
18
+ }
19
+ })
20
+
21
+ it('fits the map to bounds and adds a marker when showMarker is true', () => {
22
+ updateMap({
23
+ mapProvider,
24
+ bounds,
25
+ point,
26
+ markers,
27
+ showMarker: true,
28
+ markerColor: 'red',
29
+ })
30
+
31
+ expect(mapProvider.fitToBounds).toHaveBeenCalledWith(bounds)
32
+ expect(markers.add).toHaveBeenCalledWith(
33
+ 'search',
34
+ point,
35
+ { color: 'red' }
36
+ )
37
+ })
38
+
39
+ it('fits the map to bounds and does not add a marker when showMarker is false', () => {
40
+ updateMap({
41
+ mapProvider,
42
+ bounds,
43
+ point,
44
+ markers,
45
+ showMarker: false,
46
+ markerColor: 'blue',
47
+ })
48
+
49
+ expect(mapProvider.fitToBounds).toHaveBeenCalledWith(bounds)
50
+ expect(markers.add).not.toHaveBeenCalled()
51
+ })
52
+ })