ierail 0.3.5 → 0.4.0

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.
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