ierail 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/ierail.gemspec CHANGED
@@ -2,7 +2,7 @@ require 'date'
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'ierail'
5
- s.version = '0.3.5'
5
+ s.version = '0.4.0'
6
6
  s.date = Date.today.to_s
7
7
  s.summary = "Irish Rail Train Schedule and Status API"
8
8
  s.description = "Irish Rail Train Schedule and Status API"
@@ -10,8 +10,11 @@ Gem::Specification.new do |s|
10
10
  s.email = 'oi.sin@nis.io'
11
11
  s.files = `git ls-files`.split("\n")
12
12
  s.homepage = 'http://rubygems.org/gems/ierail'
13
- s.add_runtime_dependency 'json', '~> 1.7', '>= 1.7.7'
13
+ s.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.1'
14
14
  s.add_runtime_dependency 'rest-client', '~> 1.6', '>= 1.6.7'
15
- s.add_runtime_dependency 'nokogiri', '~> 1.5', '>= 1.5.0'
16
- s.add_runtime_dependency 'tzinfo', '~> 0.3', '>= 0.3.37'
15
+ s.add_runtime_dependency 'nokogiri', '~> 1.6', '>= 1.6.1'
16
+ s.add_runtime_dependency 'tzinfo', '~> 1.1', '>= 1.1.0'
17
+ s.add_development_dependency 'vcr', '~> 2.9', '>= 2.9.0'
18
+ s.add_development_dependency 'webmock', '~> 1.17', '>= 1.17.4'
19
+ s.add_development_dependency 'timecop', '~> 0.6', '>= 0.6.2'
17
20
  end
data/lib/core_ext.rb CHANGED
@@ -2,21 +2,21 @@ class Array
2
2
  #Filters elements, collecting those
3
3
  #whose times are before _time_
4
4
  def before time
5
- select {|t| t.expdepart <= Time.parse(time) }
5
+ query_time = Time.parse(time)
6
+ select {|t| t.arrival[:expected] <= query_time }
6
7
  end
7
8
 
8
9
  #Filters elements, collecting those
9
10
  #whose times are after _time_
10
11
  def after time
11
- select {|t| t.expdepart >= Time.parse(time) }
12
+ query_time = Time.parse(time)
13
+ select {|t| t.arrival[:expected] >= query_time }
12
14
  end
13
15
 
14
16
  # The 'in' is just sugar really, saving the
15
17
  # programmer from doing a trivial computation
16
18
  # over and over again in their code.
17
19
  def in time
18
- select { |t|
19
- ((t.expdepart - t.query_time ) / 60) < time
20
- }
20
+ select { |t| t.due_in <= time }
21
21
  end
22
22
  end
data/lib/ierail.rb CHANGED
@@ -63,10 +63,10 @@ class IERail
63
63
  # Get ALL the stations!
64
64
  # Returns array of Station objects, and each object responds to
65
65
  # {
66
- # obj#name =>"Belfast Central",
67
- # obj#location =>["-5.91744", "54.6123"]
68
- # obj#code =>"BFSTC",
69
- # obj#id =>"228"
66
+ # obj#name => "Belfast Central",
67
+ # obj#location => [-5.91744, 54.6123]
68
+ # obj#code => "BFSTC",
69
+ # obj#id => 228
70
70
  # }
71
71
  # Returns empty array if no data, but that would be odd.
72
72
  #
@@ -79,12 +79,12 @@ class IERail
79
79
  # Get ALL the trains! That are on the go at the moment.
80
80
  # Returns array of Train objects, and each object responds to
81
81
  # {
82
- # obj#status =>"R",
83
- # obj#location =>["-6.23929, ""53.3509"]
84
- # obj#code =>"D303",
85
- # obj#date =>"20 Jan 2012",
86
- # obj#message =>"D303\\n09:30 - Docklands to M3 Parkway (1 mins late)\\nDeparted Docklands next stop Broombridge",
87
- # obj#direction =>"Northbound"
82
+ # obj#status => "R",
83
+ # obj#location => [-6.23929, 53.3509]
84
+ # obj#code => "D303",
85
+ # obj#date => 20 Jan 2012,
86
+ # obj#message => "D303\\n09:30 - Docklands to M3 Parkway (1 mins late)\\nDeparted Docklands next stop Broombridge",
87
+ # obj#direction => "Northbound"
88
88
  # }
