barometer 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/README.rdoc +78 -70
  2. data/VERSION.yml +2 -2
  3. data/bin/barometer +100 -37
  4. data/lib/barometer.rb +12 -8
  5. data/lib/barometer/base.rb +48 -20
  6. data/lib/barometer/data.rb +5 -1
  7. data/lib/barometer/data/current.rb +23 -15
  8. data/lib/barometer/data/distance.rb +15 -5
  9. data/lib/barometer/data/forecast.rb +23 -5
  10. data/lib/barometer/data/geo.rb +16 -54
  11. data/lib/barometer/data/local_datetime.rb +137 -0
  12. data/lib/barometer/data/local_time.rb +134 -0
  13. data/lib/barometer/data/location.rb +6 -1
  14. data/lib/barometer/data/measurement.rb +71 -42
  15. data/lib/barometer/data/night.rb +69 -0
  16. data/lib/barometer/data/pressure.rb +15 -5
  17. data/lib/barometer/data/speed.rb +16 -5
  18. data/lib/barometer/data/sun.rb +8 -20
  19. data/lib/barometer/data/temperature.rb +22 -9
  20. data/lib/barometer/data/units.rb +10 -19
  21. data/lib/barometer/data/zone.rb +135 -9
  22. data/lib/barometer/formats.rb +12 -0
  23. data/lib/barometer/formats/coordinates.rb +42 -0
  24. data/lib/barometer/formats/format.rb +46 -0
  25. data/lib/barometer/formats/geocode.rb +51 -0
  26. data/lib/barometer/formats/icao.rb +37 -0
  27. data/lib/barometer/formats/postalcode.rb +22 -0
  28. data/lib/barometer/formats/short_zipcode.rb +17 -0
  29. data/lib/barometer/formats/weather_id.rb +107 -0
  30. data/lib/barometer/formats/zipcode.rb +31 -0
  31. data/lib/barometer/query.rb +61 -232
  32. data/lib/barometer/services.rb +14 -4
  33. data/lib/barometer/translations/icao_country_codes.yml +9 -0
  34. data/lib/barometer/translations/weather_country_codes.yml +17 -0
  35. data/lib/barometer/weather.rb +51 -30
  36. data/lib/barometer/{services → weather_services}/google.rb +23 -26
  37. data/lib/barometer/weather_services/noaa.rb +6 -0
  38. data/lib/barometer/{services → weather_services}/service.rb +101 -92
  39. data/lib/barometer/weather_services/weather_bug.rb +6 -0
  40. data/lib/barometer/weather_services/weather_dot_com.rb +261 -0
  41. data/lib/barometer/{services → weather_services}/wunderground.rb +58 -76
  42. data/lib/barometer/{services → weather_services}/yahoo.rb +91 -121
  43. data/lib/barometer/web_services/geocode.rb +33 -0
  44. data/lib/barometer/web_services/weather_id.rb +37 -0
  45. data/lib/barometer/web_services/web_service.rb +32 -0
  46. data/lib/demometer/demometer.rb +31 -4
  47. data/lib/demometer/views/forecast.erb +20 -0
  48. data/lib/demometer/views/index.erb +10 -3
  49. data/lib/demometer/views/measurement.erb +8 -3
  50. data/lib/demometer/views/readme.erb +63 -24
  51. data/spec/barometer_spec.rb +18 -36
  52. data/spec/{data_current_spec.rb → data/current_spec.rb} +73 -49
  53. data/spec/{data_distance_spec.rb → data/distance_spec.rb} +30 -30
  54. data/spec/{data_forecast_spec.rb → data/forecast_spec.rb} +57 -15
  55. data/spec/data/geo_spec.rb +91 -0
  56. data/spec/data/local_datetime_spec.rb +269 -0
  57. data/spec/data/local_time_spec.rb +239 -0
  58. data/spec/{data_location_spec.rb → data/location_spec.rb} +12 -1
  59. data/spec/{data_measurement_spec.rb → data/measurement_spec.rb} +135 -66
  60. data/spec/data/night_measurement_spec.rb +136 -0
  61. data/spec/{data_pressure_spec.rb → data/pressure_spec.rb} +29 -29
  62. data/spec/{data_speed_spec.rb → data/speed_spec.rb} +30 -30
  63. data/spec/data/sun_spec.rb +49 -0
  64. data/spec/{data_temperature_spec.rb → data/temperature_spec.rb} +44 -44
  65. data/spec/{units_spec.rb → data/units_spec.rb} +6 -6
  66. data/spec/{data_zone_spec.rb → data/zone_spec.rb} +15 -15
  67. data/spec/fixtures/formats/weather_id/90210.xml +1 -0
  68. data/spec/fixtures/formats/weather_id/atlanta.xml +1 -0
  69. data/spec/fixtures/formats/weather_id/from_USGA0028.xml +1 -0
  70. data/spec/fixtures/formats/weather_id/new_york.xml +1 -0
  71. data/spec/fixtures/{geocode_40_73.xml → geocode/40_73.xml} +0 -0
  72. data/spec/fixtures/{geocode_90210.xml → geocode/90210.xml} +0 -0
  73. data/spec/fixtures/{geocode_T5B4M9.xml → geocode/T5B4M9.xml} +0 -0
  74. data/spec/fixtures/geocode/atlanta.xml +1 -0
  75. data/spec/fixtures/{geocode_calgary_ab.xml → geocode/calgary_ab.xml} +0 -0
  76. data/spec/fixtures/{geocode_ksfo.xml → geocode/ksfo.xml} +0 -0
  77. data/spec/fixtures/{geocode_newyork_ny.xml → geocode/newyork_ny.xml} +0 -0
  78. data/spec/fixtures/{google_calgary_ab.xml → services/google/calgary_ab.xml} +0 -0
  79. data/spec/fixtures/services/weather_dot_com/90210.xml +1 -0
  80. data/spec/fixtures/{current_calgary_ab.xml → services/wunderground/current_calgary_ab.xml} +0 -0
  81. data/spec/fixtures/{forecast_calgary_ab.xml → services/wunderground/forecast_calgary_ab.xml} +0 -0
  82. data/spec/fixtures/{yahoo_90210.xml → services/yahoo/90210.xml} +0 -0
  83. data/spec/formats/coordinates_spec.rb +158 -0
  84. data/spec/formats/format_spec.rb +73 -0
  85. data/spec/formats/geocode_spec.rb +179 -0
  86. data/spec/formats/icao_spec.rb +61 -0
  87. data/spec/formats/postalcode_spec.rb +59 -0
  88. data/spec/formats/short_zipcode_spec.rb +53 -0
  89. data/spec/formats/weather_id_spec.rb +191 -0
  90. data/spec/formats/zipcode_spec.rb +111 -0
  91. data/spec/query_spec.rb +261 -288
  92. data/spec/spec_helper.rb +128 -4
  93. data/spec/{service_google_spec.rb → weather_services/google_spec.rb} +46 -46
  94. data/spec/weather_services/services_spec.rb +1118 -0
  95. data/spec/weather_services/weather_dot_com_spec.rb +327 -0
  96. data/spec/weather_services/wunderground_spec.rb +332 -0
  97. data/spec/{service_yahoo_spec.rb → weather_services/yahoo_spec.rb} +65 -81
  98. data/spec/weather_spec.rb +73 -61
  99. data/spec/web_services/geocode_spec.rb +45 -0
  100. data/spec/web_services/web_services_spec.rb +26 -0
  101. metadata +88 -36
  102. data/lib/barometer/services/noaa.rb +0 -6
  103. data/lib/barometer/services/weather_bug.rb +0 -6
  104. data/lib/barometer/services/weather_dot_com.rb +0 -6
  105. data/spec/data_geo_spec.rb +0 -94
  106. data/spec/data_sun_spec.rb +0 -76
  107. data/spec/service_wunderground_spec.rb +0 -330
  108. data/spec/services_spec.rb +0 -1106
