]> git.openstreetmap.org Git - rails.git/blob - test/controllers/geocoder_controller_test.rb
Create nominatim search query resource
[rails.git] / test / controllers / geocoder_controller_test.rb
1 require "test_helper"
2
3 class GeocoderControllerTest < ActionDispatch::IntegrationTest
4   ##
5   # test all routes which lead to this controller
6   def test_routes
7     assert_routing(
8       { :path => "/search", :method => :get },
9       { :controller => "geocoder", :action => "search" }
10     )
11     assert_routing(
12       { :path => "/geocoder/search_osm_nominatim_reverse", :method => :post },
13       { :controller => "geocoder", :action => "search_osm_nominatim_reverse" }
14     )
15   end
16
17   ##
18   # Test identification with no arguments
19   def test_identify_error
20     get search_path
21     assert_response :bad_request
22
23     get search_path, :xhr => true
24     assert_response :bad_request
25   end
26
27   ##
28   # Test identification of basic lat/lon pairs
29   def test_identify_latlon_basic
30     [
31       "50.06773 14.37742",
32       "50.06773/14.37742",
33       "50.06773, 14.37742",
34       "+50.06773 +14.37742",
35       "+50.06773, +14.37742",
36       "+50.06773/+14.37742"
37     ].each do |code|
38       latlon_check code, 50.06773, 14.37742
39     end
40   end
41
42   ##
43   # Test identification of lat/lon pairs using N/E with degrees
44   def test_identify_latlon_ne_d
45     [
46       "N50.06773 E14.37742",
47       "N50.06773, E14.37742",
48       "50.06773N 14.37742E",
49       "50.06773N, 14.37742E"
50     ].each do |code|
51       latlon_check code, 50.06773, 14.37742
52     end
53   end
54
55   ##
56   # Test identification of integer lat/lon pairs using N/E with degrees
57   def test_identify_latlon_ne_d_int_deg
58     [
59       "N50 E14",
60       "N50° E14°",
61       "50N 14E",
62       "50°N 14°E"
63     ].each do |code|
64       latlon_check code, 50, 14
65     end
66   end
67
68   ##
69   # Test identification of lat/lon pairs using N/W with degrees
70   def test_identify_latlon_nw_d
71     [
72       "N50.06773 W14.37742",
73       "N50.06773, W14.37742",
74       "50.06773N 14.37742W",
75       "50.06773N, 14.37742W"
76     ].each do |code|
77       latlon_check code, 50.06773, -14.37742
78     end
79   end
80
81   ##
82   # Test identification of lat/lon pairs using S/E with degrees
83   def test_identify_latlon_se_d
84     [
85       "S50.06773 E14.37742",
86       "S50.06773, E14.37742",
87       "50.06773S 14.37742E",
88       "50.06773S, 14.37742E"
89     ].each do |code|
90       latlon_check code, -50.06773, 14.37742
91     end
92   end
93
94   ##
95   # Test identification of lat/lon pairs using S/W with degrees
96   def test_identify_latlon_sw_d
97     [
98       "S50.06773 W14.37742",
99       "S50.06773, W14.37742",
100       "50.06773S 14.37742W",
101       "50.06773S, 14.37742W"
102     ].each do |code|
103       latlon_check code, -50.06773, -14.37742
104     end
105   end
106
107   ##
108   # Test identification of lat/lon pairs using N/E with degrees/mins
109   def test_identify_latlon_ne_dm
110     [
111       "N 50° 04.064 E 014° 22.645",
112       "N 50° 04.064' E 014° 22.645",
113       "N 50° 04.064', E 014° 22.645'",
114       "N50° 04.064 E14° 22.645",
115       "N 50 04.064 E 014 22.645",
116       "N50 4.064 E14 22.645",
117       "50° 04.064' N, 014° 22.645' E"
118     ].each do |code|
119       latlon_check code, 50.06773, 14.37742
120     end
121   end
122
123   ##
124   # Test identification of lat/lon pairs using N/W with degrees/mins
125   def test_identify_latlon_nw_dm
126     [
127       "N 50° 04.064 W 014° 22.645",
128       "N 50° 04.064' W 014° 22.645",
129       "N 50° 04.064', W 014° 22.645'",
130       "N50° 04.064 W14° 22.645",
131       "N 50 04.064 W 014 22.645",
132       "N50 4.064 W14 22.645",
133       "50° 04.064' N, 014° 22.645' W"
134     ].each do |code|
135       latlon_check code, 50.06773, -14.37742
136     end
137   end
138
139   ##
140   # Test identification of lat/lon pairs using S/E with degrees/mins
141   def test_identify_latlon_se_dm
142     [
143       "S 50° 04.064 E 014° 22.645",
144       "S 50° 04.064' E 014° 22.645",
145       "S 50° 04.064', E 014° 22.645'",
146       "S50° 04.064 E14° 22.645",
147       "S 50 04.064 E 014 22.645",
148       "S50 4.064 E14 22.645",
149       "50° 04.064' S, 014° 22.645' E"
150     ].each do |code|
151       latlon_check code, -50.06773, 14.37742
152     end
153   end
154
155   ##
156   # Test identification of lat/lon pairs using S/W with degrees/mins
157   def test_identify_latlon_sw_dm
158     [
159       "S 50° 04.064 W 014° 22.645",
160       "S 50° 04.064' W 014° 22.645",
161       "S 50° 04.064', W 014° 22.645'",
162       "S50° 04.064 W14° 22.645",
163       "S 50 04.064 W 014 22.645",
164       "S50 4.064 W14 22.645",
165       "50° 04.064' S, 014° 22.645' W"
166     ].each do |code|
167       latlon_check code, -50.06773, -14.37742
168     end
169   end
170
171   ##
172   # Test identification of lat/lon pairs using N/E with degrees/mins/secs
173   def test_identify_latlon_ne_dms
174     [
175       "N 50° 4' 03.828\" E 14° 22' 38.712\"",
176       "N 50° 4' 03.828\", E 14° 22' 38.712\"",
177       "N 50° 4′ 03.828″, E 14° 22′ 38.712″",
178       "N50 4 03.828 E14 22 38.712",
179       "N50 4 03.828, E14 22 38.712",
180       "50°4'3.828\"N 14°22'38.712\"E"
181     ].each do |code|
182       latlon_check code, 50.06773, 14.37742
183     end
184   end
185
186   ##
187   # Test identification of lat/lon pairs using N/W with degrees/mins/secs
188   def test_identify_latlon_nw_dms
189     [
190       "N 50° 4' 03.828\" W 14° 22' 38.712\"",
191       "N 50° 4' 03.828\", W 14° 22' 38.712\"",
192       "N 50° 4′ 03.828″, W 14° 22′ 38.712″",
193       "N50 4 03.828 W14 22 38.712",
194       "N50 4 03.828, W14 22 38.712",
195       "50°4'3.828\"N 14°22'38.712\"W"
196     ].each do |code|
197       latlon_check code, 50.06773, -14.37742
198     end
199   end
200
201   ##
202   # Test identification of lat/lon pairs using S/E with degrees/mins/secs
203   def test_identify_latlon_se_dms
204     [
205       "S 50° 4' 03.828\" E 14° 22' 38.712\"",
206       "S 50° 4' 03.828\", E 14° 22' 38.712\"",
207       "S 50° 4′ 03.828″, E 14° 22′ 38.712″",
208       "S50 4 03.828 E14 22 38.712",
209       "S50 4 03.828, E14 22 38.712",
210       "50°4'3.828\"S 14°22'38.712\"E"
211     ].each do |code|
212       latlon_check code, -50.06773, 14.37742
213     end
214   end
215
216   ##
217   # Test identification of lat/lon pairs using S/W with degrees/mins/secs
218   def test_identify_latlon_sw_dms
219     [
220       "S 50° 4' 03.828\" W 14° 22' 38.712\"",
221       "S 50° 4' 03.828\", W 14° 22' 38.712\"",
222       "S 50° 4′ 03.828″, W 14° 22′ 38.712″",
223       "S50 4 03.828 W14 22 38.712",
224       "S50 4 03.828, W14 22 38.712",
225       "50°4'3.828\"S 14°22'38.712\"W"
226     ].each do |code|
227       latlon_check code, -50.06773, -14.37742
228     end
229   end
230
231   ##
232   # Test identification of lat/lon pairs with missing fractions
233   def test_no_identify_latlon_ne_missing_fraction_part
234     [
235       "N50. E14.",
236       "N50.° E14.°",
237       "50.N 14.E",
238       "50.°N 14.°E",
239       "N50 1.' E14 2.'",
240       "N50° 1.' E14° 2.'",
241       "50N 1.' 14 2.'E",
242       "50° 1.'N 14° 2.'E",
243       "N50 1' 3,\" E14 2' 4.\"",
244       "N50° 1' 3.\" E14° 2' 4.\"",
245       "50N 1' 3.\" 14 2' 4.\"E",
246       "50° 1' 3.\"N 14° 2' 4.\"E"
247     ].each do |code|
248       get search_path(:query => code)
249       assert_response :success
250       assert_template :search
251       assert_template :layout => "map"
252       assert_equal %w[osm_nominatim], assigns(:sources).pluck(:name)
253     end
254   end
255
256   #
257   # Test identification of lat/lon pairs with mixed precision
258   def test_identify_latlon_ne_mixed_precision
259     latlon_check "N1 5 E15",    1.083333, 15
260     latlon_check "N1 5 9 E15",  1.085833, 15
261     latlon_check "N1 5 9 E1 5", 1.085833, 1.083333
262     latlon_check "N15 E1 5",    15, 1.083333
263     latlon_check "N15 E1 5 9",  15, 1.085833
264     latlon_check "N1 5 E1 5 9", 1.083333, 1.085833
265   end
266
267   #
268   # Test identification of lat/lon pairs with values close to zero
269   def test_identify_latlon_close_to_zero
270     [
271       "0.0000123 -0.0000456",
272       "+0.0000123 -0.0000456",
273       "N 0° 0' 0.4428\", W 0° 0' 1.6416\""
274     ].each do |code|
275       latlon_check code, 0.0000123, -0.0000456
276     end
277   end
278
279   ##
280   # Test identification of US zipcodes
281   def test_identify_us_postcode
282     %w[
283       12345
284       12345-6789
285     ].each do |code|
286       search_check code, %w[osm_nominatim]
287     end
288   end
289
290   ##
291   # Test identification of UK postcodes using examples from
292   # http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom
293   def test_identify_uk_postcode
294     [
295       "EC1A 1BB",
296       "W1A 1HQ",
297       "M1 1AA",
298       "B33 8TH",
299       "CR2 6XH",
300       "DN55 1PT"
301     ].each do |code|
302       search_check code, %w[osm_nominatim]
303     end
304   end
305
306   ##
307   # Test identification of Canadian postcodes
308   def test_identify_ca_postcode
309     search_check "A1B 2C3", %w[osm_nominatim]
310   end
311
312   ##
313   # Test identification fall through to the default case
314   def test_identify_default
315     search_check "foo bar baz", %w[osm_nominatim]
316   end
317
318   ##
319   # Test the nominatim reverse search
320   def test_search_osm_nominatim_reverse
321     with_http_stubs "nominatim" do
322       post geocoder_search_osm_nominatim_reverse_path(:lat => 51.7632, :lon => -0.0076, :zoom => 15), :xhr => true
323       results_check :name => "Broxbourne, Hertfordshire, East of England, England, United Kingdom",
324                     :lat => 51.7465723, :lon => -0.0190782,
325                     :type => "node", :id => 28825933, :zoom => 15
326
327       post geocoder_search_osm_nominatim_reverse_path(:lat => 51.7632, :lon => -0.0076, :zoom => 17), :xhr => true
328       results_check :name => "Dinant Link Road, Broxbourne, Hertfordshire, East of England, England, EN11 8HX, United Kingdom",
329                     :lat => 51.7634883, :lon => -0.0088373,
330                     :type => "way", :id => 3489841, :zoom => 17
331
332       post geocoder_search_osm_nominatim_reverse_path(:lat => 13.7709, :lon => 100.50507, :zoom => 19), :xhr => true
333       results_check :name => "MM Steak&Grill, ถนนศรีอยุธยา, บางขุนพรหม, กรุงเทพมหานคร, เขตดุสิต, กรุงเทพมหานคร, 10300, ประเทศไทย",
334                     :lat => 13.7708691, :lon => 100.505073233221,
335                     :type => "way", :id => 542901374, :zoom => 19
336     end
337   end
338
339   private
340
341   def latlon_check(query, lat, lon)
342     get search_path(:query => query)
343     assert_response :success
344     assert_template :search
345     assert_template :layout => "map"
346     assert_equal %w[latlon osm_nominatim_reverse], assigns(:sources).pluck(:name)
347     assert_nil @controller.params[:query]
348     assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lat])
349     assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lon])
350     assert_in_delta lat, @controller.params[:lat].to_f
351     assert_in_delta lon, @controller.params[:lon].to_f
352
353     get search_path(:query => query), :xhr => true
354     assert_response :success
355     assert_template :search
356     assert_template :layout => "xhr"
357     assert_equal %w[latlon osm_nominatim_reverse], assigns(:sources).pluck(:name)
358     assert_nil @controller.params[:query]
359     assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lat])
360     assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lon])
361     assert_in_delta lat, @controller.params[:lat].to_f
362     assert_in_delta lon, @controller.params[:lon].to_f
363   end
364
365   def search_check(query, sources)
366     get search_path(:query => query)
367     assert_response :success
368     assert_template :search
369     assert_template :layout => "map"
370     assert_equal sources, assigns(:sources).pluck(:name)
371
372     get search_path(:query => query), :xhr => true
373     assert_response :success
374     assert_template :search
375     assert_template :layout => "xhr"
376     assert_equal sources, assigns(:sources).pluck(:name)
377   end
378
379   def results_check(*results)
380     assert_response :success
381     assert_template :create
382     assert_template :layout => nil
383     if results.empty?
384       assert_select "ul.results-list", 0
385     else
386       assert_select "ul.results-list", 1 do
387         assert_select "li.search_results_entry", results.count
388
389         results.each do |result|
390           attrs = result.collect { |k, v| "[data-#{k}='#{v}']" }.join
391           assert_select "li.search_results_entry a.set_position#{attrs}", result[:name]
392         end
393       end
394     end
395   end
396
397   def results_check_error(error)
398     assert_response :success
399     assert_template :error
400     assert_template :layout => nil
401     assert_select ".alert.alert-danger", error
402   end
403 end