89
89
  # Returns empty array if no data
90
90
  #
@@ -97,23 +97,26 @@ class IERail
97
97
  # Get train information for a particular station, by station name. This gives data on trains thru that station
98
98
  # Returns array of StationData objects, and each object responds to
99
99
  # {
100
- # obj#servertime =>"2012-01-20T10:03:33.777",
101
- # obj#traincode =>"E909",
102
- # obj#name / obj#station_name =>"Glenageary",
103
- # obj#code / obj#station_code =>"GLGRY",
104
- # obj#query_time =>"10:03:33",
105
- # obj#train_date =>"20 Jan 2012",
106
- # obj#origin => {:name => "Bray", :time => "09:55"}
107
- # obj#destination => {:name => "Howth", :time => "11:03"}
108
- # obj#status =>"En Route",
109
- # obj#last_location =>"Arrived Killiney",
110
- # obj#duein / obj#due_in =>"6",
111
- # obj#late =>"0",
112
- # obj#late? => 0 / 1
113
- # obj#arrival => {:scheduled => "10:09", :expected => "10:09"}
114
- # obj#departure => {:scheduled => "10:09", :expected => "10:09"}
100
+ # obj#server_time => 2012-01-20T10:03:33.777,
101
+ # obj#train_code => "E909",
102
+ # obj#name / obj#station_name => "Glenageary",
103
+ # obj#code / obj#station_code => "GLGRY",
104
+ # obj#query_time => 10:03:33,
105
+ # obj#train_date => 20 Jan 2012,
106
+ # obj#origin => {:name => "Bray", :time => 09:55}
107
+ # obj#destination => {:name => "Howth", :time => 11:03}
108
+ # obj#status => "En Route",
109
+ # obj#last_location => "Arrived Killiney",
110
+ # obj#due_in => 6,
111
+ # obj#minutes_early => 0,
112
+ # obj#minutes_late => 0,
113
+ # obj#on_time? => true / false,
114
+ # obj#early? => true / false,
115
+ # obj#late? => true / false,
116
+ # obj#arrival => {:scheduled => 10:09, :expected => 10:09}
117
+ # obj#departure => {:scheduled => 10:09, :expected => 10:09}
115
118
  # obj#direction => "Northbound",
116
- # obj#train_type => "DART",
119
+ # obj#train_type => "DART",
117
120
  # }
118
121
  # Returns empty array if no data.
119
122
  #
@@ -141,27 +144,25 @@ class IERail
141
144
  # Returns an array of TrainMovement objects, and each object responds to
142
145
  # {
143
146
  # obj#location => {code: "GLGRY", name: "Glenageary", stop_number: 1 (Stop number on route), type: "O" (Origin) \ "S" (Stop) \ "D" (Destination)}
144
- # obj#train => {:code => "E909", :date => "20 Jan 2012", :origin => "Glenageary"}
145
- # obj#arrival => {:scheduled => "10:09", :expected => "10:09", :actual => "10.09"}
146
- # obj#departure => {:scheduled => "10:09", :expected => "10:09", :actual => "10.09"}
147
+ # obj#train => {:code => "E909", :date => 20 Jan 2012, :origin => "Glenageary"}
148
+ # obj#arrival => {:scheduled => 10:09, :expected => 10:09, :actual => 10.09}
149
+ # obj#departure => {:scheduled => 10:09, :expected => 10:09, :actual => 10.09}
147
150
  # obj#station => "Glenageary"
148
151
  # }
152
+ # Returns empty array if no data.
149
153
  #
150
154
  def train_movements(code, date=Time.now)
151
155
  ier = IERailGet.new("getTrainMovementsXML?TrainId=#{code}&TrainDate=#{date.strftime("%d/%m/%Y")}", "ArrayOfObjTrainMovements", "ObjTrainMovements")
152
- retval = []
153
- ier.response.each do |tm|
154
- retval << TrainMovement.new(tm)
155
- end
156
- retval
156
+
157
+ ier.response.map{ |tm| TrainMovement.new(tm) }
157
158
  end
158
159
 
159
160
  # Find station codes and descriptions using a partial string to match the station name
160
161
  # Returns an array of Structs that each respond to
161
162
  # {
162
- # struct#name =>"Sandycove",
163
- # struct#description =>"Glasthule (Sandycove )",
164
- # struct#code =>"SCOVE"
163
+ # struct#name => "Sandycove",
164
+ # struct#description => "Glasthule (Sandycove)",
165
+ # struct#code => "SCOVE"
165
166
  # }
166
167
  # or an empty array if no matches.
167
168
  #
@@ -176,28 +177,9 @@ class IERail
176
177
  end
177
178
  end
178
179
 
179
- # Get direction-specific train information for a particular station, by station name.
180
+ # Get direction-specific train information for a particular station, by station name.
180
181
  # This gives data on trains through that station
181
- # Returns array of StationData objects, and each object responds to
182
- # {
183
- # obj#servertime =>"2012-01-20T10:03:33.777",
184
- # obj#traincode =>"E909",
185
- # obj#name / obj#station_name =>"Glenageary",
186
- # obj#code / obj#station_code =>"GLGRY",
187
- # obj#query_time =>"10:03:33",
188
- # obj#train_date =>"20 Jan 2012",
189
- # obj#origin => {:name => "Bray", :time => "09:55"}
190
- # obj#destination => {:name => "Howth", :time => "11:03"}
191
- # obj#status =>"En Route",
192
- # obj#last_location =>"Arrived Killiney",
193
- # obj#duein / obj#due_in =>"6",
194
- # obj#late =>"0",
195
- # obj#late? => 0 / 1
196
- # obj#arrival => {:scheduled => "10:09", :expected => "10:09"}
197
- # obj#departure => {:scheduled => "10:09", :expected => "10:09"}
198
- # obj#direction => "Northbound",
199
- # obj#train_type => "DART",
200
- # }
182
+ # Returns array of StationData objects, and each obj looks like the one for IERail#station
201
183
  # Returns empty array if no data.
202
184
  #
203
185
 
data/lib/station.rb CHANGED
@@ -3,10 +3,10 @@ class Station
3
3
 
4
4
  def initialize hash
5
5
  @description = hash['StationDesc']
6
- @latitude = hash['StationLatitude']
7
- @longitude = hash['StationLongitude']
6
+ @latitude = hash['StationLatitude'].to_f
7
+ @longitude = hash['StationLongitude'].to_f
8
8
  @code = hash['StationCode']
9
- @id = hash['StationId']
9
+ @id = hash['StationId'].to_i
10
10
  end
11
11
 
12
12
  def location
data/lib/station_data.rb CHANGED
@@ -1,38 +1,44 @@
1
1
  class StationData
2
- attr_reader :servertime, :traincode, :station_name, :station_code,
3
- :status, :last_location, :duein, :late,
4
- :train_type, :direction, :query_time, :train_date, :expdepart
2
+ attr_reader :server_time, :train_code, :station_name, :station_code,
3
+ :status, :last_location, :due_in, :minutes_late, :minutes_early,
4
+ :train_type, :direction, :query_time, :train_date, :expected_departure,
5
+ :expected_arrival, :scheduled_arrival, :scheduled_departure
5
6
 
6
7
  def initialize hash
7
- @servertime = hash['Servertime']
8
- @traincode = hash['Traincode']
9
- @station_name = hash['Stationfullname']
10
- @station_code = hash['Stationcode']
11
- @query_time = Time.parse(hash['Querytime'])
12
- @train_date = hash['Traindate']
13
- @origin = hash['Origin']
14
- @destination = hash['Destination']
15
- @origin_time = Time.parse hash['Origintime']
16
- @destination_time = Time.parse hash['Destinationtime']
17
- @status = hash['Status']
18
- @last_location = hash['Lastlocation']
19
- @duein = hash['Duein']
20
- @late = hash['Late']
21
-
8
+ @server_time = Time.parse hash['Servertime']
9
+ @train_code = hash['Traincode']
10
+ @station_name = hash['Stationfullname']
11
+ @station_code = hash['Stationcode']
12
+ @query_time = Time.parse hash['Querytime']
13
+ @train_date = Date.parse hash['Traindate']
14
+ @origin = hash['Origin']
15
+ @destination = hash['Destination']
16
+ @origin_time = Time.parse hash['Origintime']
17
+ @destination_time = Time.parse hash['Destinationtime']
18
+ @status = hash['Status']
19
+ @last_location = hash['Lastlocation']
20
+ @due_in = hash['Duein'].to_i
21
+
22
+ # Though IE give a late value, this really represents difference from scheduled arrival
23
+ # and therefore represents the number of minutes that the train is off-schedule where
24
+ # <0: early, 0: on time and >0: late
25
+
26
+ off_schedule_minutes = hash['Late'].to_i
27
+ @minutes_late = off_schedule_minutes > 0 ? off_schedule_minutes : 0
28
+ @minutes_early = off_schedule_minutes < 0 ? -off_schedule_minutes : 0
29
+
22
30
  # If train origin is station_name, then arrival times will be 00:00, so are adjusted to suit expected origin time.