@@ -0,0 +1,327 @@
1
+ require 'spec_helper'
2
+ include Barometer
3
+
4
+ describe "WeatherDotCom" do
5
+
6
+ before(:each) do
7
+ @accepted_formats = [:short_zipcode, :weather_id]
8
+ #Barometer.config = { 1 => { :weather => { :keys => { :partner => WEATHER_PARTNER_KEY, :license => WEATHER_LICENSE_KEY }}}}
9
+ WeatherService::WeatherDotCom.keys = { :partner => WEATHER_PARTNER_KEY, :license => WEATHER_LICENSE_KEY }
10
+ end
11
+
12
+ describe "the class methods" do
13
+
14
+ it "defines accepted_formats" do
15
+ WeatherService::WeatherDotCom.accepted_formats.should == @accepted_formats
16
+ end
17
+
18
+ it "defines get_all" do
19
+ WeatherService::WeatherDotCom.respond_to?("fetch").should be_true
20
+ end
21
+
22
+ end
23
+
24
+ describe "building the current data" do
25
+
26
+ it "defines the build method" do
27
+ WeatherService::WeatherDotCom.respond_to?("build_current").should be_true
28
+ end
29
+
30
+ it "requires Hash input" do
31
+ lambda { WeatherService::WeatherDotCom.build_current }.should raise_error(ArgumentError)
32
+ lambda { WeatherService::WeatherDotCom.build_current({}) }.should_not raise_error(ArgumentError)
33
+ end
34
+
35
+ it "returns Data::CurrentMeasurement object" do
36
+ current = WeatherService::WeatherDotCom.build_current({})
37
+ current.is_a?(Data::CurrentMeasurement).should be_true
38
+ end
39
+
40
+ end
41
+
42
+ describe "building the forecast data" do
43
+
44
+ it "defines the build method" do
45
+ WeatherService::WeatherDotCom.respond_to?("build_forecast").should be_true
46
+ end
47
+
48
+ it "requires Hash input" do
49
+ lambda { WeatherService::WeatherDotCom.build_forecast }.should raise_error(ArgumentError)
50
+ lambda { WeatherService::WeatherDotCom.build_forecast({}) }.should_not raise_error(ArgumentError)
51
+ end
52
+
53
+ it "returns Array object" do
54
+ current = WeatherService::WeatherDotCom.build_forecast({})
55
+ current.is_a?(Array).should be_true
56
+ end
57
+
58
+ end
59
+
60
+ describe "building the location data" do
61
+
62
+ it "defines the build method" do
63
+ WeatherService::WeatherDotCom.respond_to?("build_location").should be_true
64
+ end
65
+
66
+ it "requires Hash input" do
67
+ lambda { WeatherService::WeatherDotCom.build_location }.should raise_error(ArgumentError)
68
+ lambda { WeatherService::WeatherDotCom.build_location({}) }.should_not raise_error(ArgumentError)
69
+ end
70
+
71
+ it "requires Barometer::Geo input" do
72
+ geo = Data::Geo.new({})
73
+ lambda { WeatherService::WeatherDotCom.build_location({}, {}) }.should raise_error(ArgumentError)
74
+ lambda { WeatherService::WeatherDotCom.build_location({}, geo) }.should_not raise_error(ArgumentError)
75
+ end
76
+
77
+ it "returns Barometer::Location object" do
78
+ location = WeatherService::WeatherDotCom.build_location({})
79
+ location.is_a?(Data::Location).should be_true
80
+ end
81
+
82
+ end
83
+
84
+ describe "building the sun data" do
85
+
86
+ it "defines the build method" do
87
+ WeatherService::WeatherDotCom.respond_to?("build_sun").should be_true
88
+ end
89
+
90
+ it "requires Hash input" do
91
+ lambda { WeatherService::WeatherDotCom.build_sun }.should raise_error(ArgumentError)
92
+ lambda { WeatherService::WeatherDotCom.build_sun({}) }.should_not raise_error(ArgumentError)
93
+ end
94
+
95
+ it "returns Barometer::Sun object" do
96
+ sun = WeatherService::WeatherDotCom.build_sun({})
97
+ sun.is_a?(Data::Sun).should be_true
98
+ end
99
+
100
+ end
101
+
102
+ describe "when measuring" do
103
+
104
+ before(:each) do
105
+ @query = Barometer::Query.new("90210")
106
+ @measurement = Data::Measurement.new
107
+
108
+ url = "http://xoap.weather.com:80/weather/local/"
109
+
110
+ FakeWeb.register_uri(:get,
111
+ "#{url}90210?dayf=5&unit=m&link=xoap&par=#{WEATHER_PARTNER_KEY}&prod=xoap&key=#{WEATHER_LICENSE_KEY}&cc=*",
112
+ :string => File.read(File.join(File.dirname(__FILE__),
113
+ '../fixtures/services/weather_dot_com',
114
+ '90210.xml')
115
+ )
116
+ )
117
+ end
118
+
119
+ describe "all" do
120
+
121
+ it "responds to _measure" do
122
+ WeatherService::WeatherDotCom.respond_to?("_measure").should be_true
123
+ end
124
+
125
+ it "requires a Barometer::Measurement object" do
126
+ lambda { WeatherService::WeatherDotCom._measure(nil, @query) }.should raise_error(ArgumentError)
127
+ lambda { WeatherService::WeatherDotCom._measure("invlaid", @query) }.should raise_error(ArgumentError)
128
+
129
+ lambda { WeatherService::WeatherDotCom._measure(@measurement, @query) }.should_not raise_error(ArgumentError)
130
+ end
131
+
132
+ it "requires a Barometer::Query query" do
133
+ lambda { WeatherService::WeatherDotCom._measure }.should raise_error(ArgumentError)
134
+ lambda { WeatherService::WeatherDotCom._measure(@measurement, 1) }.should raise_error(ArgumentError)
135
+
136
+ lambda { WeatherService::WeatherDotCom._measure(@measurement, @query) }.should_not raise_error(ArgumentError)
137
+ end
138
+
139
+ it "returns a Barometer::Measurement object" do
140
+ result = WeatherService::WeatherDotCom._measure(@measurement, @query)
141
+ result.is_a?(Data::Measurement).should be_true
142
+ result.current.is_a?(Data::CurrentMeasurement).should be_true
143
+ result.forecast.is_a?(Array).should be_true
144
+
145
+ result.source.should == :weather_dot_com
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+ describe "when answering the simple questions," do
153
+
154
+ before(:each) do
155
+ @measurement = Data::Measurement.new
156
+ end
157
+
158
+ describe "currently_wet_by_icon?" do
159
+
160
+ before(:each) do
161
+ @measurement.current = Data::CurrentMeasurement.new
162
+ end
163
+
164
+ it "returns true if matching icon code" do
165
+ @measurement.current.icon = "4"
166
+ @measurement.current.icon?.should be_true
167
+ WeatherService::WeatherDotCom.currently_wet_by_icon?(@measurement.current).should be_true
168
+ end
169
+
170
+ it "returns false if NO matching icon code" do
171
+ @measurement.current.icon = "32"
172
+ @measurement.current.icon?.should be_true
173
+ WeatherService::WeatherDotCom.currently_wet_by_icon?(@measurement.current).should be_false
174
+ end
175
+
176
+ end
177
+
178
+ describe "forecasted_wet_by_icon?" do
179
+
180
+ before(:each) do
181
+ @measurement.forecast = [Data::ForecastMeasurement.new]
182
+ @measurement.forecast.first.date = Date.today
183
+ @measurement.forecast.size.should == 1
184
+ end
185
+
186
+ it "returns true if matching icon code" do
187
+ @measurement.forecast.first.icon = "4"
188
+ @measurement.forecast.first.icon?.should be_true
189
+ WeatherService::WeatherDotCom.forecasted_wet_by_icon?(@measurement.forecast.first).should be_true
190
+ end
191
+
192
+ it "returns false if NO matching icon code" do
193
+ @measurement.forecast.first.icon = "32"
194
+ @measurement.forecast.first.icon?.should be_true
195
+ WeatherService::WeatherDotCom.forecasted_wet_by_icon?(@measurement.forecast.first).should be_false
196
+ end
197
+
198
+ end
199
+
200
+ describe "currently_sunny_by_icon?" do
201
+
202
+ before(:each) do
203
+ @measurement.current = Data::CurrentMeasurement.new
204
+ end
205
+
206
+ it "returns true if matching icon code" do
207
+ @measurement.current.icon = "32"
208
+ @measurement.current.icon?.should be_true
209
+ WeatherService::WeatherDotCom.currently_sunny_by_icon?(@measurement.current).should be_true
210
+ end
211
+
212
+ it "returns false if NO matching icon code" do
213
+ @measurement.current.icon = "4"
214
+ @measurement.current.icon?.should be_true
215
+ WeatherService::WeatherDotCom.currently_sunny_by_icon?(@measurement.current).should be_false
216
+ end
217
+
218
+ end
219
+
220
+ describe "forecasted_sunny_by_icon?" do
221
+
222
+ before(:each) do
223
+ @measurement.forecast = [Data::ForecastMeasurement.new]
224
+ @measurement.forecast.first.date = Date.today
225
+ @measurement.forecast.size.should == 1
226
+ end
227
+
228
+ it "returns true if matching icon code" do
229
+ @measurement.forecast.first.icon = "32"
230
+ @measurement.forecast.first.icon?.should be_true
231
+ WeatherService::WeatherDotCom.forecasted_sunny_by_icon?(@measurement.forecast.first).should be_true
232
+ end
233
+
234
+ it "returns false if NO matching icon code" do
235
+ @measurement.forecast.first.icon = "4"
236
+ @measurement.forecast.first.icon?.should be_true
237
+ WeatherService::WeatherDotCom.forecasted_sunny_by_icon?(@measurement.forecast.first).should be_false
238
+ end
239
+
240
+ end
241
+
242
+ end
243
+
244
+ describe "overall data correctness" do
245
+
246
+ before(:each) do
247
+ @query = Barometer::Query.new("90210")
248
+ @measurement = Data::Measurement.new
249
+
250
+ url = "http://xoap.weather.com:80/weather/local/"
251
+
252
+ FakeWeb.register_uri(:get,
253
+ "#{url}90210?dayf=5&unit=m&link=xoap&par=#{WEATHER_PARTNER_KEY}&prod=xoap&key=#{WEATHER_LICENSE_KEY}&cc=*",
254
+ :string => File.read(File.join(File.dirname(__FILE__),
255
+ '../fixtures/services/weather_dot_com',
256
+ '90210.xml')
257
+ )
258
+ )
259
+ end
260
+
261
+ it "should correctly build the data" do
262
+ result = WeatherService::WeatherDotCom._measure(@measurement, @query)
263
+
264
+ # build current
265
+ @measurement.current.humidity.to_i.should == 75
266
+ @measurement.current.icon.should == "33"
267
+ @measurement.current.condition.should == "Fair"
268
+ @measurement.current.temperature.to_i.should == 16
269
+ @measurement.current.dew_point.to_i.should == 12
270
+ @measurement.current.wind_chill.to_i.should == 16
271
+ @measurement.current.wind.to_i.should == 5
272
+ @measurement.current.wind.degrees.to_i.should == 80
273
+ @measurement.current.wind.direction.should == "E"
274
+ @measurement.current.pressure.to_f.should == 1016.6
275
+ @measurement.current.visibility.to_f.should == 16.1
276
+
277
+ # build sun
278
+ # sun_rise = Barometer::Zone.merge("6:01 am", "5/4/09 12:51 AM PDT", -7)
279
+ # sun_set = Barometer::Zone.merge("7:40 pm", "5/4/09 12:51 AM PDT", -7)
280
+ # @measurement.current.sun.rise.should == sun_rise
281
+ # @measurement.current.sun.set.should == sun_set
282
+ @measurement.current.sun.rise.to_s.should == "06:01 am"
283
+ @measurement.current.sun.set.to_s.should == "07:40 pm"
284
+
285
+ # builds location
286
+ @measurement.location.name.should == "Beverly Hills, CA (90210)"
287
+ @measurement.location.latitude.to_f.should == 34.10
288
+ @measurement.location.longitude.to_f.should == -118.41
289
+
290
+ # builds forecasts
291
+ @measurement.forecast.size.should == 5
292
+
293
+ @measurement.forecast[0].date.should == Date.parse("May 3")
294
+ @measurement.forecast[0].condition.should == "Partly Cloudy"
295
+ @measurement.forecast[0].icon.should == "30"
296
+ @measurement.forecast[0].high.should be_nil
297
+ @measurement.forecast[0].low.to_i.should == 14
298
+ @measurement.forecast[0].pop.to_i.should == 10
299
+ @measurement.forecast[0].humidity.to_i.should == 65
300
+
301
+ @measurement.forecast[0].wind.should_not be_nil
302
+ @measurement.forecast[0].wind.to_i.should == 16
303
+ @measurement.forecast[0].wind.degrees.to_i.should == 288
304
+ @measurement.forecast[0].wind.direction.should == "WNW"
305
+
306
+ # sun_rise = Barometer::Zone.merge("6:02 am", "5/4/09 12:25 AM PDT", -7)
307
+ # sun_set = Barometer::Zone.merge("7:40 pm", "5/4/09 12:25 AM PDT", -7)
308
+ # @measurement.forecast[0].sun.rise.should == sun_rise
309
+ # @measurement.forecast[0].sun.set.should == sun_set
310
+ @measurement.forecast[0].sun.rise.to_s.should == "06:02 am"
311
+ @measurement.forecast[0].sun.set.to_s.should == "07:40 pm"
312
+
313
+ @measurement.forecast[0].night.should_not be_nil
314
+ @measurement.forecast[0].night.condition.should == "Partly Cloudy"
315
+ @measurement.forecast[0].night.icon.should == "29"
316
+ @measurement.forecast[0].night.pop.to_i.should == 10
317
+ @measurement.forecast[0].night.humidity.to_i.should == 71
318
+
319
+ @measurement.forecast[0].night.wind.should_not be_nil
320
+ @measurement.forecast[0].night.wind.to_i.should == 14
321
+ @measurement.forecast[0].night.wind.degrees.to_i.should == 335
322
+ @measurement.forecast[0].night.wind.direction.should == "NNW"
323
+ end
324
+
325
+ end
326
+
327
+ end
@@ -0,0 +1,332 @@
1
+ require 'spec_helper'
2
+ include Barometer
3
+
4
+ describe "Wunderground" do
5
+
6
+ before(:each) do
7
+ @accepted_formats = [:zipcode, :postalcode, :icao, :coordinates, :geocode]
8
+ @base_uri = "http://api.wunderground.com/auto/wui/geo"
9
+ end
10
+
11
+ describe "the class methods" do
12
+
13
+ it "defines accepted_formats" do
14
+ WeatherService::Wunderground.accepted_formats.should == @accepted_formats
15
+ end
16
+
17
+ it "defines get_current" do
18
+ WeatherService::Wunderground.respond_to?("get_current").should be_true
19
+ end
20
+
21
+ it "defines get_forecast" do
22
+ WeatherService::Wunderground.respond_to?("get_forecast").should be_true
23
+ end
24
+
25
+ end
26
+
27
+ describe "building the current data" do
28
+
29
+ it "defines the build method" do
30
+ WeatherService::Wunderground.respond_to?("build_current").should be_true
31
+ end
32
+
33
+ it "requires Hash input" do
34
+ lambda { WeatherService::Wunderground.build_current }.should raise_error(ArgumentError)
35
+ WeatherService::Wunderground.build_current({})
36
+ lambda { WeatherService::Wunderground.build_current({}) }.should_not raise_error(ArgumentError)
37
+ end
38
+
39
+ it "returns Barometer::CurrentMeasurement object" do
40
+ current = WeatherService::Wunderground.build_current({})
41
+ current.is_a?(Data::CurrentMeasurement).should be_true
42
+ end
43
+
44
+ end
45
+
46
+ describe "building the forecast data" do
47
+
48
+ it "defines the build method" do
49
+ WeatherService::Wunderground.respond_to?("build_forecast").should be_true
50
+ end
51
+
52
+ it "requires Hash input" do
53
+ lambda { WeatherService::Wunderground.build_forecast }.should raise_error(ArgumentError)
54
+ lambda { WeatherService::Wunderground.build_forecast({}) }.should_not raise_error(ArgumentError)
55
+ end
56
+
57
+ it "returns Array object" do
58
+ current = WeatherService::Wunderground.build_forecast({})
59
+ current.is_a?(Array).should be_true
60
+ end
61
+
62
+ end
63
+
64
+ describe "building the station data" do
65
+
66
+ it "defines the build method" do
67
+ WeatherService::Wunderground.respond_to?("build_station").should be_true
68
+ end
69
+
70
+ it "requires Hash input" do
71
+ lambda { WeatherService::Wunderground.build_station }.should raise_error(ArgumentError)
72
+ lambda { WeatherService::Wunderground.build_station({}) }.should_not raise_error(ArgumentError)
73
+ end
74
+
75
+ it "returns Barometer::Location object" do
76
+ station = WeatherService::Wunderground.build_station({})
77
+ station.is_a?(Data::Location).should be_true
78
+ end
79
+
80
+ end
81
+
82
+ describe "building the location data" do
83
+
84
+ it "defines the build method" do
85
+ WeatherService::Wunderground.respond_to?("build_location").should be_true
86
+ end
87
+
88
+ it "requires Hash input" do
89
+ lambda { WeatherService::Wunderground.build_location }.should raise_error(ArgumentError)
90
+ lambda { WeatherService::Wunderground.build_location({}) }.should_not raise_error(ArgumentError)
91
+ end
92
+
93
+ it "returns Barometer::Location object" do
94
+ location = WeatherService::Wunderground.build_location({})
95
+ location.is_a?(Data::Location).should be_true
96
+ end
97
+
98
+ end
99
+
100
+ describe "building the timezone" do
101
+
102
+ it "defines the build method" do
103
+ WeatherService::Wunderground.respond_to?("build_timezone").should be_true
104
+ end
105
+
106
+ it "requires Hash input" do
107
+ lambda { WeatherService::Wunderground.build_timezone }.should raise_error(ArgumentError)
108
+ lambda { WeatherService::Wunderground.build_timezone({}) }.should_not raise_error(ArgumentError)
109
+ end
110
+
111
+ end
112
+
113
+ describe "building the sun data" do
114
+
115
+ before(:each) do
116
+ @zone = Data::Zone.new("Europe/Paris")
117
+ end
118
+
119
+ it "defines the build method" do
120
+ WeatherService::Wunderground.respond_to?("build_sun").should be_true
121
+ end
122
+
123
+ it "requires Hash input" do
124
+ lambda { WeatherService::Wunderground.build_sun }.should raise_error(ArgumentError)
125
+ lambda { WeatherService::Wunderground.build_sun({},@zone) }.should_not raise_error(ArgumentError)
126
+ end
127
+
128
+ it "requires Barometer::Zone input" do
129
+ lambda { WeatherService::Wunderground.build_sun({}) }.should raise_error(ArgumentError)
130
+ lambda { WeatherService::Wunderground.build_sun({}, "invalid") }.should raise_error(ArgumentError)
131
+ lambda { WeatherService::Wunderground.build_sun({},@zone) }.should_not raise_error(ArgumentError)
132
+ end
133
+
134
+ it "returns Barometer::Sun object" do
135
+ sun = WeatherService::Wunderground.build_sun({},@zone)
136
+ sun.is_a?(Data::Sun).should be_true
137
+ end
138
+
139
+ end
140
+
141
+ describe "when measuring" do
142
+
143
+ before(:each) do
144
+ @query = Barometer::Query.new("Calgary,AB")
145
+ @measurement = Data::Measurement.new
146
+
147
+ FakeWeb.register_uri(:get,
148
+ "http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=#{CGI.escape(@query.q)}",
149
+ :string => File.read(File.join(File.dirname(__FILE__),
150
+ '../fixtures/services/wunderground',
151
+ 'current_calgary_ab.xml')
152
+ )
153
+ )
154
+ FakeWeb.register_uri(:get,
155
+ "http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=#{CGI.escape(@query.q)}",
156
+ :string => File.read(File.join(File.dirname(__FILE__),
157
+ '../fixtures/services/wunderground',
158
+ 'forecast_calgary_ab.xml')
159
+ )
160
+ )
161
+ end
162
+
163
+ describe "all" do
164
+
165
+ it "responds to _measure" do
166
+ WeatherService::Wunderground.respond_to?("_measure").should be_true
167
+ end
168
+
169
+ it "requires a Barometer::Measurement object" do
170
+ lambda { WeatherService::Wunderground._measure(nil, @query) }.should raise_error(ArgumentError)
171
+ lambda { WeatherService::Wunderground._measure("invlaid", @query) }.should raise_error(ArgumentError)
172
+
173
+ lambda { WeatherService::Wunderground._measure(@measurement, @query) }.should_not raise_error(ArgumentError)
174
+ end
175
+
176
+ it "requires a Barometer::Query query" do
177
+ lambda { WeatherService::Wunderground._measure }.should raise_error(ArgumentError)
178
+ lambda { WeatherService::Wunderground._measure(@measurement, 1) }.should raise_error(ArgumentError)
179
+
180
+ lambda { WeatherService::Wunderground._measure(@measurement, @query) }.should_not raise_error(ArgumentError)
181
+ end
182
+
183
+ it "returns a Barometer::Measurement object" do
184
+ result = WeatherService::Wunderground._measure(@measurement, @query)
185
+ result.is_a?(Data::Measurement).should be_true
186
+ result.current.is_a?(Data::CurrentMeasurement).should be_true
187
+ result.forecast.is_a?(Array).should be_true
188
+
189
+ result.source.should == :wunderground
190
+ end
191
+
192
+ end
193
+
194
+ end
195
+
196
+ describe "when answering the simple questions," do
197
+
198
+ before(:each) do
199
+ @measurement = Data::Measurement.new
200
+ end
201
+
202
+ describe "currently_wet_by_icon?" do
203
+
204
+ before(:each) do
205
+ @measurement.current = Data::CurrentMeasurement.new
206
+ end
207
+
208
+ it "returns true if matching icon code" do
209
+ @measurement.current.icon = "rain"
210
+ @measurement.current.icon?.should be_true
211
+ WeatherService::Wunderground.currently_wet_by_icon?(@measurement.current).should be_true
212
+ end
213
+
214
+ it "returns false if NO matching icon code" do
215
+ @measurement.current.icon = "sunny"
216
+ @measurement.current.icon?.should be_true
217
+ WeatherService::Wunderground.currently_wet_by_icon?(@measurement.current).should be_false
218
+ end
219
+
220
+ end
221
+
222
+ describe "forecasted_wet_by_icon?" do
223
+
224
+ before(:each) do
225
+ @measurement.forecast = [Data::ForecastMeasurement.new]
226
+ @measurement.forecast.first.date = Date.today
227
+ @measurement.forecast.size.should == 1
228
+ end
229
+
230
+ it "returns true if matching icon code" do
231
+ @measurement.forecast.first.icon = "rain"
232
+ @measurement.forecast.first.icon?.should be_true
233
+ WeatherService::Wunderground.forecasted_wet_by_icon?(@measurement.forecast.first).should be_true
234
+ end
235
+
236
+ it "returns false if NO matching icon code" do
237
+ @measurement.forecast.first.icon = "sunny"
238
+ @measurement.forecast.first.icon?.should be_true
239
+ WeatherService::Wunderground.forecasted_wet_by_icon?(@measurement.forecast.first).should be_false
240
+ end
241
+
242
+ end
243
+
244
+ describe "currently_sunny_by_icon?" do
245
+
246
+ before(:each) do
247
+ @measurement.current = Data::CurrentMeasurement.new
248
+ end
249
+
250
+ it "returns true if matching icon code" do
251
+ @measurement.current.icon = "sunny"
252
+ @measurement.current.icon?.should be_true
253
+ WeatherService::Wunderground.currently_sunny_by_icon?(@measurement.current).should be_true
254
+ end
255
+
256
+ it "returns false if NO matching icon code" do
257
+ @measurement.current.icon = "rain"
258
+ @measurement.current.icon?.should be_true
259
+ WeatherService::Wunderground.currently_sunny_by_icon?(@measurement.current).should be_false
260
+ end
261
+
262
+ end
263
+
264
+ describe "forecasted_sunny_by_icon?" do
265
+
266
+ before(:each) do
267
+ @measurement.forecast = [Data::ForecastMeasurement.new]
268
+ @measurement.forecast.first.date = Date.today
269
+ @measurement.forecast.size.should == 1
270
+ end
271
+
272
+ it "returns true if matching icon code" do
273
+ @measurement.forecast.first.icon = "sunny"
274
+ @measurement.forecast.first.icon?.should be_true
275
+ WeatherService::Wunderground.forecasted_sunny_by_icon?(@measurement.forecast.first).should be_true
276
+ end
277
+
278
+ it "returns false if NO matching icon code" do
279
+ @measurement.forecast.first.icon = "rain"
280
+ @measurement.forecast.first.icon?.should be_true
281
+ WeatherService::Wunderground.forecasted_sunny_by_icon?(@measurement.forecast.first).should be_false
282
+ end
283
+
284
+ end
285
+
286
+ end
287
+
288
+ describe "overall data correctness" do
289
+
290
+ before(:each) do
291
+ @query = Barometer::Query.new("Calgary,AB")
292
+ @measurement = Data::Measurement.new
293
+
294
+ FakeWeb.register_uri(:get,
295
+ "http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=#{CGI.escape(@query.q)}",
296
+ :string => File.read(File.join(File.dirname(__FILE__),
297
+ '../fixtures/services/wunderground',
298
+ 'current_calgary_ab.xml')
299
+ )
300
+ )
301
+ FakeWeb.register_uri(:get,
302
+ "http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=#{CGI.escape(@query.q)}",
303
+ :string => File.read(File.join(File.dirname(__FILE__),
304
+ '../fixtures/services/wunderground',
305
+ 'forecast_calgary_ab.xml')
306
+ )
307
+ )
308
+ end
309
+
310
+ # TODO: complete this
311
+ it "should correctly build the data" do
312
+ result = WeatherService::Wunderground._measure(@measurement, @query)
313
+
314
+ # build timezone
315
+ @measurement.timezone.timezone.should == "America/Edmonton"
316
+
317
+ # time = Time.local(2009, 4, 23, 18, 00, 0)
318
+ # rise = Time.local(time.year, time.month, time.day, 6, 23)
319
+ # set = Time.local(time.year, time.month, time.day, 20, 45)
320
+ # sun_rise = @measurement.timezone.tz.local_to_utc(rise)
321
+ # sun_set = @measurement.timezone.tz.local_to_utc(set)
322
+
323
+ # build current
324
+ #@measurement.current.sun.rise.should == sun_rise
325
+ #@measurement.current.sun.set.should == sun_set
326
+ @measurement.current.sun.rise.to_s.should == "06:23 am"
327
+ @measurement.current.sun.set.to_s.should == "08:45 pm"
328
+ end
329
+
330
+ end
331
+
332
+ end