Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: refactor ♻️ adding Atco::Header record type, separate unit & integration tests and name translink specs #15

Merged
merged 4 commits into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading