noaa_weather_client 0.0.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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +7 -0
  7. data/.yardopts +2 -0
  8. data/Gemfile +8 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +107 -0
  11. data/Rakefile +8 -0
  12. data/bin/noaa_weather_client +43 -0
  13. data/data/xml/current_observation.xsd +79 -0
  14. data/data/xml/dwml.xsd +97 -0
  15. data/data/xml/location.xsd +142 -0
  16. data/data/xml/meta_data.xsd +100 -0
  17. data/data/xml/moreWeatherInformation.xsd +23 -0
  18. data/data/xml/ndfd_data.xsd +43 -0
  19. data/data/xml/parameters.xsd +1173 -0
  20. data/data/xml/summarizationType.xsd +29 -0
  21. data/data/xml/time_layout.xsd +51 -0
  22. data/lib/noaa_weather_client.rb +9 -0
  23. data/lib/noaa_weather_client/cli.rb +53 -0
  24. data/lib/noaa_weather_client/cli/templates.rb +53 -0
  25. data/lib/noaa_weather_client/client.rb +61 -0
  26. data/lib/noaa_weather_client/errors.rb +7 -0
  27. data/lib/noaa_weather_client/responses/current_observation.rb +93 -0
  28. data/lib/noaa_weather_client/responses/forecast.rb +84 -0
  29. data/lib/noaa_weather_client/responses/generic_response.rb +9 -0
  30. data/lib/noaa_weather_client/responses/lat_lon_list.rb +25 -0
  31. data/lib/noaa_weather_client/responses/reactive_xml_response.rb +29 -0
  32. data/lib/noaa_weather_client/responses/station.rb +28 -0
  33. data/lib/noaa_weather_client/responses/stations.rb +41 -0
  34. data/lib/noaa_weather_client/responses/validatable_xml_response.rb +22 -0
  35. data/lib/noaa_weather_client/rest_client_factory.rb +12 -0
  36. data/lib/noaa_weather_client/services/calculate_distance_between_lat_lon.rb +20 -0
  37. data/lib/noaa_weather_client/services/current_observations.rb +32 -0
  38. data/lib/noaa_weather_client/services/find_nearest_station.rb +16 -0
  39. data/lib/noaa_weather_client/services/forecast_by_day.rb +52 -0
  40. data/lib/noaa_weather_client/services/postal_code_to_coordinate.rb +36 -0
  41. data/lib/noaa_weather_client/services/rest_service.rb +28 -0
  42. data/lib/noaa_weather_client/services/soap_service.rb +16 -0
  43. data/lib/noaa_weather_client/services/weather_stations.rb +32 -0
  44. data/lib/noaa_weather_client/soap_client_factory.rb +17 -0
  45. data/lib/noaa_weather_client/station_filters.rb +8 -0
  46. data/lib/noaa_weather_client/version.rb +3 -0
  47. data/lib/noaa_weather_client/xml_parser_factory.rb +9 -0
  48. data/noaa_weather_client.gemspec +27 -0
  49. data/spec/fixtures/vcr_cassettes/current_observations.yml +25890 -0
  50. data/spec/fixtures/vcr_cassettes/forecast_by_day_3.yml +772 -0
  51. data/spec/fixtures/vcr_cassettes/forecast_by_day_7.yml +829 -0
  52. data/spec/fixtures/vcr_cassettes/nearest_weather_station.yml +25842 -0
  53. data/spec/fixtures/vcr_cassettes/postal_code_to_coordinate.yml +75 -0
  54. data/spec/fixtures/vcr_cassettes/weather_stations.yml +25842 -0
  55. data/spec/fixtures/xml/forecast.xml +144 -0
  56. data/spec/lib/noaa_client/client_spec.rb +93 -0
  57. data/spec/lib/noaa_client/responses/current_observation_spec.rb +122 -0
  58. data/spec/lib/noaa_client/responses/forecast_spec.rb +66 -0
  59. data/spec/lib/noaa_client/responses/lat_lon_list_spec.rb +30 -0
  60. data/spec/lib/noaa_client/responses/station_spec.rb +53 -0
  61. data/spec/lib/noaa_client/responses/stations_spec.rb +86 -0
  62. data/spec/lib/noaa_client/rest_client_factory_spec.rb +15 -0
  63. data/spec/lib/noaa_client/services/calculate_distance_between_lat_lon_spec.rb +16 -0
  64. data/spec/lib/noaa_client/services/current_observations_spec.rb +47 -0
  65. data/spec/lib/noaa_client/services/find_nearest_station_spec.rb +36 -0
  66. data/spec/lib/noaa_client/services/forecast_by_day_spec.rb +62 -0
  67. data/spec/lib/noaa_client/services/postal_code_to_coordinate_spec.rb +41 -0
  68. data/spec/lib/noaa_client/services/rest_service_spec.rb +45 -0
  69. data/spec/lib/noaa_client/services/soap_service_spec.rb +56 -0
  70. data/spec/lib/noaa_client/services/weather_stations_spec.rb +40 -0
  71. data/spec/lib/noaa_client/soap_client_factory_spec.rb +13 -0
  72. data/spec/lib/noaa_client/xml_parser_factory_spec.rb +14 -0
  73. data/spec/spec_helper.rb +31 -0
  74. metadata +228 -0
