abuiles-geokit 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +19 -0
  5. data/History.txt +77 -0
  6. data/Manifest.txt +21 -0
  7. data/README.markdown +273 -0
  8. data/Rakefile +13 -0
  9. data/geokit.gemspec +24 -0
  10. data/lib/geokit.rb +55 -0
  11. data/lib/geokit/bounds.rb +95 -0
  12. data/lib/geokit/geo_loc.rb +115 -0
  13. data/lib/geokit/geocoders.rb +68 -0
  14. data/lib/geokit/geocoders/ca_geocoder.rb +54 -0
  15. data/lib/geokit/geocoders/geo_plugin_geocoder.rb +30 -0
  16. data/lib/geokit/geocoders/geocode_error.rb +7 -0
  17. data/lib/geokit/geocoders/geocoder.rb +75 -0
  18. data/lib/geokit/geocoders/geonames_geocoder.rb +53 -0
  19. data/lib/geokit/geocoders/google_geocoder.rb +145 -0
  20. data/lib/geokit/geocoders/google_premier_geocoder.rb +147 -0
  21. data/lib/geokit/geocoders/ip_geocoder.rb +76 -0
  22. data/lib/geokit/geocoders/multi_geocoder.rb +60 -0
  23. data/lib/geokit/geocoders/us_geocoder.rb +50 -0
  24. data/lib/geokit/geocoders/yahoo_geocoder.rb +49 -0
  25. data/lib/geokit/inflector.rb +39 -0
  26. data/lib/geokit/lat_lng.rb +112 -0
  27. data/lib/geokit/mappable.rb +210 -0
  28. data/lib/geokit/too_many_queries_error.rb +4 -0
  29. data/lib/geokit/version.rb +3 -0
  30. data/test/test_base_geocoder.rb +58 -0
  31. data/test/test_bounds.rb +97 -0
  32. data/test/test_ca_geocoder.rb +39 -0
  33. data/test/test_geoloc.rb +72 -0
  34. data/test/test_geoplugin_geocoder.rb +58 -0
  35. data/test/test_google_geocoder.rb +225 -0
  36. data/test/test_google_premier_geocoder.rb +88 -0
  37. data/test/test_google_reverse_geocoder.rb +47 -0
  38. data/test/test_inflector.rb +24 -0
  39. data/test/test_ipgeocoder.rb +109 -0
  40. data/test/test_latlng.rb +209 -0
  41. data/test/test_multi_geocoder.rb +91 -0
  42. data/test/test_multi_ip_geocoder.rb +36 -0
  43. data/test/test_us_geocoder.rb +54 -0
  44. data/test/test_yahoo_geocoder.rb +103 -0
  45. metadata +141 -0
