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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +3 -0
- data/.rubocop.yml +31 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/Guardfile +25 -0
- data/LICENSE.md +32 -0
- data/README.md +77 -0
- data/Rakefile +3 -0
- data/doc/guides/Logging.md +13 -0
- data/doc/guides/Network Rail/CORPUS.md +34 -0
- data/doc/guides/Network Rail/SMART.md +39 -0
- data/doc/guides/Network Rail/Schedule.md +138 -0
- data/file +0 -0
- data/lib/rail_feeds/credentials.rb +45 -0
- data/lib/rail_feeds/logging.rb +51 -0
- data/lib/rail_feeds/network_rail/corpus.rb +77 -0
- data/lib/rail_feeds/network_rail/credentials.rb +22 -0
- data/lib/rail_feeds/network_rail/http_client.rb +57 -0
- data/lib/rail_feeds/network_rail/schedule/association.rb +208 -0
- data/lib/rail_feeds/network_rail/schedule/data.rb +215 -0
- data/lib/rail_feeds/network_rail/schedule/days.rb +95 -0
- data/lib/rail_feeds/network_rail/schedule/fetcher.rb +193 -0
- data/lib/rail_feeds/network_rail/schedule/header/cif.rb +102 -0
- data/lib/rail_feeds/network_rail/schedule/header/json.rb +79 -0
- data/lib/rail_feeds/network_rail/schedule/header.rb +22 -0
- data/lib/rail_feeds/network_rail/schedule/parser/cif.rb +141 -0
- data/lib/rail_feeds/network_rail/schedule/parser/json.rb +87 -0
- data/lib/rail_feeds/network_rail/schedule/parser.rb +108 -0
- data/lib/rail_feeds/network_rail/schedule/stp_indicator.rb +72 -0
- data/lib/rail_feeds/network_rail/schedule/tiploc.rb +100 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/change_en_route.rb +158 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location/intermediate.rb +119 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location/origin.rb +91 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location/terminating.rb +72 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule/location.rb +76 -0
- data/lib/rail_feeds/network_rail/schedule/train_schedule.rb +392 -0
- data/lib/rail_feeds/network_rail/schedule.rb +33 -0
- data/lib/rail_feeds/network_rail/smart.rb +186 -0
- data/lib/rail_feeds/network_rail/stomp_client.rb +77 -0
- data/lib/rail_feeds/network_rail.rb +16 -0
- data/lib/rail_feeds/version.rb +14 -0
- data/lib/rail_feeds.rb +10 -0
- data/rail_feeds.gemspec +32 -0
- data/spec/fixtures/network_rail/schedule/data/full.yaml +60 -0
- data/spec/fixtures/network_rail/schedule/data/starting.yaml +131 -0
- data/spec/fixtures/network_rail/schedule/data/update-gap.yaml +10 -0
- data/spec/fixtures/network_rail/schedule/data/update-next.yaml +13 -0
- data/spec/fixtures/network_rail/schedule/data/update-old.yaml +10 -0
- data/spec/fixtures/network_rail/schedule/data/update.yaml +112 -0
- data/spec/fixtures/network_rail/schedule/parser/train_create.json +1 -0
- data/spec/fixtures/network_rail/schedule/parser/train_delete.json +1 -0
- data/spec/fixtures/network_rail/schedule/train_schedule/json-data.yaml +67 -0
- data/spec/rail_feeds/credentials_spec.rb +46 -0
- data/spec/rail_feeds/logging_spec.rb +81 -0
- data/spec/rail_feeds/network_rail/corpus_spec.rb +92 -0
- data/spec/rail_feeds/network_rail/credentials_spec.rb +22 -0
- data/spec/rail_feeds/network_rail/http_client_spec.rb +88 -0
- data/spec/rail_feeds/network_rail/schedule/association_spec.rb +205 -0
- data/spec/rail_feeds/network_rail/schedule/data_spec.rb +219 -0
- data/spec/rail_feeds/network_rail/schedule/days_shared.rb +99 -0
- data/spec/rail_feeds/network_rail/schedule/days_spec.rb +4 -0
- data/spec/rail_feeds/network_rail/schedule/fetcher_spec.rb +228 -0
- data/spec/rail_feeds/network_rail/schedule/header/cif_spec.rb +72 -0
- data/spec/rail_feeds/network_rail/schedule/header/json_spec.rb +51 -0
- data/spec/rail_feeds/network_rail/schedule/header_spec.rb +19 -0
- data/spec/rail_feeds/network_rail/schedule/parser/cif_spec.rb +197 -0
- data/spec/rail_feeds/network_rail/schedule/parser/json_spec.rb +172 -0
- data/spec/rail_feeds/network_rail/schedule/parser_spec.rb +34 -0
- data/spec/rail_feeds/network_rail/schedule/stp_indicator_shared.rb +49 -0
- data/spec/rail_feeds/network_rail/schedule/stp_indicator_spec.rb +4 -0
- data/spec/rail_feeds/network_rail/schedule/tiploc_spec.rb +77 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/change_en_route_spec.rb +121 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location/intermediate_spec.rb +95 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location/origin_spec.rb +87 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location/terminating_spec.rb +81 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule/location_spec.rb +35 -0
- data/spec/rail_feeds/network_rail/schedule/train_schedule_spec.rb +284 -0
- data/spec/rail_feeds/network_rail/schedule_spec.rb +41 -0
- data/spec/rail_feeds/network_rail/smart_spec.rb +194 -0
- data/spec/rail_feeds/network_rail/stomp_client_spec.rb +151 -0
- data/spec/rail_feeds/network_rail_spec.rb +7 -0
- data/spec/rail_feeds_spec.rb +11 -0
- data/spec/spec_helper.rb +47 -0
- 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
|