1+ import { getGeoDiff } from "./index" ;
2+ import { GeoCoordinates , GeoDiff , GeoDirection , GeoStatus , GeoUnit } from "@models/geo" ;
3+
4+ const PARIS : GeoCoordinates = [ 2.3522 , 48.8566 ] ;
5+ const LONDON : GeoCoordinates = [ - 0.1278 , 51.5074 ] ;
6+ const TOKYO : GeoCoordinates = [ 139.6917 , 35.6895 ] ;
7+ const PARIS_VERY_CLOSE : GeoCoordinates = [ 2.35221 , 48.85661 ] ; // ~1 meter away
8+
9+ describe ( "getGeoDiff" , ( ) => {
10+ it ( "returns EQUAL when no previous and current coordinates are provided" , ( ) => {
11+ expect ( getGeoDiff ( null , undefined ) ) . toStrictEqual ( {
12+ type : "geo" ,
13+ status : GeoStatus . EQUAL ,
14+ diff : {
15+ previousCoordinates : null ,
16+ coordinates : null ,
17+ direction : GeoDirection . Stationary ,
18+ distance : 0 ,
19+ label : "0 kilometers" ,
20+ unit : "kilometer"
21+ }
22+ } )
23+ } ) ;
24+ it ( "returns ADDED when no previous coordinates are provided" , ( ) => {
25+ expect ( getGeoDiff ( null , PARIS ) ) . toStrictEqual ( {
26+ type : "geo" ,
27+ status : GeoStatus . ADDED ,
28+ diff : {
29+ previousCoordinates : null ,
30+ coordinates : PARIS ,
31+ direction : GeoDirection . Stationary ,
32+ distance : 0 ,
33+ label : "0 kilometers" ,
34+ unit : "kilometer"
35+ }
36+ } )
37+ } ) ;
38+ it ( "returns DELETED when no current coordinates are provided" , ( ) => {
39+ expect ( getGeoDiff ( PARIS , undefined ) ) . toStrictEqual ( {
40+ type : "geo" ,
41+ status : GeoStatus . DELETED ,
42+ diff : {
43+ previousCoordinates : PARIS ,
44+ coordinates : null ,
45+ direction : GeoDirection . Stationary ,
46+ distance : 0 ,
47+ label : "0 kilometers" ,
48+ unit : "kilometer"
49+ }
50+ } )
51+ } ) ;
52+ it ( "returns ERROR when coordinates are invalid" , ( ) => {
53+ //@ts -expect-error - we want to test invalid coordinates
54+ expect ( getGeoDiff ( [ 1 , 2 , 3 ] , [ 1 , "5" ] ) ) . toStrictEqual ( {
55+ type : "geo" ,
56+ status : GeoStatus . ERROR ,
57+ diff : {
58+ previousCoordinates : [ 1 , 2 , 3 ] ,
59+ coordinates : [ 1 , "5" ] ,
60+ direction : GeoDirection . Stationary ,
61+ distance : 0 ,
62+ label : "0 kilometers" ,
63+ unit : "kilometer"
64+ }
65+ } )
66+ } ) ;
67+ it ( "returns EQUAL when coordinates are identical" , ( ) => {
68+ expect ( getGeoDiff ( PARIS , PARIS ) ) . toStrictEqual ( {
69+ type : "geo" ,
70+ status : GeoStatus . EQUAL ,
71+ diff : {
72+ coordinates : PARIS ,
73+ previousCoordinates : PARIS ,
74+ direction : GeoDirection . Stationary ,
75+ distance : 0 ,
76+ label : "0 kilometers" ,
77+ unit : "kilometer" ,
78+ } ,
79+ } ) ;
80+ } ) ;
81+ it ( "returns UPDATED when coordinates are slightly different - normal accuracy" , ( ) => {
82+ expect ( getGeoDiff ( PARIS , PARIS_VERY_CLOSE , { unit : "meter" , accuracy : "normal" } ) ) . toStrictEqual ( {
83+ type : "geo" ,
84+ status : GeoStatus . UPDATED ,
85+ diff : {
86+ coordinates : PARIS_VERY_CLOSE ,
87+ previousCoordinates : PARIS ,
88+ direction : GeoDirection . NorthEast ,
89+ distance : 1.33 ,
90+ label : "1.33 meters" ,
91+ unit : "meter" ,
92+ } ,
93+ } )
94+ } ) ;
95+ it ( "returns UPDATED when coordinates are slightly different - high accuracy" , ( ) => {
96+ expect ( getGeoDiff ( PARIS , PARIS_VERY_CLOSE , { unit : "meter" , accuracy : "high" } ) ) . toStrictEqual ( {
97+ type : "geo" ,
98+ status : GeoStatus . UPDATED ,
99+ diff : {
100+ coordinates : PARIS_VERY_CLOSE ,
101+ previousCoordinates : PARIS ,
102+ direction : GeoDirection . NorthEast ,
103+ distance : 1.33 ,
104+ label : "1.33 meters" ,
105+ unit : "meter" ,
106+ } ,
107+ } )
108+ } ) ;
109+ it ( "returns UPDATED when coordinates are different - normal accuracy" , ( ) => {
110+ expect ( getGeoDiff ( PARIS , LONDON ) ) . toStrictEqual ( {
111+ "type" : "geo" ,
112+ "status" : "updated" ,
113+ "diff" : {
114+ "coordinates" : [ - 0.1278 , 51.5074 ] ,
115+ "previousCoordinates" : [ 2.3522 , 48.8566 ] ,
116+ "direction" : GeoDirection . NorthWest ,
117+ "distance" : 343.56 ,
118+ "label" : "343.56 kilometers" ,
119+ "unit" : "kilometer"
120+ }
121+ } )
122+ expect ( getGeoDiff ( PARIS , TOKYO ) ) . toStrictEqual ( {
123+ "type" : "geo" ,
124+ "status" : "updated" ,
125+ "diff" : {
126+ "coordinates" : [ 139.6917 , 35.6895 ] ,
127+ "previousCoordinates" : [ 2.3522 , 48.8566 ] ,
128+ "direction" : GeoDirection . NorthEast ,
129+ "distance" : 9712.07 ,
130+ "label" : "9,712.07 kilometers" ,
131+ "unit" : "kilometer"
132+ }
133+ } )
134+ } )
135+ it ( "returns UPDATED when coordinates are different - high accuracy" , ( ) => {
136+ expect ( getGeoDiff ( PARIS , LONDON , { accuracy : "high" } ) ) . toStrictEqual ( {
137+ "type" : "geo" ,
138+ "status" : "updated" ,
139+ "diff" : {
140+ "coordinates" : [ - 0.1278 , 51.5074 ] ,
141+ "previousCoordinates" : [ 2.3522 , 48.8566 ] ,
142+ "direction" : GeoDirection . NorthWest ,
143+ "distance" : 343.92 ,
144+ "label" : "343.92 kilometers" ,
145+ "unit" : "kilometer"
146+ }
147+ } )
148+ expect ( getGeoDiff ( PARIS , TOKYO , { accuracy : "high" } ) ) . toStrictEqual ( {
149+ "type" : "geo" ,
150+ "status" : "updated" ,
151+ "diff" : {
152+ "coordinates" : [ 139.6917 , 35.6895 ] ,
153+ "previousCoordinates" : [ 2.3522 , 48.8566 ] ,
154+ "direction" : GeoDirection . NorthEast ,
155+ "distance" : 9735.66 ,
156+ "label" : "9,735.66 kilometers" ,
157+ "unit" : "kilometer"
158+ }
159+ } )
160+ } )
161+ it ( "properly compute different units" , ( ) => {
162+ const formatDiff = ( distance : number , label : string , unit : GeoUnit ) : GeoDiff => ( {
163+ type : "geo" ,
164+ status : GeoStatus . UPDATED ,
165+ diff : {
166+ coordinates : LONDON ,
167+ previousCoordinates : PARIS ,
168+ direction : GeoDirection . NorthWest ,
169+ distance,
170+ label,
171+ unit
172+ } ,
173+ } )
174+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "centimeter" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 34355606 , "34,355,606 centimeters" , "centimeter" ) )
175+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "foot" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 1127152 , "1,127,152 feet" , "foot" ) )
176+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "inch" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 13525836 , "13,525,836 inches" , "inch" ) )
177+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "kilometer" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 344 , "344 kilometers" , "kilometer" ) )
178+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "meter" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 343556 , "343,556 meters" , "meter" ) )
179+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "mile" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 213 , "213 miles" , "mile" ) )
180+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "mile-scandinavian" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 34 , "34 miles-scandinavian" , "mile-scandinavian" ) )
181+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "millimeter" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 343556060 , "343,556,060 millimeters" , "millimeter" ) )
182+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "yard" , maxDecimals : 0 } ) ) . toStrictEqual ( formatDiff ( 375716 , "375,716 yards" , "yard" ) )
183+ } ) ;
184+ it ( "return locale-aware labels" , ( ) => {
185+ expect ( getGeoDiff ( PARIS , LONDON , {
186+ unit : "kilometer" ,
187+ locale : "it-IT" ,
188+ maxDecimals : 0 ,
189+ } ) . diff . label ) . toStrictEqual ( "344 chilometri" )
190+ expect ( getGeoDiff ( PARIS , LONDON , {
191+ unit : "kilometer" ,
192+ locale : "zh" ,
193+ maxDecimals : 0 ,
194+ } ) . diff . label ) . toBe ( "344公里" )
195+ } ) ;
196+ it ( "handles maxDecimals" , ( ) => {
197+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "meter" , maxDecimals : 0 } ) . diff . distance ) . toStrictEqual ( 343556 )
198+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "meter" , maxDecimals : 1 } ) . diff . distance ) . toStrictEqual ( 343556.1 )
199+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "meter" , maxDecimals : 5 } ) . diff . distance ) . toStrictEqual ( 343556.06034 )
200+ // 2 decimals by default
201+ expect ( getGeoDiff ( PARIS , LONDON , { unit : "meter" } ) . diff . distance ) . toStrictEqual ( 343556.06 )
202+ } )
203+ it ( "falls back to Haversine when Vincenty throws" , async ( ) => {
204+ jest . resetModules ( ) ;
205+ jest . doMock ( "./vincenty" , ( ) => ( {
206+ getVincentyDistance : jest . fn ( ( ) => {
207+ throw new Error ( "Vincenty convergence failed" ) ;
208+ } ) ,
209+ } ) ) ;
210+ // eslint-disable-next-line @typescript-eslint/no-require-imports
211+ const { getGeoDiff } = require ( "." ) ;
212+ expect ( getGeoDiff ( PARIS , LONDON , { accuracy : "high" } ) ) . toStrictEqual ( {
213+ "type" : "geo" ,
214+ "status" : "updated" ,
215+ "diff" : {
216+ "coordinates" : [ - 0.1278 , 51.5074 ] ,
217+ "previousCoordinates" : [ 2.3522 , 48.8566 ] ,
218+ "direction" : "north-west" ,
219+ "distance" : 343.56 ,
220+ "label" : "343.56 kilometers" ,
221+ "unit" : "kilometer"
222+ }
223+ } )
224+ } ) ;
225+ } ) ;
0 commit comments