noaa_weather_client 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/.yardopts +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +107 -0
- data/Rakefile +8 -0
- data/bin/noaa_weather_client +43 -0
- data/data/xml/current_observation.xsd +79 -0
- data/data/xml/dwml.xsd +97 -0
- data/data/xml/location.xsd +142 -0
- data/data/xml/meta_data.xsd +100 -0
- data/data/xml/moreWeatherInformation.xsd +23 -0
- data/data/xml/ndfd_data.xsd +43 -0
- data/data/xml/parameters.xsd +1173 -0
- data/data/xml/summarizationType.xsd +29 -0
- data/data/xml/time_layout.xsd +51 -0
- data/lib/noaa_weather_client.rb +9 -0
- data/lib/noaa_weather_client/cli.rb +53 -0
- data/lib/noaa_weather_client/cli/templates.rb +53 -0
- data/lib/noaa_weather_client/client.rb +61 -0
- data/lib/noaa_weather_client/errors.rb +7 -0
- data/lib/noaa_weather_client/responses/current_observation.rb +93 -0
- data/lib/noaa_weather_client/responses/forecast.rb +84 -0
- data/lib/noaa_weather_client/responses/generic_response.rb +9 -0
- data/lib/noaa_weather_client/responses/lat_lon_list.rb +25 -0
- data/lib/noaa_weather_client/responses/reactive_xml_response.rb +29 -0
- data/lib/noaa_weather_client/responses/station.rb +28 -0
- data/lib/noaa_weather_client/responses/stations.rb +41 -0
- data/lib/noaa_weather_client/responses/validatable_xml_response.rb +22 -0
- data/lib/noaa_weather_client/rest_client_factory.rb +12 -0
- data/lib/noaa_weather_client/services/calculate_distance_between_lat_lon.rb +20 -0
- data/lib/noaa_weather_client/services/current_observations.rb +32 -0
- data/lib/noaa_weather_client/services/find_nearest_station.rb +16 -0
- data/lib/noaa_weather_client/services/forecast_by_day.rb +52 -0
- data/lib/noaa_weather_client/services/postal_code_to_coordinate.rb +36 -0
- data/lib/noaa_weather_client/services/rest_service.rb +28 -0
- data/lib/noaa_weather_client/services/soap_service.rb +16 -0
- data/lib/noaa_weather_client/services/weather_stations.rb +32 -0
- data/lib/noaa_weather_client/soap_client_factory.rb +17 -0
- data/lib/noaa_weather_client/station_filters.rb +8 -0
- data/lib/noaa_weather_client/version.rb +3 -0
- data/lib/noaa_weather_client/xml_parser_factory.rb +9 -0
- data/noaa_weather_client.gemspec +27 -0
- data/spec/fixtures/vcr_cassettes/current_observations.yml +25890 -0
- data/spec/fixtures/vcr_cassettes/forecast_by_day_3.yml +772 -0
- data/spec/fixtures/vcr_cassettes/forecast_by_day_7.yml +829 -0
- data/spec/fixtures/vcr_cassettes/nearest_weather_station.yml +25842 -0
- data/spec/fixtures/vcr_cassettes/postal_code_to_coordinate.yml +75 -0
- data/spec/fixtures/vcr_cassettes/weather_stations.yml +25842 -0
- data/spec/fixtures/xml/forecast.xml +144 -0
- data/spec/lib/noaa_client/client_spec.rb +93 -0
- data/spec/lib/noaa_client/responses/current_observation_spec.rb +122 -0
- data/spec/lib/noaa_client/responses/forecast_spec.rb +66 -0
- data/spec/lib/noaa_client/responses/lat_lon_list_spec.rb +30 -0
- data/spec/lib/noaa_client/responses/station_spec.rb +53 -0
- data/spec/lib/noaa_client/responses/stations_spec.rb +86 -0
- data/spec/lib/noaa_client/rest_client_factory_spec.rb +15 -0
- data/spec/lib/noaa_client/services/calculate_distance_between_lat_lon_spec.rb +16 -0
- data/spec/lib/noaa_client/services/current_observations_spec.rb +47 -0
- data/spec/lib/noaa_client/services/find_nearest_station_spec.rb +36 -0
- data/spec/lib/noaa_client/services/forecast_by_day_spec.rb +62 -0
- data/spec/lib/noaa_client/services/postal_code_to_coordinate_spec.rb +41 -0
- data/spec/lib/noaa_client/services/rest_service_spec.rb +45 -0
- data/spec/lib/noaa_client/services/soap_service_spec.rb +56 -0
- data/spec/lib/noaa_client/services/weather_stations_spec.rb +40 -0
- data/spec/lib/noaa_client/soap_client_factory_spec.rb +13 -0
- data/spec/lib/noaa_client/xml_parser_factory_spec.rb +14 -0
- data/spec/spec_helper.rb +31 -0
- metadata +228 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require_relative '../../../spec_helper'
|
3
|
+
require_relative '../../../../lib/noaa_weather_client/responses/station'
|
4
|
+
|
5
|
+
module NoaaWeatherClient
|
6
|
+
module Responses
|
7
|
+
describe Station do
|
8
|
+
let(:source) {
|
9
|
+
<<-xml
|
10
|
+
<station>
|
11
|
+
<station_id>TAPA</station_id>
|
12
|
+
<state>AG</state>
|
13
|
+
<station_name>Vc Bird Intl Airport Antigua</station_name>
|
14
|
+
<latitude>17.117</latitude>
|
15
|
+
<longitude>-61.783</longitude>
|
16
|
+
<html_url>http://weather.noaa.gov/weather/current/TAPA.html</html_url>
|
17
|
+
<rss_url>http://weather.gov/xml/current_obs/TAPA.rss</rss_url>
|
18
|
+
<xml_url>http://weather.gov/xml/current_obs/TAPA.xml</xml_url>
|
19
|
+
</station>
|
20
|
+
xml
|
21
|
+
}
|
22
|
+
let(:station) { Station.new Nokogiri::XML.parse(source) }
|
23
|
+
|
24
|
+
it "accepts an attributes hash" do
|
25
|
+
station
|
26
|
+
end
|
27
|
+
|
28
|
+
it "exposes station id" do
|
29
|
+
expect(station.station_id).to eq('TAPA')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "exposes station name" do
|
33
|
+
expect(station.station_name).to eq('Vc Bird Intl Airport Antigua')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "exposes state" do
|
37
|
+
expect(station.state).to eq('AG')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "exposes latitude" do
|
41
|
+
expect(station.latitude).to eq(17.117)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "exposes longitude" do
|
45
|
+
expect(station.longitude).to eq(-61.783)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "exposes xml url" do
|
49
|
+
expect(station.xml_url).to eq('http://w1.weather.gov/xml/current_obs/TAPA.xml')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require_relative '../../../spec_helper'
|
3
|
+
require_relative '../../../../lib/noaa_weather_client/responses/stations'
|
4
|
+
|
5
|
+
module NoaaWeatherClient
|
6
|
+
module Responses
|
7
|
+
describe Stations do
|
8
|
+
let(:fake_response) { STATIONS_XML }
|
9
|
+
let(:stations) { Stations.new fake_response }
|
10
|
+
|
11
|
+
it "requires a response" do
|
12
|
+
stations
|
13
|
+
expect { Stations.new }.to raise_error(ArgumentError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "exposes a list of stations via enumerable" do
|
17
|
+
count = 0
|
18
|
+
expect { stations.each { |d| count += 1 } }.to change { count }.by(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "passes station xml to the station class" do
|
22
|
+
mock_station_class = double(new: nil)
|
23
|
+
first, last = Nokogiri::XML.parse(fake_response).css('station')
|
24
|
+
expect(mock_station_class).to receive(:new).with { |station|
|
25
|
+
station.to_xml == first.to_xml
|
26
|
+
}
|
27
|
+
expect(mock_station_class).to receive(:new).with { |station|
|
28
|
+
station.to_xml == last.to_xml
|
29
|
+
}
|
30
|
+
Stations.new(fake_response, station_class: mock_station_class).each { |s| }
|
31
|
+
end
|
32
|
+
|
33
|
+
it "allows fetching of stations via array#fetch" do
|
34
|
+
expect(stations.fetch(0).station_id).to eq('TAPA')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "allows fetching of stations via array#[]" do
|
38
|
+
expect(stations[0].station_id).to eq('TAPA')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "exposes number of stations via size" do
|
42
|
+
expect(stations.size).to eq(2)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "exposes source xml" do
|
46
|
+
expect(stations.to_xml).to eq(Nokogiri::XML.parse(fake_response).to_xml)
|
47
|
+
end
|
48
|
+
|
49
|
+
STATIONS_XML =<<-RESPONSE
|
50
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
51
|
+
<wx_station_index>
|
52
|
+
<credit>NOAA's National Weather Service</credit>
|
53
|
+
<credit_URL>http://weather.gov/</credit_URL>
|
54
|
+
<image>
|
55
|
+
<url>http://weather.gov/images/xml_logo.gif</url>
|
56
|
+
<title>NOAA's National Weather Service</title>
|
57
|
+
<link>http://weather.gov</link>
|
58
|
+
</image>
|
59
|
+
<suggested_pickup>08:00 EST</suggested_pickup>
|
60
|
+
<suggested_pickup_period>1140</suggested_pickup_period>
|
61
|
+
<station>
|
62
|
+
<station_id>TAPA</station_id>
|
63
|
+
<state>AG</state>
|
64
|
+
<station_name>Vc Bird Intl Airport Antigua</station_name>
|
65
|
+
<latitude>17.117</latitude>
|
66
|
+
<longitude>-61.783</longitude>
|
67
|
+
<html_url>http://weather.noaa.gov/weather/current/TAPA.html</html_url>
|
68
|
+
<rss_url>http://weather.gov/xml/current_obs/TAPA.rss</rss_url>
|
69
|
+
<xml_url>http://weather.gov/xml/current_obs/TAPA.xml</xml_url>
|
70
|
+
</station>
|
71
|
+
|
72
|
+
<station>
|
73
|
+
<station_id>TKPN</station_id>
|
74
|
+
<state>AG</state>
|
75
|
+
<station_name>Charlestown/Newcast</station_name>
|
76
|
+
<latitude>17.2</latitude>
|
77
|
+
<longitude>-62.583</longitude>
|
78
|
+
<html_url>http://weather.noaa.gov/weather/current/TKPN.html</html_url>
|
79
|
+
<rss_url>http://weather.gov/xml/current_obs/TKPN.rss</rss_url>
|
80
|
+
<xml_url>http://weather.gov/xml/current_obs/TKPN.xml</xml_url>
|
81
|
+
</station>
|
82
|
+
</wx_station_index>
|
83
|
+
RESPONSE
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require_relative '../../spec_helper'
|
3
|
+
require_relative '../../../lib/noaa_weather_client/rest_client_factory'
|
4
|
+
|
5
|
+
module NoaaWeatherClient
|
6
|
+
describe RestClientFactory do
|
7
|
+
it "builds a rest client with the provided url" do
|
8
|
+
mock_provider = double()
|
9
|
+
url = "http://www.google.com"
|
10
|
+
uri = URI(url)
|
11
|
+
expect(mock_provider).to receive(:new).with(uri.host, uri.port)
|
12
|
+
RestClientFactory.build_client provider: mock_provider, url: url
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/calculate_distance_between_lat_lon'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe CalculateDistanceBetweenLatLon do
|
7
|
+
let(:springfield) { [ 37.1962, -93.2861 ] }
|
8
|
+
let(:kansas_city) { [ 39.1000, -94.5800 ] }
|
9
|
+
|
10
|
+
it "calculates the distance between two points" do
|
11
|
+
expect(CalculateDistanceBetweenLatLon.get_distance(*springfield, *kansas_city))
|
12
|
+
.to eq(240.02560432981815)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/current_observations'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe CurrentObservations do
|
7
|
+
let(:mock_station) { double(xml_url: 'http://w1.weather.gov/xml/current_obs/KSGF.xml') }
|
8
|
+
let(:current_observations) { CurrentObservations.new options }
|
9
|
+
|
10
|
+
it "accepts an options hash" do
|
11
|
+
CurrentObservations.new {}
|
12
|
+
end
|
13
|
+
|
14
|
+
context "#fetch" do
|
15
|
+
let(:options) { { rest_service: double(object_from_response: nil) } }
|
16
|
+
|
17
|
+
it "requires a station" do
|
18
|
+
current_observations.fetch mock_station, options
|
19
|
+
expect { current_observations.fetch }.to raise_error(ArgumentError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "accepts an options hash" do
|
23
|
+
current_observations.fetch mock_station, options
|
24
|
+
end
|
25
|
+
|
26
|
+
it "passes the stations xml url to the service" do
|
27
|
+
expect(options[:rest_service]).to receive(:object_from_response)
|
28
|
+
.with(anything, mock_station.xml_url, anything)
|
29
|
+
current_observations.fetch mock_station
|
30
|
+
end
|
31
|
+
|
32
|
+
it "passes the get action to the service" do
|
33
|
+
expect(options[:rest_service]).to receive(:object_from_response)
|
34
|
+
.with(:get, anything, anything)
|
35
|
+
current_observations.fetch mock_station
|
36
|
+
end
|
37
|
+
|
38
|
+
it "passes an optional response class to the service" do
|
39
|
+
options[:response_class] = :some_response_class
|
40
|
+
expect(options[:rest_service]).to receive(:object_from_response)
|
41
|
+
.with(anything, anything, hash_including(response_class: options[:response_class]))
|
42
|
+
current_observations.fetch mock_station
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/find_nearest_station'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe FindNearestStation do
|
7
|
+
let(:location) { double(latitude:39.1000, longitude: -94.5800) } #kansas city
|
8
|
+
let(:washington_dc) { double(station_name: 'Washington D.C.', latitude: 38.8951 , longitude: -77.0367) }
|
9
|
+
let(:detroit) { double(station_name: 'Detroit', latitude: 42.3314 , longitude: -83.0458) }
|
10
|
+
let(:stations) { [ washington_dc, detroit ] }
|
11
|
+
|
12
|
+
it "requires latitude, longitude, and a list of stations" do
|
13
|
+
FindNearestStation.find(location.latitude, location.longitude, stations)
|
14
|
+
expect { FindNearestStation.find }.to raise_error(ArgumentError)
|
15
|
+
expect { FindNearestStation.find location.latitude}.to raise_error(ArgumentError)
|
16
|
+
expect { FindNearestStation.find location.latitude, location.longitude}.to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "accepts an options hash" do
|
20
|
+
FindNearestStation.find(location.latitude, location.longitude, stations, {})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "accepts a callable filter for the stations" do
|
24
|
+
mock_filter = ->(station) { station == washington_dc ? true : false }
|
25
|
+
FindNearestStation.find(location.latitude, location.longitude, stations, { filter: mock_filter })
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns the closest of the provided stations" do
|
29
|
+
expect(
|
30
|
+
FindNearestStation.find(location.latitude, location.longitude, stations)
|
31
|
+
.station_name
|
32
|
+
).to eq(detroit.station_name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/forecast_by_day'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe ForecastByDay do
|
7
|
+
it "accepts an options hash" do
|
8
|
+
ForecastByDay.new {}
|
9
|
+
end
|
10
|
+
|
11
|
+
context "#fetch" do
|
12
|
+
let(:options) { { soap_service: double(object_from_response: nil) } }
|
13
|
+
let(:forecast) { ForecastByDay.new options }
|
14
|
+
let(:lat) { 37.1962 }
|
15
|
+
let(:lon) { -93.2861 }
|
16
|
+
|
17
|
+
it "requires lat and lon" do
|
18
|
+
forecast.fetch lat, lon
|
19
|
+
expect { forecast.fetch }.to raise_error(ArgumentError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "accepts an options hash" do
|
23
|
+
forecast.fetch lat, lon, {}
|
24
|
+
end
|
25
|
+
|
26
|
+
it "passes optional arguments to the service" do
|
27
|
+
args = { key: 'value' }
|
28
|
+
expect(options[:soap_service]).to receive(:object_from_response)
|
29
|
+
.with(anything, hash_including(key: 'value'), anything)
|
30
|
+
forecast.fetch lat, lon, args
|
31
|
+
end
|
32
|
+
|
33
|
+
it "passes lat as string to the service" do
|
34
|
+
expect(options[:soap_service]).to receive(:object_from_response)
|
35
|
+
.with(anything, hash_including(latitude: lat.to_s), anything)
|
36
|
+
forecast.fetch lat, lon
|
37
|
+
end
|
38
|
+
|
39
|
+
it "passes lon as string to the service" do
|
40
|
+
expect(options[:soap_service]).to receive(:object_from_response)
|
41
|
+
.with(anything, hash_including(longitude: lon.to_s), anything)
|
42
|
+
forecast.fetch lat, lon
|
43
|
+
end
|
44
|
+
|
45
|
+
it "passes the soap action to the service" do
|
46
|
+
expect(options[:soap_service]).to receive(:object_from_response)
|
47
|
+
.with(:ndf_dgen_by_day, anything, anything)
|
48
|
+
forecast.fetch lat, lon
|
49
|
+
end
|
50
|
+
|
51
|
+
it "passes an optional response class to the service" do
|
52
|
+
options[:response_class] = :some_response_class
|
53
|
+
expect(options[:soap_service]).to receive(:object_from_response)
|
54
|
+
.with(anything, anything, hash_including(response_class: options[:response_class]))
|
55
|
+
|
56
|
+
forecast = ForecastByDay.new options
|
57
|
+
forecast.fetch lat, lon
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/postal_code_to_coordinate'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe PostalCodeToCoordinate do
|
7
|
+
it "accepts an options hash" do
|
8
|
+
PostalCodeToCoordinate.new {}
|
9
|
+
end
|
10
|
+
|
11
|
+
context "#resolve" do
|
12
|
+
let(:options) { { rest_service: double(object_from_response: nil) } }
|
13
|
+
let(:zip) { 90210 }
|
14
|
+
let(:zip_lat_lon) { PostalCodeToCoordinate.new options }
|
15
|
+
|
16
|
+
it "accepts an options hash" do
|
17
|
+
zip_lat_lon.resolve options
|
18
|
+
end
|
19
|
+
|
20
|
+
it "passes action to the service" do
|
21
|
+
expect(options[:rest_service]).to receive(:object_from_response)
|
22
|
+
.with(:get, anything, anything)
|
23
|
+
zip_lat_lon.resolve zip
|
24
|
+
end
|
25
|
+
|
26
|
+
it "passes zip as string to the service" do
|
27
|
+
expect(options[:rest_service]).to receive(:object_from_response)
|
28
|
+
.with(anything, /#{zip}/, anything)
|
29
|
+
zip_lat_lon.resolve zip
|
30
|
+
end
|
31
|
+
|
32
|
+
it "passes an optional response class to the service" do
|
33
|
+
options[:response_class] = :some_response_class
|
34
|
+
expect(options[:rest_service]).to receive(:object_from_response)
|
35
|
+
.with(anything, anything, hash_including(response_class: options[:response_class]))
|
36
|
+
zip_lat_lon.resolve zip
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/rest_service'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe RestService do
|
7
|
+
let(:fake_response) { double(body: 'fake_response_body') }
|
8
|
+
let(:mock_client) { double(request: fake_response) }
|
9
|
+
let(:mock_response_class) { double(new: nil) }
|
10
|
+
let(:implementer) { Class.new { include RestService }.new }
|
11
|
+
let(:args) { [ :get, 'http://www.google.com', { client: mock_client } ] }
|
12
|
+
|
13
|
+
context "#object_from_response" do
|
14
|
+
it "requires an action and url" do
|
15
|
+
implementer.object_from_response :get, 'http://www.google.com', client: mock_client
|
16
|
+
expect { implementer.object_from_response }.to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "accepts an options hash" do
|
20
|
+
implementer.object_from_response :get, 'http://www.google.com', client: mock_client
|
21
|
+
end
|
22
|
+
|
23
|
+
it "builds a request from the args" do
|
24
|
+
expect(implementer).to receive(:build_request_for_action).with(*args)
|
25
|
+
implementer.object_from_response(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "passes the rest response to the response class" do
|
29
|
+
expect(mock_client).to receive(:request).and_return(fake_response)
|
30
|
+
expect(mock_response_class).to receive(:new).with(fake_response.body)
|
31
|
+
action, url, opts = *args
|
32
|
+
implementer.object_from_response(action, url, opts.merge(response_class: mock_response_class))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns a new wrapped response body" do
|
36
|
+
expect(mock_response_class).to receive(:new).with(fake_response.body).and_return(mock_response_class)
|
37
|
+
action, url, opts = *args
|
38
|
+
expect(
|
39
|
+
implementer.object_from_response(action, url, opts.merge(response_class: mock_response_class))
|
40
|
+
).to eq(mock_response_class)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative '../../../spec_helper'
|
2
|
+
require_relative '../../../../lib/noaa_weather_client/services/soap_service'
|
3
|
+
|
4
|
+
module NoaaWeatherClient
|
5
|
+
module Services
|
6
|
+
describe SoapService do
|
7
|
+
let(:fake_response) { double(body: 'fake_response_body') }
|
8
|
+
let(:mock_client) { double(call: fake_response) }
|
9
|
+
let(:mock_response_class) { double(new: nil) }
|
10
|
+
let(:implementer) { Class.new { include SoapService }.new }
|
11
|
+
|
12
|
+
context "#object_from_response" do
|
13
|
+
it "requires a soap action and message" do
|
14
|
+
implementer.object_from_response :soap_action, :message, client: mock_client
|
15
|
+
expect { implementer.object_from_response }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts an options hash" do
|
19
|
+
implementer.object_from_response :soap_action, :message, client: mock_client
|
20
|
+
end
|
21
|
+
|
22
|
+
it "calls the soap client with the soap action" do
|
23
|
+
expect(mock_client).to receive(:call).with(:soap_action, anything)
|
24
|
+
implementer.object_from_response :soap_action, :message, client: mock_client
|
25
|
+
end
|
26
|
+
|
27
|
+
it "calls the soap client with the message" do
|
28
|
+
expect(mock_client).to receive(:call).with(anything, hash_including(message: :message))
|
29
|
+
implementer.object_from_response :soap_action, :message, client: mock_client
|
30
|
+
end
|
31
|
+
|
32
|
+
it "passes the soap response to the response" do
|
33
|
+
expect(mock_client).to receive(:call).and_return(fake_response)
|
34
|
+
expect(mock_response_class).to receive(:new).with(fake_response.body)
|
35
|
+
implementer.object_from_response :soap_action, :message, client: mock_client, response_class: mock_response_class
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns a new wrapped response body" do
|
39
|
+
expect(mock_response_class).to receive(:new).with(fake_response.body).and_return(mock_response_class)
|
40
|
+
expect(implementer.object_from_response(:soap_action,
|
41
|
+
:message,
|
42
|
+
client: mock_client,
|
43
|
+
response_class: mock_response_class)).to eq(mock_response_class)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when a Savon:Error occurs" do
|
47
|
+
it "raises a CommunicationError" do
|
48
|
+
allow(mock_client).to receive(:call).and_raise(Savon::Error)
|
49
|
+
expect { implementer.object_from_response :soap_action, :message, client: mock_client }
|
50
|
+
.to raise_error(Errors::CommunicationError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|