network_rail 0.0.1.alpha

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 (33) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +88 -0
  6. data/Rakefile +5 -0
  7. data/lib/network_rail/client.rb +64 -0
  8. data/lib/network_rail/configuration.rb +25 -0
  9. data/lib/network_rail/exception/authentication_error.rb +6 -0
  10. data/lib/network_rail/exception/block_required.rb +6 -0
  11. data/lib/network_rail/exception/connection_error.rb +6 -0
  12. data/lib/network_rail/exception/no_login_credentials.rb +6 -0
  13. data/lib/network_rail/message/train_movement/activation.rb +10 -0
  14. data/lib/network_rail/message/train_movement/arrival.rb +10 -0
  15. data/lib/network_rail/message/train_movement/base.rb +18 -0
  16. data/lib/network_rail/message/train_movement/cancellation.rb +10 -0
  17. data/lib/network_rail/message/train_movement/change_of_identity.rb +10 -0
  18. data/lib/network_rail/message/train_movement/change_of_origin.rb +10 -0
  19. data/lib/network_rail/message/train_movement/departure.rb +10 -0
  20. data/lib/network_rail/message/train_movement/movement.rb +37 -0
  21. data/lib/network_rail/message/train_movement/reinstatement.rb +10 -0
  22. data/lib/network_rail/message/train_movement.rb +31 -0
  23. data/lib/network_rail/operators.rb +82 -0
  24. data/lib/network_rail/version.rb +3 -0
  25. data/lib/network_rail.rb +9 -0
  26. data/network_rail.gemspec +28 -0
  27. data/spec/fixtures/train_movements.json +412 -0
  28. data/spec/network_rail/client_spec.rb +137 -0
  29. data/spec/network_rail/message/train_movement/base_spec.rb +21 -0
  30. data/spec/network_rail/message/train_movement/movement_spec.rb +69 -0
  31. data/spec/network_rail/message/train_movement_spec.rb +25 -0
  32. data/spec/spec_helper.rb +10 -0
  33. metadata +161 -0