23
31
  # Likewise if destination is station_name, departure times should suit expected destination time.
24
32
  # See: http://api.irishrail.ie/realtime/ Point 8
25
- is_departure_station = @station_name.eql?(@origin)
26
- is_terminating_station = @station_name.eql?(@destination)
27
-
28
- @exparrival = is_departure_station ? @origin_time : Time.parse(hash['Exparrival'])
29
- @expdepart = is_terminating_station ? @destination_time : Time.parse(hash['Expdepart'])
30
- @scharrival = is_departure_station ? @origin_time + @late.to_i : Time.parse(hash['Scharrival'])
31
- @schdepart = is_terminating_station ? @destination_time + @late.to_i : Time.parse(hash['Schdepart'])
32
- @direction = hash['Direction']
33
- @train_type = hash['Traintype']
34
-
35
-
33
+ is_departure_station = @station_name.eql?(@origin)
34
+ is_terminating_station = @station_name.eql?(@destination)
35
+
36
+ @expected_arrival = is_departure_station ? @origin_time : Time.parse(hash['Exparrival'])
37
+ @expected_departure = is_terminating_station ? @destination_time : Time.parse(hash['Expdepart'])
38
+ @scheduled_arrival = is_departure_station ? @origin_time + off_schedule_minutes : Time.parse(hash['Scharrival'])
39
+ @scheduled_departure = is_terminating_station ? @destination_time + off_schedule_minutes : Time.parse(hash['Schdepart'])
40
+ @direction = hash['Direction']
41
+ @train_type = hash['Traintype']
36
42
  end
37
43
 
38
44
  def origin
@@ -44,18 +50,25 @@ class StationData
44
50
  end
45
51
 
46
52
  def arrival
47
- {scheduled: @scharrival, expected: @exparrival}
53
+ {scheduled: @scheduled_arrival, expected: @expected_arrival}
48
54
  end
49
55
 
50
56
  def departure
51
- {scheduled: @schdepart, expected: @expdepart}
57
+ {scheduled: @scheduled_departure, expected: @expected_departure}
52
58
  end
53
59
 
54
60
  def late?
55
- @late.to_i > 0
61
+ @minutes_late > 0
62
+ end
63
+
64
+ def early?
65
+ @minutes_early > 0
66
+ end
67
+
68
+ def on_time?
69
+ !late? && !early?
56
70
  end
57
71
 
58
72
  alias :name :station_name
59
73
  alias :code :station_code
60
- alias :due_in :duein
61
74
  end
data/lib/train.rb CHANGED
@@ -3,10 +3,10 @@ class Train
3
3
 
4
4
  def initialize hash
5
5
  @status = hash['TrainStatus']
6
- @longitude = hash['TrainLongitude']
7
- @latitude = hash['TrainLatitude']
6
+ @longitude = hash['TrainLongitude'].to_f
7
+ @latitude = hash['TrainLatitude'].to_f
8
8
  @code = hash['TrainCode']
9
- @date = hash['TrainDate']
9
+ @date = Date.parse hash['TrainDate']
10
10
  @message = hash['PublicMessage']
11
11
  @direction = hash['Direction']
12
12
  end
data/test/unit/helper.rb CHANGED
@@ -1,5 +1,24 @@
1
1
  require 'simplecov'
2
2
  require 'coveralls'
3
+ require 'tzinfo'
4
+ require 'vcr'
5
+ require 'timecop'
6
+ require 'time'
7
+ require 'minitest/autorun'
8
+ require 'ierail'
9
+
10
+ def get_original_time(t)
11
+ @when = Time.parse(t.to_s)
12
+ if TZInfo::Timezone.get('Europe/Dublin').current_period.dst?
13
+ unless @when.zone == 'IST'
14
+ @when -= @when.utc_offset - 3600
15
+ end
16
+ else
17
+ @when -= @when.utc_offset
18
+ end
19
+
20
+ @when
21
+ end
3
22
 
