@osimatic/helpers-js 1.5.19 → 1.5.21
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.
- package/data_table.js +87 -80
- package/index.js +2 -2
- package/open_street_map.js +354 -183
- package/package.json +6 -2
- package/tests/contact_details.test.js +0 -7
- package/tests/open_street_map.test.js +592 -251
|
@@ -1,77 +1,186 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @jest-environment jsdom
|
|
3
3
|
*/
|
|
4
|
-
const { OpenStreetMap } = require('../open_street_map');
|
|
4
|
+
const { OpenStreetMap, OsmMap } = require('../open_street_map');
|
|
5
5
|
const L = require('leaflet');
|
|
6
6
|
|
|
7
|
+
function createMockMap(zoom = 6) {
|
|
8
|
+
return {
|
|
9
|
+
setView: jest.fn(),
|
|
10
|
+
getZoom: jest.fn(() => zoom),
|
|
11
|
+
setZoom: jest.fn(),
|
|
12
|
+
fitBounds: jest.fn(),
|
|
13
|
+
invalidateSize: jest.fn(),
|
|
14
|
+
off: jest.fn(),
|
|
15
|
+
remove: jest.fn(),
|
|
16
|
+
addLayer: jest.fn(),
|
|
17
|
+
removeLayer: jest.fn(),
|
|
18
|
+
eachLayer: jest.fn(),
|
|
19
|
+
addControl: jest.fn(),
|
|
20
|
+
on: jest.fn(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function createMockMarker(lat = 48.8566, lng = 2.3522) {
|
|
25
|
+
return {
|
|
26
|
+
on: jest.fn(),
|
|
27
|
+
addTo: jest.fn().mockReturnThis(),
|
|
28
|
+
bindPopup: jest.fn(),
|
|
29
|
+
getLatLng: jest.fn(() => ({ lat, lng })),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
7
33
|
describe('OpenStreetMap', () => {
|
|
34
|
+
describe('createMap', () => {
|
|
35
|
+
let mockMap;
|
|
36
|
+
let mockTileLayer;
|
|
37
|
+
let domUtilGetSpy;
|
|
38
|
+
let mapSpy;
|
|
39
|
+
let tileLayerSpy;
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
mockMap = createMockMap();
|
|
43
|
+
mockTileLayer = { addTo: jest.fn() };
|
|
44
|
+
domUtilGetSpy = jest.spyOn(L.DomUtil, 'get').mockReturnValue(null);
|
|
45
|
+
mapSpy = jest.spyOn(L, 'map').mockReturnValue(mockMap);
|
|
46
|
+
tileLayerSpy = jest.spyOn(L, 'tileLayer').mockReturnValue(mockTileLayer);
|
|
47
|
+
jest.spyOn(L, 'latLngBounds').mockReturnValue({ _bounds: [] });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
afterEach(() => jest.restoreAllMocks());
|
|
51
|
+
|
|
52
|
+
test('should return null when mapContainer is null', () => {
|
|
53
|
+
const result = OpenStreetMap.createMap(null);
|
|
54
|
+
expect(result).toBeNull();
|
|
55
|
+
expect(mapSpy).not.toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('should return null when mapContainer is undefined', () => {
|
|
59
|
+
const result = OpenStreetMap.createMap(undefined);
|
|
60
|
+
expect(result).toBeNull();
|
|
61
|
+
expect(mapSpy).not.toHaveBeenCalled();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('should create and return a Leaflet map for a valid DOM element', () => {
|
|
65
|
+
const div = document.createElement('div');
|
|
66
|
+
document.body.appendChild(div);
|
|
67
|
+
|
|
68
|
+
const result = OpenStreetMap.createMap(div);
|
|
69
|
+
|
|
70
|
+
expect(mapSpy).toHaveBeenCalledWith(div, {});
|
|
71
|
+
expect(tileLayerSpy).toHaveBeenCalled();
|
|
72
|
+
expect(mockTileLayer.addTo).toHaveBeenCalledWith(mockMap);
|
|
73
|
+
expect(result).toBe(mockMap);
|
|
74
|
+
|
|
75
|
+
document.body.removeChild(div);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('should reset _leaflet_id when container already has one', () => {
|
|
79
|
+
const div = document.createElement('div');
|
|
80
|
+
document.body.appendChild(div);
|
|
81
|
+
const existingContainer = { _leaflet_id: 42 };
|
|
82
|
+
domUtilGetSpy.mockReturnValue(existingContainer);
|
|
83
|
+
|
|
84
|
+
OpenStreetMap.createMap(div);
|
|
85
|
+
|
|
86
|
+
expect(existingContainer._leaflet_id).toBeNull();
|
|
87
|
+
document.body.removeChild(div);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('should pass options to L.map', () => {
|
|
91
|
+
const div = document.createElement('div');
|
|
92
|
+
document.body.appendChild(div);
|
|
93
|
+
|
|
94
|
+
OpenStreetMap.createMap(div, { zoomControl: false });
|
|
95
|
+
|
|
96
|
+
expect(mapSpy).toHaveBeenCalledWith(div, { zoomControl: false });
|
|
97
|
+
document.body.removeChild(div);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('should center on France by default', () => {
|
|
101
|
+
const div = document.createElement('div');
|
|
102
|
+
document.body.appendChild(div);
|
|
103
|
+
|
|
104
|
+
OpenStreetMap.createMap(div);
|
|
105
|
+
|
|
106
|
+
expect(mockMap.fitBounds).toHaveBeenCalled();
|
|
107
|
+
document.body.removeChild(div);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
8
111
|
describe('getUrl', () => {
|
|
9
112
|
test('should generate OpenStreetMap URL with latitude and longitude', () => {
|
|
10
113
|
const url = OpenStreetMap.getUrl(48.8566, 2.3522);
|
|
11
|
-
|
|
12
114
|
expect(url).toBe('https://www.openstreetmap.org/?mlat=48.8566&mlon=2.3522#map=17/48.8566/2.3522&layers=N');
|
|
13
115
|
});
|
|
14
116
|
|
|
15
117
|
test('should handle negative coordinates', () => {
|
|
16
118
|
const url = OpenStreetMap.getUrl(-33.8688, 151.2093);
|
|
17
|
-
|
|
18
119
|
expect(url).toContain('mlat=-33.8688');
|
|
19
120
|
expect(url).toContain('mlon=151.2093');
|
|
20
121
|
});
|
|
21
122
|
|
|
22
123
|
test('should handle zero coordinates', () => {
|
|
23
124
|
const url = OpenStreetMap.getUrl(0, 0);
|
|
24
|
-
|
|
25
125
|
expect(url).toContain('mlat=0');
|
|
26
126
|
expect(url).toContain('mlon=0');
|
|
27
127
|
});
|
|
28
128
|
|
|
29
129
|
test('should include zoom level 17', () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
expect(url).toContain('#map=17/');
|
|
130
|
+
expect(OpenStreetMap.getUrl(48.8566, 2.3522)).toContain('#map=17/');
|
|
33
131
|
});
|
|
34
132
|
|
|
35
133
|
test('should include layers=N parameter', () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
expect(url).toContain('&layers=N');
|
|
134
|
+
expect(OpenStreetMap.getUrl(48.8566, 2.3522)).toContain('&layers=N');
|
|
39
135
|
});
|
|
40
136
|
});
|
|
41
137
|
|
|
42
138
|
describe('getUrlFromCoordinates', () => {
|
|
43
139
|
test('should parse coordinate string and generate URL', () => {
|
|
44
140
|
const url = OpenStreetMap.getUrlFromCoordinates('48.8566,2.3522');
|
|
45
|
-
|
|
46
141
|
expect(url).toBe('https://www.openstreetmap.org/?mlat=48.8566&mlon=2.3522#map=17/48.8566/2.3522&layers=N');
|
|
47
142
|
});
|
|
48
143
|
|
|
49
144
|
test('should handle negative coordinates in string', () => {
|
|
50
145
|
const url = OpenStreetMap.getUrlFromCoordinates('-33.8688,151.2093');
|
|
51
|
-
|
|
52
146
|
expect(url).toContain('mlat=-33.8688');
|
|
53
147
|
expect(url).toContain('mlon=151.2093');
|
|
54
148
|
});
|
|
55
149
|
|
|
56
150
|
test('should parse coordinates with spaces', () => {
|
|
57
151
|
const url = OpenStreetMap.getUrlFromCoordinates('48.8566, 2.3522');
|
|
58
|
-
|
|
59
152
|
expect(url).toContain('mlat=48.8566');
|
|
60
153
|
expect(url).toContain('mlon=2.3522');
|
|
61
154
|
});
|
|
62
155
|
|
|
63
156
|
test('should handle decimal coordinates', () => {
|
|
64
157
|
const url = OpenStreetMap.getUrlFromCoordinates('48.856614,2.352222');
|
|
65
|
-
|
|
66
158
|
expect(url).toContain('mlat=48.856614');
|
|
67
159
|
expect(url).toContain('mlon=2.352222');
|
|
68
160
|
});
|
|
69
161
|
});
|
|
70
162
|
|
|
163
|
+
describe('centerOnFrance', () => {
|
|
164
|
+
test('should call setView with France coordinates', () => {
|
|
165
|
+
const mockMap = createMockMap();
|
|
166
|
+
OpenStreetMap.centerOnFrance(mockMap);
|
|
167
|
+
expect(mockMap.setView).toHaveBeenCalledWith([46.52863469527167, 2.43896484375], 6);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('should use zoom level 6', () => {
|
|
171
|
+
const mockMap = createMockMap();
|
|
172
|
+
OpenStreetMap.centerOnFrance(mockMap);
|
|
173
|
+
expect(mockMap.setView).toHaveBeenCalledWith(expect.any(Array), 6);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('should not throw when map is null', () => {
|
|
177
|
+
expect(() => OpenStreetMap.centerOnFrance(null)).not.toThrow();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
71
181
|
describe('getCountryBoundingBoxes', () => {
|
|
72
182
|
test('should return object with country codes', () => {
|
|
73
183
|
const boxes = OpenStreetMap.getCountryBoundingBoxes();
|
|
74
|
-
|
|
75
184
|
expect(typeof boxes).toBe('object');
|
|
76
185
|
expect(boxes).toHaveProperty('fr');
|
|
77
186
|
expect(boxes).toHaveProperty('de');
|
|
@@ -79,66 +188,41 @@ describe('OpenStreetMap', () => {
|
|
|
79
188
|
});
|
|
80
189
|
|
|
81
190
|
test('should have France bounding box', () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expect(boxes.fr).toEqual([[41.333, -5.142], [51.091, 9.559]]);
|
|
191
|
+
expect(OpenStreetMap.getCountryBoundingBoxes().fr).toEqual([[41.333, -5.142], [51.091, 9.559]]);
|
|
85
192
|
});
|
|
86
193
|
|
|
87
194
|
test('should have Germany bounding box', () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
expect(boxes.de).toEqual([[47.270, 5.866], [55.058, 15.041]]);
|
|
195
|
+
expect(OpenStreetMap.getCountryBoundingBoxes().de).toEqual([[47.270, 5.866], [55.058, 15.041]]);
|
|
91
196
|
});
|
|
92
197
|
|
|
93
198
|
test('should have USA bounding box', () => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
expect(boxes.us).toEqual([[24.396, -124.848], [49.384, -66.885]]);
|
|
199
|
+
expect(OpenStreetMap.getCountryBoundingBoxes().us).toEqual([[24.396, -124.848], [49.384, -66.885]]);
|
|
97
200
|
});
|
|
98
201
|
|
|
99
202
|
test('should include European countries', () => {
|
|
100
203
|
const boxes = OpenStreetMap.getCountryBoundingBoxes();
|
|
101
|
-
|
|
102
|
-
expect(boxes).toHaveProperty('fr'); // France
|
|
103
|
-
expect(boxes).toHaveProperty('de'); // Germany
|
|
104
|
-
expect(boxes).toHaveProperty('es'); // Spain
|
|
105
|
-
expect(boxes).toHaveProperty('it'); // Italy
|
|
106
|
-
expect(boxes).toHaveProperty('gb'); // UK
|
|
204
|
+
['fr', 'de', 'es', 'it', 'gb'].forEach(c => expect(boxes).toHaveProperty(c));
|
|
107
205
|
});
|
|
108
206
|
|
|
109
207
|
test('should include Asian countries', () => {
|
|
110
208
|
const boxes = OpenStreetMap.getCountryBoundingBoxes();
|
|
111
|
-
|
|
112
|
-
expect(boxes).toHaveProperty('cn'); // China
|
|
113
|
-
expect(boxes).toHaveProperty('in'); // India
|
|
114
|
-
expect(boxes).toHaveProperty('jp'); // Japan
|
|
209
|
+
['cn', 'in', 'jp'].forEach(c => expect(boxes).toHaveProperty(c));
|
|
115
210
|
});
|
|
116
211
|
|
|
117
212
|
test('should include American countries', () => {
|
|
118
213
|
const boxes = OpenStreetMap.getCountryBoundingBoxes();
|
|
119
|
-
|
|
120
|
-
expect(boxes).toHaveProperty('us'); // USA
|
|
121
|
-
expect(boxes).toHaveProperty('ca'); // Canada
|
|
122
|
-
expect(boxes).toHaveProperty('br'); // Brazil
|
|
123
|
-
expect(boxes).toHaveProperty('mx'); // Mexico
|
|
214
|
+
['us', 'ca', 'br', 'mx'].forEach(c => expect(boxes).toHaveProperty(c));
|
|
124
215
|
});
|
|
125
216
|
|
|
126
217
|
test('should include African countries', () => {
|
|
127
218
|
const boxes = OpenStreetMap.getCountryBoundingBoxes();
|
|
128
|
-
|
|
129
|
-
expect(boxes).toHaveProperty('ma'); // Morocco
|
|
130
|
-
expect(boxes).toHaveProperty('eg'); // Egypt
|
|
131
|
-
expect(boxes).toHaveProperty('za'); // South Africa
|
|
219
|
+
['ma', 'eg', 'za'].forEach(c => expect(boxes).toHaveProperty(c));
|
|
132
220
|
});
|
|
133
221
|
|
|
134
222
|
test('should have bounding box format [[S,W], [N,E]]', () => {
|
|
135
|
-
const
|
|
136
|
-
const frBox = boxes.fr;
|
|
137
|
-
|
|
223
|
+
const frBox = OpenStreetMap.getCountryBoundingBoxes().fr;
|
|
138
224
|
expect(Array.isArray(frBox)).toBe(true);
|
|
139
225
|
expect(frBox).toHaveLength(2);
|
|
140
|
-
expect(Array.isArray(frBox[0])).toBe(true);
|
|
141
|
-
expect(Array.isArray(frBox[1])).toBe(true);
|
|
142
226
|
expect(frBox[0]).toHaveLength(2);
|
|
143
227
|
expect(frBox[1]).toHaveLength(2);
|
|
144
228
|
});
|
|
@@ -146,329 +230,586 @@ describe('OpenStreetMap', () => {
|
|
|
146
230
|
|
|
147
231
|
describe('getCountryBoundingBox', () => {
|
|
148
232
|
test('should return bounding box for France', () => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
expect(box).toEqual([[41.333, -5.142], [51.091, 9.559]]);
|
|
233
|
+
expect(OpenStreetMap.getCountryBoundingBox('FR')).toEqual([[41.333, -5.142], [51.091, 9.559]]);
|
|
152
234
|
});
|
|
153
235
|
|
|
154
236
|
test('should be case insensitive', () => {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
expect(boxLower).toEqual(boxUpper);
|
|
160
|
-
expect(boxMixed).toEqual(boxUpper);
|
|
237
|
+
const box = OpenStreetMap.getCountryBoundingBox('FR');
|
|
238
|
+
expect(OpenStreetMap.getCountryBoundingBox('fr')).toEqual(box);
|
|
239
|
+
expect(OpenStreetMap.getCountryBoundingBox('Fr')).toEqual(box);
|
|
161
240
|
});
|
|
162
241
|
|
|
163
242
|
test('should handle whitespace in country code', () => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
expect(box).toEqual([[41.333, -5.142], [51.091, 9.559]]);
|
|
243
|
+
expect(OpenStreetMap.getCountryBoundingBox(' FR ')).toEqual([[41.333, -5.142], [51.091, 9.559]]);
|
|
167
244
|
});
|
|
168
245
|
|
|
169
246
|
test('should return null for unknown country code', () => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
expect(box).toBeNull();
|
|
247
|
+
expect(OpenStreetMap.getCountryBoundingBox('XX')).toBeNull();
|
|
173
248
|
});
|
|
174
249
|
|
|
175
250
|
test('should return null for empty string', () => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
expect(box).toBeNull();
|
|
251
|
+
expect(OpenStreetMap.getCountryBoundingBox('')).toBeNull();
|
|
179
252
|
});
|
|
180
253
|
|
|
181
254
|
test('should return null for null', () => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
expect(box).toBeNull();
|
|
255
|
+
expect(OpenStreetMap.getCountryBoundingBox(null)).toBeNull();
|
|
185
256
|
});
|
|
186
257
|
|
|
187
258
|
test('should return null for undefined', () => {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
expect(box).toBeNull();
|
|
259
|
+
expect(OpenStreetMap.getCountryBoundingBox(undefined)).toBeNull();
|
|
191
260
|
});
|
|
192
261
|
|
|
193
262
|
test('should return bounding box for Germany', () => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
expect(box).toEqual([[47.270, 5.866], [55.058, 15.041]]);
|
|
263
|
+
expect(OpenStreetMap.getCountryBoundingBox('DE')).toEqual([[47.270, 5.866], [55.058, 15.041]]);
|
|
197
264
|
});
|
|
198
265
|
|
|
199
266
|
test('should return bounding box for USA', () => {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
expect(box).toEqual([[24.396, -124.848], [49.384, -66.885]]);
|
|
267
|
+
expect(OpenStreetMap.getCountryBoundingBox('US')).toEqual([[24.396, -124.848], [49.384, -66.885]]);
|
|
203
268
|
});
|
|
204
269
|
|
|
205
270
|
test('should return bounding box for Japan', () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
expect(box).toEqual([[24.249, 122.938], [45.557, 153.987]]);
|
|
271
|
+
expect(OpenStreetMap.getCountryBoundingBox('JP')).toEqual([[24.249, 122.938], [45.557, 153.987]]);
|
|
209
272
|
});
|
|
210
273
|
|
|
211
274
|
test('should return bounding box for Brazil', () => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
expect(box).toEqual([[-33.751, -73.987], [5.271, -34.729]]);
|
|
275
|
+
expect(OpenStreetMap.getCountryBoundingBox('BR')).toEqual([[-33.751, -73.987], [5.271, -34.729]]);
|
|
215
276
|
});
|
|
216
277
|
});
|
|
217
278
|
|
|
218
|
-
describe('
|
|
279
|
+
describe('centerMapOnCountry', () => {
|
|
219
280
|
let mockMap;
|
|
220
|
-
let mockTileLayer;
|
|
221
|
-
let domUtilGetSpy;
|
|
222
|
-
let mapSpy;
|
|
223
|
-
let tileLayerSpy;
|
|
224
281
|
|
|
225
282
|
beforeEach(() => {
|
|
226
|
-
mockMap =
|
|
227
|
-
|
|
228
|
-
getZoom: jest.fn(() => 6),
|
|
229
|
-
setZoom: jest.fn(),
|
|
230
|
-
fitBounds: jest.fn(),
|
|
231
|
-
invalidateSize: jest.fn(),
|
|
232
|
-
};
|
|
233
|
-
mockTileLayer = { addTo: jest.fn() };
|
|
234
|
-
domUtilGetSpy = jest.spyOn(L.DomUtil, 'get').mockReturnValue(null);
|
|
235
|
-
mapSpy = jest.spyOn(L, 'map').mockReturnValue(mockMap);
|
|
236
|
-
tileLayerSpy = jest.spyOn(L, 'tileLayer').mockReturnValue(mockTileLayer);
|
|
283
|
+
mockMap = createMockMap();
|
|
284
|
+
jest.spyOn(L, 'latLngBounds').mockReturnValue({ _bounds: [] });
|
|
237
285
|
});
|
|
238
286
|
|
|
239
|
-
afterEach(() =>
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
287
|
+
afterEach(() => jest.restoreAllMocks());
|
|
288
|
+
|
|
289
|
+
test('should not throw when map is null', () => {
|
|
290
|
+
expect(() => OpenStreetMap.centerMapOnCountry(null, 'FR')).not.toThrow();
|
|
243
291
|
});
|
|
244
292
|
|
|
245
|
-
test('should
|
|
246
|
-
|
|
293
|
+
test('should not call fitBounds for unknown country', () => {
|
|
294
|
+
OpenStreetMap.centerMapOnCountry(mockMap, 'XX');
|
|
295
|
+
expect(mockMap.fitBounds).not.toHaveBeenCalled();
|
|
296
|
+
});
|
|
247
297
|
|
|
248
|
-
|
|
249
|
-
|
|
298
|
+
test('should call fitBounds for known country', () => {
|
|
299
|
+
OpenStreetMap.centerMapOnCountry(mockMap, 'FR');
|
|
300
|
+
expect(mockMap.fitBounds).toHaveBeenCalled();
|
|
250
301
|
});
|
|
251
302
|
|
|
252
|
-
test('should
|
|
253
|
-
|
|
303
|
+
test('should be case insensitive', () => {
|
|
304
|
+
OpenStreetMap.centerMapOnCountry(mockMap, 'fr');
|
|
305
|
+
expect(mockMap.fitBounds).toHaveBeenCalled();
|
|
306
|
+
});
|
|
254
307
|
|
|
255
|
-
|
|
256
|
-
|
|
308
|
+
test('should enforce minZoom when current zoom is too low', () => {
|
|
309
|
+
mockMap.getZoom.mockReturnValue(1);
|
|
310
|
+
OpenStreetMap.centerMapOnCountry(mockMap, 'FR');
|
|
311
|
+
expect(mockMap.setZoom).toHaveBeenCalledWith(3);
|
|
257
312
|
});
|
|
258
313
|
|
|
259
|
-
test('should
|
|
260
|
-
|
|
261
|
-
|
|
314
|
+
test('should not enforce minZoom when zoom is sufficient', () => {
|
|
315
|
+
mockMap.getZoom.mockReturnValue(6);
|
|
316
|
+
OpenStreetMap.centerMapOnCountry(mockMap, 'FR');
|
|
317
|
+
expect(mockMap.setZoom).not.toHaveBeenCalled();
|
|
318
|
+
});
|
|
319
|
+
});
|
|
262
320
|
|
|
263
|
-
|
|
321
|
+
describe('centerMapToLocations', () => {
|
|
322
|
+
let mockMap;
|
|
264
323
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
324
|
+
beforeEach(() => {
|
|
325
|
+
mockMap = createMockMap(12);
|
|
326
|
+
jest.spyOn(L, 'latLngBounds').mockReturnValue({ _bounds: [] });
|
|
327
|
+
});
|
|
269
328
|
|
|
270
|
-
|
|
329
|
+
afterEach(() => jest.restoreAllMocks());
|
|
330
|
+
|
|
331
|
+
test('should call fitBounds with location bounds', () => {
|
|
332
|
+
const locations = [[48.8566, 2.3522], [48.8606, 2.3376]];
|
|
333
|
+
OpenStreetMap.centerMapToLocations(mockMap, locations);
|
|
334
|
+
expect(mockMap.invalidateSize).toHaveBeenCalledWith(false);
|
|
335
|
+
expect(mockMap.fitBounds).toHaveBeenCalled();
|
|
271
336
|
});
|
|
272
337
|
|
|
273
|
-
test('should
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
domUtilGetSpy.mockReturnValue(existingContainer);
|
|
338
|
+
test('should not do anything when map is null', () => {
|
|
339
|
+
OpenStreetMap.centerMapToLocations(null, [[48.8566, 2.3522]]);
|
|
340
|
+
expect(mockMap.invalidateSize).not.toHaveBeenCalled();
|
|
341
|
+
});
|
|
278
342
|
|
|
279
|
-
|
|
343
|
+
test('should not do anything when locations list is empty', () => {
|
|
344
|
+
OpenStreetMap.centerMapToLocations(mockMap, []);
|
|
345
|
+
expect(mockMap.invalidateSize).not.toHaveBeenCalled();
|
|
346
|
+
});
|
|
280
347
|
|
|
281
|
-
|
|
348
|
+
test('should set zoom to maxZoom if current zoom exceeds it', () => {
|
|
349
|
+
mockMap.getZoom.mockReturnValue(20);
|
|
350
|
+
OpenStreetMap.centerMapToLocations(mockMap, [[48.8566, 2.3522]], [20, 20], 18);
|
|
351
|
+
expect(mockMap.setZoom).toHaveBeenCalledWith(18);
|
|
352
|
+
});
|
|
282
353
|
|
|
283
|
-
|
|
354
|
+
test('should use custom padding', () => {
|
|
355
|
+
OpenStreetMap.centerMapToLocations(mockMap, [[48.8566, 2.3522]], [50, 50]);
|
|
356
|
+
expect(mockMap.fitBounds).toHaveBeenCalledWith(expect.anything(), { padding: [50, 50] });
|
|
284
357
|
});
|
|
358
|
+
});
|
|
285
359
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const
|
|
360
|
+
describe('centerMapToGooglePlace', () => {
|
|
361
|
+
test('should call setView with place location', () => {
|
|
362
|
+
const mockMap = createMockMap(10);
|
|
363
|
+
const place = { geometry: { location: { lat: () => 48.8566, lng: () => 2.3522 } } };
|
|
364
|
+
OpenStreetMap.centerMapToGooglePlace(mockMap, place);
|
|
365
|
+
expect(mockMap.setView).toHaveBeenCalledWith([48.8566, 2.3522], 15);
|
|
366
|
+
});
|
|
290
367
|
|
|
291
|
-
|
|
368
|
+
test('should not throw when place is null', () => {
|
|
369
|
+
expect(() => OpenStreetMap.centerMapToGooglePlace(createMockMap(), null)).not.toThrow();
|
|
370
|
+
});
|
|
292
371
|
|
|
293
|
-
|
|
372
|
+
test('should not throw when place has no geometry', () => {
|
|
373
|
+
expect(() => OpenStreetMap.centerMapToGooglePlace(createMockMap(), {})).not.toThrow();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
294
376
|
|
|
295
|
-
|
|
377
|
+
describe('centerMapToCoordinates', () => {
|
|
378
|
+
test('should call setView with provided coordinates', () => {
|
|
379
|
+
const mockMap = createMockMap(10);
|
|
380
|
+
OpenStreetMap.centerMapToCoordinates(mockMap, 48.8566, 2.3522);
|
|
381
|
+
expect(mockMap.setView).toHaveBeenCalledWith([48.8566, 2.3522], 15);
|
|
296
382
|
});
|
|
297
383
|
|
|
298
|
-
test('should
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
384
|
+
test('should use minimum zoom of 15 if current zoom is lower', () => {
|
|
385
|
+
const mockMap = createMockMap(10);
|
|
386
|
+
OpenStreetMap.centerMapToCoordinates(mockMap, 48.8566, 2.3522);
|
|
387
|
+
expect(mockMap.setView).toHaveBeenCalledWith(expect.any(Array), 15);
|
|
388
|
+
});
|
|
302
389
|
|
|
303
|
-
|
|
390
|
+
test('should keep current zoom if higher than 15', () => {
|
|
391
|
+
const mockMap = createMockMap(18);
|
|
392
|
+
OpenStreetMap.centerMapToCoordinates(mockMap, 48.8566, 2.3522);
|
|
393
|
+
expect(mockMap.setView).toHaveBeenCalledWith(expect.any(Array), 18);
|
|
394
|
+
});
|
|
304
395
|
|
|
305
|
-
|
|
396
|
+
test('should not call setView when map is null', () => {
|
|
397
|
+
const mockMap = createMockMap(10);
|
|
398
|
+
OpenStreetMap.centerMapToCoordinates(null, 48.8566, 2.3522);
|
|
399
|
+
expect(mockMap.setView).not.toHaveBeenCalled();
|
|
400
|
+
});
|
|
306
401
|
|
|
307
|
-
|
|
308
|
-
|
|
402
|
+
test('should handle negative coordinates', () => {
|
|
403
|
+
const mockMap = createMockMap(10);
|
|
404
|
+
OpenStreetMap.centerMapToCoordinates(mockMap, -33.8688, 151.2093);
|
|
405
|
+
expect(mockMap.setView).toHaveBeenCalledWith([-33.8688, 151.2093], 15);
|
|
309
406
|
});
|
|
310
407
|
});
|
|
311
408
|
|
|
312
|
-
describe('
|
|
313
|
-
test('should call
|
|
314
|
-
const mockMap =
|
|
315
|
-
|
|
316
|
-
|
|
409
|
+
describe('clearSelections', () => {
|
|
410
|
+
test('should call eachLayer on map', () => {
|
|
411
|
+
const mockMap = createMockMap();
|
|
412
|
+
mockMap.eachLayer = jest.fn();
|
|
413
|
+
OpenStreetMap.clearSelections(mockMap);
|
|
414
|
+
expect(mockMap.eachLayer).toHaveBeenCalled();
|
|
415
|
+
});
|
|
317
416
|
|
|
318
|
-
|
|
417
|
+
test('should remove L.Marker layers', () => {
|
|
418
|
+
const removeSpy = jest.spyOn(L.Marker.prototype, 'remove').mockImplementation(() => {});
|
|
419
|
+
const mockMap = createMockMap();
|
|
420
|
+
mockMap.eachLayer = jest.fn((cb) => { cb(new L.Marker([0, 0])); });
|
|
319
421
|
|
|
320
|
-
|
|
422
|
+
OpenStreetMap.clearSelections(mockMap);
|
|
423
|
+
|
|
424
|
+
expect(removeSpy).toHaveBeenCalled();
|
|
425
|
+
removeSpy.mockRestore();
|
|
321
426
|
});
|
|
322
427
|
|
|
323
|
-
test('should
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
428
|
+
test('should not throw when map is null', () => {
|
|
429
|
+
expect(() => OpenStreetMap.clearSelections(null)).not.toThrow();
|
|
430
|
+
});
|
|
431
|
+
});
|
|
327
432
|
|
|
328
|
-
|
|
433
|
+
describe('addTempMarker', () => {
|
|
434
|
+
let mockMarker;
|
|
329
435
|
|
|
330
|
-
|
|
436
|
+
beforeEach(() => {
|
|
437
|
+
mockMarker = { on: jest.fn() };
|
|
438
|
+
jest.spyOn(L, 'marker').mockReturnValue(mockMarker);
|
|
331
439
|
});
|
|
332
|
-
});
|
|
333
440
|
|
|
334
|
-
|
|
335
|
-
test('should call setView with provided coordinates', () => {
|
|
336
|
-
const mockMap = {
|
|
337
|
-
setView: jest.fn(),
|
|
338
|
-
getZoom: jest.fn(() => 10)
|
|
339
|
-
};
|
|
441
|
+
afterEach(() => jest.restoreAllMocks());
|
|
340
442
|
|
|
341
|
-
|
|
443
|
+
test('should create a draggable marker and add it to the map', () => {
|
|
444
|
+
const mockMap = createMockMap();
|
|
445
|
+
const result = OpenStreetMap.addTempMarker(mockMap, 48.8566, 2.3522);
|
|
446
|
+
expect(L.marker).toHaveBeenCalledWith([48.8566, 2.3522], { draggable: true });
|
|
447
|
+
expect(mockMap.addLayer).toHaveBeenCalledWith(mockMarker);
|
|
448
|
+
expect(result).toBe(mockMarker);
|
|
449
|
+
});
|
|
342
450
|
|
|
343
|
-
|
|
451
|
+
test('should register dragend when onDragEnd is provided', () => {
|
|
452
|
+
OpenStreetMap.addTempMarker(createMockMap(), 48.8566, 2.3522, jest.fn());
|
|
453
|
+
expect(mockMarker.on).toHaveBeenCalledWith('dragend', expect.any(Function));
|
|
344
454
|
});
|
|
345
455
|
|
|
346
|
-
test('should
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
};
|
|
456
|
+
test('should not register dragend when onDragEnd is not provided', () => {
|
|
457
|
+
OpenStreetMap.addTempMarker(createMockMap(), 48.8566, 2.3522);
|
|
458
|
+
expect(mockMarker.on).not.toHaveBeenCalled();
|
|
459
|
+
});
|
|
351
460
|
|
|
352
|
-
|
|
461
|
+
test('should call onDragEnd with the marker on dragend', () => {
|
|
462
|
+
const onDragEnd = jest.fn();
|
|
463
|
+
let dragEndHandler;
|
|
464
|
+
mockMarker.on = jest.fn((event, handler) => { dragEndHandler = handler; });
|
|
353
465
|
|
|
354
|
-
|
|
466
|
+
OpenStreetMap.addTempMarker(createMockMap(), 48.8566, 2.3522, onDragEnd);
|
|
467
|
+
dragEndHandler({ target: mockMarker });
|
|
468
|
+
|
|
469
|
+
expect(onDragEnd).toHaveBeenCalledWith(mockMarker);
|
|
355
470
|
});
|
|
471
|
+
});
|
|
356
472
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
473
|
+
describe('resetTempSelection', () => {
|
|
474
|
+
test('should remove tempLayer from map', () => {
|
|
475
|
+
const mockMap = createMockMap();
|
|
476
|
+
OpenStreetMap.resetTempSelection(mockMap, {});
|
|
477
|
+
expect(mockMap.removeLayer).toHaveBeenCalled();
|
|
478
|
+
});
|
|
362
479
|
|
|
363
|
-
|
|
480
|
+
test('should not call removeLayer when tempLayer is null', () => {
|
|
481
|
+
const mockMap = createMockMap();
|
|
482
|
+
OpenStreetMap.resetTempSelection(mockMap, null);
|
|
483
|
+
expect(mockMap.removeLayer).not.toHaveBeenCalled();
|
|
484
|
+
});
|
|
364
485
|
|
|
365
|
-
|
|
486
|
+
test('should not throw when both are null', () => {
|
|
487
|
+
expect(() => OpenStreetMap.resetTempSelection(null, null)).not.toThrow();
|
|
366
488
|
});
|
|
489
|
+
});
|
|
367
490
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
491
|
+
describe('destroyMap', () => {
|
|
492
|
+
test('should call off and remove on map', () => {
|
|
493
|
+
const mockMap = createMockMap();
|
|
494
|
+
OpenStreetMap.destroyMap(mockMap);
|
|
495
|
+
expect(mockMap.off).toHaveBeenCalled();
|
|
496
|
+
expect(mockMap.remove).toHaveBeenCalled();
|
|
497
|
+
});
|
|
373
498
|
|
|
374
|
-
|
|
499
|
+
test('should not throw when map is null', () => {
|
|
500
|
+
expect(() => OpenStreetMap.destroyMap(null)).not.toThrow();
|
|
501
|
+
});
|
|
502
|
+
});
|
|
375
503
|
|
|
376
|
-
|
|
504
|
+
describe('setZoom', () => {
|
|
505
|
+
test('should call setZoom on map', () => {
|
|
506
|
+
const mockMap = createMockMap();
|
|
507
|
+
OpenStreetMap.setZoom(mockMap, 12);
|
|
508
|
+
expect(mockMap.setZoom).toHaveBeenCalledWith(12);
|
|
377
509
|
});
|
|
378
510
|
|
|
379
|
-
test('should
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
};
|
|
511
|
+
test('should not throw when map is null', () => {
|
|
512
|
+
expect(() => OpenStreetMap.setZoom(null, 12)).not.toThrow();
|
|
513
|
+
});
|
|
514
|
+
});
|
|
384
515
|
|
|
385
|
-
|
|
516
|
+
describe('setView', () => {
|
|
517
|
+
test('should call setView on map', () => {
|
|
518
|
+
const mockMap = createMockMap();
|
|
519
|
+
OpenStreetMap.setView(mockMap, [48.8566, 2.3522], 12);
|
|
520
|
+
expect(mockMap.setView).toHaveBeenCalledWith([48.8566, 2.3522], 12);
|
|
521
|
+
});
|
|
386
522
|
|
|
387
|
-
|
|
523
|
+
test('should not throw when map is null', () => {
|
|
524
|
+
expect(() => OpenStreetMap.setView(null, [0, 0], 10)).not.toThrow();
|
|
388
525
|
});
|
|
389
526
|
});
|
|
390
527
|
|
|
391
|
-
describe('
|
|
392
|
-
|
|
393
|
-
const mockMap = {
|
|
394
|
-
invalidateSize: jest.fn(),
|
|
395
|
-
fitBounds: jest.fn(),
|
|
396
|
-
getZoom: jest.fn(() => 12),
|
|
397
|
-
setZoom: jest.fn()
|
|
398
|
-
};
|
|
528
|
+
describe('addMarker', () => {
|
|
529
|
+
let mockMarker;
|
|
399
530
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
531
|
+
beforeEach(() => {
|
|
532
|
+
mockMarker = createMockMarker();
|
|
533
|
+
jest.spyOn(L, 'marker').mockReturnValue(mockMarker);
|
|
534
|
+
jest.spyOn(L, 'icon').mockReturnValue({});
|
|
535
|
+
});
|
|
403
536
|
|
|
404
|
-
|
|
537
|
+
afterEach(() => jest.restoreAllMocks());
|
|
405
538
|
|
|
406
|
-
|
|
407
|
-
expect(
|
|
408
|
-
|
|
539
|
+
test('should return null when map is null', () => {
|
|
540
|
+
expect(OpenStreetMap.addMarker(null, '48.8566,2.3522', {})).toBeNull();
|
|
541
|
+
});
|
|
409
542
|
|
|
410
|
-
|
|
543
|
+
test('should create marker at parsed coordinates', () => {
|
|
544
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', {});
|
|
545
|
+
expect(L.marker).toHaveBeenCalledWith([48.8566, 2.3522], expect.any(Object));
|
|
411
546
|
});
|
|
412
547
|
|
|
413
|
-
test('should
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
};
|
|
548
|
+
test('should set icon when provided', () => {
|
|
549
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', { icon: '/img/marker.png' });
|
|
550
|
+
expect(L.icon).toHaveBeenCalledWith({ iconUrl: '/img/marker.png', iconSize: [22, 32] });
|
|
551
|
+
});
|
|
418
552
|
|
|
419
|
-
|
|
553
|
+
test('should not set icon when not provided', () => {
|
|
554
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', {});
|
|
555
|
+
expect(L.icon).not.toHaveBeenCalled();
|
|
556
|
+
});
|
|
420
557
|
|
|
421
|
-
|
|
558
|
+
test('should set title when provided', () => {
|
|
559
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', { title: 'Test' });
|
|
560
|
+
expect(L.marker).toHaveBeenCalledWith(expect.any(Array), expect.objectContaining({ title: 'Test' }));
|
|
422
561
|
});
|
|
423
562
|
|
|
424
|
-
test('should
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
};
|
|
563
|
+
test('should bind popup when provided', () => {
|
|
564
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', { popup: '<p>info</p>' });
|
|
565
|
+
expect(mockMarker.bindPopup).toHaveBeenCalledWith('<p>info</p>');
|
|
566
|
+
});
|
|
429
567
|
|
|
430
|
-
|
|
568
|
+
test('should not bind popup when not provided', () => {
|
|
569
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', {});
|
|
570
|
+
expect(mockMarker.bindPopup).not.toHaveBeenCalled();
|
|
571
|
+
});
|
|
431
572
|
|
|
432
|
-
|
|
573
|
+
test('should add marker to map', () => {
|
|
574
|
+
const mockMap = createMockMap();
|
|
575
|
+
OpenStreetMap.addMarker(mockMap, '48.8566,2.3522', {});
|
|
576
|
+
expect(mockMarker.addTo).toHaveBeenCalledWith(mockMap);
|
|
433
577
|
});
|
|
434
578
|
|
|
435
|
-
test('should
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
fitBounds: jest.fn(),
|
|
439
|
-
getZoom: jest.fn(() => 20),
|
|
440
|
-
setZoom: jest.fn()
|
|
441
|
-
};
|
|
579
|
+
test('should return the marker', () => {
|
|
580
|
+
expect(OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', {})).toBe(mockMarker);
|
|
581
|
+
});
|
|
442
582
|
|
|
443
|
-
|
|
444
|
-
|
|
583
|
+
test('should register popupopen when on_click is provided', () => {
|
|
584
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', { on_click: jest.fn() });
|
|
585
|
+
expect(mockMarker.on).toHaveBeenCalledWith('popupopen', expect.any(Function));
|
|
586
|
+
});
|
|
445
587
|
|
|
446
|
-
|
|
588
|
+
test('should not register popupopen when no callbacks provided', () => {
|
|
589
|
+
OpenStreetMap.addMarker(createMockMap(), '48.8566,2.3522', {});
|
|
590
|
+
expect(mockMarker.on).not.toHaveBeenCalled();
|
|
591
|
+
});
|
|
592
|
+
});
|
|
447
593
|
|
|
448
|
-
|
|
594
|
+
describe('addMarkers', () => {
|
|
595
|
+
beforeEach(() => {
|
|
596
|
+
jest.spyOn(L, 'marker').mockReturnValue(createMockMarker());
|
|
597
|
+
jest.spyOn(L, 'icon').mockReturnValue({});
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
afterEach(() => jest.restoreAllMocks());
|
|
449
601
|
|
|
450
|
-
|
|
602
|
+
test('should return empty array when map is null', () => {
|
|
603
|
+
expect(OpenStreetMap.addMarkers(null, ['48.8566,2.3522'], {})).toEqual([]);
|
|
451
604
|
});
|
|
452
605
|
|
|
453
|
-
test('should
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
606
|
+
test('should return empty array when list is empty', () => {
|
|
607
|
+
expect(OpenStreetMap.addMarkers(createMockMap(), [], {})).toEqual([]);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
test('should return one marker per location', () => {
|
|
611
|
+
const result = OpenStreetMap.addMarkers(createMockMap(), ['48.8566,2.3522', '48.86,2.35'], {});
|
|
612
|
+
expect(result).toHaveLength(2);
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
describe('connectMarkers', () => {
|
|
617
|
+
let mockPolyline;
|
|
618
|
+
|
|
619
|
+
beforeEach(() => {
|
|
620
|
+
mockPolyline = { addTo: jest.fn() };
|
|
621
|
+
jest.spyOn(L, 'polyline').mockReturnValue(mockPolyline);
|
|
622
|
+
});
|
|
460
623
|
|
|
461
|
-
|
|
462
|
-
const latLngBoundsSpy = jest.spyOn(L, 'latLngBounds').mockReturnValue({ _bounds: locations });
|
|
624
|
+
afterEach(() => jest.restoreAllMocks());
|
|
463
625
|
|
|
464
|
-
|
|
626
|
+
test('should not draw when locations is empty', () => {
|
|
627
|
+
OpenStreetMap.connectMarkers(createMockMap(), []);
|
|
628
|
+
expect(L.polyline).not.toHaveBeenCalled();
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
test('should not draw when map is null', () => {
|
|
632
|
+
OpenStreetMap.connectMarkers(null, [[0, 0], [1, 1]]);
|
|
633
|
+
expect(L.polyline).not.toHaveBeenCalled();
|
|
634
|
+
});
|
|
465
635
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
636
|
+
test('should not draw with only one location', () => {
|
|
637
|
+
OpenStreetMap.connectMarkers(createMockMap(), [[0, 0]]);
|
|
638
|
+
expect(L.polyline).not.toHaveBeenCalled();
|
|
639
|
+
});
|
|
470
640
|
|
|
471
|
-
|
|
641
|
+
test('should draw n-1 polylines for n locations', () => {
|
|
642
|
+
OpenStreetMap.connectMarkers(createMockMap(), [[0, 0], [1, 1], [2, 2]]);
|
|
643
|
+
expect(L.polyline).toHaveBeenCalledTimes(2);
|
|
472
644
|
});
|
|
473
645
|
});
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
describe('OsmMap', () => {
|
|
649
|
+
let mockMap;
|
|
650
|
+
|
|
651
|
+
beforeEach(() => {
|
|
652
|
+
mockMap = createMockMap();
|
|
653
|
+
jest.spyOn(L.DomUtil, 'get').mockReturnValue(null);
|
|
654
|
+
jest.spyOn(L, 'map').mockReturnValue(mockMap);
|
|
655
|
+
jest.spyOn(L, 'tileLayer').mockReturnValue({ addTo: jest.fn() });
|
|
656
|
+
jest.spyOn(L, 'latLngBounds').mockReturnValue({ _bounds: [] });
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
afterEach(() => jest.restoreAllMocks());
|
|
660
|
+
|
|
661
|
+
function makeOsmMap() {
|
|
662
|
+
const div = document.createElement('div');
|
|
663
|
+
document.body.appendChild(div);
|
|
664
|
+
const osmMap = new OsmMap(div);
|
|
665
|
+
document.body.removeChild(div);
|
|
666
|
+
return osmMap;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
test('constructor initializes markers, locations, tempSelection, tempLayer', () => {
|
|
670
|
+
const osmMap = makeOsmMap();
|
|
671
|
+
expect(osmMap.markers).toEqual([]);
|
|
672
|
+
expect(osmMap.locations).toEqual([]);
|
|
673
|
+
expect(osmMap.tempSelection).toBeNull();
|
|
674
|
+
expect(osmMap.tempLayer).toBeNull();
|
|
675
|
+
expect(osmMap.map).toBe(mockMap);
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
test('setZoom delegates to map', () => {
|
|
679
|
+
makeOsmMap().setZoom(12);
|
|
680
|
+
expect(mockMap.setZoom).toHaveBeenCalledWith(12);
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test('deleteMarkers clears markers and locations', () => {
|
|
684
|
+
const osmMap = makeOsmMap();
|
|
685
|
+
osmMap.markers.push({});
|
|
686
|
+
osmMap.locations.push([0, 0]);
|
|
687
|
+
osmMap.deleteMarkers();
|
|
688
|
+
expect(osmMap.markers).toHaveLength(0);
|
|
689
|
+
expect(osmMap.locations).toHaveLength(0);
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
test('clearSelections calls eachLayer on map', () => {
|
|
693
|
+
mockMap.eachLayer = jest.fn();
|
|
694
|
+
makeOsmMap().clearSelections();
|
|
695
|
+
expect(mockMap.eachLayer).toHaveBeenCalled();
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
test('addTempMarker sets tempLayer', () => {
|
|
699
|
+
const mockTempMarker = { on: jest.fn() };
|
|
700
|
+
jest.spyOn(L, 'marker').mockReturnValue(mockTempMarker);
|
|
701
|
+
|
|
702
|
+
const osmMap = makeOsmMap();
|
|
703
|
+
osmMap.addTempMarker(48.8566, 2.3522);
|
|
704
|
+
|
|
705
|
+
expect(osmMap.tempLayer).toBe(mockTempMarker);
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test('addTempMarker updates tempSelection on dragend', () => {
|
|
709
|
+
let dragEndHandler;
|
|
710
|
+
const mockTempMarker = {
|
|
711
|
+
on: jest.fn((e, h) => { dragEndHandler = h; }),
|
|
712
|
+
getLatLng: jest.fn(() => ({ lat: 48.86, lng: 2.35 })),
|
|
713
|
+
};
|
|
714
|
+
jest.spyOn(L, 'marker').mockReturnValue(mockTempMarker);
|
|
715
|
+
|
|
716
|
+
const osmMap = makeOsmMap();
|
|
717
|
+
osmMap.addTempMarker(48.8566, 2.3522);
|
|
718
|
+
dragEndHandler({ target: mockTempMarker });
|
|
719
|
+
|
|
720
|
+
expect(osmMap.tempSelection).toEqual({ type: 'point', lat: 48.86, long: 2.35 });
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
test('resetTempSelection removes tempLayer and resets state', () => {
|
|
724
|
+
const osmMap = makeOsmMap();
|
|
725
|
+
const mockLayer = {};
|
|
726
|
+
osmMap.tempLayer = mockLayer;
|
|
727
|
+
osmMap.tempSelection = { type: 'point', lat: 1, long: 2 };
|
|
728
|
+
|
|
729
|
+
osmMap.resetTempSelection();
|
|
730
|
+
|
|
731
|
+
expect(mockMap.removeLayer).toHaveBeenCalledWith(mockLayer);
|
|
732
|
+
expect(osmMap.tempLayer).toBeNull();
|
|
733
|
+
expect(osmMap.tempSelection).toBeNull();
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
test('addMarker pushes to markers and locations', () => {
|
|
737
|
+
const mockMarker = createMockMarker(48.8566, 2.3522);
|
|
738
|
+
jest.spyOn(L, 'marker').mockReturnValue(mockMarker);
|
|
739
|
+
jest.spyOn(L, 'icon').mockReturnValue({});
|
|
740
|
+
|
|
741
|
+
const osmMap = makeOsmMap();
|
|
742
|
+
osmMap.addMarker('48.8566,2.3522', {});
|
|
743
|
+
|
|
744
|
+
expect(osmMap.markers).toHaveLength(1);
|
|
745
|
+
expect(osmMap.locations).toEqual([[48.8566, 2.3522]]);
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
test('addMarker does nothing when map is null', () => {
|
|
749
|
+
const osmMap = makeOsmMap();
|
|
750
|
+
osmMap.map = null;
|
|
751
|
+
osmMap.addMarker('48.8566,2.3522', {});
|
|
752
|
+
expect(osmMap.markers).toHaveLength(0);
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
test('addMarkers pushes all markers to markers and locations', () => {
|
|
756
|
+
jest.spyOn(L, 'marker').mockReturnValue(createMockMarker());
|
|
757
|
+
jest.spyOn(L, 'icon').mockReturnValue({});
|
|
758
|
+
|
|
759
|
+
const osmMap = makeOsmMap();
|
|
760
|
+
osmMap.addMarkers(['48.8566,2.3522', '48.86,2.35'], {});
|
|
761
|
+
|
|
762
|
+
expect(osmMap.markers).toHaveLength(2);
|
|
763
|
+
expect(osmMap.locations).toHaveLength(2);
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
test('setView delegates to map', () => {
|
|
767
|
+
makeOsmMap().setView([48.8566, 2.3522], 10);
|
|
768
|
+
expect(mockMap.setView).toHaveBeenCalledWith([48.8566, 2.3522], 10);
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
test('centerOnFrance calls setView with France coords', () => {
|
|
772
|
+
makeOsmMap().centerOnFrance();
|
|
773
|
+
expect(mockMap.setView).toHaveBeenCalledWith([46.52863469527167, 2.43896484375], 6);
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
test('centerOnCountry calls fitBounds for known country', () => {
|
|
777
|
+
makeOsmMap().centerOnCountry('FR');
|
|
778
|
+
expect(mockMap.fitBounds).toHaveBeenCalled();
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
test('centerOnMarkers calls fitBounds with locations', () => {
|
|
782
|
+
const osmMap = makeOsmMap();
|
|
783
|
+
osmMap.locations = [[48.8566, 2.3522]];
|
|
784
|
+
osmMap.centerOnMarkers([20, 20]);
|
|
785
|
+
expect(mockMap.invalidateSize).toHaveBeenCalled();
|
|
786
|
+
expect(mockMap.fitBounds).toHaveBeenCalled();
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
test('centerOnGooglePlace calls setView with place coords', () => {
|
|
790
|
+
const place = { geometry: { location: { lat: () => 48.8566, lng: () => 2.3522 } } };
|
|
791
|
+
makeOsmMap().centerOnGooglePlace(place);
|
|
792
|
+
expect(mockMap.setView).toHaveBeenCalledWith([48.8566, 2.3522], 15);
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
test('centerOnCoordinates calls setView', () => {
|
|
796
|
+
makeOsmMap().centerOnCoordinates(48.8566, 2.3522);
|
|
797
|
+
expect(mockMap.setView).toHaveBeenCalledWith([48.8566, 2.3522], 15);
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
test('connectMarkers draws polylines between locations', () => {
|
|
801
|
+
jest.spyOn(L, 'polyline').mockReturnValue({ addTo: jest.fn() });
|
|
802
|
+
|
|
803
|
+
const osmMap = makeOsmMap();
|
|
804
|
+
osmMap.locations = [[0, 0], [1, 1], [2, 2]];
|
|
805
|
+
osmMap.connectMarkers();
|
|
806
|
+
|
|
807
|
+
expect(L.polyline).toHaveBeenCalledTimes(2);
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
test('destroyMap calls off and remove', () => {
|
|
811
|
+
makeOsmMap().destroyMap();
|
|
812
|
+
expect(mockMap.off).toHaveBeenCalled();
|
|
813
|
+
expect(mockMap.remove).toHaveBeenCalled();
|
|
814
|
+
});
|
|
474
815
|
});
|