ns-yapi 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/Gemfile.lock +3 -1
- data/LICENSE.mkd +7 -0
- data/README.md +71 -7
- data/lib/model/prices_url.rb +16 -0
- data/lib/ns_client.rb +84 -39
- data/ns.gemspec +1 -1
- data/spec/fixtures/prices_invalid_station_name.xml +6 -0
- data/spec/model/prices_url_spec.rb +45 -0
- data/spec/ns_client_spec.rb +57 -8
- data/spec/spec_helper.rb +17 -1
- metadata +10 -4
data/Gemfile
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
2
|
|
3
3
|
gem "httpclient", "~> 2.3.3"
|
4
|
+
gem 'rake'
|
4
5
|
|
5
6
|
gemspec
|
6
7
|
|
7
8
|
group :test do
|
8
9
|
gem 'rspec'
|
9
10
|
gem 'simplecov'
|
10
|
-
gem 'rake'
|
11
11
|
gem "webmock", "~> 1.11.0"
|
12
|
+
gem "timecop", "~> 0.6.1"
|
12
13
|
gem 'mocha', require: 'mocha/api'
|
13
14
|
gem 'coveralls', require: false
|
14
15
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ns-yapi (0.
|
4
|
+
ns-yapi (0.3.0)
|
5
5
|
httpclient
|
6
6
|
nokogiri
|
7
7
|
nori
|
@@ -47,6 +47,7 @@ GEM
|
|
47
47
|
simplecov-html (~> 0.7.1)
|
48
48
|
simplecov-html (0.7.1)
|
49
49
|
thor (0.18.1)
|
50
|
+
timecop (0.6.1)
|
50
51
|
webmock (1.11.0)
|
51
52
|
addressable (>= 2.2.7)
|
52
53
|
crack (>= 0.3.2)
|
@@ -62,4 +63,5 @@ DEPENDENCIES
|
|
62
63
|
rake
|
63
64
|
rspec
|
64
65
|
simplecov
|
66
|
+
timecop (~> 0.6.1)
|
65
67
|
webmock (~> 1.11.0)
|
data/LICENSE.mkd
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2013 Zilverline / Stefan Hendriks
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
Yet Another NS API [![Build Status](https://travis-ci.org/stefanhendriks/ns-api.png?branch=master)](https://travis-ci.org/stefanhendriks/ns-api) [![Coverage Status](https://coveralls.io/repos/stefanhendriks/ns-api/badge.png)](https://coveralls.io/r/stefanhendriks/ns-api)
|
1
|
+
Yet Another NS API [![Build Status](https://travis-ci.org/stefanhendriks/ns-api.png?branch=master)](https://travis-ci.org/stefanhendriks/ns-api) [![Coverage Status](https://coveralls.io/repos/stefanhendriks/ns-api/badge.png)](https://coveralls.io/r/stefanhendriks/ns-api)
|
2
2
|
==================
|
3
3
|
A Ruby client for the NS API.
|
4
4
|
|
5
5
|
Goal
|
6
6
|
====
|
7
|
-
I'd like to write a comprehensive, yet very thin implementation of the NS API.
|
7
|
+
I'd like to write a comprehensive, yet very thin implementation of the NS API.
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
Pull requests are welcome.
|
9
|
+
Currently this gem supports
|
10
|
+
* fetching all stations
|
11
|
+
* fetching disruptions
|
12
|
+
* fetching prices (you need to have a contract with NS for this)
|
14
13
|
|
15
14
|
Usage
|
16
15
|
=====
|
@@ -54,6 +53,15 @@ station.lat # 51.69048
|
|
54
53
|
station.long # 5.29362
|
55
54
|
```
|
56
55
|
|
56
|
+
If you find it too tedious ploughing through all objects in the array, you can also use the ```stations_short``` method. This will return a hash with the station code as key, the
|
57
|
+
value is an array with the name and country of the station.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
client.stations_short
|
61
|
+
=> {"HT"=>["'s-Hertogenbosch", "NL"], "HTO"=>["Hertogenbosch O.", "NL"], "HDE"=>["'t Harde", "NL"], "AHBF"=>["Aachen", "D"], "ARE"=>["Aachen R. Erde", "D"], "ASCH"=>["Aachen Schanz", "D"], "AW"=>["Aachen-West", "D"], "ATN"=>["Aalten", "NL"], "AC"=>["Abcoude", "NL"], "EAHS"=>["Ahaus", "D"], "AIME"=>["Aime-la-Plagne", "F"], "AIXTGV"=>["Aix-en-Provence", "F"], "AKM"=>["Akkrum", "NL"], "ALBERT"=>["Albertville", "F"], "ALESS"=>["Alessandria", "I"], "AMR"=>["Alkmaar", "NL"], "AMRN"=>["Alkmaar Noord", "NL"], "AML"=>["Almelo", "NL"], "AMRI"=>["Almelo de Riet", "NL"], "ALMB"=>["Almere Buiten", "NL"], "ALM"=>["Almere C.", "NL"], "ALMM"=>["Muziekwijk", "NL"], "ALMO"=>["Oostvaarders", "NL"], "ALMP"=>["Parkwijk", "NL"], "AMPO"=>["Poort", "NL"], "APN"=>["Alphen a/d Rijn", "NL"], "EABG"=>["Altenberge", "D"], "AMF"=>["Amersfoort", "NL"], "AMFS"=>["Schothorst", "NL"]....
|
62
|
+
```
|
63
|
+
|
64
|
+
|
57
65
|
Retrieve disruptions
|
58
66
|
====================
|
59
67
|
```ruby
|
@@ -72,3 +80,59 @@ disruptions = client.disruptions "Amsterdam"
|
|
72
80
|
# will raise an NSClient::InvalidStationNameError error when station name is invalid
|
73
81
|
client.disruptions "bla" # NSClient::InvalidStationNameError: Could not find a station with name 'bla'
|
74
82
|
```
|
83
|
+
|
84
|
+
Retrieve prices
|
85
|
+
===============
|
86
|
+
Prices can be retrieved by using a valid ```from```,```to```,```via``` parameter. You can use the name of the station or the code. (as you can see above with the stations calls)
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
# retrieving prices requires a from and to at minimum. Which assumes prices for today
|
90
|
+
prices = client.prices from: "Amsterdam Centraal", to: "Purmerend"
|
91
|
+
|
92
|
+
# if you'd rather retrieve prices for a specific date, this is an optional parameter. If not given, today is assumed.
|
93
|
+
tomorrow = Date.today + 1.day
|
94
|
+
prices_tomorrow = client.prices from: "Amsterdam Centraal", to: "Purmerend", date: tomorrow
|
95
|
+
|
96
|
+
# you can specify a via option, this is also optional
|
97
|
+
prices_via = client.prices from: "Amsterdam Centraal", to: "Purmerend", via: "Zaandam"
|
98
|
+
|
99
|
+
# retrieve prices for tomorrow, via specific station
|
100
|
+
prices_via_tomorrow = client.prices from: "Amsterdam Centraal", to: "Purmerend", via: "Zaandam", date: tomorrow
|
101
|
+
|
102
|
+
# Using an invalid station name will result in a...
|
103
|
+
# NSClient::InvalidStationNameError: 'Amsterdam' is not a valid station name
|
104
|
+
prices = client.prices from: "Amsterdam", to "Purmerend"
|
105
|
+
|
106
|
+
```
|
107
|
+
|
108
|
+
Prices Response data
|
109
|
+
--------------------
|
110
|
+
A prices response is an object PricesResponse, which contains tariffunits (a measurement for cost-distance) and a hash with prices.
|
111
|
+
|
112
|
+
Each key in this hash is the type of prices (ie 'Dagretour', or 'Enkele reis').
|
113
|
+
|
114
|
+
In case different types would be added by the NS, than this API will simply add them to the hash, which makes it quite flexible.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
prices = client.prices from: "Amsterdam Centraal", to: "Purmerend"
|
118
|
+
|
119
|
+
# show tarif units (tariefeenheden)
|
120
|
+
prices.tariff_units # 10
|
121
|
+
|
122
|
+
# show prices for "Dagretour", easy method
|
123
|
+
dagretour_prices = prices.dagretour # is same as prices.products["Dagretour"]
|
124
|
+
|
125
|
+
# first price for "Dagretour", contains three values
|
126
|
+
dagretour_prices[0].type # vol tarief
|
127
|
+
dagretour_prices[0].train_class # "2"
|
128
|
+
dagretour_prices[0].amount # 2.40
|
129
|
+
|
130
|
+
# show prices for "Enkele reis", easy method
|
131
|
+
enkelereis_prices = prices.enkelereis
|
132
|
+
```
|
133
|
+
|
134
|
+
|
135
|
+
Copyright
|
136
|
+
---------
|
137
|
+
Copyright (c) 2013 Zilverline / Stefan Hendriks.
|
138
|
+
See [LICENSE](https://github.com/zilverline/ns-api/blob/master/LICENSE.mkd) for details.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class PricesUrl
|
2
|
+
|
3
|
+
def initialize(url)
|
4
|
+
raise InvalidURL, "You must give an url, ie http://www.ns.nl/api" unless url
|
5
|
+
@url = url
|
6
|
+
end
|
7
|
+
|
8
|
+
def url (opts = {date: nil, from: "", to: "", date: nil})
|
9
|
+
opts[:date] = opts[:date].strftime("%d%m%Y") if opts[:date]
|
10
|
+
uri = URI.escape(opts.collect{|k,v| "#{k}=#{v}"}.join('&'))
|
11
|
+
"#{@url}?#{uri}"
|
12
|
+
end
|
13
|
+
|
14
|
+
class InvalidURL < StandardError
|
15
|
+
end
|
16
|
+
end
|
data/lib/ns_client.rb
CHANGED
@@ -5,6 +5,8 @@ require 'nokogiri'
|
|
5
5
|
|
6
6
|
require 'httpclient'
|
7
7
|
|
8
|
+
require "addressable/uri"
|
9
|
+
|
8
10
|
this = Pathname.new(__FILE__).realpath
|
9
11
|
lib_path = File.expand_path("..", this)
|
10
12
|
$:.unshift(lib_path)
|
@@ -42,17 +44,61 @@ class NSClient
|
|
42
44
|
def initialize(username, password)
|
43
45
|
@client = HTTPClient.new
|
44
46
|
@client.set_auth("http://webservices.ns.nl", username, password)
|
47
|
+
@prices_url = PricesUrl.new("http://webservices.ns.nl/ns-api-prijzen-v2")
|
45
48
|
end
|
46
49
|
|
47
50
|
def stations
|
48
|
-
|
51
|
+
parse_stations(get_xml("http://webservices.ns.nl/ns-api-stations-v2"))
|
52
|
+
end
|
53
|
+
|
54
|
+
def stations_short
|
55
|
+
parse_stations_as_map(get_xml("http://webservices.ns.nl/ns-api-stations-v2"))
|
56
|
+
end
|
57
|
+
|
58
|
+
def disruptions (query = nil)
|
59
|
+
response_xml = get_xml(disruption_url(query))
|
60
|
+
raise_error_when_response_is_error(response_xml)
|
61
|
+
parse_disruptions(response_xml)
|
62
|
+
end
|
63
|
+
|
64
|
+
def prices (opts = {from: nil, to: nil, via: nil, date: nil})
|
65
|
+
raise MissingParameter, "from and to station is required" if (opts[:from] == nil && opts[:to] == nil)
|
66
|
+
raise MissingParameter, "from station is required" unless opts[:from]
|
67
|
+
raise MissingParameter, "to station is required" unless opts[:to]
|
68
|
+
response_xml = get_xml(@prices_url.url(opts))
|
69
|
+
raise_error_when_response_is_error(response_xml)
|
70
|
+
parse_prices(response_xml)
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_prices(response_xml)
|
74
|
+
prices_response = PricesResponse.new
|
75
|
+
(response_xml/'/Producten').each do |products|
|
76
|
+
prices_response.tariff_units = (products/'./Tariefeenheden').text.to_i
|
77
|
+
|
78
|
+
(products/'Product').each do |product|
|
79
|
+
prices = []
|
80
|
+
(product/'Prijs').each do |price_element|
|
81
|
+
product_price = ProductPrice.new
|
82
|
+
product_price.type = price_element.attr("korting")
|
83
|
+
product_price.train_class = price_element.attr("klasse")
|
84
|
+
product_price.amount = price_element.text.gsub(",", ".").to_f
|
85
|
+
prices << product_price
|
86
|
+
end
|
87
|
+
name = product.attr('naam')
|
88
|
+
prices_response.products[name] = prices
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
prices_response
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_stations(response_xml)
|
49
96
|
result = []
|
50
|
-
|
51
|
-
(xdoc/'/Stations/Station').each do |station|
|
97
|
+
(response_xml/'/Stations/Station').each do |station|
|
52
98
|
s = Station.new
|
53
99
|
s.code = (station/'./Code').text
|
54
100
|
s.type = (station/'./Type').text
|
55
|
-
s.
|
101
|
+
s.country = (station/'./Land').text
|
56
102
|
s.short_name = (station/'./Namen/Kort').text
|
57
103
|
s.name = (station/'./Namen/Middel').text
|
58
104
|
s.long_name = (station/'./Namen/Lang').text
|
@@ -64,18 +110,20 @@ class NSClient
|
|
64
110
|
result
|
65
111
|
end
|
66
112
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
raise InvalidStationNameError, message
|
113
|
+
def parse_stations_as_map(response_xml)
|
114
|
+
result = {}
|
115
|
+
(response_xml/'/Stations/Station').each do |station|
|
116
|
+
code = (station/'./Code').text
|
117
|
+
name = (station/'./Namen/Middel').text
|
118
|
+
country = (station/'./Land').text
|
119
|
+
result[code] = [name, country]
|
75
120
|
end
|
121
|
+
result
|
122
|
+
end
|
76
123
|
|
77
|
-
|
78
|
-
|
124
|
+
def parse_disruptions(response_xml)
|
125
|
+
result = {planned: [], unplanned: []}
|
126
|
+
(response_xml/'/Storingen').each do |disruption|
|
79
127
|
(disruption/'Ongepland/Storing').each do |unplanned|
|
80
128
|
unplanned_disruption = UnplannedDisruption.new
|
81
129
|
unplanned_disruption.id = (unplanned/'./id').text
|
@@ -101,34 +149,20 @@ class NSClient
|
|
101
149
|
result
|
102
150
|
end
|
103
151
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
prices_response = PricesResponse.new
|
109
|
-
(xdoc/'/Producten').each do |products|
|
110
|
-
prices_response.tariff_units = (products/'./Tariefeenheden').text.to_i
|
111
|
-
|
112
|
-
(products/'Product').each do |product|
|
113
|
-
prices = []
|
114
|
-
(product/'Prijs').each do |price_element|
|
115
|
-
product_price = ProductPrice.new
|
116
|
-
product_price.amount = price_element.text
|
117
|
-
prices << product_price
|
118
|
-
end
|
119
|
-
name = product.attr('naam')
|
120
|
-
prices_response.products[name] = prices
|
121
|
-
end
|
122
|
-
|
152
|
+
def raise_error_when_response_is_error(xdoc)
|
153
|
+
(xdoc/'/error').each do |error|
|
154
|
+
message = (error/'./message').text
|
155
|
+
raise InvalidStationNameError, message
|
123
156
|
end
|
124
|
-
prices_response
|
125
157
|
end
|
126
158
|
|
159
|
+
def get_xml(url)
|
160
|
+
response = @client.get url
|
161
|
+
Nokogiri.XML(response.content)
|
162
|
+
end
|
127
163
|
|
128
164
|
def disruption_url(query)
|
129
|
-
if query
|
130
|
-
return "http://webservices.ns.nl/ns-api-storingen?station=#{query}"
|
131
|
-
end
|
165
|
+
return "http://webservices.ns.nl/ns-api-storingen?station=#{query}" if query
|
132
166
|
"http://webservices.ns.nl/ns-api-storingen?actual=true"
|
133
167
|
end
|
134
168
|
|
@@ -139,10 +173,19 @@ class NSClient
|
|
139
173
|
@products = {}
|
140
174
|
@tariff_units = 0
|
141
175
|
end
|
176
|
+
|
177
|
+
def enkele_reis
|
178
|
+
products["Enkele reis"]
|
179
|
+
end
|
180
|
+
|
181
|
+
def dagretour
|
182
|
+
products["Dagretour"]
|
183
|
+
end
|
184
|
+
|
142
185
|
end
|
143
186
|
|
144
187
|
class ProductPrice
|
145
|
-
attr_accessor :
|
188
|
+
attr_accessor :type, :train_class, :amount
|
146
189
|
end
|
147
190
|
|
148
191
|
class UnplannedDisruption
|
@@ -154,11 +197,13 @@ class NSClient
|
|
154
197
|
end
|
155
198
|
|
156
199
|
class Station
|
157
|
-
attr_accessor :code, :type, :
|
200
|
+
attr_accessor :code, :type, :country, :short_name, :name, :long_name, :uiccode, :synonyms, :lat, :long
|
158
201
|
end
|
159
202
|
|
160
203
|
class InvalidStationNameError < StandardError
|
204
|
+
end
|
161
205
|
|
206
|
+
class MissingParameter < StandardError
|
162
207
|
end
|
163
208
|
|
164
209
|
end
|
data/ns.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
6
|
gem.name = "ns-yapi"
|
7
|
-
gem.version = '0.
|
7
|
+
gem.version = '0.3.0'
|
8
8
|
gem.authors = ["Stefan Hendriks"]
|
9
9
|
gem.email = ["stefanhen83@gmail.com"]
|
10
10
|
gem.description = %q{Yet Another (Ruby) NS API client}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PricesUrl do
|
4
|
+
|
5
|
+
it "takes a fixed url as constructor argument" do
|
6
|
+
PricesUrl.new("www.somehost.com")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "raises an error when no url is given" do
|
10
|
+
expect { PricesUrl.new(nil) }.to raise_error(PricesUrl::InvalidURL, "You must give an url, ie http://www.ns.nl/api")
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:prices_url) { PricesUrl.new("hostname") }
|
14
|
+
|
15
|
+
it "uses given date" do
|
16
|
+
prices_url.url(date: Date.new(2013, 7, 12)).should == "hostname?date=12072013"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "uses from" do
|
20
|
+
expected_from = "Amsterdam"
|
21
|
+
prices_url.url(from:"Amsterdam").should == "hostname?from=#{expected_from}"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "uses to" do
|
25
|
+
expected_to = "Purmerend"
|
26
|
+
prices_url.url(to:"Purmerend").should == "hostname?to=#{expected_to}"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "uses via" do
|
30
|
+
expected_via = "Zaandam"
|
31
|
+
prices_url.url(via:"Zaandam").should == "hostname?via=#{expected_via}"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "uses any all variables for from/to/via" do
|
35
|
+
prices_url.url(from:"Purmerend",to: "Amsterdam", via:"Zaandam").should == "hostname?from=Purmerend&to=Amsterdam&via=Zaandam"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "html encodes" do
|
39
|
+
prices_url.url(from:"Purmerend",to: "Amsterdam Centraal").should == "hostname?from=Purmerend&to=Amsterdam%20Centraal"
|
40
|
+
end
|
41
|
+
|
42
|
+
ANY_DATE = Date.new(2013, 8, 13)
|
43
|
+
ANY_DATE_STR = "13082013"
|
44
|
+
|
45
|
+
end
|
data/spec/ns_client_spec.rb
CHANGED
@@ -26,12 +26,19 @@ describe NSClient do
|
|
26
26
|
first_station.short_name.should == "H'bosch"
|
27
27
|
first_station.name.should == "'s-Hertogenbosch"
|
28
28
|
first_station.long_name.should == "'s-Hertogenbosch"
|
29
|
-
first_station.
|
29
|
+
first_station.country.should == "NL"
|
30
30
|
first_station.uiccode.should == "8400319"
|
31
31
|
first_station.lat.should == "51.69048"
|
32
32
|
first_station.long.should == "5.29362"
|
33
33
|
end
|
34
34
|
|
35
|
+
it "should retrieve a convenient hash with usable station names and codes for prices usage" do
|
36
|
+
stations = @client.stations_short
|
37
|
+
stations.size.should == 620
|
38
|
+
stations["HT"].should == ["'s-Hertogenbosch", "NL"]
|
39
|
+
end
|
40
|
+
|
41
|
+
|
35
42
|
end
|
36
43
|
|
37
44
|
context "Disruptions" do
|
@@ -105,6 +112,7 @@ describe NSClient do
|
|
105
112
|
end
|
106
113
|
|
107
114
|
context "Prices" do
|
115
|
+
|
108
116
|
it "should retrieve prices for a trip" do
|
109
117
|
stub_ns_client_request "http://username:password@webservices.ns.nl/ns-api-prijzen-v2?from=Purmerend&to=Amsterdam&via=Zaandam&date=17062013", load_fixture('prices.xml')
|
110
118
|
date = Date.strptime('17-06-2013', '%d-%m-%Y')
|
@@ -113,17 +121,58 @@ describe NSClient do
|
|
113
121
|
response.tariff_units.should == 10
|
114
122
|
response.products.size.should == 2
|
115
123
|
|
116
|
-
enkele_reis
|
117
|
-
|
124
|
+
response.enkele_reis.size.should == 6
|
125
|
+
response.dagretour.size.should == 6
|
118
126
|
end
|
119
127
|
|
120
|
-
|
128
|
+
it "should retrieve expected price data" do
|
129
|
+
stub_ns_client_request "http://username:password@webservices.ns.nl/ns-api-prijzen-v2?from=Purmerend&to=Amsterdam&via=Zaandam&date=17062013", load_fixture('prices.xml')
|
130
|
+
date = Date.strptime('17-06-2013', '%d-%m-%Y')
|
131
|
+
response = @client.prices from: "Purmerend", to: "Amsterdam", via: "Zaandam", date: date
|
132
|
+
response.class.should == NSClient::PricesResponse
|
133
|
+
response.tariff_units.should == 10
|
134
|
+
response.products.size.should == 2
|
121
135
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
136
|
+
assert_price(response.enkele_reis[0], "vol tarief", "2", 2.4)
|
137
|
+
assert_price(response.enkele_reis[1], "reductie_20", "2", 1.90)
|
138
|
+
assert_price(response.enkele_reis[2], "reductie_40", "2", 1.40)
|
139
|
+
assert_price(response.enkele_reis[3], "vol tarief", "1", 4.10)
|
140
|
+
assert_price(response.enkele_reis[4], "reductie_20", "1", 3.3)
|
141
|
+
assert_price(response.enkele_reis[5], "reductie_40", "1", 2.5)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should raise error when from is not given" do
|
145
|
+
expect {
|
146
|
+
@client.prices from: nil, to: "Amsterdam"
|
147
|
+
}.to raise_error(NSClient::MissingParameter, "from station is required")
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should raise an error when from is not a valid station name" do
|
151
|
+
date = Date.strptime('17-06-2013', '%d-%m-%Y')
|
152
|
+
stub_ns_client_request "http://username:password@webservices.ns.nl/ns-api-prijzen-v2?from=Amsterdam&to=Purmerend&date=17062013", load_fixture('prices_invalid_station_name.xml')
|
153
|
+
expect {
|
154
|
+
@client.prices from: "Amsterdam", to: "Purmerend", date: date
|
155
|
+
}.to raise_error(NSClient::InvalidStationNameError, "'Amsterdam' is not a valid station name")
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should raise error when to is not given" do
|
159
|
+
expect {
|
160
|
+
@client.prices from: "Purmerend", to: nil
|
161
|
+
}.to raise_error(NSClient::MissingParameter, "to station is required")
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should raise error complaining about from and to missing when both not given" do
|
165
|
+
expect {
|
166
|
+
@client.prices from: nil, to: nil
|
167
|
+
}.to raise_error(NSClient::MissingParameter, "from and to station is required")
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
126
171
|
|
172
|
+
def assert_price(element, expected_type, expected_train_class, expected_amount)
|
173
|
+
element.type.should == expected_type
|
174
|
+
element.train_class.should == expected_train_class
|
175
|
+
element.amount.should == expected_amount
|
127
176
|
end
|
128
177
|
|
129
178
|
def stub_ns_client_request(url, response)
|
data/spec/spec_helper.rb
CHANGED
@@ -4,22 +4,38 @@ SimpleCov.start
|
|
4
4
|
require 'coveralls'
|
5
5
|
Coveralls.wear!
|
6
6
|
|
7
|
+
|
7
8
|
require 'httpclient'
|
8
9
|
|
9
10
|
require 'mocha/api'
|
10
11
|
require 'webmock/rspec'
|
11
|
-
|
12
|
+
require 'timecop'
|
12
13
|
|
13
14
|
spec_helper = Pathname.new(__FILE__).realpath
|
14
15
|
lib_path = File.expand_path("../../lib", spec_helper)
|
15
16
|
$:.unshift(lib_path)
|
16
17
|
|
18
|
+
##############################################################
|
19
|
+
# Configure rspec
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.order = "random"
|
23
|
+
|
24
|
+
config.after(:each) do
|
25
|
+
Timecop.return # make sure timecop is disabled after each test
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
# END
|
31
|
+
##############################################################
|
17
32
|
$ROOT = File.expand_path("../", lib_path)
|
18
33
|
|
19
34
|
Dir.glob(File.join(lib_path, '/**/*.rb')).each do |file|
|
20
35
|
require file
|
21
36
|
end
|
22
37
|
|
38
|
+
# helper methods for easier testing
|
23
39
|
def load_fixture(filename)
|
24
40
|
File.read(File.join($ROOT, "spec/fixtures/#{filename}"))
|
25
41
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ns-yapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httpclient
|
@@ -71,7 +71,9 @@ files:
|
|
71
71
|
- .travis.yml
|
72
72
|
- Gemfile
|
73
73
|
- Gemfile.lock
|
74
|
+
- LICENSE.mkd
|
74
75
|
- README.md
|
76
|
+
- lib/model/prices_url.rb
|
75
77
|
- lib/ns_client.rb
|
76
78
|
- ns.gemspec
|
77
79
|
- rakefile.rb
|
@@ -80,7 +82,9 @@ files:
|
|
80
82
|
- spec/fixtures/disruptions_amsterdam.xml
|
81
83
|
- spec/fixtures/no_disruptions.xml
|
82
84
|
- spec/fixtures/prices.xml
|
85
|
+
- spec/fixtures/prices_invalid_station_name.xml
|
83
86
|
- spec/fixtures/stations.xml
|
87
|
+
- spec/model/prices_url_spec.rb
|
84
88
|
- spec/ns_client_spec.rb
|
85
89
|
- spec/nsyapi_spec.rb
|
86
90
|
- spec/spec_helper.rb
|
@@ -98,7 +102,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
102
|
version: '0'
|
99
103
|
segments:
|
100
104
|
- 0
|
101
|
-
hash: -
|
105
|
+
hash: -1397451197090581967
|
102
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
107
|
none: false
|
104
108
|
requirements:
|
@@ -107,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
111
|
version: '0'
|
108
112
|
segments:
|
109
113
|
- 0
|
110
|
-
hash: -
|
114
|
+
hash: -1397451197090581967
|
111
115
|
requirements: []
|
112
116
|
rubyforge_project:
|
113
117
|
rubygems_version: 1.8.24
|
@@ -120,7 +124,9 @@ test_files:
|
|
120
124
|
- spec/fixtures/disruptions_amsterdam.xml
|
121
125
|
- spec/fixtures/no_disruptions.xml
|
122
126
|
- spec/fixtures/prices.xml
|
127
|
+
- spec/fixtures/prices_invalid_station_name.xml
|
123
128
|
- spec/fixtures/stations.xml
|
129
|
+
- spec/model/prices_url_spec.rb
|
124
130
|
- spec/ns_client_spec.rb
|
125
131
|
- spec/nsyapi_spec.rb
|
126
132
|
- spec/spec_helper.rb
|