4
23
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
24
  SimpleCov::Formatter::HTMLFormatter,
data/test/unit/ierail.rb CHANGED
@@ -2,63 +2,150 @@ $:.unshift(File.join(File.dirname(__FILE__), '..','..', 'lib'))
2
2
 
3
3
  require_relative 'helper'
4
4
 
5
- require 'minitest/autorun'
6
- require 'ierail'
7
- require 'tzinfo'
8
-
9
5
  class IERailTest < MiniTest::Unit::TestCase
10
6
  def setup
11
7
  @ir = IERail.new
12
8
 
13
- @now = Time.now
14
-
15
- if TZInfo::Timezone.get('Europe/Dublin').current_period.dst?
16
- unless @now.zone == 'IST'
17
- @now -= @now.utc_offset - 3600
18
- end
19
- else
20
- @now -= @now.utc_offset
9
+ VCR.configure do |c|
10
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
11
+ c.hook_into :webmock
21
12
  end
22
13
  end
23
14
 
24
15
  def test_that_the_train_directions_are_correct
25
- northbound_train = @ir.northbound_from('Howth Junction').sample
26
- southbound_train = @ir.southbound_from('Clongriffin').sample
27
- assert_equal northbound_train.direction, 'Northbound'
28
- assert_equal southbound_train.direction, 'Southbound'
16
+ VCR.use_cassette('northbound') do |cassette|
17
+ time = get_original_time(cassette.originally_recorded_at)
18
+
19
+ Timecop.freeze(time || Time.now) do
20
+ northbound_train = @ir.northbound_from('Dublin Connolly').sample
21
+ assert_equal northbound_train.direction, 'Northbound'
22
+ end
23
+ end
24
+ VCR.use_cassette('northbound') do |cassette|
25
+ time = get_original_time(cassette.originally_recorded_at)
26
+
27
+ Timecop.freeze(time || Time.now) do
28
+ southbound_train = @ir.southbound_from('Dublin Connolly').sample
29
+ assert_equal southbound_train.direction, 'Southbound'
30
+ end
31
+ end
29
32
  end
30
33
 
31
34
  def test_that_an_empty_array_is_returned_when_no_data
32
- nonexistant = @ir.westbound_from('Clongriffin')
33
- assert_empty nonexistant
35
+ VCR.use_cassette('westbound') do |cassette|
36
+ time = get_original_time(cassette.originally_recorded_at)
37
+
38
+ Timecop.freeze(time || Time.now) do
39
+ nonexistant = @ir.westbound_from('Clongriffin')
40
+ assert_empty nonexistant
41
+ end
42
+ end
34
43
  end
35
44
 
36
45
  def test_that_the_before_time_constraint_works
37
- #Thirty minutes from now
38
- thirty_mins = @now + (60 * 30)
39
- time = "#{thirty_mins.hour}:#{thirty_mins.min}" # "HH:MM"
40
- before_train = @ir.southbound_from('Dublin Connolly').before(time).sample
41
- assert before_train.expdepart <= thirty_mins
46
+ VCR.use_cassette('northbound') do |cassette|
47
+ time = get_original_time(cassette.originally_recorded_at)
48
+
49
+ Timecop.freeze(time || Time.now) do
50
+ #Thirty minutes from now
51
+ thirty_mins = Time.now + (60 * 30)
52
+ time = "#{thirty_mins.hour}:#{thirty_mins.min}" # "HH:MM"
53
+ before_train = @ir.southbound_from('Dublin Connolly').before(time).sample
54
+ assert before_train.expected_departure <= thirty_mins
55
+ end
56
+ end
42
57
  end
43
58
 
44
59
  def test_that_the_after_time_constraint_works
