@osimatic/helpers-js 1.4.23 → 1.4.24

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.
@@ -0,0 +1,509 @@
1
+ const { Country, GeographicCoordinates, Polygon } = require('../location');
2
+
3
+ describe('Country', () => {
4
+ describe('getCountries', () => {
5
+ test('should return an object with country codes', () => {
6
+ const countries = Country.getCountries();
7
+ expect(typeof countries).toBe('object');
8
+ expect(countries).toHaveProperty('FR');
9
+ expect(countries).toHaveProperty('US');
10
+ expect(countries).toHaveProperty('GB');
11
+ });
12
+
13
+ test('should have correct country names', () => {
14
+ const countries = Country.getCountries();
15
+ expect(countries.FR).toBe('France');
16
+ expect(countries.US).toBe('United States');
17
+ expect(countries.GB).toBe('United Kingdom');
18
+ });
19
+ });
20
+
21
+ describe('getCountryName', () => {
22
+ test('should return country name for valid code', () => {
23
+ expect(Country.getCountryName('FR')).toBe('France');
24
+ expect(Country.getCountryName('US')).toBe('United States');
25
+ expect(Country.getCountryName('CA')).toBe('Canada');
26
+ });
27
+
28
+ test('should return the code itself if country not found', () => {
29
+ expect(Country.getCountryName('XX')).toBe('XX');
30
+ expect(Country.getCountryName('ZZZ')).toBe('ZZZ');
31
+ });
32
+ });
33
+
34
+ describe('getContinents', () => {
35
+ test('should return an object with continent IDs', () => {
36
+ const continents = Country.getContinents();
37
+ expect(typeof continents).toBe('object');
38
+ expect(continents[1]).toBe('Europe');
39
+ expect(continents[3]).toBe('Afrique');
40
+ expect(continents[6]).toBe('Asie');
41
+ });
42
+ });
43
+
44
+ describe('getFlagPath', () => {
45
+ test('should return correct flag path', () => {
46
+ const path = Country.getFlagPath('FR');
47
+ expect(path).toContain('fr.png');
48
+ });
49
+
50
+ test('should lowercase the country code', () => {
51
+ const path = Country.getFlagPath('US');
52
+ expect(path).toContain('us.png');
53
+ });
54
+ });
55
+ });
56
+
57
+ describe('GeographicCoordinates', () => {
58
+ describe('check', () => {
59
+ test('should validate correct coordinates', () => {
60
+ expect(GeographicCoordinates.check('48.8566,2.3522')).toBe(true);
61
+ expect(GeographicCoordinates.check('0,0')).toBe(true);
62
+ expect(GeographicCoordinates.check('-45.5,-73.6')).toBe(true);
63
+ expect(GeographicCoordinates.check('90,180')).toBe(true);
64
+ expect(GeographicCoordinates.check('-90,-180')).toBe(true);
65
+ });
66
+
67
+ test('should reject invalid coordinates', () => {
68
+ expect(GeographicCoordinates.check('91,180')).toBe(false);
69
+ expect(GeographicCoordinates.check('45,181')).toBe(false);
70
+ expect(GeographicCoordinates.check('abc,def')).toBe(false);
71
+ expect(GeographicCoordinates.check('45')).toBe(false);
72
+ });
73
+ });
74
+
75
+ describe('parse', () => {
76
+ test('should parse valid coordinate string', () => {
77
+ const coords = GeographicCoordinates.parse('48.8566,2.3522');
78
+ expect(coords).toEqual([48.8566, 2.3522]);
79
+ });
80
+
81
+ test('should handle spaces and semicolons', () => {
82
+ expect(GeographicCoordinates.parse('48.8566, 2.3522')).toEqual([48.8566, 2.3522]);
83
+ expect(GeographicCoordinates.parse('48.8566;2.3522')).toEqual([48.8566, 2.3522]);
84
+ expect(GeographicCoordinates.parse(' 48.8566 , 2.3522 ')).toEqual([48.8566, 2.3522]);
85
+ });
86
+
87
+ test('should return null for invalid input', () => {
88
+ expect(GeographicCoordinates.parse(null)).toBeNull();
89
+ expect(GeographicCoordinates.parse('')).toBeNull();
90
+ expect(GeographicCoordinates.parse('NaN,NaN')).toBeNull();
91
+ expect(GeographicCoordinates.parse('invalid')).toBeNull();
92
+ });
93
+
94
+ test('should return string when asString=true', () => {
95
+ const coords = GeographicCoordinates.parse('48.8566,2.3522', true);
96
+ expect(typeof coords).toBe('string');
97
+ });
98
+ });
99
+
100
+ describe('toFixed', () => {
101
+ test('should format number with default 6 decimals', () => {
102
+ expect(GeographicCoordinates.toFixed(48.85661234)).toBe('48.856612');
103
+ });
104
+
105
+ test('should format number with custom decimals', () => {
106
+ expect(GeographicCoordinates.toFixed(48.85661234, 2)).toBe('48.86');
107
+ expect(GeographicCoordinates.toFixed(48.85661234, 4)).toBe('48.8566');
108
+ });
109
+ });
110
+
111
+ describe('format', () => {
112
+ test('should format coordinates with default 6 decimals', () => {
113
+ expect(GeographicCoordinates.format(48.8566, 2.3522)).toBe('48.856600,2.352200');
114
+ });
115
+
116
+ test('should format coordinates with custom decimals', () => {
117
+ expect(GeographicCoordinates.format(48.8566, 2.3522, 2)).toBe('48.86,2.35');
118
+ });
119
+ });
120
+
121
+ describe('convertToGeoJson', () => {
122
+ test('should convert to GeoJSON Point format', () => {
123
+ const geoJson = GeographicCoordinates.convertToGeoJson(48.8566, 2.3522);
124
+ expect(geoJson).toEqual({
125
+ type: 'Point',
126
+ coordinates: [2.3522, 48.8566]
127
+ });
128
+ });
129
+
130
+ test('should convert strings to numbers', () => {
131
+ const geoJson = GeographicCoordinates.convertToGeoJson('48.8566', '2.3522');
132
+ expect(geoJson.coordinates[0]).toBe(2.3522);
133
+ expect(geoJson.coordinates[1]).toBe(48.8566);
134
+ });
135
+ });
136
+
137
+ describe('parseFromGeoJson', () => {
138
+ test('should parse GeoJSON Point to [lat, long]', () => {
139
+ const geoJson = { type: 'Point', coordinates: [2.3522, 48.8566] };
140
+ const coords = GeographicCoordinates.parseFromGeoJson(geoJson);
141
+ expect(coords).toEqual([48.8566, 2.3522]);
142
+ });
143
+
144
+ test('should parse GeoJSON string', () => {
145
+ const geoJsonStr = '{"type":"Point","coordinates":[2.3522,48.8566]}';
146
+ const coords = GeographicCoordinates.parseFromGeoJson(geoJsonStr);
147
+ expect(coords).toEqual([48.8566, 2.3522]);
148
+ });
149
+
150
+ test('should return null for invalid GeoJSON', () => {
151
+ expect(GeographicCoordinates.parseFromGeoJson({ type: 'Point', coordinates: [] })).toBeNull();
152
+ expect(GeographicCoordinates.parseFromGeoJson({ type: 'Point' })).toBeNull();
153
+ });
154
+
155
+ test('should return string when asString=true', () => {
156
+ const geoJson = { type: 'Point', coordinates: [2.3522, 48.8566] };
157
+ const coords = GeographicCoordinates.parseFromGeoJson(geoJson, true);
158
+ expect(coords).toBe('48.8566,2.3522');
159
+ });
160
+ });
161
+
162
+ describe('haversine', () => {
163
+ test('should calculate distance between two points', () => {
164
+ // Paris to London: ~344 km
165
+ const distance = GeographicCoordinates.haversine(48.8566, 2.3522, 51.5074, -0.1278);
166
+ expect(distance).toBeGreaterThan(340000);
167
+ expect(distance).toBeLessThan(345000);
168
+ });
169
+
170
+ test('should return 0 for same coordinates', () => {
171
+ const distance = GeographicCoordinates.haversine(48.8566, 2.3522, 48.8566, 2.3522);
172
+ expect(distance).toBe(0);
173
+ });
174
+ });
175
+
176
+ describe('isPointCorrespondingToLocationsList', () => {
177
+ test('should return true when point matches string coordinate in list', () => {
178
+ const locationsList = ['48.8566,2.3522', '51.5074,-0.1278'];
179
+ expect(GeographicCoordinates.isPointCorrespondingToLocationsList(48.8566, 2.3522, locationsList, 1)).toBe(true);
180
+ });
181
+
182
+ test('should return true when point matches GeoJSON Point in list', () => {
183
+ const locationsList = [
184
+ { type: 'Point', coordinates: [2.3522, 48.8566] }
185
+ ];
186
+ expect(GeographicCoordinates.isPointCorrespondingToLocationsList(48.8566, 2.3522, locationsList, 1)).toBe(true);
187
+ });
188
+
189
+ test('should return false when point does not match any location', () => {
190
+ const locationsList = ['51.5074,-0.1278'];
191
+ expect(GeographicCoordinates.isPointCorrespondingToLocationsList(48.8566, 2.3522, locationsList, 1)).toBe(false);
192
+ });
193
+
194
+ test('should return true when point is inside polygon', () => {
195
+ const locationsList = [
196
+ {
197
+ type: 'Polygon',
198
+ coordinates: [[
199
+ [2.3, 48.8],
200
+ [2.4, 48.8],
201
+ [2.4, 48.9],
202
+ [2.3, 48.9],
203
+ [2.3, 48.8]
204
+ ]]
205
+ }
206
+ ];
207
+ expect(GeographicCoordinates.isPointCorrespondingToLocationsList(48.85, 2.35, locationsList)).toBe(true);
208
+ });
209
+ });
210
+
211
+ describe('getAllLatLongsFromGeoJsonList', () => {
212
+ test('should extract coordinates from Point', () => {
213
+ const geoJsonList = [
214
+ { type: 'Point', coordinates: [2.3522, 48.8566] }
215
+ ];
216
+ const coords = GeographicCoordinates.getAllLatLongsFromGeoJsonList(geoJsonList);
217
+ expect(coords).toEqual([[48.8566, 2.3522]]);
218
+ });
219
+
220
+ test('should extract coordinates from Polygon', () => {
221
+ const geoJsonList = [
222
+ {
223
+ type: 'Polygon',
224
+ coordinates: [[
225
+ [2.3, 48.8],
226
+ [2.4, 48.9]
227
+ ]]
228
+ }
229
+ ];
230
+ const coords = GeographicCoordinates.getAllLatLongsFromGeoJsonList(geoJsonList);
231
+ expect(coords).toEqual([[48.8, 2.3], [48.9, 2.4]]);
232
+ });
233
+
234
+ test('should handle mixed GeoJSON types', () => {
235
+ const geoJsonList = [
236
+ { type: 'Point', coordinates: [2.3522, 48.8566] },
237
+ {
238
+ type: 'Polygon',
239
+ coordinates: [[
240
+ [2.3, 48.8],
241
+ [2.4, 48.9]
242
+ ]]
243
+ }
244
+ ];
245
+ const coords = GeographicCoordinates.getAllLatLongsFromGeoJsonList(geoJsonList);
246
+ expect(coords.length).toBe(3);
247
+ });
248
+ });
249
+ });
250
+
251
+ describe('Polygon', () => {
252
+ describe('convertToGeoJson', () => {
253
+ test('should convert latlngs to GeoJSON Polygon', () => {
254
+ const latlngs = [
255
+ { lat: 48.8, lng: 2.3 },
256
+ { lat: 48.9, lng: 2.4 },
257
+ { lat: 48.85, lng: 2.5 }
258
+ ];
259
+ const geoJson = Polygon.convertToGeoJson(latlngs);
260
+ expect(geoJson.type).toBe('Polygon');
261
+ expect(geoJson.coordinates[0]).toHaveLength(4); // Should be closed
262
+ expect(geoJson.coordinates[0][0]).toEqual([2.3, 48.8]);
263
+ expect(geoJson.coordinates[0][3]).toEqual([2.3, 48.8]); // Closed
264
+ });
265
+
266
+ test('should handle multi-ring polygons', () => {
267
+ const latlngs = [
268
+ [
269
+ { lat: 48.8, lng: 2.3 },
270
+ { lat: 48.9, lng: 2.4 },
271
+ { lat: 48.85, lng: 2.5 }
272
+ ]
273
+ ];
274
+ const geoJson = Polygon.convertToGeoJson(latlngs);
275
+ expect(geoJson.type).toBe('Polygon');
276
+ expect(geoJson.coordinates).toHaveLength(1);
277
+ });
278
+
279
+ test('should not duplicate closing point if already closed', () => {
280
+ const latlngs = [
281
+ { lat: 48.8, lng: 2.3 },
282
+ { lat: 48.9, lng: 2.4 },
283
+ { lat: 48.85, lng: 2.5 },
284
+ { lat: 48.8, lng: 2.3 }
285
+ ];
286
+ const geoJson = Polygon.convertToGeoJson(latlngs);
287
+ expect(geoJson.coordinates[0]).toHaveLength(4);
288
+ });
289
+ });
290
+
291
+ describe('format', () => {
292
+ test('should format a valid polygon', () => {
293
+ const polygon = {
294
+ type: 'Polygon',
295
+ coordinates: [[
296
+ [2.3, 48.8],
297
+ [2.4, 48.9],
298
+ [2.5, 48.85],
299
+ [2.3, 48.8]
300
+ ]]
301
+ };
302
+ const formatted = Polygon.format(polygon);
303
+ expect(formatted).toHaveProperty('label');
304
+ expect(formatted).toHaveProperty('title');
305
+ expect(formatted.label).toContain('Polygone de');
306
+ expect(formatted.label).toContain('sommets');
307
+ });
308
+
309
+ test('should handle empty polygon', () => {
310
+ const polygon = {
311
+ type: 'Polygon',
312
+ coordinates: [[]]
313
+ };
314
+ const formatted = Polygon.format(polygon);
315
+ expect(formatted.label).toBe('Polygon (vide)');
316
+ });
317
+
318
+ test('should parse JSON string', () => {
319
+ const polygonStr = '{"type":"Polygon","coordinates":[[[2.3,48.8],[2.4,48.9],[2.3,48.8]]]}';
320
+ const formatted = Polygon.format(polygonStr);
321
+ expect(formatted).toHaveProperty('label');
322
+ });
323
+ });
324
+
325
+ describe('getStartCoordinates', () => {
326
+ test('should return start coordinates as array', () => {
327
+ const polygon = {
328
+ type: 'Polygon',
329
+ coordinates: [[
330
+ [2.3, 48.8],
331
+ [2.4, 48.9],
332
+ [2.3, 48.8]
333
+ ]]
334
+ };
335
+ const coords = Polygon.getStartCoordinates(polygon);
336
+ expect(coords).toEqual([48.8, 2.3]);
337
+ });
338
+
339
+ test('should return start coordinates as string when asString=true', () => {
340
+ const polygon = {
341
+ type: 'Polygon',
342
+ coordinates: [[
343
+ [2.3, 48.8],
344
+ [2.4, 48.9],
345
+ [2.3, 48.8]
346
+ ]]
347
+ };
348
+ const coords = Polygon.getStartCoordinates(polygon, true);
349
+ expect(coords).toBe('48.8,2.3');
350
+ });
351
+
352
+ test('should return null for empty polygon', () => {
353
+ const polygon = {
354
+ type: 'Polygon',
355
+ coordinates: [[]]
356
+ };
357
+ const coords = Polygon.getStartCoordinates(polygon);
358
+ expect(coords).toBeNull();
359
+ });
360
+ });
361
+
362
+ describe('isPointOnSegmentDeg', () => {
363
+ test('should return true for point on segment', () => {
364
+ const A = [0, 0];
365
+ const B = [2, 2];
366
+ expect(Polygon.isPointOnSegmentDeg(1, 1, A, B)).toBe(true);
367
+ });
368
+
369
+ test('should return false for point not on segment', () => {
370
+ const A = [0, 0];
371
+ const B = [2, 2];
372
+ expect(Polygon.isPointOnSegmentDeg(1, 0, A, B)).toBe(false);
373
+ });
374
+
375
+ test('should return true for point at segment endpoints', () => {
376
+ const A = [0, 0];
377
+ const B = [2, 2];
378
+ expect(Polygon.isPointOnSegmentDeg(0, 0, A, B)).toBe(true);
379
+ expect(Polygon.isPointOnSegmentDeg(2, 2, A, B)).toBe(true);
380
+ });
381
+ });
382
+
383
+ describe('isPointInRing', () => {
384
+ test('should return true for point inside ring', () => {
385
+ const ring = [
386
+ [0, 0],
387
+ [4, 0],
388
+ [4, 4],
389
+ [0, 4],
390
+ [0, 0]
391
+ ];
392
+ expect(Polygon.isPointInRing(2, 2, ring)).toBe(true);
393
+ });
394
+
395
+ test('should return false for point outside ring', () => {
396
+ const ring = [
397
+ [0, 0],
398
+ [4, 0],
399
+ [4, 4],
400
+ [0, 4],
401
+ [0, 0]
402
+ ];
403
+ expect(Polygon.isPointInRing(5, 5, ring)).toBe(false);
404
+ });
405
+
406
+ test('should return true for point on ring edge', () => {
407
+ const ring = [
408
+ [0, 0],
409
+ [4, 0],
410
+ [4, 4],
411
+ [0, 4],
412
+ [0, 0]
413
+ ];
414
+ expect(Polygon.isPointInRing(2, 0, ring)).toBe(true);
415
+ });
416
+ });
417
+
418
+ describe('isPointInPolygon', () => {
419
+ test('should return true for point inside polygon', () => {
420
+ const polygon = {
421
+ type: 'Polygon',
422
+ coordinates: [[
423
+ [0, 0],
424
+ [4, 0],
425
+ [4, 4],
426
+ [0, 4],
427
+ [0, 0]
428
+ ]]
429
+ };
430
+ expect(Polygon.isPointInPolygon(2, 2, polygon)).toBe(true);
431
+ });
432
+
433
+ test('should return false for point outside polygon', () => {
434
+ const polygon = {
435
+ type: 'Polygon',
436
+ coordinates: [[
437
+ [0, 0],
438
+ [4, 0],
439
+ [4, 4],
440
+ [0, 4],
441
+ [0, 0]
442
+ ]]
443
+ };
444
+ expect(Polygon.isPointInPolygon(5, 5, polygon)).toBe(false);
445
+ });
446
+
447
+ test('should return false for point in hole', () => {
448
+ const polygon = {
449
+ type: 'Polygon',
450
+ coordinates: [
451
+ // Outer ring
452
+ [
453
+ [0, 0],
454
+ [4, 0],
455
+ [4, 4],
456
+ [0, 4],
457
+ [0, 0]
458
+ ],
459
+ // Hole
460
+ [
461
+ [1, 1],
462
+ [3, 1],
463
+ [3, 3],
464
+ [1, 3],
465
+ [1, 1]
466
+ ]
467
+ ]
468
+ };
469
+ expect(Polygon.isPointInPolygon(2, 2, polygon)).toBe(false);
470
+ });
471
+ });
472
+
473
+ describe('toLatLngRings', () => {
474
+ test('should convert GeoJSON to LatLng rings', () => {
475
+ const polygon = {
476
+ type: 'Polygon',
477
+ coordinates: [[
478
+ [2.3, 48.8],
479
+ [2.4, 48.9],
480
+ [2.5, 48.85],
481
+ [2.3, 48.8]
482
+ ]]
483
+ };
484
+ const rings = Polygon.toLatLngRings(polygon);
485
+ expect(rings).toHaveLength(1);
486
+ expect(rings[0][0]).toEqual([48.8, 2.3]);
487
+ });
488
+
489
+ test('should return false for invalid polygon', () => {
490
+ const polygon = { type: 'Polygon', coordinates: [] };
491
+ expect(Polygon.toLatLngRings(polygon)).toBe(false);
492
+ });
493
+
494
+ test('should close unclosed rings', () => {
495
+ const polygon = {
496
+ type: 'Polygon',
497
+ coordinates: [[
498
+ [2.3, 48.8],
499
+ [2.4, 48.9],
500
+ [2.5, 48.85]
501
+ ]]
502
+ };
503
+ const rings = Polygon.toLatLngRings(polygon);
504
+ const lastPoint = rings[0][rings[0].length - 1];
505
+ const firstPoint = rings[0][0];
506
+ expect(lastPoint).toEqual(firstPoint);
507
+ });
508
+ });
509
+ });
@@ -0,0 +1 @@
1
+ /c/OSIMATIC/helpers-js
@@ -0,0 +1 @@
1
+ /c/OSIMATIC/helpers-js
@@ -0,0 +1 @@
1
+ /c/OSIMATIC/helpers-js
@@ -0,0 +1 @@
1
+ /c/OSIMATIC/helpers-js
@@ -0,0 +1 @@
1
+ /c/OSIMATIC/helpers-js
@@ -0,0 +1 @@
1
+ /c/OSIMATIC/helpers-js