Skip to content

Commit

Permalink
feature: refactor ♻️ adding Atco::Header record type, separate unit &…
Browse files Browse the repository at this point in the history
… integration tests and name translink specs (#15)

* header record type
* feature: refactor ♻️
  * refactor: improve Atco::Header extracting parse method from main module
  * refactor: provide attributes method for easier testing / to_json
  * tests: separate out unit and integration tests
  * tests: name translink tests
* Update CONTRIBUTORS.md
* release: bump version to 1.0.8

---------

Co-authored-by: Ian Dunlop <[email protected]>
  • Loading branch information
davidjrice and ianwdunlop authored Apr 13, 2024
1 parent 17dc0eb commit 072db74
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 110 deletions.
3 changes: 2 additions & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

* David Rice [@davidjrice](https://github.com/davidjrice)
* Thomas Buckley-Houston [@tombh](https://github.com/tombh)
* Martin Sidaway [@martinjos](https://github.com/martinjos)
* Martin Sidaway [@martinjos](https://github.com/martinjos)
* Ian Dunlop [@ianwdunlop](https://github.com/ianwdunlop)
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
atco (1.0.7)
atco (1.0.8)

GEM
remote: https://rubygems.org/
Expand Down
13 changes: 2 additions & 11 deletions lib/atco.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require "open3"
require "tempfile"
require_relative "atco/header"
require_relative "atco/location"
require_relative "atco/journey"
require_relative "atco/stop"
Expand Down Expand Up @@ -39,7 +40,7 @@ def parse(file) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,

data.each_with_index do |line, line_number| # rubocop:disable Metrics/BlockLength
if line_number.zero?
header = parse_header(line)
header = Header.parse(line)
next
end

Expand Down Expand Up @@ -78,16 +79,6 @@ def parse(file) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,
{ header: header, locations: locations, journeys: journeys, unparsed: unparsed }
end

def parse_header(string)
{
file_type: string[0, 8],
version: "#{string[8, 2].to_i}.#{string[10, 2].to_i}",
file_originator: string[12, 32].strip!,
source_product: string[44, 16].strip!,
production_datetime: string[60, 14]
}
end

def parse_bank_holiday(string)
{
record_identity: string[0, 2],
Expand Down
48 changes: 48 additions & 0 deletions lib/atco/header.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

module Atco
# Atco::Header is a class to abstract ATCO-CIF Header data.
class Header
attr_accessor :file_type,
:version,
:file_originator,
:source_product,
:production_datetime

# Public: Parse a header line from an ATCO-CIF file.
# EXAMPLE:
# "ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n"
def self.parse(line)
data = {
file_type: line[0, 8],
version: "#{line[8, 2].to_i}.#{line[10, 2].to_i}",
file_originator: line[12, 32].strip!,
source_product: line[44, 16].strip!,
production_datetime: line[60, 14]
}
new(data)
end

def initialize(data)
@file_type = data[:file_type]
@version = data[:version]
@file_originator = data[:file_originator]
@source_product = data[:source_product]
@production_datetime = data[:production_datetime]
end

def attributes
{
file_type: @file_type,
version: @version,
file_originator: @file_originator,
source_product: @source_product,
production_datetime: @production_datetime
}
end

def to_json(*attrs)
attributes.to_json(*attrs)
end
end
end
2 changes: 1 addition & 1 deletion lib/atco/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Atco
VERSION = "1.0.7"
VERSION = "1.0.8"
end
96 changes: 0 additions & 96 deletions spec/atco_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,6 @@
expect(Atco::VERSION).not_to be nil
end

it "should parse header from fixture" do
result = Atco.parse("spec/fixtures/example.cif")
expect(result[:header]).to eq(
{
file_type: "ATCO-CIF",
file_originator: "Electronic Registration",
source_product: "MIA 4.20.18",
version: "5.0",
production_datetime: "20090915113809"
}
)
end

it "should parse locations from fixture" do
result = Atco.parse("spec/fixtures/example.cif")
expect(result[:header]).to eq(
{
file_type: "ATCO-CIF",
file_originator: "Electronic Registration",
source_product: "MIA 4.20.18",
version: "5.0",
production_datetime: "20090915113809"
}
)
end

it "should parse header" do
expect(Atco.parse_header("ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n")).to eq(
{
file_type: "ATCO-CIF",
version: "5.0",
file_originator: "Electronic Registration",
source_product: "MIA 4.20.18",
production_datetime: "20090915113809"
}
)
end

it "should parse bank holiday" do
expect(Atco.parse_bank_holiday("QHN20061225")).to eq(
{
Expand Down Expand Up @@ -159,62 +121,4 @@
}
)
end

describe "with example.cif" do # rubocop:disable Metrics/BlockLength
before(:all) do
@atco = Atco.parse("spec/fixtures/example.cif")
end

it "should parse 1 journey" do
expect(@atco[:journeys].size).to eq(1)
end

it "should parse journeys into Atco::Joruney objects" do
expect(@atco[:journeys]["139748"]).to be_a_kind_of(Atco::Journey)
end

it "should parse 6 stops for journey 139748" do
expect(@atco[:journeys]["139748"].stops.size).to eq(6)
end

it "should parse 2 locations" do
expect(@atco[:locations].size).to eq(2)
end

it "should output file as JSON" do
output = File.join(File.dirname(__FILE__), "artefacts", "test.json")
File.open(output, "w+") do |f|
f.flush
f.write(JSON.pretty_generate(@atco))
end

expect(File.exist?(output)).to be true

data = File.read(output)
json = JSON.parse(data)
expect(json).to be_a(Hash)
end

it "should return 17 unparsed lines" do
expect(@atco[:unparsed].size).to eq(17)
end

it "should not parse GS records" do
expect(@atco[:unparsed][0]).to eq(
{
line: "GS00001433 N Belfast Metro Ops 7000\n",
line_number: 3
}
)
end

it "should not parse GR records" do
expect(@atco[:unparsed][1]).to eq(
{
line: "GR00001433Donegall Square East 7000\n", # rubocop:disable Layout/LineLength
line_number: 4
}
)
end
end
end
File renamed without changes.
71 changes: 71 additions & 0 deletions spec/integration/translink_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

RSpec.describe "with example.cif" do # rubocop:disable Metrics/BlockLength
before(:all) do
@atco = Atco.parse("spec/fixtures/translink-example.cif")
end

it "should parse header from fixture" do
expect(@atco[:header].attributes).to eq(
{
file_type: "ATCO-CIF",
file_originator: "Electronic Registration",
source_product: "MIA 4.20.18",
version: "5.0",
production_datetime: "20090915113809"
}
)
end

it "should parse 1 journey" do
expect(@atco[:journeys].size).to eq(1)
end

it "should parse journeys into Atco::Joruney objects" do
expect(@atco[:journeys]["139748"]).to be_a_kind_of(Atco::Journey)
end

it "should parse 6 stops for journey 139748" do
expect(@atco[:journeys]["139748"].stops.size).to eq(6)
end

it "should parse 2 locations" do
expect(@atco[:locations].size).to eq(2)
end

it "should output file as JSON" do
output = File.join(File.dirname(__FILE__), "..", "artefacts", "test.json")
File.open(output, "w+") do |f|
f.flush
f.write(JSON.pretty_generate(@atco))
end

expect(File.exist?(output)).to be true

data = File.read(output)
json = JSON.parse(data)
expect(json).to be_a(Hash)
end

it "should return 17 unparsed lines" do
expect(@atco[:unparsed].size).to eq(17)
end

it "should not parse GS records" do
expect(@atco[:unparsed][0]).to eq(
{
line: "GS00001433 N Belfast Metro Ops 7000\n",
line_number: 3
}
)
end

it "should not parse GR records" do
expect(@atco[:unparsed][1]).to eq(
{
line: "GR00001433Donegall Square East 7000\n", # rubocop:disable Layout/LineLength
line_number: 4
}
)
end
end
30 changes: 30 additions & 0 deletions spec/unit/header_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

RSpec.describe Atco::Header do
before(:all) do
line = "ATCO-CIF0500Electronic Registration MIA 4.20.18 20090915113809\r\n"
@header = Atco::Header.parse(line)
end

it "should be a Header object" do
expect(@header).to be_a_kind_of(Atco::Header)
end

it "should parse header to attributes" do
expect(@header.attributes).to eq(
{
file_type: "ATCO-CIF",
version: "5.0",
file_originator: "Electronic Registration",
source_product: "MIA 4.20.18",
production_datetime: "20090915113809"
}
)
end

it "should parse header to json" do
expect(@header.to_json).to eq(
"{\"file_type\":\"ATCO-CIF\",\"version\":\"5.0\",\"file_originator\":\"Electronic Registration\",\"source_product\":\"MIA 4.20.18\",\"production_datetime\":\"20090915113809\"}" # rubocop:disable Metrics/LineLength
)
end
end

0 comments on commit 072db74

Please sign in to comment.