@@ -0,0 +1,412 @@
1
+ [
2
+ {
3
+ "header":{
4
+ "msg_type":"0003",
5
+ "source_dev_id":"",
6
+ "user_id":"",
7
+ "original_data_source":"SMART",
8
+ "msg_queue_timestamp":"1364295570000",
9
+ "source_system_id":"TRUST"
10
+ },
11
+ "body":{
12
+ "event_type":"ARRIVAL",
13
+ "gbtt_timestamp":"",
14
+ "original_loc_stanox":"",
15
+ "planned_timestamp":"1364295630000",
16
+ "timetable_variation":"0",
17
+ "original_loc_timestamp":"",
18
+ "current_train_id":"",
19
+ "delay_monitoring_point":"true",
20
+ "next_report_run_time":"1",
21
+ "reporting_stanox":"87171",
22
+ "actual_timestamp":"1364295600000",
23
+ "correction_ind":"false",
24
+ "event_source":"AUTOMATIC",
25
+ "train_file_address":null,
26
+ "platform":"",
27
+ "division_code":"84",
28
+ "train_terminated":"false",
29
+ "train_id":"821L30ME26",
30
+ "offroute_ind":"false",
31
+ "variation_status":"ON TIME",
32
+ "train_service_code":"24623104",
33
+ "toc_id":"84",
34
+ "loc_stanox":"87171",
35
+ "auto_expected":"true",
36
+ "direction_ind":"",
37
+ "route":"0",
38
+ "planned_event_type":"ARRIVAL",
39
+ "next_report_stanox":"87169",
40
+ "line_ind":""
41
+ }
42
+ },
43
+ {
44
+ "header":{
45
+ "msg_type":"0003",
46
+ "source_dev_id":"",
47
+ "user_id":"",
48
+ "original_data_source":"SMART",
49
+ "msg_queue_timestamp":"1364295571000",
50
+ "source_system_id":"TRUST"
51
+ },
52
+ "body":{
53
+ "event_type":"DEPARTURE",
54
+ "gbtt_timestamp":"1364295540000",
55
+ "original_loc_stanox":"",
56
+ "planned_timestamp":"1364295540000",
57
+ "timetable_variation":"0",
58
+ "original_loc_timestamp":"",
59
+ "current_train_id":"",
60
+ "delay_monitoring_point":"true",
61
+ "next_report_run_time":"14",
62
+ "reporting_stanox":"86921",
63
+ "actual_timestamp":"1364295540000",
64
+ "correction_ind":"false",
65
+ "event_source":"AUTOMATIC",
66
+ "train_file_address":null,
67
+ "platform":" 2",
68
+ "division_code":"84",
69
+ "train_terminated":"false",
70
+ "train_id":"861W12MG26",
71
+ "offroute_ind":"false",
72
+ "variation_status":"ON TIME",
73
+ "train_service_code":"24620104",
74
+ "toc_id":"84",
75
+ "loc_stanox":"86921",
76
+ "auto_expected":"true",
77
+ "direction_ind":"UP",
78
+ "route":"2",
79
+ "planned_event_type":"DEPARTURE",
80
+ "next_report_stanox":"86901",
81
+ "line_ind":""
82
+ }
83
+ },
84
+ {
85
+ "header":{
86
+ "msg_type":"0003",
87
+ "source_dev_id":"",
88
+ "user_id":"",
89
+ "original_data_source":"SMART",
90
+ "msg_queue_timestamp":"1364295572000",
91
+ "source_system_id":"TRUST"
92
+ },
93
+ "body":{
94
+ "event_type":"ARRIVAL",
95
+ "gbtt_timestamp":"1364295660000",
96
+ "original_loc_stanox":"",
97
+ "planned_timestamp":"1364295690000",
98
+ "timetable_variation":"2",
99
+ "original_loc_timestamp":"",
100
+ "current_train_id":"",
101
+ "delay_monitoring_point":"true",
102
+ "next_report_run_time":"6",
103
+ "reporting_stanox":"87214",
104
+ "actual_timestamp":"1364295540000",
105
+ "correction_ind":"false",
106
+ "event_source":"AUTOMATIC",
107
+ "train_file_address":null,
108
+ "platform":"",
109
+ "division_code":"84",
110
+ "train_terminated":"false",
111
+ "train_id":"875Y29MH26",
112
+ "offroute_ind":"false",
113
+ "variation_status":"EARLY",
114
+ "train_service_code":"24676004",
115
+ "toc_id":"84",
116
+ "loc_stanox":"87214",
117
+ "auto_expected":"true",
118
+ "direction_ind":"DOWN",
119
+ "route":"0",
120
+ "planned_event_type":"ARRIVAL",
121
+ "next_report_stanox":"87215",
122
+ "line_ind":""
123
+ }
124
+ },
125
+ {
126
+ "header":{
127
+ "msg_type":"0003",
128
+ "source_dev_id":"",
129
+ "user_id":"",
130
+ "original_data_source":"SMART",
131
+ "msg_queue_timestamp":"1364295574000",
132
+ "source_system_id":"TRUST"
133
+ },
134
+ "body":{
135
+ "event_type":"DEPARTURE",
136
+ "gbtt_timestamp":"1364295000000",
137
+ "original_loc_stanox":"",
138
+ "planned_timestamp":"1364295030000",
139
+ "timetable_variation":"9",
140
+ "original_loc_timestamp":"",
141
+ "current_train_id":"",
142
+ "delay_monitoring_point":"true",
143
+ "next_report_run_time":"4",
144
+ "reporting_stanox":"86341",
145
+ "actual_timestamp":"1364295540000",
146
+ "correction_ind":"false",
147
+ "event_source":"AUTOMATIC",
148
+ "train_file_address":null,
149
+ "platform":" 2",
150
+ "division_code":"84",
151
+ "train_terminated":"false",
152
+ "train_id":"871P23MF26",
153
+ "offroute_ind":"false",
154
+ "variation_status":"LATE",
155
+ "train_service_code":"24621104",
156
+ "toc_id":"84",
157
+ "loc_stanox":"86341",
158
+ "auto_expected":"true",
159
+ "direction_ind":"DOWN",
160
+ "route":"1",
161
+ "planned_event_type":"DEPARTURE",
162
+ "next_report_stanox":"86334",
163
+ "line_ind":""
164
+ }
165
+ },
166
+ {
167
+ "header":{
168
+ "msg_type":"0003",
169
+ "source_dev_id":"",
170
+ "user_id":"",
171
+ "original_data_source":"SMART",
172
+ "msg_queue_timestamp":"1364295574000",
173
+ "source_system_id":"TRUST"
174
+ },
175
+ "body":{
176
+ "event_type":"DEPARTURE",
177
+ "gbtt_timestamp":"1364295540000",
178
+ "original_loc_stanox":"",
179
+ "planned_timestamp":"1364295540000",
180
+ "timetable_variation":"0",
181
+ "original_loc_timestamp":"",
182
+ "current_train_id":"",
183
+ "delay_monitoring_point":"true",
184
+ "next_report_run_time":"3",
185
+ "reporting_stanox":"86311",
186
+ "actual_timestamp":"1364295540000",
187
+ "correction_ind":"false",
188
+ "event_source":"AUTOMATIC",
189
+ "train_file_address":null,
190
+ "platform":" 3",
191
+ "division_code":"84",
192
+ "train_terminated":"false",
193
+ "train_id":"861T38MH26",
194
+ "offroute_ind":"false",
195
+ "variation_status":"ON TIME",
196
+ "train_service_code":"24631204",
197
+ "toc_id":"84",
198
+ "loc_stanox":"86311",
199
+ "auto_expected":"true",
200
+ "direction_ind":"UP",
201
+ "route":"2",
202
+ "planned_event_type":"DEPARTURE",
203
+ "next_report_stanox":"86313",
204
+ "line_ind":"M"
205
+ }
206
+ },
207
+ {
208
+ "header":{
209
+ "msg_type":"0003",
210
+ "source_dev_id":"",
211
+ "user_id":"",
212
+ "original_data_source":"SMART",
213
+ "msg_queue_timestamp":"1364295575000",
214
+ "source_system_id":"TRUST"
215
+ },
216
+ "body":{
217
+ "event_type":"ARRIVAL",
218
+ "gbtt_timestamp":"1364295660000",
219
+ "original_loc_stanox":"",
220
+ "planned_timestamp":"1364295660000",
221
+ "timetable_variation":"1",
222
+ "original_loc_timestamp":"",
223
+ "current_train_id":"",
224
+ "delay_monitoring_point":"true",
225
+ "next_report_run_time":"2",
226
+ "reporting_stanox":"87135",
227
+ "actual_timestamp":"1364295600000",
228
+ "correction_ind":"false",
229
+ "event_source":"AUTOMATIC",
230
+ "train_file_address":null,
231
+ "platform":" 2",
232
+ "division_code":"84",
233
+ "train_terminated":"false",
234
+ "train_id":"742C94MF26",
235
+ "offroute_ind":"false",
236
+ "variation_status":"EARLY",
237
+ "train_service_code":"24672104",
238
+ "toc_id":"84",
239
+ "loc_stanox":"87135",
240
+ "auto_expected":"true",
241
+ "direction_ind":"UP",
242
+ "route":"0",
243
+ "planned_event_type":"ARRIVAL",
244
+ "next_report_stanox":"87149",
245
+ "line_ind":""
246
+ }
247
+ },
248
+ {
249
+ "header":{
250
+ "msg_type":"0003",
251
+ "source_dev_id":"",
252
+ "user_id":"",
253
+ "original_data_source":"SMART",
254
+ "msg_queue_timestamp":"1364295577000",
255
+ "source_system_id":"TRUST"
256
+ },
257
+ "body":{
258
+ "event_type":"ARRIVAL",
259
+ "gbtt_timestamp":"1364295540000",
260
+ "original_loc_stanox":"",
261
+ "planned_timestamp":"1364295510000",
262
+ "timetable_variation":"2",
263
+ "original_loc_timestamp":"",
264
+ "current_train_id":"",
265
+ "delay_monitoring_point":"true",
266
+ "next_report_run_time":"1",
267
+ "reporting_stanox":"87121",
268
+ "actual_timestamp":"1364295600000",
269
+ "correction_ind":"false",
270
+ "event_source":"AUTOMATIC",
271
+ "train_file_address":null,
272
+ "platform":" 2",
273
+ "division_code":"84",
274
+ "train_terminated":"false",
275
+ "train_id":"872U25MG26",
276
+ "offroute_ind":"false",
277
+ "variation_status":"LATE",
278
+ "train_service_code":"24671105",
279
+ "toc_id":"84",
280
+ "loc_stanox":"87121",
281
+ "auto_expected":"true",
282
+ "direction_ind":"DOWN",
283
+ "route":"0",
284
+ "planned_event_type":"ARRIVAL",
285
+ "next_report_stanox":"87117",
286
+ "line_ind":""
287
+ }
288
+ },
289
+ {
290
+ "header":{
291
+ "msg_type":"0003",
292
+ "source_dev_id":"",
293
+ "user_id":"",
294
+ "original_data_source":"SMART",
295
+ "msg_queue_timestamp":"1364295579000",
296
+ "source_system_id":"TRUST"
297
+ },
298
+ "body":{
299
+ "event_type":"ARRIVAL",
300
+ "gbtt_timestamp":"1364295780000",
301
+ "original_loc_stanox":"",
302
+ "planned_timestamp":"1364295750000",
303
+ "timetable_variation":"2",
304
+ "original_loc_timestamp":"",
305
+ "current_train_id":"",
306
+ "delay_monitoring_point":"true",
307
+ "next_report_run_time":"3",
308
+ "reporting_stanox":"86042",
309
+ "actual_timestamp":"1364295600000",
310
+ "correction_ind":"false",
311
+ "event_source":"AUTOMATIC",
312
+ "train_file_address":null,
313
+ "platform":"",
314
+ "division_code":"84",
315
+ "train_terminated":"false",
316
+ "train_id":"872L25MG26",
317
+ "offroute_ind":"false",
318
+ "variation_status":"EARLY",
319
+ "train_service_code":"24629204",
320
+ "toc_id":"84",
321
+ "loc_stanox":"86042",
322
+ "auto_expected":"true",
323
+ "direction_ind":"DOWN",
324
+ "route":"0",
325
+ "planned_event_type":"ARRIVAL",
326
+ "next_report_stanox":"86045",
327
+ "line_ind":"S"
328
+ }
329
+ },
330
+ {
331
+ "header":{
332
+ "msg_type":"0003",
333
+ "source_dev_id":"",
334
+ "user_id":"",
335
+ "original_data_source":"SMART",
336
+ "msg_queue_timestamp":"1364295579000",
337
+ "source_system_id":"TRUST"
338
+ },
339
+ "body":{
340
+ "event_type":"DEPARTURE",
341
+ "gbtt_timestamp":"",
342
+ "original_loc_stanox":"",
343
+ "planned_timestamp":"1364295600000",
344
+ "timetable_variation":"1",
345
+ "original_loc_timestamp":"",
346
+ "current_train_id":"",
347
+ "delay_monitoring_point":"false",
348
+ "next_report_run_time":"1",
349
+ "reporting_stanox":"00000",
350
+ "actual_timestamp":"1364295540000",
351
+ "correction_ind":"false",
352
+ "event_source":"AUTOMATIC",
353
+ "train_file_address":null,
354
+ "platform":"",
355
+ "division_code":"84",
356
+ "train_terminated":"false",
357
+ "train_id":"871T21ME26",
358
+ "offroute_ind":"false",
359
+ "variation_status":"EARLY",
360
+ "train_service_code":"24629204",
361
+ "toc_id":"84",
362
+ "loc_stanox":"86302",
363
+ "auto_expected":"true",
364
+ "direction_ind":"DOWN",
365
+ "route":"1",
366
+ "planned_event_type":"DEPARTURE",
367
+ "next_report_stanox":"86333",
368
+ "line_ind":""
369
+ }
370
+ },
371
+ {
372
+ "header":{
373
+ "msg_type":"0003",
374
+ "source_dev_id":"",
375
+ "user_id":"",
376
+ "original_data_source":"SMART",
377
+ "msg_queue_timestamp":"1364295580000",
378
+ "source_system_id":"TRUST"
379
+ },
380
+ "body":{
381
+ "event_type":"DEPARTURE",
382
+ "gbtt_timestamp":"",
383
+ "original_loc_stanox":"",
384
+ "planned_timestamp":"",
385
+ "timetable_variation":"0",
386
+ "original_loc_timestamp":"",
387
+ "current_train_id":"",
388
+ "delay_monitoring_point":"false",
389
+ "next_report_run_time":"",
390
+ "reporting_stanox":"",
391
+ "actual_timestamp":"1364295540000",
392
+ "correction_ind":"false",
393
+ "event_source":"AUTOMATIC",
394
+ "train_file_address":null,
395
+ "platform":"",
396
+ "division_code":"84",
397
+ "train_terminated":"false",
398
+ "train_id":"872B27MH26",
399
+ "offroute_ind":"true",
400
+ "variation_status":"OFF ROUTE",
401
+ "train_service_code":"24620204",
402
+ "toc_id":"84",
403
+ "loc_stanox":"86005",
404
+ "auto_expected":"",
405
+ "direction_ind":"",
406
+ "route":"",
407
+ "planned_event_type":"DEPARTURE",
408
+ "next_report_stanox":"",
409
+ "line_ind":""
410
+ }
411
+ }
412
+ ]
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetworkRail::Client do
4
+ before do
5
+ @stomp_client = stub("Stomp::Client",
6
+ open?: true,
7
+ protocol: Stomp::SPL_11,
8
+ connection_frame: stub(command: true),
9
+ subscribe: stub(true)
10
+ )
11
+ end
12
+
13
+ describe "#new" do
14
+ context "without login credentials" do
15
+ it "raises an exception" do
16
+ lambda {
17
+ client = described_class.new
18
+ }.should raise_exception(NetworkRail::Exception::NoLoginCredentials)
19
+ end
20
+ end
21
+
22
+ context "with login credentials" do
23
+ before(:all) do
24
+ NetworkRail.configure do |config|
25
+ config.user_name = 'test'
26
+ config.password = 'test'
27
+ end
28
+ end
29
+
30
+ it "passes the login credentials in the request" do
31
+ Stomp::Client.should_receive(:new).once do |options|
32
+ options[:hosts][0][:login].should == 'test'
33
+ options[:hosts][0][:passcode].should == 'test'
34
+ end.and_return(@stomp_client)
35
+ client = described_class.new
36
+ end
37
+
38
+ context "after connection attempt" do
39
+ before(:each) do
40
+ Stomp::Client.stub(:new).and_return(@stomp_client)
41
+ end
42
+
43
+ context "when there is a connection error" do
44
+ it "raises an exception" do
45
+ @stomp_client.stub(:open?).and_return(false)
46
+ lambda {
47
+ client = described_class.new
48
+ }.should raise_exception(NetworkRail::Exception::ConnectionError)
49
+ end
50
+ end
51
+
52
+ context "when there is an authentication error" do
53
+ it "raises an exception" do
54
+ @stomp_client.stub(:connection_frame).and_return(stub(command: Stomp::CMD_ERROR, body: "java.lang.SecurityException: User name [test] or password is invalid. (RuntimeError)"))
55
+ lambda {
56
+ client = described_class.new
57
+ }.should raise_exception(NetworkRail::Exception::AuthenticationError)
58
+ end
59
+ end
60
+
61
+ context "when there is an unexpected error" do
62
+ it "raises an exception" do
63
+ @stomp_client.stub(:connection_frame).and_return(stub(command: Stomp::CMD_ERROR, body: ''))
64
+ lambda {
65
+ client = described_class.new
66
+ }.should raise_exception(NetworkRail::Exception::ConnectionError)
67
+ end
68
+ end
69
+
70
+ context "when the connection is established" do
71
+ it "returns an instance of #{described_class.to_s}" do
72
+ client = described_class.new
73
+ client.should be_kind_of described_class
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "#train_movements" do
81
+ before do
82
+ NetworkRail.configure do |config|
83
+ config.user_name = 'test'
84
+ config.password = 'test'
85
+ end
86
+ Stomp::Client.stub(:new).and_return(@stomp_client)
87
+
88
+ @client = described_class.new
89
+ end
90
+
91
+ context "with no block" do
92
+ it "raises an exception" do
93
+ lambda { @client.train_movements }.should raise_exception(NetworkRail::Exception::BlockRequired)
94
+ end
95
+ end
96
+
97
+ context "with no train operator parameter" do
98
+ it "defaults to all train operators and subscribes to the train movements feed" do
99
+ @stomp_client.should_receive(:subscribe).once.with("/topic/TRAIN_MVT_ALL_TOC")
100
+ @client.train_movements {|i| }
101
+ end
102
+ end
103
+
104
+ context "with train operator parameter" do
105
+ it "maps the operator parameter to the Network Rail business code and subscribes to the train movements feed" do
106
+ @stomp_client.should_receive(:subscribe).once.with("/topic/TRAIN_MVT_HY_TOC")
107
+ @client.train_movements(operator: :south_west_trains) {|i| }
108
+ end
109
+ end
110
+
111
+ describe "parsing responses" do
112
+ before do
113
+ @stomp_client.stub(:subscribe).and_yield(fixture('train_movements.json'))
114
+ end
115
+
116
+ it "calls NetworkRail::Message::TrainMovement#factory for each message received" do
117
+ NetworkRail::Message::TrainMovement.should_receive(:factory).exactly(10).times
118
+ @client.train_movements {|i| }
119
+ end
120
+
121
+ it "yields an instance of NetworkRail::Message::TrainMovement for each message received" do
122
+ expect {|b| @client.train_movements(&b) }.to yield_successive_args(
123
+ NetworkRail::Message::TrainMovement::Arrival,
124
+ NetworkRail::Message::TrainMovement::Departure,
125
+ NetworkRail::Message::TrainMovement::Arrival,
126
+ NetworkRail::Message::TrainMovement::Departure,
127
+ NetworkRail::Message::TrainMovement::Departure,
128
+ NetworkRail::Message::TrainMovement::Arrival,
129
+ NetworkRail::Message::TrainMovement::Arrival,
130
+ NetworkRail::Message::TrainMovement::Arrival,
131
+ NetworkRail::Message::TrainMovement::Departure,
132
+ NetworkRail::Message::TrainMovement::Departure
133
+ )
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetworkRail::Message::TrainMovement::Base do
4
+ describe "#factory" do
5
+ it "returns an instance of the class" do
6
+ described_class.should_receive(:new).once.with('test')
7
+ described_class.factory('test')
8
+ end
9
+ end
10
+
11
+ describe "#initialize" do
12
+ before do
13
+ @messages = JSON.parse fixture('train_movements.json')
14
+ end
15
+
16
+ it "assigns the original parsed JSON message to #original_message" do
17
+ object = described_class.new @messages.first
18
+ object.original_message.should == @messages.first
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetworkRail::Message::TrainMovement::Movement do
4
+ before do
5
+ @messages = JSON.parse fixture('train_movements.json')
6
+ end
7
+
8
+ describe "#factory" do
9
+ it "calls the factory method on a different subclass depending on the message type" do
10
+ @messages.each do |message|
11
+ target_class = case message['body']['event_type']
12
+ when "ARRIVAL" then NetworkRail::Message::TrainMovement::Arrival
13
+ when "DEPARTURE" then NetworkRail::Message::TrainMovement::Departure
14
+ end
15
+
16
+ target_class.should_receive :new
17
+ described_class.factory(message)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "#initialize" do
23
+ it "converts actual_timestamp to Time and assigns to #time" do
24
+ object = described_class.new @messages.first
25
+ object.time.should be_a Time
26
+ object.time.year.should == 2013
27
+ end
28
+
29
+ it "converts planned_timestamp to Time and assigns to #planned_time" do
30
+ object = described_class.new @messages.first
31
+ object.planned_time.should be_a Time
32
+ object.planned_time.year.should == 2013
33
+ end
34
+
35
+ it "converts toc_id to a symbol representing the train operator and assings to #operator" do
36
+ object = described_class.new @messages.first
37
+ object.operator.should == :south_west_trains
38
+ end
39
+ end
40
+
41
+ describe "#on_time?" do
42
+ context "when within the late threshold" do
43
+ it "returns true" do
44
+ object = described_class.new @messages.first
45
+ object.time = Time.now
46
+ object.planned_time = Time.now - 1.minute
47
+ object.on_time?.should == true
48
+ end
49
+ end
50
+
51
+ context "when outside the late threshold" do
52
+ it "returns false" do
53
+ object = described_class.new @messages.first
54
+ object.time = Time.now
55
+ object.planned_time = Time.now - 1.hour
56
+ object.on_time?.should == false
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "#delay" do
62
+ it "returns the difference in seconds between #time and #planned_time" do
63
+ object = described_class.new @messages.first
64
+ object.time = Time.now
65
+ object.planned_time = Time.now - 1.hour
66
+ object.delay.should == 3600
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetworkRail::Message::TrainMovement do
4
+ describe "#factory" do
5
+ before do
6
+ @messages = JSON.parse fixture('train_movements.json')
7
+ end
8
+
9
+ it "calls the factory method on a different subclass of NetworkRail::Message::TrainMovement::Base depending on the message type" do
10
+ @messages.each do |message|
11
+ target_class = case message['header']['msg_type']
12
+ when "0001" then NetworkRail::Message::TrainMovement::Activation
13
+ when "0002" then NetworkRail::Message::TrainMovement::Cancellation
14
+ when "0003" then NetworkRail::Message::TrainMovement::Movement
15
+ when "0005" then NetworkRail::Message::TrainMovement::Reinstatement
16
+ when "0006" then NetworkRail::Message::TrainMovement::ChangeOfOrigin
17
+ when "0007" then NetworkRail::Message::TrainMovement::ChangeOfIdentity
18
+ end
19
+
20
+ target_class.should_receive(:factory).once
21
+ described_class.factory(message)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ require 'network_rail'
2
+ require 'active_support/all'
3
+
4
+ def fixture_path
5
+ File.expand_path("../fixtures", __FILE__)
6
+ end
7
+
8
+ def fixture(file)
9
+ File.read(fixture_path + '/' + file)
10
+ end