rail_feeds 0.0.1

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