rail_feeds 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +31 -0
  5. data/.travis.yml +26 -0
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +6 -0
  8. data/Guardfile +25 -0
  9. data/LICENSE.md +32 -0
  10. data/README.md +77 -0
  11. data/Rakefile +3 -0
  12. data/doc/guides/Logging.md +13 -0
  13. data/doc/guides/Network Rail/CORPUS.md +34 -0
  14. data/doc/guides/Network Rail/SMART.md +39 -0
  15. data/doc/guides/Network Rail/Schedule.md +138 -0
  16. data/file +0 -0
  17. data/lib/rail_feeds/credentials.rb +45 -0
  18. data/lib/rail_feeds/logging.rb +51 -0
  19. data/lib/rail_feeds/network_rail/corpus.rb +77 -0
  20. data/lib/rail_feeds/network_rail/credentials.rb +22 -0
  21. data/lib/rail_feeds/network_rail/http_client.rb +57 -0
  22. data/lib/rail_feeds/network_rail/schedule/association.rb +208 -0
  23. data/lib/rail_feeds/network_rail/schedule/data.rb +215 -0
  24. data/lib/rail_feeds/network_rail/schedule/days.rb +95 -0
  25. data/lib/rail_feeds/network_rail/schedule/fetcher.rb +193 -0
  26. data/lib/rail_feeds/network_rail/schedule/header/cif.rb +102 -0
  27. data/lib/rail_feeds/network_rail/schedule/header/json.rb +79 -0
  28. data/lib/rail_feeds/network_rail/schedule/header.rb +22 -0
  29. data/lib/rail_feeds/network_rail/schedule/parser/cif.rb +141 -0
  30. data/lib/rail_feeds/network_rail/schedule/parser/json.rb +87 -0
  31. data/lib/rail_feeds/network_rail/schedule/parser.rb +108 -0
  32. data/lib/rail_feeds/network_rail/schedule/stp_indicator.rb +72 -0
  33. data/lib/rail_feeds/network_rail/schedule/tiploc.rb +100 -0
  34. data/lib/rail_feeds/network_rail/schedule/train_schedule/change_en_route.rb +158 -0
  35. data/lib/rail_feeds/network_rail/schedule/train_schedule/location/intermediate.rb +119 -0
  36. data/lib/rail_feeds/network_rail/schedule/train_schedule/location/origin.rb +91 -0
  37. data/lib/rail_feeds/network_rail/schedule/train_schedule/location/terminating.rb +72 -0
  38. data/lib/rail_feeds/network_rail/schedule/train_schedule/location.rb +76 -0
  39. data/lib/rail_feeds/network_rail/schedule/train_schedule.rb +392 -0
  40. data/lib/rail_feeds/network_rail/schedule.rb +33 -0
  41. data/lib/rail_feeds/network_rail/smart.rb +186 -0
  42. data/lib/rail_feeds/network_rail/stomp_client.rb +77 -0
  43. data/lib/rail_feeds/network_rail.rb +16 -0
  44. data/lib/rail_feeds/version.rb +14 -0
  45. data/lib/rail_feeds.rb +10 -0
  46. data/rail_feeds.gemspec +32 -0
  47. data/spec/fixtures/network_rail/schedule/data/full.yaml +60 -0
  48. data/spec/fixtures/network_rail/schedule/data/starting.yaml +131 -0
  49. data/spec/fixtures/network_rail/schedule/data/update-gap.yaml +10 -0
  50. data/spec/fixtures/network_rail/schedule/data/update-next.yaml +13 -0
  51. data/spec/fixtures/network_rail/schedule/data/update-old.yaml +10 -0
  52. data/spec/fixtures/network_rail/schedule/data/update.yaml +112 -0
  53. data/spec/fixtures/network_rail/schedule/parser/train_create.json +1 -0
  54. data/spec/fixtures/network_rail/schedule/parser/train_delete.json +1 -0
  55. data/spec/fixtures/network_rail/schedule/train_schedule/json-data.yaml +67 -0
  56. data/spec/rail_feeds/credentials_spec.rb +46 -0
  57. data/spec/rail_feeds/logging_spec.rb +81 -0
  58. data/spec/rail_feeds/network_rail/corpus_spec.rb +92 -0
  59. data/spec/rail_feeds/network_rail/credentials_spec.rb +22 -0
  60. data/spec/rail_feeds/network_rail/http_client_spec.rb +88 -0
  61. data/spec/rail_feeds/network_rail/schedule/association_spec.rb +205 -0
  62. data/spec/rail_feeds/network_rail/schedule/data_spec.rb +219 -0
  63. data/spec/rail_feeds/network_rail/schedule/days_shared.rb +99 -0
  64. data/spec/rail_feeds/network_rail/schedule/days_spec.rb +4 -0
  65. data/spec/rail_feeds/network_rail/schedule/fetcher_spec.rb +228 -0
  66. data/spec/rail_feeds/network_rail/schedule/header/cif_spec.rb +72 -0
  67. data/spec/rail_feeds/network_rail/schedule/header/json_spec.rb +51 -0
  68. data/spec/rail_feeds/network_rail/schedule/header_spec.rb +19 -0
  69. data/spec/rail_feeds/network_rail/schedule/parser/cif_spec.rb +197 -0
  70. data/spec/rail_feeds/network_rail/schedule/parser/json_spec.rb +172 -0
  71. data/spec/rail_feeds/network_rail/schedule/parser_spec.rb +34 -0
  72. data/spec/rail_feeds/network_rail/schedule/stp_indicator_shared.rb +49 -0
  73. data/spec/rail_feeds/network_rail/schedule/stp_indicator_spec.rb +4 -0
  74. data/spec/rail_feeds/network_rail/schedule/tiploc_spec.rb +77 -0
  75. data/spec/rail_feeds/network_rail/schedule/train_schedule/change_en_route_spec.rb +121 -0
  76. data/spec/rail_feeds/network_rail/schedule/train_schedule/location/intermediate_spec.rb +95 -0
  77. data/spec/rail_feeds/network_rail/schedule/train_schedule/location/origin_spec.rb +87 -0
  78. data/spec/rail_feeds/network_rail/schedule/train_schedule/location/terminating_spec.rb +81 -0
  79. data/spec/rail_feeds/network_rail/schedule/train_schedule/location_spec.rb +35 -0
  80. data/spec/rail_feeds/network_rail/schedule/train_schedule_spec.rb +284 -0
  81. data/spec/rail_feeds/network_rail/schedule_spec.rb +41 -0
  82. data/spec/rail_feeds/network_rail/smart_spec.rb +194 -0
  83. data/spec/rail_feeds/network_rail/stomp_client_spec.rb +151 -0
  84. data/spec/rail_feeds/network_rail_spec.rb +7 -0
  85. data/spec/rail_feeds_spec.rb +11 -0
  86. data/spec/spec_helper.rb +47 -0
  87. metadata +282 -0
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Intermediate do
4
+ subject { described_class.new tiploc: 'ccccccc', tiploc_suffix: 3 }
5
+ let(:line) do
6
+ 'LIttttttt1aaaaadddddpppppAAAADDDDPlaLinPataaaaaaaaaaaa123456 '
7
+ end
8
+
9
+ describe '::from_cif' do
10
+ it 'Sets attributes' do
11
+ subject = described_class.from_cif line
12
+
13
+ expect(subject.tiploc).to eq 'ttttttt'
14
+ expect(subject.tiploc_suffix).to eq 1
15
+ expect(subject.scheduled_arrival).to eq 'aaaaa'
16
+ expect(subject.scheduled_departure).to eq 'ddddd'
17
+ expect(subject.scheduled_pass).to eq 'ppppp'
18
+ expect(subject.public_arrival).to eq 'AAAA'
19
+ expect(subject.public_departure).to eq 'DDDD'
20
+ expect(subject.platform).to eq 'Pla'
21
+ expect(subject.line).to eq 'Lin'
22
+ expect(subject.path).to eq 'Pat'
23
+ expect(subject.activity).to eq 'aaaaaaaaaaaa'
24
+ expect(subject.engineering_allowance).to eq 12.0
25
+ expect(subject.pathing_allowance).to eq 34.0
26
+ expect(subject.performance_allowance).to eq 56.0
27
+ end
28
+
29
+ it 'Fails for invalid line' do
30
+ expect { described_class.from_cif('bad line') }
31
+ .to raise_error ArgumentError, "Invalid line:\nbad line"
32
+ end
33
+ end
34
+
35
+ it '#to_cif' do
36
+ subject = described_class.from_cif line
37
+ expect(subject.to_cif).to eq "#{line}\n"
38
+ end
39
+
40
+ it '#to_hash_for_json' do
41
+ subject = described_class.from_cif line
42
+ expect(subject.to_hash_for_json).to eq(
43
+ location_type: 'LI',
44
+ record_identity: 'LI',
45
+ tiploc_code: 'ttttttt',
46
+ tiploc_instance: 1,
47
+ arrival: 'aaaaa',
48
+ departure: 'ddddd',
49
+ pass: 'ppppp',
50
+ public_arrival: 'AAAA',
51
+ public_departure: 'DDDD',
52
+ platform: 'Pla',
53
+ line: 'Lin',
54
+ path: 'Pat',
55
+ engineering_allowance: '12',
56
+ pathing_allowance: '34',
57
+ performance_allowance: '56'
58
+ )
59
+ end
60
+
61
+ describe '#hash' do
62
+ it 'Uses tiploc and tiploc_suffix' do
63
+ expect(subject.hash).to eq 'ccccccc-3'
64
+ end
65
+ end
66
+
67
+ describe '#==' do
68
+ let(:location1) { described_class.new tiploc: 'a', tiploc_suffix: 1 }
69
+ let(:location2) { described_class.new tiploc: 'a', tiploc_suffix: 1 }
70
+
71
+ it 'Neither tiploc or tiploc_suffix match' do
72
+ location1.tiploc = 'b'
73
+ location1.tiploc_suffix = 2
74
+ expect(location1).to_not eq location2
75
+ end
76
+
77
+ it 'Tiploc matches but tiploc_suffix doesn\'t' do
78
+ location1.tiploc_suffix = 2
79
+ expect(location1).to_not eq location2
80
+ end
81
+
82
+ it 'Tiploc_suffix matches but tiploc doesn\'t' do
83
+ location1.tiploc = 'b'
84
+ expect(location1).to_not eq location2
85
+ end
86
+
87
+ it 'Both tiploc and tiploc_suffix match' do
88
+ expect(location1).to eq location2
89
+ end
90
+
91
+ it 'Compares to nil without error' do
92
+ expect(location1).to_not eq nil
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Origin do
4
+ subject { described_class.new tiploc: 'aaaaaaa', tiploc_suffix: 1 }
5
+ let(:line) do
6
+ 'LOttttttt1dddddDDDDPlaLin2H3 aaaaaaaaaaaa45 '
7
+ end
8
+
9
+ describe '::from_cif' do
10
+ it 'Sets attributes' do
11
+ subject = described_class.from_cif line
12
+
13
+ expect(subject.tiploc).to eq 'ttttttt'
14
+ expect(subject.tiploc_suffix).to eq 1
15
+ expect(subject.scheduled_departure).to eq 'ddddd'
16
+ expect(subject.public_departure).to eq 'DDDD'
17
+ expect(subject.platform).to eq 'Pla'
18
+ expect(subject.line).to eq 'Lin'
19
+ expect(subject.engineering_allowance).to eq 2.5
20
+ expect(subject.pathing_allowance).to eq 3.0
21
+ expect(subject.activity).to eq 'aaaaaaaaaaaa'
22
+ expect(subject.performance_allowance).to eq 45.0
23
+ end
24
+
25
+ it 'Fails for invalid line' do
26
+ expect { described_class.from_cif('bad line') }
27
+ .to raise_error ArgumentError, "Invalid line:\nbad line"
28
+ end
29
+ end
30
+
31
+ it '#to_cif' do
32
+ subject = described_class.from_cif line
33
+ expect(subject.to_cif).to eq "#{line}\n"
34
+ end
35
+
36
+ it '#to_hash_for_json' do
37
+ subject = described_class.from_cif line
38
+ expect(subject.to_hash_for_json).to eq(
39
+ location_type: 'LO',
40
+ record_identity: 'LO',
41
+ tiploc_code: 'ttttttt',
42
+ tiploc_instance: 1,
43
+ departure: 'ddddd',
44
+ public_departure: 'DDDD',
45
+ platform: 'Pla',
46
+ line: 'Lin',
47
+ engineering_allowance: '2H',
48
+ pathing_allowance: '3',
49
+ performance_allowance: '45'
50
+ )
51
+ end
52
+
53
+ describe '#hash' do
54
+ it 'Uses tiploc and tiploc_suffix' do
55
+ expect(subject.hash).to eq 'aaaaaaa-1'
56
+ end
57
+ end
58
+
59
+ describe '#==' do
60
+ let(:location1) { described_class.new tiploc: 'a', tiploc_suffix: 1 }
61
+ let(:location2) { described_class.new tiploc: 'a', tiploc_suffix: 1 }
62
+
63
+ it 'Neither tiploc or tiploc_suffix match' do
64
+ location1.tiploc = 'b'
65
+ location1.tiploc_suffix = 2
66
+ expect(location1).to_not eq location2
67
+ end
68
+
69
+ it 'Tiploc matches but tiploc_suffix doesn\'t' do
70
+ location1.tiploc_suffix = 2
71
+ expect(location1).to_not eq location2
72
+ end
73
+
74
+ it 'Tiploc_suffix matches but tiploc doesn\'t' do
75
+ location1.tiploc = 'b'
76
+ expect(location1).to_not eq location2
77
+ end
78
+
79
+ it 'Both tiploc and tiploc_suffix match' do
80
+ expect(location1).to eq location2
81
+ end
82
+
83
+ it 'Compares to nil without error' do
84
+ expect(location1).to_not eq nil
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Terminating do
4
+ subject { described_class.new tiploc: 'bbbbbbb', tiploc_suffix: 2 }
5
+ let(:line) do
6
+ 'LTttttttt1aaaaaAAAAPlaPataaaaaaaaaaaa '
7
+ end
8
+
9
+ describe '::from_cif' do
10
+ it 'Sets attributes' do
11
+ subject = described_class.from_cif line
12
+
13
+ expect(subject.tiploc).to eq 'ttttttt'
14
+ expect(subject.tiploc_suffix).to eq 1
15
+ expect(subject.scheduled_arrival).to eq 'aaaaa'
16
+ expect(subject.public_arrival).to eq 'AAAA'
17
+ expect(subject.platform).to eq 'Pla'
18
+ expect(subject.path).to eq 'Pat'
19
+ expect(subject.activity).to eq 'aaaaaaaaaaaa'
20
+ end
21
+
22
+ it 'Fails for invalid line' do
23
+ expect { described_class.from_cif('bad line') }
24
+ .to raise_error ArgumentError, "Invalid line:\nbad line"
25
+ end
26
+ end
27
+
28
+ it '#to_cif' do
29
+ subject = described_class.from_cif line
30
+ expect(subject.to_cif).to eq "#{line}\n"
31
+ end
32
+
33
+ it '#to_hash_for_json' do
34
+ subject = described_class.from_cif line
35
+ expect(subject.to_hash_for_json).to eq(
36
+ location_type: 'LT',
37
+ record_identity: 'LT',
38
+ tiploc_code: 'ttttttt',
39
+ tiploc_instance: 1,
40
+ arrival: 'aaaaa',
41
+ public_arrival: 'AAAA',
42
+ platform: 'Pla',
43
+ path: 'Pat'
44
+ )
45
+ end
46
+
47
+ describe '#hash' do
48
+ it 'Uses tiploc and tiploc_suffix' do
49
+ expect(subject.hash).to eq 'bbbbbbb-2'
50
+ end
51
+ end
52
+
53
+ describe '#==' do
54
+ let(:location1) { described_class.new tiploc: 'a', tiploc_suffix: 1 }
55
+ let(:location2) { described_class.new tiploc: 'a', tiploc_suffix: 1 }
56
+
57
+ it 'Neither tiploc or tiploc_suffix match' do
58
+ location1.tiploc = 'b'
59
+ location1.tiploc_suffix = 2
60
+ expect(location1).to_not eq location2
61
+ end
62
+
63
+ it 'Tiploc matches but tiploc_suffix doesn\'t' do
64
+ location1.tiploc_suffix = 2
65
+ expect(location1).to_not eq location2
66
+ end
67
+
68
+ it 'Tiploc_suffix matches but tiploc doesn\'t' do
69
+ location1.tiploc = 'b'
70
+ expect(location1).to_not eq location2
71
+ end
72
+
73
+ it 'Both tiploc and tiploc_suffix match' do
74
+ expect(location1).to eq location2
75
+ end
76
+
77
+ it 'Compares to nil without error' do
78
+ expect(location1).to_not eq nil
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RailFeeds::NetworkRail::Schedule::TrainSchedule::Location do
4
+ it 'Can\'t be instantiated' do
5
+ expect { described_class.new }.to raise_error RuntimeError, 'This class should never be instantiated'
6
+ end
7
+
8
+ describe 'Make relevant location type from line' do
9
+ it 'Origin' do
10
+ line = 'LO'
11
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Origin)
12
+ .to receive(:from_cif).with(line).and_return(:location)
13
+ expect(described_class.from_cif(line)).to eq :location
14
+ end
15
+
16
+ it 'Intermediate' do
17
+ line = 'LI'
18
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Intermediate)
19
+ .to receive(:from_cif).with(line).and_return(:location)
20
+ expect(described_class.from_cif(line)).to eq :location
21
+ end
22
+
23
+ it 'Terminating' do
24
+ line = 'LT'
25
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Terminating)
26
+ .to receive(:from_cif).with(line).and_return(:location)
27
+ expect(described_class.from_cif(line)).to eq :location
28
+ end
29
+
30
+ it 'Fails on bad line' do
31
+ line = 'bad_line'
32
+ expect { described_class.from_cif(line) }.to raise_error ArgumentError, 'Improper line type ba: bad_line'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,284 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RailFeeds::NetworkRail::Schedule::TrainSchedule do
4
+ let(:line_basic) do
5
+ 'BSNa123450102030405061010101bscciiii2222111111111 PPPtttt333ooooooSFR catebran P'
6
+ end
7
+ let(:line_extra) do
8
+ 'BX 11111TTY '
9
+ end
10
+ let :json do
11
+ file = File.join RSPEC_FIXTURES, 'network_rail', 'schedule', 'train_schedule', 'json-data.yaml'
12
+ YAML.load(File.read(file)).to_json
13
+ end
14
+
15
+ subject do
16
+ described_class.new(
17
+ uid: 'a12345',
18
+ start_date: Date.new(2001, 2, 3),
19
+ end_date: Date.new(2004, 5, 6),
20
+ days: [true, false, true, false, true, false, true],
21
+ bank_holiday_running: 'b',
22
+ status: 's',
23
+ category: 'cc',
24
+ signalling_headcode: 'iiii',
25
+ reservation_headcode: 2222,
26
+ service_code: 11111111,
27
+ power_type: 'PPP',
28
+ timing_load: 'tttt',
29
+ speed: 333,
30
+ operating_characteristics: 'oooooo',
31
+ seating_class: 'S',
32
+ sleeping_class: 'F',
33
+ reservations: 'R',
34
+ catering: 'cate',
35
+ branding: 'bran',
36
+ stp_indicator: :permanent,
37
+ uic: 11111,
38
+ atoc: 'TT',
39
+ applicable_timetable: true
40
+ )
41
+ end
42
+
43
+ it '::from_json' do
44
+ subject = described_class.from_json json
45
+ expect(subject.uid).to eq 'W20309'
46
+ expect(subject.category).to eq 'OO'
47
+ expect(subject.status).to eq 'S'
48
+ expect(subject.reservation_headcode).to eq 1234
49
+ expect(subject.signalling_headcode).to eq '2U10'
50
+ expect(subject.service_code).to eq '24627006'
51
+ expect(subject.start_date).to eq Date.new(2018, 5, 21)
52
+ expect(subject.end_date).to eq Date.new(2018, 12, 7)
53
+ expect(subject.days).to eq [true, true, true, true, true, false, false]
54
+ expect(subject.bank_holiday_running).to eq 'B'
55
+ expect(subject.power_type).to eq 'EMU'
56
+ expect(subject.timing_load).to eq '483'
57
+ expect(subject.speed).to eq 45
58
+ expect(subject.operating_characteristics).to eq 'OPER-CHAR'
59
+ expect(subject.seating_class).to eq 'S'
60
+ expect(subject.sleeping_class).to eq 'B'
61
+ expect(subject.reservations).to eq 'R'
62
+ expect(subject.catering).to eq 'C'
63
+ expect(subject.branding).to eq 'Br'
64
+ expect(subject.uic).to eq 12345
65
+ expect(subject.atoc).to eq 'IL'
66
+ expect(subject.applicable_timetable).to eq true
67
+ expect(subject.stp_indicator).to eq :permanent
68
+ expect(subject.journey.size).to eq 3
69
+ end
70
+
71
+ describe '#update_from_line' do
72
+ it 'Standard information' do
73
+ subject.update_from_cif line_basic
74
+ expect(subject.uid).to eq 'a12345'
75
+ expect(subject.start_date).to eq Date.new(2001, 2, 3)
76
+ expect(subject.end_date).to eq Date.new(2004, 5, 6)
77
+ expect(subject.days).to eq [true, false, true, false, true, false, true]
78
+ expect(subject.bank_holiday_running).to eq 'b'
79
+ expect(subject.status).to eq 's'
80
+ expect(subject.category).to eq 'cc'
81
+ expect(subject.signalling_headcode).to eq 'iiii'
82
+ expect(subject.reservation_headcode).to eq 2222
83
+ expect(subject.service_code).to eq 11111111
84
+ expect(subject.power_type).to eq 'PPP'
85
+ expect(subject.timing_load).to eq 'tttt'
86
+ expect(subject.speed).to eq 333
87
+ expect(subject.operating_characteristics).to eq 'oooooo'
88
+ expect(subject.seating_class).to eq 'S'
89
+ expect(subject.sleeping_class).to eq 'F'
90
+ expect(subject.reservations).to eq 'R'
91
+ expect(subject.catering).to eq 'cate'
92
+ expect(subject.branding).to eq 'bran'
93
+ expect(subject.stp_indicator).to eq :permanent
94
+ end
95
+
96
+ it 'Extra information' do
97
+ subject.update_from_cif line_extra
98
+ expect(subject.uic).to eq 11111
99
+ expect(subject.atoc).to eq 'TT'
100
+ expect(subject.applicable_timetable).to eq true
101
+ end
102
+
103
+ it 'Origin location' do
104
+ line = 'LO'
105
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
106
+ .to receive(:from_cif).with(line).and_return(:origin)
107
+ subject.update_from_cif line
108
+ expect(subject.journey).to eq [:origin]
109
+ end
110
+
111
+ it 'Intermediate location' do
112
+ line = 'LI'
113
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
114
+ .to receive(:from_cif).with(line).and_return(:intermediate)
115
+ subject.update_from_cif line
116
+ expect(subject.journey).to eq [:intermediate]
117
+ end
118
+
119
+ it 'Terminating location' do
120
+ line = 'LT'
121
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
122
+ .to receive(:from_cif).with(line).and_return(:terminating)
123
+ subject.update_from_cif line
124
+ expect(subject.journey).to eq [:terminating]
125
+ end
126
+
127
+ it 'Series of locations' do
128
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
129
+ .to receive(:from_cif).with('LO').and_return(:origin)
130
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
131
+ .to receive(:from_cif).with('LI').and_return(:intermediate)
132
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
133
+ .to receive(:from_cif).with('LT').and_return(:terminating)
134
+ subject.update_from_cif 'LO'
135
+ subject.update_from_cif 'LI'
136
+ subject.update_from_cif 'LT'
137
+ expect(subject.journey).to eq %i[origin intermediate terminating]
138
+ end
139
+
140
+ it 'Change en route' do
141
+ line = 'CR'
142
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::ChangeEnRoute)
143
+ .to receive(:from_cif).with(line).and_return(:change)
144
+ subject.update_from_cif line
145
+ expect(subject.journey).to eq [:change]
146
+ end
147
+
148
+ it '#journey contains locations and change en routes' do
149
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
150
+ .to receive(:from_cif).with('LO').and_return(:origin)
151
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
152
+ .to receive(:from_cif).with('LI').and_return(:intermediate)
153
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::Location)
154
+ .to receive(:from_cif).with('LT').and_return(:terminating)
155
+ expect(RailFeeds::NetworkRail::Schedule::TrainSchedule::ChangeEnRoute)
156
+ .to receive(:from_cif).with('CR').and_return(:change)
157
+ subject.update_from_cif 'LO'
158
+ subject.update_from_cif 'CR'
159
+ subject.update_from_cif 'LI'
160
+ subject.update_from_cif 'LT'
161
+ expect(subject.journey).to eq %i[origin change intermediate terminating]
162
+ end
163
+
164
+ it 'Fails on bad line' do
165
+ line = 'bad line'
166
+ expect { subject.update_from_cif line }
167
+ .to raise_error ArgumentError, 'Improper line type ba: bad line'
168
+ end
169
+
170
+ it 'Delete line' do
171
+ line = 'BSDC77714180526 P'
172
+ subject.update_from_cif line
173
+ expect(subject.uid).to eq 'C77714'
174
+ expect(subject.start_date).to eq Date.new(2018, 5, 26)
175
+ expect(subject.end_date).to be_nil
176
+ expect(subject.days).to eq [false, false, false, false, false, false, false]
177
+ expect(subject.bank_holiday_running).to be_nil
178
+ expect(subject.status).to be_nil
179
+ expect(subject.category).to be_nil
180
+ expect(subject.signalling_headcode).to be_nil
181
+ expect(subject.reservation_headcode).to be_nil
182
+ expect(subject.service_code).to be_nil
183
+ expect(subject.power_type).to be_nil
184
+ expect(subject.timing_load).to be_nil
185
+ expect(subject.speed).to be_nil
186
+ expect(subject.operating_characteristics).to be_nil
187
+ expect(subject.seating_class).to be_nil
188
+ expect(subject.sleeping_class).to be_nil
189
+ expect(subject.reservations).to be_nil
190
+ expect(subject.catering).to be_nil
191
+ expect(subject.branding).to be_nil
192
+ expect(subject.stp_indicator).to eq :permanent
193
+ end
194
+ end
195
+
196
+ it '#to_cif' do
197
+ origin = double RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Origin
198
+ change = double RailFeeds::NetworkRail::Schedule::TrainSchedule::ChangeEnRoute
199
+ intermediate = double RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Intermediate
200
+ terminating = double RailFeeds::NetworkRail::Schedule::TrainSchedule::Location::Terminating
201
+ subject.journey = [origin, change, intermediate, terminating]
202
+
203
+ expect(origin).to receive(:to_cif).and_return("origin\n")
204
+ expect(change).to receive(:to_cif).and_return("change\n")
205
+ expect(intermediate).to receive(:to_cif).and_return("intermediate\n")
206
+ expect(terminating).to receive(:to_cif).and_return("terminating\n")
207
+
208
+ expect(subject.to_cif).to eq [
209
+ line_basic,
210
+ line_extra,
211
+ 'origin',
212
+ 'change',
213
+ 'intermediate',
214
+ 'terminating'
215
+ ].map { |i| "#{i}\n" }.join
216
+ end
217
+
218
+ it '#to_json' do
219
+ subject = described_class.from_json json
220
+ expect(subject.to_json).to eq json
221
+ end
222
+
223
+ describe '#<=>' do
224
+ # By start daste then uid
225
+ let(:train1) { described_class.new start_date: Date.new(2000, 1, 1), uid: 9999 }
226
+ let(:train2) { described_class.new start_date: Date.new(2000, 1, 2), uid: 1000 }
227
+ let(:train3) { described_class.new start_date: Date.new(2000, 1, 2), uid: 2000 }
228
+
229
+ it 'Match' do
230
+ train1a = described_class.new start_date: Date.new(2000, 1, 1), uid: 9999
231
+ expect(train1 <=> train1a).to eq 0
232
+ expect(train1a <=> train1).to eq 0
233
+ end
234
+
235
+ it 'Doesn\'t match' do
236
+ expect(train1 <=> train2).to eq(-1)
237
+ expect(train1 <=> train3).to eq(-1)
238
+ expect(train2 <=> train1).to eq 1
239
+ expect(train2 <=> train3).to eq(-1)
240
+ expect(train3 <=> train1).to eq 1
241
+ expect(train3 <=> train2).to eq 1
242
+ end
243
+
244
+ it 'Compares to nil without error' do
245
+ expect { train1 <=> nil }.to_not raise_error
246
+ end
247
+ end
248
+
249
+ describe '#==' do
250
+ let(:train1) { described_class.new }
251
+ let(:train2) { described_class.new }
252
+ before :each do
253
+ train1.uid = train2.uid = 'a01234'
254
+ train1.start_date = train2.start_date = Date.new(1, 2, 3)
255
+ end
256
+
257
+ it 'Matches on neither :uid or :start_date' do
258
+ train1.uid = nil
259
+ train1.start_date = nil
260
+ expect(train1).to_not eq train2
261
+ end
262
+
263
+ it 'Matches on :uid only' do
264
+ train1.start_date = nil
265
+ expect(train1).to_not eq train2
266
+ end
267
+
268
+ it 'Matches on :start_date only' do
269
+ train1.uid = nil
270
+ expect(train1).to_not eq train2
271
+ end
272
+
273
+ it 'Matches on both :uid or :start_date' do
274
+ expect(train1).to eq train2
275
+ end
276
+
277
+ it 'Compares to nil without error' do
278
+ expect(train1).to_not eq nil
279
+ end
280
+ end
281
+
282
+ it_behaves_like 'it has an STP indicator'
283
+ it_behaves_like 'it has a days array'
284
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe RailFeeds::NetworkRail::Schedule do
4
+ describe '::nil_or_i' do
5
+ it 'Empty value' do
6
+ expect(described_class.nil_or_i(' ')).to be_nil
7
+ end
8
+ it 'Nonempty value' do
9
+ expect(described_class.nil_or_i(' 1 ')).to eq 1
10
+ end
11
+ end
12
+
13
+ describe '::nil_or_strip' do
14
+ it 'Empty value' do
15
+ expect(described_class.nil_or_strip(' ')).to be_nil
16
+ end
17
+ it 'Nonempty value' do
18
+ expect(described_class.nil_or_strip(' 1 ')).to eq '1'
19
+ end
20
+ end
21
+
22
+ describe '::make_date' do
23
+ context 'Empty value' do
24
+ it 'Empty values not allowed' do
25
+ expect { described_class.make_date(' ') }.to raise_error ArgumentError
26
+ end
27
+ it 'Empty values allowed' do
28
+ expect(described_class.make_date(' ', allow_nil: true)).to be_nil
29
+ end
30
+ end
31
+
32
+ context 'Nonempty value' do
33
+ it 'Normal date' do
34
+ expect(described_class.make_date('050607')).to eq Date.new(2005, 6, 7)
35
+ end
36
+ it '999999' do
37
+ expect(described_class.make_date('999999')).to eq Date.new(9999, 12, 31)
38
+ end
39
+ end
40
+ end
41
+ end