@@ -0,0 +1,144 @@
1
+ <?xml version="1.0"?>
2
+ <dwml version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
3
+ <head>
4
+ <product srsName="WGS 1984" concise-name="dwmlByDay" operational-mode="official">
5
+ <title>NOAA's National Weather Service Forecast by 24 Hour Period</title>
6
+ <field>meteorological</field>
7
+ <category>forecast</category>
8
+ <creation-date refresh-frequency="PT1H">2013-08-12T03:47:26Z</creation-date>
9
+ </product>
10
+ <source>
11
+ <more-information>http://graphical.weather.gov/xml/</more-information>
12
+ <production-center>Meteorological Development Laboratory<sub-center>Product Generation Branch</sub-center></production-center>
13
+ <disclaimer>http://www.nws.noaa.gov/disclaimer.html</disclaimer>
14
+ <credit>http://www.weather.gov/</credit>
15
+ <credit-logo>http://www.weather.gov/images/xml_logo.gif</credit-logo>
16
+ <feedback>http://www.weather.gov/feedback.php</feedback>
17
+ </source>
18
+ </head>
19
+ <data>
20
+ <location>
21
+ <location-key>point1</location-key>
22
+ <point latitude="37.20" longitude="-93.29"/>
23
+ </location>
24
+ <moreWeatherInformation applicable-location="point1">http://forecast.weather.gov/MapClick.php?textField1=37.20&amp;textField2=-93.29</moreWeatherInformation>
25
+ <time-layout time-coordinate="local" summarization="24hourly">
26
+ <layout-key>k-p24h-n7-1</layout-key>
27
+ <start-valid-time period-name="Today">2013-08-12T06:00:00-05:00</start-valid-time>
28
+ <end-valid-time>2013-08-13T06:00:00-05:00</end-valid-time>
29
+ <start-valid-time period-name="Tomorrow">2013-08-13T06:00:00-05:00</start-valid-time>
30
+ <end-valid-time>2013-08-14T06:00:00-05:00</end-valid-time>
31
+ <start-valid-time period-name="Monday">2013-08-14T06:00:00-05:00</start-valid-time>
32
+ <end-valid-time>2013-08-15T06:00:00-05:00</end-valid-time>
33
+ <start-valid-time period-name="Tuesday">2013-08-15T06:00:00-05:00</start-valid-time>
34
+ <end-valid-time>2013-08-16T06:00:00-05:00</end-valid-time>
35
+ <start-valid-time period-name="Wednesday">2013-08-16T06:00:00-05:00</start-valid-time>
36
+ <end-valid-time>2013-08-17T06:00:00-05:00</end-valid-time>
37
+ <start-valid-time period-name="Thursday">2013-08-17T06:00:00-05:00</start-valid-time>
38
+ <end-valid-time>2013-08-18T06:00:00-05:00</end-valid-time>
39
+ <start-valid-time period-name="Friday">2013-08-18T06:00:00-05:00</start-valid-time>
40
+ <end-valid-time>2013-08-19T06:00:00-05:00</end-valid-time>
41
+ </time-layout>
42
+ <time-layout time-coordinate="local" summarization="12hourly">
43
+ <layout-key>k-p12h-n14-2</layout-key>
44
+ <start-valid-time>2013-08-12T06:00:00-05:00</start-valid-time>
45
+ <end-valid-time>2013-08-12T18:00:00-05:00</end-valid-time>
46
+ <start-valid-time>2013-08-12T18:00:00-05:00</start-valid-time>
47
+ <end-valid-time>2013-08-13T06:00:00-05:00</end-valid-time>
48
+ <start-valid-time>2013-08-13T06:00:00-05:00</start-valid-time>
49
+ <end-valid-time>2013-08-13T18:00:00-05:00</end-valid-time>
50
+ <start-valid-time>2013-08-13T18:00:00-05:00</start-valid-time>
51
+ <end-valid-time>2013-08-14T06:00:00-05:00</end-valid-time>
52
+ <start-valid-time>2013-08-14T06:00:00-05:00</start-valid-time>
53
+ <end-valid-time>2013-08-14T18:00:00-05:00</end-valid-time>
54
+ <start-valid-time>2013-08-14T18:00:00-05:00</start-valid-time>
55
+ <end-valid-time>2013-08-15T06:00:00-05:00</end-valid-time>
56
+ <start-valid-time>2013-08-15T06:00:00-05:00</start-valid-time>
57
+ <end-valid-time>2013-08-15T18:00:00-05:00</end-valid-time>
58
+ <start-valid-time>2013-08-15T18:00:00-05:00</start-valid-time>
59
+ <end-valid-time>2013-08-16T06:00:00-05:00</end-valid-time>
60
+ <start-valid-time>2013-08-16T06:00:00-05:00</start-valid-time>
61
+ <end-valid-time>2013-08-16T18:00:00-05:00</end-valid-time>
62
+ <start-valid-time>2013-08-16T18:00:00-05:00</start-valid-time>
63
+ <end-valid-time>2013-08-17T06:00:00-05:00</end-valid-time>
64
+ <start-valid-time>2013-08-17T06:00:00-05:00</start-valid-time>
65
+ <end-valid-time>2013-08-17T18:00:00-05:00</end-valid-time>
66
+ <start-valid-time>2013-08-17T18:00:00-05:00</start-valid-time>
67
+ <end-valid-time>2013-08-18T06:00:00-05:00</end-valid-time>
68
+ <start-valid-time>2013-08-18T06:00:00-05:00</start-valid-time>
69
+ <end-valid-time>2013-08-18T18:00:00-05:00</end-valid-time>
70
+ <start-valid-time>2013-08-18T18:00:00-05:00</start-valid-time>
71
+ <end-valid-time>2013-08-19T06:00:00-05:00</end-valid-time>
72
+ </time-layout>
73
+ <time-layout time-coordinate="local" summarization="24hourly">
74
+ <layout-key>k-p7d-n1-3</layout-key>
75
+ <start-valid-time>2013-08-12T06:00:00-05:00</start-valid-time>
76
+ <end-valid-time>2013-08-19T06:00:00-05:00</end-valid-time>
77
+ </time-layout>
78
+ <parameters applicable-location="point1">
79
+ <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n7-1">
80
+ <name>Daily Maximum Temperature</name>
81
+ <value>86</value>
82
+ <value>81</value>
83
+ <value>78</value>
84
+ <value>77</value>
85
+ <value>78</value>
86
+ <value>81</value>
87
+ <value>83</value>
88
+ </temperature>
89
+ <temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n7-1">
90
+ <name>Daily Minimum Temperature</name>
91
+ <value>69</value>
92
+ <value>65</value>
93
+ <value>57</value>
94
+ <value>57</value>
95
+ <value>59</value>
96
+ <value>61</value>
97
+ <value xsi:nil="true"/>
98
+ </temperature>
99
+ <probability-of-precipitation type="12 hour" units="percent" time-layout="k-p12h-n14-2">
100
+ <name>12 Hourly Probability of Precipitation</name>
101
+ <value>46</value>
102
+ <value>46</value>
103
+ <value>54</value>
104
+ <value>32</value>
105
+ <value>12</value>
106
+ <value>4</value>
107
+ <value>6</value>
108
+ <value>6</value>
109
+ <value>7</value>
110
+ <value>5</value>
111
+ <value>4</value>
112
+ <value>5</value>
113
+ <value>5</value>
114
+ <value xsi:nil="true"/>
115
+ </probability-of-precipitation>
116
+ <weather time-layout="k-p24h-n7-1">
117
+ <name>Weather Type, Coverage, and Intensity</name>
118
+ <weather-conditions weather-summary="Chance Thunderstorms">
119
+ <value coverage="chance" intensity="none" weather-type="thunderstorms" qualifier="none"/>
120
+ <value coverage="chance" intensity="light" additive="and" weather-type="rain showers" qualifier="none"/>
121
+ </weather-conditions>
122
+ <weather-conditions weather-summary="Chance Thunderstorms">
123
+ <value coverage="chance" intensity="none" weather-type="thunderstorms" qualifier="none"/>
124
+ <value coverage="chance" intensity="light" additive="and" weather-type="rain showers" qualifier="none"/>
125
+ </weather-conditions>
126
+ <weather-conditions weather-summary="Partly Sunny"/>
127
+ <weather-conditions weather-summary="Partly Sunny"/>
128
+ <weather-conditions weather-summary="Mostly Sunny"/>
129
+ <weather-conditions weather-summary="Mostly Sunny"/>
130
+ <weather-conditions weather-summary="Mostly Sunny"/>
131
+ </weather>
132
+ <conditions-icon type="forecast-NWS" time-layout="k-p24h-n7-1">
133
+ <name>Conditions Icons</name>
134
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/tsra50.jpg</icon-link>
135
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/tsra50.jpg</icon-link>
136
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/sct.jpg</icon-link>
137
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/sct.jpg</icon-link>
138
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/few.jpg</icon-link>
139
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/few.jpg</icon-link>
140
+ <icon-link>http://www.nws.noaa.gov/weather/images/fcicons/few.jpg</icon-link>
141
+ </conditions-icon>
142
+ </parameters>
143
+ </data>
144
+ </dwml>
@@ -0,0 +1,93 @@
1
+ require_relative '../../spec_helper'
2
+ require_relative '../../../lib/noaa_weather_client/client'
3
+
4
+ module NoaaWeatherClient
5
+ describe Client do
6
+ let(:client) { Client.new }
7
+
8
+ it "requires no arguments" do
9
+ Client.new
10
+ end
11
+
12
+ context "#forecast_by_day" do
13
+ it "fetches a 7 day forecast by default" do
14
+ VCR.use_cassette(:forecast_by_day_7) do
15
+ expect(client.forecast_by_day(37.1962, -93.2861).size).to eq(7)
16
+ end
17
+ end
18
+
19
+ it "fetches less than 7 day forecast if requested" do
20
+ VCR.use_cassette(:forecast_by_day_3) do
21
+ expect(client.forecast_by_day(37.1962, -93.2861, days: 3).size).to eq(3)
22
+ end
23
+ end
24
+ end
25
+
26
+ context "#weather_stations" do
27
+ it "fetches a list of all weather stations" do
28
+ VCR.use_cassette(:weather_stations) do
29
+ expect(client.weather_stations.size).to be > 2500
30
+ end
31
+ end
32
+
33
+ it "caches weather stations" do
34
+ VCR.use_cassette(:weather_stations) do
35
+ stations = client.weather_stations
36
+ expect(client.weather_stations.object_id).to eq(stations.object_id)
37
+ end
38
+ end
39
+
40
+ it "reloads stations with :reload flag" do
41
+ VCR.use_cassette(:weather_stations) do
42
+ stations = client.weather_stations
43
+ client.instance_variable_set('@weather_stations', double)
44
+ expect(client.weather_stations(relaod: true).object_id).to_not eq(stations.object_id)
45
+ end
46
+ end
47
+ end
48
+
49
+ context "#current_observations" do
50
+ it "fetches the current weather observation from the station nearest the coordinates" do
51
+ VCR.use_cassette(:current_observations) do
52
+ expect(client.current_observations(37.1962, -93.2861).station_id).to eq('KSGF')
53
+ end
54
+ end
55
+
56
+ it "fetches the current weather observation with temp in f" do
57
+ VCR.use_cassette(:current_observations) do
58
+ expect(client.current_observations(37.1962, -93.2861).temp_f).to be
59
+ end
60
+ end
61
+
62
+ it "fetches the current weather observation with weather condition" do
63
+ VCR.use_cassette(:current_observations) do
64
+ expect(client.current_observations(37.1962, -93.2861).weather).to be
65
+ end
66
+ end
67
+ end
68
+
69
+ context "#nearest_weather_station" do
70
+ it "fetches the station nearest the coordinates" do
71
+ VCR.use_cassette(:nearest_weather_station) do
72
+ expect(client.nearest_weather_station(37.1962, -93.2861).station_id).to eq('KSGF')
73
+ end
74
+ end
75
+
76
+ it "uses a cached set of stations if provided" do
77
+ stations = [ double(latitude: 38.3456, longitude: -97.3345, station_id: 'cached_station') ]
78
+ expect(
79
+ client.nearest_weather_station(37.1962, -93.2861, stations: stations).station_id
80
+ ).to eq('cached_station')
81
+ end
82
+ end
83
+
84
+ context "#postal_code_to_coordinate" do
85
+ it "resolves a postal code to coordinate" do
86
+ VCR.use_cassette(:postal_code_to_coordinate) do
87
+ expect(client.postal_code_to_coordinate(65804).latitude).to eq(37.1962)
88
+ expect(client.postal_code_to_coordinate(65804).longitude).to eq(-93.2861)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,122 @@
1
+
2
+ require_relative '../../../spec_helper'
3
+ require_relative '../../../../lib/noaa_weather_client/responses/current_observation'
4
+
5
+ module NoaaWeatherClient
6
+ module Responses
7
+ describe CurrentObservation do
8
+ let(:body) {
9
+ VCR.use_cassette(:current_observations, match_requests_on: [:method, :uri]) { |c|
10
+ c.http_interactions.response_for(
11
+ VCR::Request.new.tap { |r|
12
+ r.method = :get
13
+ r.uri = 'http://w1.weather.gov/xml/current_obs/KSGF.xml'
14
+ }).body
15
+ }
16
+ }
17
+ let(:current_observation) { CurrentObservation.new body }
18
+
19
+ it "requires a response" do
20
+ current_observation
21
+ expect { CurrentObservation.new }.to raise_error(ArgumentError)
22
+ end
23
+
24
+ context "when the response is invalid" do
25
+ it "raises an ArgumentError" do
26
+ expect { CurrentObservation.new '<invalid></invalid>' }.to raise_error(Errors::InvalidXmlError)
27
+ end
28
+ end
29
+
30
+ it "exposes location" do
31
+ expect(current_observation.location).to eq('Springfield-Branson National Airport, MO')
32
+ end
33
+ it "exposes station_id" do
34
+ expect(current_observation.station_id).to eq('KSGF')
35
+ end
36
+ it "exposes latitude" do
37
+ expect(current_observation.latitude).to eq(37.23)
38
+ end
39
+ it "exposes longitude" do
40
+ expect(current_observation.longitude).to eq(-93.38)
41
+ end
42
+ it "exposes observation_time_string" do
43
+ expect(current_observation.observation_time_string).to eq('Last Updated on Aug 12 2013, 8:52 pm CDT')
44
+ end
45
+ it "exposes observation_time" do
46
+ expect(current_observation.observation_time).to eq(Time.parse '2013-08-12 20:52:00 -0500')
47
+ end
48
+ it "exposes weather" do
49
+ expect(current_observation.weather).to eq('Fair')
50
+ end
51
+ it "exposes temperature_string" do
52
+ expect(current_observation.temperature_string).to eq('74.0 F (23.3 C)')
53
+ end
54
+ it "exposes temperature_fahrenheit" do
55
+ expect(current_observation.temperature_fahrenheit).to eq(74.0)
56
+ end
57
+ it "exposes temperature_celsius" do
58
+ expect(current_observation.temperature_celsius).to eq(23.3)
59
+ end
60
+ it "exposes relative_humidity" do
61
+ expect(current_observation.relative_humidity).to eq(85)
62
+ end
63
+ it "exposes wind_string" do
64
+ expect(current_observation.wind_string).to eq('Calm')
65
+ end
66
+ it "exposes wind_dir" do
67
+ expect(current_observation.wind_dir).to eq('North')
68
+ end
69
+ it "exposes wind_degrees" do
70
+ expect(current_observation.wind_degrees).to eq(0)
71
+ end
72
+ it "exposes wind_mph" do
73
+ expect(current_observation.wind_mph).to eq(0.0)
74
+ end
75
+ it "exposes wind_kt" do
76
+ expect(current_observation.wind_kt).to eq(0)
77
+ end
78
+ it "exposes pressure_string" do
79
+ expect(current_observation.pressure_string).to eq('1014.7 mb')
80
+ end
81
+ it "exposes pressure_mb" do
82
+ expect(current_observation.pressure_mb).to eq(1014.7)
83
+ end
84
+ it "exposes pressure_in" do
85
+ expect(current_observation.pressure_in).to eq(30.00)
86
+ end
87
+ it "exposes dewpoint_string" do
88
+ expect(current_observation.dewpoint_string).to eq('69.1 F (20.6 C)')
89
+ end
90
+ it "exposes dewpoint_fahrenheit" do
91
+ expect(current_observation.dewpoint_fahrenheit).to eq(69.1)
92
+ end
93
+ it "exposes dewpoint_celsius" do
94
+ expect(current_observation.dewpoint_celsius).to eq(20.6)
95
+ end
96
+ it "exposes visibility_mi" do
97
+ expect(current_observation.visibility_mi).to eq(10.00)
98
+ end
99
+ it "exposes icon_url_base" do
100
+ expect(current_observation.icon_url_base).to eq('http://forecast.weather.gov/images/wtf/small/')
101
+ end
102
+ it "exposes two_day_history_url" do
103
+ expect(current_observation.two_day_history_url).to eq('http://www.weather.gov/data/obhistory/KSGF.html')
104
+ end
105
+ it "exposes icon_url_name" do
106
+ expect(current_observation.icon_url_name).to eq('nskc.png')
107
+ end
108
+ it "exposes ob_url" do
109
+ expect(current_observation.ob_url).to eq('http://www.weather.gov/data/METAR/KSGF.1.txt')
110
+ end
111
+ it "exposes disclaimer_url" do
112
+ expect(current_observation.disclaimer_url).to eq('http://weather.gov/disclaimer.html')
113
+ end
114
+ it "exposes copyright_url" do
115
+ expect(current_observation.copyright_url).to eq('http://weather.gov/disclaimer.html')
116
+ end
117
+ it "exposes privacy_policy_url" do
118
+ expect(current_observation.privacy_policy_url).to eq('http://weather.gov/notice.html')
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,66 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/noaa_weather_client/responses/forecast'
3
+
4
+ module NoaaWeatherClient
5
+ module Responses
6
+ describe Forecast do
7
+ let(:fake_response) { { ndf_dgen_by_day_response: { dwml_by_day_out: load_xml_fixture(:forecast) } } }
8
+ let(:fake_invalid_response) { { ndf_dgen_by_day_response: { dwml_by_day_out: '<invalid></invalid>' } } }
9
+ let(:forecast) { Forecast.new fake_response }
10
+
11
+ it "requires a response" do
12
+ forecast
13
+ expect { Forecast.new }.to raise_error(ArgumentError)
14
+ end
15
+
16
+ context "when the response is invalid" do
17
+ it "raises an ArgumentError" do
18
+ expect { Forecast.new fake_invalid_response }.to raise_error(Errors::InvalidXmlError)
19
+ end
20
+ end
21
+
22
+ it "exposes a list of days via enumerable" do
23
+ count = 0
24
+ expect { forecast.each { |d| count += 1 } }.to change { count }.by(7)
25
+ end
26
+
27
+ it "exposes number of stations via size" do
28
+ expect(forecast.size).to eq(7)
29
+ end
30
+
31
+ describe '#days' do
32
+ let(:period) { double(start_time: Time.parse('2013-08-12 06:00:00 -0500'),
33
+ end_time: Time.parse('2013-08-13 06:00:00 -0500'),
34
+ name: 'Today') }
35
+ let(:max) { 86.0 }
36
+ let(:min) { 69.0 }
37
+ let(:weather_summary) { 'Chance Thunderstorms' }
38
+ let(:day) { forecast.days.first }
39
+
40
+ it "exposes start_time from period" do
41
+ expect(day.start_time).to eq(period.start_time)
42
+ end
43
+
44
+ it "exposes end_time from period" do
45
+ expect(day.end_time).to eq(period.end_time)
46
+ end
47
+
48
+ it "exposes weekday name" do
49
+ expect(day.name).to eq("Monday")
50
+ end
51
+
52
+ it "fetches max temp" do
53
+ expect(day.maximum_temperature).to eq(max)
54
+ end
55
+
56
+ it "fetches min temp" do
57
+ expect(day.minimum_temperature).to eq(min)
58
+ end
59
+
60
+ it "fetches weather summary from parameters" do
61
+ expect(day.weather_summary).to eq(weather_summary)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../../../spec_helper'
2
+ require_relative '../../../../lib/noaa_weather_client/responses/lat_lon_list'
3
+
4
+ module NoaaWeatherClient
5
+ module Responses
6
+ describe LatLonList do
7
+ let(:fake_response) { ZIP_XML }
8
+ let(:lat_lon_list) { LatLonList.new fake_response }
9
+
10
+ it "requires a response" do
11
+ lat_lon_list
12
+ expect { LatLonList.new }.to raise_error(ArgumentError)
13
+ end
14
+
15
+ it "exposes latitude as float" do
16
+ expect(lat_lon_list.latitude).to eq(37.1962)
17
+ end
18
+
19
+ it "exposes longitude as float" do
20
+ expect(lat_lon_list.longitude).to eq(-93.2861)
21
+ end
22
+
23
+ ZIP_XML = <<-xml
24
+ <?xml version='1.0'?><dwml version='1.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd'><latLonList>37.1962,-93.2861</latLonList></dwml>
25
+ xml
26
+ end
27
+ end
28
+ end
29
+
30
+