@@ -0,0 +1,4 @@
1
+ module Geokit
2
+ class TooManyQueriesError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module Geokit
2
+ VERSION = "1.6.1"
3
+ end
@@ -0,0 +1,58 @@
1
+ require 'test/unit'
2
+ require 'net/http'
3
+ require 'rubygems'
4
+ require 'mocha'
5
+ require 'geokit'
6
+
7
+ class MockSuccess < Net::HTTPSuccess #:nodoc: all
8
+ def initialize
9
+ end
10
+ end
11
+
12
+ class MockFailure < Net::HTTPServiceUnavailable #:nodoc: all
13
+ def initialize
14
+ end
15
+ end
16
+
17
+ # Base class for testing geocoders.
18
+ class BaseGeocoderTest < Test::Unit::TestCase #:nodoc: all
19
+
20
+ class Geokit::Geocoders::TestGeocoder < Geokit::Geocoders::Geocoder
21
+ def self.do_get(url)
22
+ sleep(2)
23
+ end
24
+ end
25
+
26
+ # Defines common test fixtures.
27
+ def setup
28
+ @address = 'San Francisco, CA'
29
+ @full_address = '100 Spear St, San Francisco, CA, 94105-1522, US'
30
+ @full_address_short_zip = '100 Spear St, San Francisco, CA, 94105, US'
31
+
32
+ @latlng = Geokit::LatLng.new(37.7742, -122.417068)
33
+ @success = Geokit::GeoLoc.new({:city=>"SAN FRANCISCO", :state=>"CA", :country_code=>"US", :lat=>@latlng.lat, :lng=>@latlng.lng})
34
+ @success.success = true
35
+ end
36
+
37
+ def test_timeout_call_web_service
38
+ url = "http://www.anything.com"
39
+ Geokit::Geocoders::request_timeout = 1
40
+ assert_nil Geokit::Geocoders::TestGeocoder.call_geocoder_service(url)
41
+ end
42
+
43
+ def test_successful_call_web_service
44
+ url = "http://www.anything.com"
45
+ Geokit::Geocoders::Geocoder.expects(:do_get).with(url).returns("SUCCESS")
46
+ assert_equal "SUCCESS", Geokit::Geocoders::Geocoder.call_geocoder_service(url)
47
+ end
48
+
49
+ def test_find_geocoder_methods
50
+ public_methods = Geokit::Geocoders::Geocoder.public_methods.map { |m| m.to_s }
51
+ assert public_methods.include?("yahoo_geocoder")
52
+ assert public_methods.include?("google_geocoder")
53
+ assert public_methods.include?("ca_geocoder")
54
+ assert public_methods.include?("us_geocoder")
55
+ assert public_methods.include?("multi_geocoder")
56
+ assert public_methods.include?("ip_geocoder")
57
+ end
58
+ end
@@ -0,0 +1,97 @@
1
+ require 'test/unit'
2
+ require 'geokit'
3
+
4
+ class BoundsTest < Test::Unit::TestCase #:nodoc: all
5
+
6
+ def setup
7
+ # This is the area in Texas
8
+ @sw = Geokit::LatLng.new(32.91663,-96.982841)
9
+ @ne = Geokit::LatLng.new(32.96302,-96.919495)
10
+ @bounds=Geokit::Bounds.new(@sw,@ne)
11
+ @loc_a=Geokit::LatLng.new(32.918593,-96.958444) # inside bounds
12
+ @loc_b=Geokit::LatLng.new(32.914144,-96.958444) # outside bouds
13
+
14
+ # this is a cross-meridan area
15
+ @cross_meridian=Geokit::Bounds.normalize([30,170],[40,-170])
16
+ @inside_cm=Geokit::LatLng.new(35,175)
17
+ @inside_cm_2=Geokit::LatLng.new(35,-175)
18
+ @east_of_cm=Geokit::LatLng.new(35,-165)
19
+ @west_of_cm=Geokit::LatLng.new(35,165)
20
+
21
+ end
22
+
23
+ def test_equality
24
+ assert_equal Geokit::Bounds.new(@sw,@ne), Geokit::Bounds.new(@sw,@ne)
25
+ end
26
+
27
+ def test_normalize
28
+ res=Geokit::Bounds.normalize(@sw,@ne)
29
+ assert_equal res,Geokit::Bounds.new(@sw,@ne)
30
+ res=Geokit::Bounds.normalize([@sw,@ne])
31
+ assert_equal res,Geokit::Bounds.new(@sw,@ne)
32
+ res=Geokit::Bounds.normalize([@sw.lat,@sw.lng],[@ne.lat,@ne.lng])
33
+ assert_equal res,Geokit::Bounds.new(@sw,@ne)
34
+ res=Geokit::Bounds.normalize([[@sw.lat,@sw.lng],[@ne.lat,@ne.lng]])
35
+ assert_equal res,Geokit::Bounds.new(@sw,@ne)
36
+ end
37
+
38
+ def test_point_inside_bounds
39
+ assert @bounds.contains?(@loc_a)
40
+ end
41
+
42
+ def test_point_outside_bounds
43
+ assert !@bounds.contains?(@loc_b)
44
+ end
45
+
46
+ def test_point_inside_bounds_cross_meridian
47
+ assert @cross_meridian.contains?(@inside_cm)
48
+ assert @cross_meridian.contains?(@inside_cm_2)
49
+ end
50
+
51
+ def test_point_outside_bounds_cross_meridian
52
+ assert !@cross_meridian.contains?(@east_of_cm)
53
+ assert !@cross_meridian.contains?(@west_of_cm)
54
+ end
55
+
56
+ def test_center
57
+ assert_in_delta 32.939828,@bounds.center.lat,0.00005
58
+ assert_in_delta(-96.9511763,@bounds.center.lng,0.00005)
59
+ end
60
+
61
+ def test_center_cross_meridian
62
+ assert_in_delta 35.41160, @cross_meridian.center.lat,0.00005
63
+ assert_in_delta 179.38112, @cross_meridian.center.lng,0.00005
64
+ end
65
+
66
+ def test_creation_from_circle
67
+ bounds=Geokit::Bounds.from_point_and_radius([32.939829, -96.951176],2.5)
68
+ inside=Geokit::LatLng.new 32.9695270000,-96.9901590000
69
+ outside=Geokit::LatLng.new 32.8951550000,-96.9584440000
70
+ assert bounds.contains?(inside)
71
+ assert !bounds.contains?(outside)
72
+ end
73
+
74
+ def test_bounds_to_span
75
+ sw = Geokit::LatLng.new(32, -96)
76
+ ne = Geokit::LatLng.new(40, -70)
77
+ bounds = Geokit::Bounds.new(sw, ne)
78
+
79
+ assert_equal Geokit::LatLng.new(8, 26), bounds.to_span
80
+ end
81
+
82
+ def test_bounds_to_span_with_bounds_crossing_prime_meridian
83
+ sw = Geokit::LatLng.new(20, -70)
84
+ ne = Geokit::LatLng.new(40, 100)
85
+ bounds = Geokit::Bounds.new(sw, ne)
86
+
87
+ assert_equal Geokit::LatLng.new(20, 170), bounds.to_span
88
+ end
89
+
90
+ def test_bounds_to_span_with_bounds_crossing_dateline
91
+ sw = Geokit::LatLng.new(20, 100)
92
+ ne = Geokit::LatLng.new(40, -70)
93
+ bounds = Geokit::Bounds.new(sw, ne)
94
+
95
+ assert_equal Geokit::LatLng.new(20, 190), bounds.to_span
96
+ end
97
+ end
@@ -0,0 +1,39 @@
1
+ Geokit::Geocoders::geocoder_ca = "SOMEKEYVALUE"
2
+
3
+ class CaGeocoderTest < BaseGeocoderTest #:nodoc: all
4
+
5
+ CA_SUCCESS=<<-EOF
6
+ <?xml version="1.0" encoding="UTF-8" ?>
7
+ <geodata><latt>49.243086</latt><longt>-123.153684</longt></geodata>
8
+ EOF
9
+
10
+ def setup
11
+ @ca_full_hash = {:street_address=>"2105 West 32nd Avenue",:city=>"Vancouver", :state=>"BC"}
12
+ @ca_full_loc = Geokit::GeoLoc.new(@ca_full_hash)
13
+ end
14
+
15
+ def test_geocoder_with_geo_loc_with_account
16
+ response = MockSuccess.new
17
+ response.expects(:body).returns(CA_SUCCESS)
18
+ url = "http://geocoder.ca/?stno=2105&addresst=West+32nd+Avenue&city=Vancouver&prov=BC&auth=SOMEKEYVALUE&geoit=xml"
19
+ Geokit::Geocoders::CaGeocoder.expects(:call_geocoder_service).with(url).returns(response)
20
+ verify(Geokit::Geocoders::CaGeocoder.geocode(@ca_full_loc))
21
+ end
22
+
23
+ def test_service_unavailable
24
+ response = MockFailure.new
25
+ #Net::HTTP.expects(:get_response).with(URI.parse("http://geocoder.ca/?stno=2105&addresst=West+32nd+Avenue&city=Vancouver&prov=BC&auth=SOMEKEYVALUE&geoit=xml")).returns(response)
26
+ url = "http://geocoder.ca/?stno=2105&addresst=West+32nd+Avenue&city=Vancouver&prov=BC&auth=SOMEKEYVALUE&geoit=xml"
27
+ Geokit::Geocoders::CaGeocoder.expects(:call_geocoder_service).with(url).returns(response)
28
+ assert !Geokit::Geocoders::CaGeocoder.geocode(@ca_full_loc).success
29
+ end
30
+
31
+ private
32
+
33
+ def verify(location)
34
+ assert_equal "BC", location.state
35
+ assert_equal "Vancouver", location.city
36
+ assert_equal "49.243086,-123.153684", location.ll
37
+ assert !location.is_us?
38
+ end
39
+ end
@@ -0,0 +1,72 @@
1
+ require 'test/unit'
2
+ require 'geokit'
3
+
4
+ class GeoLocTest < Test::Unit::TestCase #:nodoc: all
5
+
6
+ def setup
7
+ @loc = Geokit::GeoLoc.new
8
+ end
9
+
10
+ def test_is_us
11
+ assert !@loc.is_us?
12
+ @loc.country_code = 'US'
13
+ assert @loc.is_us?
14
+ end
15
+
16
+ def test_success
17
+ assert !@loc.success?
18
+ @loc.success = false
19
+ assert !@loc.success?
20
+ @loc.success = true
21
+ assert @loc.success?
22
+ end
23
+
24
+ def test_street_number
25
+ @loc.street_address = '123 Spear St.'
26
+ assert_equal '123', @loc.street_number
27
+ end
28
+
29
+ def test_street_name
30
+ @loc.street_address = '123 Spear St.'
31
+ assert_equal 'Spear St.', @loc.street_name
32
+ end
33
+
34
+ def test_city
35
+ @loc.city = "san francisco"
36
+ assert_equal 'San Francisco', @loc.city
37
+ end
38
+
39
+ def test_full_address
40
+ @loc.city = 'San Francisco'
41
+ @loc.state = 'CA'
42
+ @loc.zip = '94105'
43
+ @loc.country_code = 'US'
44
+ assert_equal 'San Francisco, CA, 94105, US', @loc.full_address
45
+ @loc.full_address = 'Irving, TX, 75063, US'
46
+ assert_equal 'Irving, TX, 75063, US', @loc.full_address
47
+ end
48
+
49
+ def test_hash
50
+ @loc.city = 'San Francisco'
51
+ @loc.state = 'CA'
52
+ @loc.zip = '94105'
53
+ @loc.country_code = 'US'
54
+ @another = Geokit::GeoLoc.new @loc.to_hash
55
+ assert_equal @loc, @another
56
+ end
57
+
58
+ def test_all
59
+ assert_equal [@loc], @loc.all
60
+ end
61
+
62
+ def test_to_yaml
63
+ @loc.city = 'San Francisco'
64
+ @loc.state = 'CA'
65
+ @loc.zip = '94105'
66
+ @loc.country_code = 'US'
67
+ assert_equal(
68
+ "--- &id001 !ruby/object:Geokit::GeoLoc \nall: \n- *id001\ncity: San Francisco\ncountry_code: US\nfull_address: \nlat: \nlng: \nprecision: unknown\nprovince: \nstate: CA\nstreet_address: \nsuccess: false\nzip: \"94105\"\n",
69
+ @loc.to_yaml)
70
+ end
71
+
72
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+
3
+ class IpGeocoderTest < BaseGeocoderTest #:nodoc: all
4
+
5
+ IP_SUCCESS=<<-EOF
6
+ <?xml version="1.0" encoding="UTF-8"?>
7
+ <geoPlugin>
8
+ <geoplugin_city>Belo Horizonte</geoplugin_city>
9
+ <geoplugin_region>Minas Gerais</geoplugin_region>
10
+ <geoplugin_areaCode>0</geoplugin_areaCode>
11
+ <geoplugin_dmaCode>0</geoplugin_dmaCode>
12
+ <geoplugin_countryCode>BR</geoplugin_countryCode>
13
+ <geoplugin_countryName>Brazil</geoplugin_countryName>
14
+ <geoplugin_continentCode>SA</geoplugin_continentCode>
15
+ <geoplugin_latitude>-19.916700</geoplugin_latitude>
16
+ <geoplugin_longitude>-43.933300</geoplugin_longitude>
17
+ <geoplugin_currencyCode>BRL</geoplugin_currencyCode>
18
+ <geoplugin_currencySymbol>&#82;&#36;</geoplugin_currencySymbol>
19
+ <geoplugin_currencyConverter>2.2575001717</geoplugin_currencyConverter>
20
+ </geoPlugin>
21
+ EOF
22
+
23
+ def setup
24
+ super
25
+ @success.provider = "geoPlugin"
26
+ end
27
+
28
+ def test_successful_lookup
29
+ success = MockSuccess.new
30
+ success.expects(:body).returns(IP_SUCCESS)
31
+ url = 'http://www.geoplugin.net/xml.gp?ip=200.150.38.66'
32
+ Geokit::Geocoders::GeoPluginGeocoder.expects(:call_geocoder_service).with(url).returns(success)
33
+ location = Geokit::Geocoders::GeoPluginGeocoder.geocode('200.150.38.66')
34
+ assert_not_nil location
35
+ assert_equal -19.916700, location.lat
36
+ assert_equal -43.933300, location.lng
37
+ assert_equal "Belo Horizonte", location.city
38
+ assert_equal "Minas Gerais", location.state
39
+ assert_equal "BR", location.country_code
40
+ assert_equal "geoPlugin", location.provider
41
+ assert location.success?
42
+ end
43
+
44
+ def test_invalid_ip
45
+ location = Geokit::Geocoders::GeoPluginGeocoder.geocode("pixrum")
46
+ assert_not_nil location
47
+ assert !location.success?
48
+ end
49
+
50
+ def test_service_unavailable
51
+ failure = MockFailure.new
52
+ url = 'http://www.geoplugin.net/xml.gp?ip=10.10.10.10'
53
+ Geokit::Geocoders::GeoPluginGeocoder.expects(:call_geocoder_service).with(url).returns(failure)
54
+ location = Geokit::Geocoders::GeoPluginGeocoder.geocode("10.10.10.10")
55
+ assert_not_nil location
56
+ assert !location.success?
57
+ end
58
+ end
@@ -0,0 +1,225 @@
1
+ Geokit::Geocoders::google = 'Google'
2
+
3
+ class GoogleGeocoderTest < BaseGeocoderTest #:nodoc: all
4
+
5
+ GOOGLE_FULL=<<-EOF.strip
6
+ <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>100 spear st, san francisco, ca</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>100 Spear St, San Francisco, CA 94105, USA</address><AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>San Francisco</SubAdministrativeAreaName><Locality><LocalityName>San Francisco</LocalityName><Thoroughfare><ThoroughfareName>100 Spear St</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>94105</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><Point><coordinates>-122.393985,37.792501,0</coordinates></Point></Placemark></Response></kml>
7
+ EOF
8
+
9
+ GOOGLE_RESULT_WITH_SUGGESTED_BOUNDS=<<-EOF.strip
10
+ <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>100 spear st, san francisco, ca</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>100 Spear St, San Francisco, CA 94105, USA</address><AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>San Francisco</SubAdministrativeAreaName><Locality><LocalityName>San Francisco</LocalityName><Thoroughfare><ThoroughfareName>100 Spear St</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>94105</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north="37.7956328" south="37.7893376" east="-122.3908573" west="-122.3971525" /></ExtendedData><Point><coordinates>-122.393985,37.792501,0</coordinates></Point></Placemark></Response></kml>
11
+ EOF
12
+
13
+ GOOGLE_CITY=<<-EOF.strip
14
+ <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>San Francisco</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>San Francisco, CA, USA</address><AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><Locality><LocalityName>San Francisco</LocalityName></Locality></AdministrativeArea></Country></AddressDetails><Point><coordinates>-122.418333,37.775000,0</coordinates></Point></Placemark></Response></kml>
15
+ EOF
16
+
17
+ GOOGLE_MULTI="<?xml version='1.0' encoding='UTF-8'?>\n<kml xmlns='http://earth.google.com/kml/2.0'><Response>\n <name>via Sandro Pertini 8, Ossona, MI</name>\n <Status>\n <code>200</code>\n <request>geocode</request>\n </Status>\n <Placemark id='p1'>\n <address>Via Sandro Pertini, 8, 20010 Mesero MI, Italy</address>\n <AddressDetails Accuracy='8' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>IT</CountryNameCode><CountryName>Italy</CountryName><AdministrativeArea><AdministrativeAreaName>Lombardy</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Milan</SubAdministrativeAreaName><Locality><LocalityName>Mesero</LocalityName><Thoroughfare><ThoroughfareName>8 Via Sandro Pertini</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>20010</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails>\n <Point><coordinates>8.8527131,45.4966243,0</coordinates></Point>\n </Placemark>\n <Placemark id='p2'>\n <address>Via Sandro Pertini, 20010 Ossona MI, Italy</address>\n <AddressDetails Accuracy='6' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>IT</CountryNameCode><CountryName>Italy</CountryName><AdministrativeArea><AdministrativeAreaName>Lombardy</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Milan</SubAdministrativeAreaName><Locality><LocalityName>Ossona</LocalityName><Thoroughfare><ThoroughfareName>Via Sandro Pertini</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>20010</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails>\n <Point><coordinates>8.9023200,45.5074444,0</coordinates></Point>\n </Placemark>\n</Response></kml>\n"
18
+
19
+ GOOGLE_REVERSE_MADRID="<?xml version='1.0' encoding='UTF-8' ?><kml xmlns='http://earth.google.com/kml/2.0'><Response><name>40.416741,-3.703250</name><Status><code>200</code><request>geocode</request></Status><Placemark id='p1'><address>Plaza de la Puerta del Sol, 28013, Madrid, Spain</address><AddressDetails Accuracy='6' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>ES</CountryNameCode><CountryName>Spain</CountryName><AdministrativeArea><AdministrativeAreaName>Madrid</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Madrid</SubAdministrativeAreaName><Locality><LocalityName>Madrid</LocalityName><Thoroughfare><ThoroughfareName>Plaza de la Puerta del Sol</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>28013</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north='40.4199522' south='40.4136570' east='-3.7001138' west='-3.7064091' /></ExtendedData><Point><coordinates>-3.7032537,40.4168023,0</coordinates></Point></Placemark><Placemark id='p2'><address>28013, Madrid, Spain</address><AddressDetails Accuracy='5' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>ES</CountryNameCode><CountryName>Spain</CountryName><AdministrativeArea><AdministrativeAreaName>Madrid</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Madrid</SubAdministrativeAreaName><Locality><LocalityName>Madrid</LocalityName><PostalCode><PostalCodeNumber>28013</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north='40.4244113' south='40.4142840' east='-3.6969862' west='-3.7224820' /></ExtendedData><Point><coordinates>-3.7117806,40.4189645,0</coordinates></Point></Placemark><Placemark id='p3'><address>Madrid, Spain</address><AddressDetails Accuracy='4' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>ES</CountryNameCode><CountryName>Spain</CountryName><AdministrativeArea><AdministrativeAreaName>Madrid</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Madrid</SubAdministrativeAreaName><Locality><LocalityName>Madrid</LocalityName></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north='40.6435181' south='40.3120713' east='-3.5180102' west='-3.8890049' /></ExtendedData><Point><coordinates>-3.7032498,40.4167413,0</coordinates></Point></Placemark><Placemark id='p4'><address>Madrid, Spain</address><AddressDetails Accuracy='2' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>ES</CountryNameCode><CountryName>Spain</CountryName><AdministrativeArea><AdministrativeAreaName>Madrid</AdministrativeAreaName></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north='41.1649106' south='39.8845366' east='-3.0531322' west='-4.5791745' /></ExtendedData><Point><coordinates>-3.5812692,40.4167088,0</coordinates></Point></Placemark><Placemark id='p5'><address>Madrid, Spain</address><AddressDetails Accuracy='3' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>ES</CountryNameCode><CountryName>Spain</CountryName><AdministrativeArea><AdministrativeAreaName>Madrid</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Madrid</SubAdministrativeAreaName></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north='41.1649106' south='39.8845366' east='-3.0531322' west='-4.5791745' /></ExtendedData><Point><coordinates>-3.5812692,40.4167088,0</coordinates></Point></Placemark><Placemark id='p6'><address>Spain</address><AddressDetails Accuracy='1' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>ES</CountryNameCode><CountryName>Spain</CountryName></Country></AddressDetails><ExtendedData><LatLonBox north='43.7903881' south='27.6377504' east='4.3279851' west='-18.1606948' /></ExtendedData><Point><coordinates>-3.7492200,40.4636670,0</coordinates></Point></Placemark></Response></kml>"
20
+
21
+ GOOGLE_COUNTRY_CODE_BIASED_RESULT = <<-EOF.strip
22
+ <?xml version="1.0" encoding="UTF-8" ?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>Syracuse</name><Status><code>200</code><request>geocode</request></Status><Placemark id="p1"><address>Syracuse, Italy</address><AddressDetails Accuracy="3" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>IT</CountryNameCode><CountryName>Italy</CountryName><AdministrativeArea><AdministrativeAreaName>Sicily</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Syracuse</SubAdministrativeAreaName></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north="37.4125978" south="36.6441736" east="15.3367367" west="14.7724913" /></ExtendedData><Point><coordinates>14.9856176,37.0630218,0</coordinates></Point></Placemark></Response></kml>
23
+ EOF
24
+
25
+ GOOGLE_BOUNDS_BIASED_RESULT = <<-EOF.strip
26
+ <?xml version="1.0" encoding="UTF-8" ?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>Winnetka</name><Status><code>200</code><request>geocode</request></Status><Placemark id="p1"><address>Winnetka, California, USA</address><AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><AddressLine>Winnetka</AddressLine></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north="34.2353090" south="34.1791050" east="-118.5534191" west="-118.5883200" /></ExtendedData><Point><coordinates>-118.5710220,34.2131710,0</coordinates></Point></Placemark></Response></kml>
27
+ EOF
28
+
29
+ GOOGLE_TOO_MANY=<<-EOF.strip
30
+ <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>100 spear st, san francisco, ca</name><Status><code>620</code><request>geocode</request></Status></Response></kml>
31
+ EOF
32
+
33
+ def setup
34
+ super
35
+ @google_full_hash = {:street_address=>"100 Spear St", :city=>"San Francisco", :state=>"CA", :zip=>"94105", :country_code=>"US"}
36
+ @google_city_hash = {:city=>"San Francisco", :state=>"CA"}
37
+
38
+ @google_full_loc = Geokit::GeoLoc.new(@google_full_hash)
39
+ @google_city_loc = Geokit::GeoLoc.new(@google_city_hash)
40
+ end
41
+
42
+ def test_google_full_address
43
+ response = MockSuccess.new
44
+ response.expects(:body).returns(GOOGLE_FULL)
45
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@address)}"
46
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
47
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@address)
48
+ assert_equal "CA", res.state
49
+ assert_equal "San Francisco", res.city
50
+ assert_equal "37.792501,-122.393985", res.ll # slightly dif from yahoo
51
+ assert res.is_us?
52
+ assert_equal "100 Spear St, San Francisco, CA 94105, USA", res.full_address #slightly different from yahoo
53
+ assert_equal "google", res.provider
54
+ end
55
+
56
+ def test_google_full_address_with_geo_loc
57
+ response = MockSuccess.new
58
+ response.expects(:body).returns(GOOGLE_FULL)
59
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@full_address_short_zip)}"
60
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
61
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@google_full_loc)
62
+ assert_equal "CA", res.state
63
+ assert_equal "San Francisco", res.city
64
+ assert_equal "37.792501,-122.393985", res.ll # slightly dif from yahoo
65
+ assert res.is_us?
66
+ assert_equal "100 Spear St, San Francisco, CA 94105, USA", res.full_address #slightly different from yahoo
67
+ assert_equal "google", res.provider
68
+ end
69
+
70
+ def test_google_full_address_accuracy
71
+ response = MockSuccess.new
72
+ response.expects(:body).returns(GOOGLE_FULL)
73
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@full_address_short_zip)}"
74
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
75
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@google_full_loc)
76
+ assert_equal 8, res.accuracy
77
+ end
78
+
79
+ def test_google_city
80
+ response = MockSuccess.new
81
+ response.expects(:body).returns(GOOGLE_CITY)
82
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@address)}"
83
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
84
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@address)
85
+ assert_equal "CA", res.state
86
+ assert_equal "San Francisco", res.city
87
+ assert_equal "37.775,-122.418333", res.ll
88
+ assert res.is_us?
89
+ assert_equal "San Francisco, CA, USA", res.full_address
90
+ assert_nil res.street_address
91
+ assert_equal "google", res.provider
92
+ end
93
+
94
+ def test_google_city_accuracy
95
+ response = MockSuccess.new
96
+ response.expects(:body).returns(GOOGLE_CITY)
97
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@address)}"
98
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
99
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@address)
100
+ assert_equal 4, res.accuracy
101
+ end
102
+
103
+ def test_google_city_with_geo_loc
104
+ response = MockSuccess.new
105
+ response.expects(:body).returns(GOOGLE_CITY)
106
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@address)}"
107
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
108
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@google_city_loc)
109
+ assert_equal "CA", res.state
110
+ assert_equal "San Francisco", res.city
111
+ assert_equal "37.775,-122.418333", res.ll
112
+ assert res.is_us?
113
+ assert_equal "San Francisco, CA, USA", res.full_address
114
+ assert_nil res.street_address
115
+ assert_equal "google", res.provider
116
+ end
117
+
118
+ def test_google_suggested_bounds
119
+ response = MockSuccess.new
120
+ response.expects(:body).returns(GOOGLE_RESULT_WITH_SUGGESTED_BOUNDS)
121
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@full_address_short_zip)}"
122
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
123
+ res = Geokit::Geocoders::GoogleGeocoder.geocode(@google_full_loc)
124
+
125
+ assert_instance_of Geokit::Bounds, res.suggested_bounds
126
+ assert_equal Geokit::Bounds.new(Geokit::LatLng.new(37.7893376, -122.3971525), Geokit::LatLng.new(37.7956328, -122.3908573)), res.suggested_bounds
127
+ end
128
+
129
+ def test_service_unavailable
130
+ response = MockFailure.new
131
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@address)}"
132
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
133
+ assert !Geokit::Geocoders::GoogleGeocoder.geocode(@google_city_loc).success
134
+ end
135
+
136
+ def test_multiple_results
137
+ #Geokit::Geocoders::GoogleGeocoder.do_geocode('via Sandro Pertini 8, Ossona, MI')
138
+ response = MockSuccess.new
139
+ response.expects(:body).returns(GOOGLE_MULTI)
140
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape('via Sandro Pertini 8, Ossona, MI')}"
141
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
142
+ res=Geokit::Geocoders::GoogleGeocoder.geocode('via Sandro Pertini 8, Ossona, MI')
143
+ assert_equal "Lombardy", res.state
144
+ assert_equal "Mesero", res.city
145
+ assert_equal "45.4966243,8.8527131", res.ll
146
+ assert !res.is_us?
147
+ assert_equal "Via Sandro Pertini, 8, 20010 Mesero MI, Italy", res.full_address
148
+ assert_equal "8 Via Sandro Pertini", res.street_address
149
+ assert_equal "google", res.provider
150
+
151
+ assert_equal 2, res.all.size
152
+ res = res.all[1]
153
+ assert_equal "Lombardy", res.state
154
+ assert_equal "Ossona", res.city
155
+ assert_equal "45.5074444,8.90232", res.ll
156
+ assert !res.is_us?
157
+ assert_equal "Via Sandro Pertini, 20010 Ossona MI, Italy", res.full_address
158
+ assert_equal "Via Sandro Pertini", res.street_address
159
+ assert_equal "google", res.provider
160
+ end
161
+
162
+ def test_reverse_geocode
163
+ #Geokit::Geocoders::GoogleGeocoder.do_reverse_geocode("40.4167413, -3.7032498")
164
+ madrid = Geokit::GeoLoc.new
165
+ madrid.lat, madrid.lng = "40.4167413", "-3.7032498"
166
+ response = MockSuccess.new
167
+ response.expects(:body).returns(GOOGLE_REVERSE_MADRID)
168
+ url = "http://maps.google.com/maps/geo?key=#{Geokit::Geocoders::google}&ll=#{Geokit::Inflector::url_escape(madrid.ll)}&oe=utf-8&output=xml"
169
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).
170
+ returns(response)
171
+ res=Geokit::Geocoders::GoogleGeocoder.do_reverse_geocode(madrid.ll)
172
+
173
+ assert_equal madrid.lat.to_s.slice(1..5), res.lat.to_s.slice(1..5)
174
+ assert_equal madrid.lng.to_s.slice(1..5), res.lng.to_s.slice(1..5)
175
+ assert_equal "ES", res.country_code
176
+ assert_equal "google", res.provider
177
+
178
+ assert_equal "Madrid", res.city
179
+ assert_equal "Madrid", res.state
180
+
181
+ assert_equal "Spain", res.country
182
+ assert_equal "zip+4", res.precision
183
+ assert_equal true, res.success
184
+
185
+ assert_equal "Plaza de la Puerta del Sol, 28013, Madrid, Spain", res.full_address
186
+ assert_equal "28013", res.zip
187
+ assert_equal "Plaza De La Puerta Del Sol", res.street_address
188
+ end
189
+
190
+ def test_country_code_biasing
191
+ response = MockSuccess.new
192
+ response.expects(:body).returns(GOOGLE_COUNTRY_CODE_BIASED_RESULT)
193
+
194
+ url = "http://maps.google.com/maps/geo?gl=it&key=Google&oe=utf-8&output=xml&q=Syracuse"
195
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
196
+ biased_result = Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse', :bias => 'it')
197
+
198
+ assert_equal 'IT', biased_result.country_code
199
+ assert_equal 'Sicily', biased_result.state
200
+ end
201
+
202
+ def test_bounds_biasing
203
+ response = MockSuccess.new
204
+ response.expects(:body).returns(GOOGLE_BOUNDS_BIASED_RESULT)
205
+
206
+ url = "http://maps.google.com/maps/geo?key=Google&ll=34.19769320884902%2C-118.54716002778494&oe=utf-8&output=xml&q=Winnetka&spn=0.2470479999999995%2C0.29491400000000567"
207
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
208
+
209
+ bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487])
210
+ biased_result = Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds)
211
+
212
+ assert_equal 'US', biased_result.country_code
213
+ assert_equal 'CA', biased_result.state
214
+ end
215
+
216
+ def test_too_many_queries
217
+ response = MockSuccess.new
218
+ response.expects(:body).returns(GOOGLE_TOO_MANY)
219
+ url = "http://maps.google.com/maps/geo?key=Google&oe=utf-8&output=xml&q=#{Geokit::Inflector.url_escape(@address)}"
220
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
221
+ assert_raise Geokit::TooManyQueriesError do
222
+ res=Geokit::Geocoders::GoogleGeocoder.geocode(@address)
223
+ end
224
+ end
225
+ end