45
- #Thirty minutes from now
46
- thirty_mins = @now + (60 * 30)
47
- time = "#{thirty_mins.hour}:#{thirty_mins.min}" # "HH:MM"
48
- after_train = @ir.southbound_from('Dublin Connolly').after(time).sample
49
- assert after_train.expdepart >= thirty_mins
60
+ VCR.use_cassette('southbound') do |cassette|
61
+ time = get_original_time(cassette.originally_recorded_at)
62
+
63
+ Timecop.freeze(time || Time.now) do
64
+ #Thirty minutes from now
65
+ thirty_mins = Time.now + (60 * 30)
66
+ time = "#{thirty_mins.hour}:#{thirty_mins.min}" # "HH:MM"
67
+ after_train = @ir.southbound_from('Dublin Connolly').after(time).sample
68
+ assert after_train.expected_departure >= thirty_mins
69
+ end
70
+ end
50
71
  end
51
72
 
52
73
  def test_that_the_in_constraint_works
53
- mins = 30
54
- thirty_mins = @now + (60 * mins)
55
- time = "#{thirty_mins.hour}:#{thirty_mins.min}" # "HH:MM"
56
- before_train = @ir.southbound_from('Malahide').before(time)
57
-
58
- in_half_an_hour = @ir.southbound_from('Malahide').in(mins)
59
- assert_equal before_train.count, in_half_an_hour.count
60
- before_train.each_with_index { |b,i|
61
- assert_equal b.traincode, in_half_an_hour[i].traincode
62
- }
74
+ VCR.use_cassette('southbound_from') do |cassette|
75
+ time = get_original_time(cassette.originally_recorded_at)
76
+
77
+ Timecop.freeze(time || Time.now) do
78
+ mins = 30
79
+ thirty_mins = Time.now + (60 * mins)
80
+ time = "#{thirty_mins.hour}:#{thirty_mins.min}" # "HH:MM"
81
+ southbounds = @ir.southbound_from('Dublin Connolly')
82
+
83
+ before_train = southbounds.before(time)
84
+
85
+ in_half_an_hour = southbounds.in(mins)
86
+ assert_equal before_train.count, in_half_an_hour.count
87
+ before_train.each_with_index { |b,i|
88
+ assert_equal b.train_code, in_half_an_hour[i].train_code
89
+ }
90
+ end
91
+ end
92
+ end
93
+
94
+ def test_station_times
95
+ VCR.use_cassette('station_times') do |cassette|
96
+ time = get_original_time(cassette.originally_recorded_at)
97
+
98
+ Timecop.freeze(time || Time.now) do
99
+ station_data = @ir.station_times('Dublin Connolly',30).sample
100
+ assert_instance_of StationData, station_data
101
+ end
102
+ end
103
+ end
104
+
105
+ def test_find_station
106
+ VCR.use_cassette('find_station') do |cassette|
107
+ time = get_original_time(cassette.originally_recorded_at)
108
+
109
+ Timecop.freeze(time || Time.now) do
110
+ station = @ir.find_station('Dublin Connolly').sample
111
+ assert_instance_of Struct::Station, station
112
+ end
113
+ end
114
+ end
115
+
116
+ def test_that_station_times_returns_station_data
117
+ VCR.use_cassette('station_times') do |cassette|
118
+ time = get_original_time(cassette.originally_recorded_at)
119
+
120
+ Timecop.freeze(time || Time.now) do
121
+ train = @ir.station_times('Dublin Connolly', 30).sample #random train in next 30 mins
122
+ assert_equal train.class, StationData #StationData has already been tested
123
+ end
124
+ end
125
+ end
126
+
127
+ def test_that_station_times_equivalent_to_in
128
+ VCR.use_cassette('station_times') do |cassette|
129
+ trains = @ir.station_times('Dublin Connolly', 30)
130
+
131
+ VCR.use_cassette('station') do |cassette|
132
+ in_half_an_hour = @ir.station('Dublin Connolly').in(30)
133
+
134
+ assert_equal trains.count, in_half_an_hour.count
135
+ trains_codes = trains.map {|t| t.train_code}
136
+ half_hour_train_codes = in_half_an_hour.map {|t| t.train_code}
137
+ assert_equal trains_codes, half_hour_train_codes
138
+ end
139
+ end
140
+ end
141
+
142
+ def test_that_found_station_is_a_struct_with_name_description_code
143
+ VCR.use_cassette('find_station') do |cassette|
144
+ station = @ir.find_station('Dublin Connolly').sample
145
+ assert_equal station.class, Struct::Station
146
+ refute_nil station.name
147
+ refute_nil station.description
148
+ refute_nil station.code
149
+ end
63
150
  end
64
151
  end