abuiles-geokit 1.6.1

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.
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