From 65b5bb7928e60e75ee7fab335a5612532b26b9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Junstr=C3=B6m?= Date: Sat, 16 Jun 2018 23:20:22 +0200 Subject: [PATCH 1/5] Less mocking --- spec/fixtures/total_in_full_utf_8.txt | 61 +++++++++++++++++++ .../line_processors/account_end_spec.rb | 23 ++++--- .../line_processors/account_start_spec.rb | 31 ++++------ .../line_processors/international_spec.rb | 36 ++++------- 4 files changed, 100 insertions(+), 51 deletions(-) create mode 100644 spec/fixtures/total_in_full_utf_8.txt diff --git a/spec/fixtures/total_in_full_utf_8.txt b/spec/fixtures/total_in_full_utf_8.txt new file mode 100644 index 0000000..0f9f26c --- /dev/null +++ b/spec/fixtures/total_in_full_utf_8.txt @@ -0,0 +1,61 @@ +00TI222222 2011102504133012345601TL1TOTALIN +1010181 SEK20111024 +2038952344444 00000000030255022222333334444451 +3038952345678 38952145778 +40FAKTURANR:38952344444 INTERN REF: 9780858 +40FAKTURANR:38952345678 38952145778ABC +601234567 19999999999 +61TESTBOLAGET AB +62GATAN 12 +6312345 TESTSTAD +200000000000000000000000000 00000000042973522222333334444455 +40TACK FÖR LÅNET +50FÖRETAGET AB FRISKVÅRDAVD. +6099999999 +61FÖRETAGET AB +62GATAN 7 +6388888 TESTORTEN +200000000000000000000000000 0000000002109002222233333444446734523455 +40BETALNING FÖR VARA 123 +50TESTFABRIKEN AB +51GATAN 22 +5211111 TESTVIKEN +6098765433 29999999999 +61NORDEA BANK AB +6310571 STOCKHOLM +200000000000000000000000000 00000000014836522222333334444472 +601222211 19999999999 +2038952345555 00000000088000022222333334444423 +40FAKT 38952345555,FAKTURANR +602232567 19999999999 +70000000000000000 000000000100000EUR000000088000 +25987654123 00000000005255022222333334444457 +40FAKTURA NR: 987654123 ABC KUNDNR: 123 +40ÅTERBETALNING +601234567 19999999999 +61TESTBOLAGET AB +62GATAN 12 +6312345 TESTSTAD +90000000060000000000191900020111024001 +109690017 SEK20111024 +200000000000000000000000000 00000000092343411111222223333344 +40BETALNING AVSEENDE KÖP 110902 +601234567 19999999999 +61TESTBOLAGET AB +62GATAN 12 +6312345 TESTSTAD +2038952678900 00000000001050022222333334444477 +50TESTFÖRETAG ENHET 2.A +6054321 19999999999 +61TESTFÖRETAG +62TESTV 55 +6312345 TESTSTAD +2038952678888 00000000002050022222333334444422 +3038952345999 +40FAKTNR=38952348888 OCH FAKTNR=38952345999 +6098765555 19999999999 +61TESTER AB +62VÄGEN 1 +6388888 TESTORTEN +90000000030000000000095443420111024001 +99000000000000061 diff --git a/spec/total_in/line_processors/account_end_spec.rb b/spec/total_in/line_processors/account_end_spec.rb index 66d0806..7c770e9 100644 --- a/spec/total_in/line_processors/account_end_spec.rb +++ b/spec/total_in/line_processors/account_end_spec.rb @@ -3,13 +3,17 @@ module TotalIn module LineProcessors - RSpec.describe "AccountEnd" do + RSpec.describe AccountEnd do let :line do - double "Line", attributes: {} + double "LineParsers::AccountEnd", attributes: { + number_of_transactions: 1, + amount: 20, + statement_reference: "123" + } end let :account do - Document::Account.new + Document::Account.new account_number: "213" end let :contexts do @@ -17,17 +21,20 @@ module LineProcessors end it "moves to the nearest account and assigns the line attributes" do - allow(account).to receive :assign_attributes - AccountEnd.call line, contexts - expect(account).to have_received(:assign_attributes).with line.attributes + expect(account.attributes).to eq({ + account_number: "213", + number_of_transactions: 1, + amount: 20, + statement_reference: "123" + }) end it "sets the account as the current context" do - new_contexts = AccountEnd.call line, contexts + c = AccountEnd.call line, contexts - expect(new_contexts.current).to be account + expect(c.current).to be account end end end diff --git a/spec/total_in/line_processors/account_start_spec.rb b/spec/total_in/line_processors/account_start_spec.rb index 3aca012..e1bab1f 100644 --- a/spec/total_in/line_processors/account_start_spec.rb +++ b/spec/total_in/line_processors/account_start_spec.rb @@ -5,7 +5,11 @@ module TotalIn module LineProcessors RSpec.describe "AccountStart" do let :line do - double "Line", attributes: {} + double "LineParsers::AccountStart", attributes: { + account_number: "12345", + currency: "SEK", + date: Date.new + } end let :document do @@ -21,29 +25,20 @@ module LineProcessors end it "instantiates a new account with the line attributes" do - allow(Document::Account).to receive :new + c = AccountStart.call line, contexts + account = c.current - AccountStart.call line, contexts - - expect(Document::Account).to have_received(:new).with line.attributes + expect(account).to be_a Document::Account + expect(account.attributes).to eq line.attributes end it "adds the account to the document" do - fake_account = double "Document::Account" - allow(Document::Account).to receive(:new) { fake_account } - - AccountStart.call line, contexts - - expect(document.accounts).to include fake_account - end - - it "sets the account as the current context" do - fake_account = double "Document::Account" - allow(Document::Account).to receive(:new) { fake_account } + expect(document.accounts).to be_empty - new_contexts = AccountStart.call line, contexts + c = AccountStart.call line, contexts - expect(new_contexts.current).to be fake_account + expect(document.accounts.size).to eq 1 + expect(document.accounts.first).to eq c.current end end end diff --git a/spec/total_in/line_processors/international_spec.rb b/spec/total_in/line_processors/international_spec.rb index c89576b..8dd71e0 100644 --- a/spec/total_in/line_processors/international_spec.rb +++ b/spec/total_in/line_processors/international_spec.rb @@ -5,41 +5,27 @@ module TotalIn module LineProcessors RSpec.describe "International" do let :line do - double "Line", attributes: {} - end - - let :transaction do - Document::Transaction.new + double "LineParsers::International", attributes: { cost: 20, amount: 300 } end let :contexts do - Contexts.new transaction - end - - it "instantiates a new International with the line attributes" do - international = double "Document::International" - allow(Document::International).to receive(:new) { international } - - International.call line, contexts - - expect(Document::International).to have_received(:new).with line.attributes + Contexts.new Document::Transaction.new end - it "assigns the international instance to the transaction" do - international = double "Document::International" - allow(Document::International).to receive(:new) { international } + it "moves to the nearest transaction" do + contexts.add Document::Sender.new - International.call line, contexts + c = International.call line, contexts - expect(transaction.international).to be international + expect(c.current).to be_a Document::Transaction end - it "moves to the nearest transaction" do - contexts.add Document::Sender.new - - new_contexts = International.call line, contexts + it "assigns the transaction a new International with the line's attributes" do + c = International.call line, contexts + international = c.current.international - expect(new_contexts.current).to be transaction + expect(international).to be_a Document::International + expect(international.attributes).to eq line.attributes end end end From 27e8185a7f573313321ded444c8d8ef324c4cad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Junstr=C3=B6m?= Date: Mon, 25 Jun 2018 08:44:23 +0200 Subject: [PATCH 2/5] Remove context in favour of functions and iterator Bumps ruby to latest --- .ruby-version | 2 +- lib/total_in/contexts.rb | 54 ----- lib/total_in/line_handlers.rb | 99 -------- lib/total_in/line_parsers.rb | 32 ++- lib/total_in/line_processors.rb | 135 ----------- lib/total_in/parser.rb | 226 ++++++++++++++++-- .../line_parsers/sender_account_spec.rb | 4 +- .../line_processors/account_end_spec.rb | 42 ---- .../line_processors/account_start_spec.rb | 45 ---- .../line_processors/addresses_spec.rb | 44 ---- .../line_processors/deduction_start_spec.rb | 54 ----- .../line_processors/document_end_spec.rb | 32 --- .../line_processors/document_start_spec.rb | 29 --- .../line_processors/international_spec.rb | 32 --- .../total_in/line_processors/locality_spec.rb | 46 ---- .../total_in/line_processors/messages_spec.rb | 25 -- spec/total_in/line_processors/names_spec.rb | 45 ---- .../line_processors/payment_start_spec.rb | 53 ---- .../line_processors/reference_numbers_spec.rb | 24 -- .../line_processors/sender_account_spec.rb | 46 ---- total-in.gemspec | 2 +- 21 files changed, 242 insertions(+), 829 deletions(-) delete mode 100644 lib/total_in/contexts.rb delete mode 100644 lib/total_in/line_handlers.rb delete mode 100644 lib/total_in/line_processors.rb delete mode 100644 spec/total_in/line_processors/account_end_spec.rb delete mode 100644 spec/total_in/line_processors/account_start_spec.rb delete mode 100644 spec/total_in/line_processors/addresses_spec.rb delete mode 100644 spec/total_in/line_processors/deduction_start_spec.rb delete mode 100644 spec/total_in/line_processors/document_end_spec.rb delete mode 100644 spec/total_in/line_processors/document_start_spec.rb delete mode 100644 spec/total_in/line_processors/international_spec.rb delete mode 100644 spec/total_in/line_processors/locality_spec.rb delete mode 100644 spec/total_in/line_processors/messages_spec.rb delete mode 100644 spec/total_in/line_processors/names_spec.rb delete mode 100644 spec/total_in/line_processors/payment_start_spec.rb delete mode 100644 spec/total_in/line_processors/reference_numbers_spec.rb delete mode 100644 spec/total_in/line_processors/sender_account_spec.rb diff --git a/.ruby-version b/.ruby-version index 5859406..73462a5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.2.3 +2.5.1 diff --git a/lib/total_in/contexts.rb b/lib/total_in/contexts.rb deleted file mode 100644 index 36498bd..0000000 --- a/lib/total_in/contexts.rb +++ /dev/null @@ -1,54 +0,0 @@ -module TotalIn - class Contexts - def initialize containers = nil - Array(containers).compact.each do |container| - add container - end - end - - def result - contexts.first - end - - def current - contexts.last - end - - def add container - contexts.push container - end - - def move_up - contexts.pop - end - - def move_to container_class - until current.is_a?(container_class) - move_up - end if contexts.any? - end - - def move_to_or_add_to_parent container_class, parent_container_class - return self if current.is_a?(container_class) - - until current.kind_of?(parent_container_class) - move_up - end - - entity = container_class.new - - setter_name = StringHelpers.underscore container_class.name.split("::").last - current.public_send "#{setter_name}=", entity - - add entity - - self - end - - private - - def contexts - @contexts ||= [] - end - end -end diff --git a/lib/total_in/line_handlers.rb b/lib/total_in/line_handlers.rb deleted file mode 100644 index 17f40b0..0000000 --- a/lib/total_in/line_handlers.rb +++ /dev/null @@ -1,99 +0,0 @@ -require "total_in/line_parsers" -require "total_in/line_processors" - -module TotalIn - module LineHandlers - def self.mapping - { - "00" => self.document_start, - "99" => self.document_end, - "10" => self.account_start, - "90" => self.account_end, - "20" => self.payment_start, - "25" => self.deduction_start, - "30" => self.reference_numbers, - "40" => self.messages, - "50" => self.sender_names, - "51" => self.sender_address, - "52" => self.sender_locality, - "60" => self.sender_account_start, - "61" => self.sender_account_names, - "62" => self.sender_account_address, - "63" => self.sender_account_locality, - "70" => self.international - } - end - - def self.document_start - Handler.new LineParsers::DocumentStart, LineProcessors::DocumentStart - end - - def self.document_end - Handler.new LineParsers::DocumentEnd, LineProcessors::DocumentEnd - end - - def self.account_start - Handler.new LineParsers::AccountStart, LineProcessors::AccountStart - end - - def self.account_end - Handler.new LineParsers::AccountEnd, LineProcessors::AccountEnd - end - - def self.payment_start - Handler.new LineParsers::PaymentStart, LineProcessors::PaymentStart - end - - def self.deduction_start - Handler.new LineParsers::DeductionStart, LineProcessors::DeductionStart - end - - def self.reference_numbers - Handler.new LineParsers::ReferenceNumbers, LineProcessors::ReferenceNumbers - end - - def self.messages - Handler.new LineParsers::Messages, LineProcessors::Messages - end - - def self.sender_names - Handler.new LineParsers::Names, LineProcessors::Names.new(Document::Sender) - end - - def self.sender_address - Handler.new LineParsers::Addresses, LineProcessors::Addresses.new(Document::Sender) - end - - def self.sender_locality - Handler.new LineParsers::Locality, LineProcessors::Locality.new(Document::Sender) - end - - def self.sender_account_start - Handler.new LineParsers::SenderAccount, LineProcessors::SenderAccount - end - - def self.sender_account_names - Handler.new LineParsers::Names, LineProcessors::Names.new(Document::SenderAccount) - end - - def self.sender_account_address - Handler.new LineParsers::Addresses, LineProcessors::Addresses.new(Document::SenderAccount) - end - - def self.sender_account_locality - Handler.new LineParsers::Locality, LineProcessors::Locality.new(Document::SenderAccount) - end - - def self.international - Handler.new LineParsers::International, LineProcessors::International - end - - Handler = Struct.new :parser, :processor do - def process line, contexts - line_parser = self.parser.new(line) - - processor.call line_parser, contexts - end - end - end -end diff --git a/lib/total_in/line_parsers.rb b/lib/total_in/line_parsers.rb index 9a50696..41ae095 100644 --- a/lib/total_in/line_parsers.rb +++ b/lib/total_in/line_parsers.rb @@ -2,6 +2,7 @@ module TotalIn module LineParsers + class DocumentStart < LineParser field :id, 2..13 field :created_at, 14..33, :time @@ -52,9 +53,15 @@ class Messages < Values end class Names < Values + def full_name + values.join(" ") + end end class Addresses < Values + def address + values.join(" ") + end end class Locality < LineParser @@ -63,7 +70,7 @@ class Locality < LineParser field :country_code, 46..47 end - class SenderAccount < LineParser + class SenderAccountStart < LineParser field :account_number, 2..37 field :origin_code, 38..38, :integer field :company_organization_number, 39..58 @@ -76,5 +83,28 @@ class International < LineParser field :amount_currency, 53..55 field :exchange_rate, 56..67, :integer end + + PARSERS = { + document_start: DocumentStart, + account_start: AccountStart, + payment_start: PaymentStart, + deduction_start: DeductionStart, + reference_numbers: ReferenceNumbers, + messages: Messages, + sender_start: Names, + sender_address: Addresses, + sender_locality: Locality, + sender_account_start: SenderAccountStart, + sender_account_names: Names, + sender_account_address: Addresses, + sender_account_locality: Locality, + international: International, + account_end: AccountEnd, + document_end: DocumentEnd + } + + def self.parser_for_type type + PARSERS.fetch(type) + end end end diff --git a/lib/total_in/line_processors.rb b/lib/total_in/line_processors.rb deleted file mode 100644 index d9e116e..0000000 --- a/lib/total_in/line_processors.rb +++ /dev/null @@ -1,135 +0,0 @@ -require "total_in/document" - -module TotalIn - module LineProcessors - DocumentStart = ->(line, contexts) { - document = Document.new line.attributes - - contexts.add document - - contexts - } - - DocumentEnd = ->(line, contexts) { - contexts.move_to Document - - contexts.current.number_of_lines = line.number_of_lines - - contexts - } - - AccountStart = ->(line, contexts) { - contexts.move_to Document - - account = Document::Account.new line.attributes - - contexts.current.accounts << account - contexts.add account - - contexts - } - - AccountEnd = ->(line, contexts) { - contexts.move_to Document::Account - - contexts.current.assign_attributes line.attributes - - contexts - } - - PaymentStart = ->(line, contexts) { - contexts.move_to Document::Account - - payment = Document::Payment.new line.attributes - payment.reference_numbers << line.reference_number if line.reference_number - - contexts.current.payments << payment - - contexts.add payment - - contexts - } - - DeductionStart = ->(line, contexts) { - contexts.move_to Document::Account - - deduction = Document::Deduction.new line.attributes - deduction.reference_numbers << line.reference_number if line.reference_number - - contexts.current.deductions << deduction - contexts.add deduction - - contexts - } - - ReferenceNumbers = ->(line, contexts) { - contexts.current.reference_numbers.concat line.values - - contexts - } - - Messages = ->(line, contexts) { - line.values.each do |message| - contexts.current.add_message message - end - - contexts - } - - class WithTargetClass - attr_reader :target_class - - def initialize target_class - @target_class = target_class - end - end - - class Names < WithTargetClass - def call line, contexts - contexts.move_to_or_add_to_parent self.target_class, Document::Transaction - - contexts.current.name = line.values.join " " - - contexts - end - end - - class Addresses < WithTargetClass - def call line, contexts - contexts.move_to_or_add_to_parent self.target_class, Document::Transaction - - contexts.current.address = line.values.join " " - - contexts - end - end - - class Locality < WithTargetClass - def call line, contexts - contexts.move_to_or_add_to_parent self.target_class, Document::Transaction - - contexts.current.assign_attributes line.attributes - - contexts - end - end - - SenderAccount = ->(line, contexts) { - contexts.move_to_or_add_to_parent Document::SenderAccount, Document::Transaction - - contexts.current.assign_attributes line.attributes - - contexts - } - - International = ->(line, contexts) { - contexts.move_to Document::Transaction - - international = Document::International.new line.attributes - - contexts.current.international = international - - contexts - } - end -end diff --git a/lib/total_in/parser.rb b/lib/total_in/parser.rb index e77bb72..e12a2f4 100644 --- a/lib/total_in/parser.rb +++ b/lib/total_in/parser.rb @@ -1,11 +1,30 @@ require "total_in/file_format_validator" -require "total_in/line_handlers" -require "total_in/contexts" +require "total_in/line_parsers" +require "total_in/document" module TotalIn class InvalidFileFormatError < ArgumentError; end; class Parser + LINE_TYPES = { + 0 => :document_start, + 99 => :document_end, + 10 => :account_start, + 90 => :account_end, + 20 => :payment_start, + 25 => :deduction_start, + 30 => :reference_numbers, + 40 => :messages, + 50 => :sender_start, + 51 => :sender_address, + 52 => :sender_locality, + 60 => :sender_account_start, + 61 => :sender_account_names, + 62 => :sender_account_address, + 63 => :sender_account_locality, + 70 => :international + }.freeze + attr_reader :file # Parser.new accepts a File instance or a String @@ -15,12 +34,185 @@ def initialize file validate_file_format end - def result - contexts = self.lines.each_with_object(Contexts.new) do |line, c| - parse_line line, c + ParseRunner = ->(parsers:, context:, iterator:) { + loop do + line_type, line = iterator.peek + break unless parsers.key?(line_type) + iterator.next + + context = parsers.fetch(line_type).call(line, context, iterator) end - contexts.result + context + } + + PARSERS = { + document_start: ->(line, document, _) { + document.assign_attributes( + LineParsers::DocumentStart.new(line).attributes + ) + document + }, + account_start: ->(line, document, iterator) { + document.accounts << AccountParser.call(line, iterator) + document + }, + payment_start: ->(line, account, iterator) { + account.payments << PaymentParser.call(line, iterator) + account + }, + reference_numbers: ->(line, transaction, _) { + transaction.reference_numbers.concat( + LineParsers::ReferenceNumbers.new(line).values + ) + transaction + }, + messages: ->(line, transaction, _) { + LineParsers::Messages.new(line).values.each do |message| + transaction.add_message(message) + end + transaction + }, + sender_start: ->(line, transaction, iterator) { + transaction.sender = SenderParser.call(line, iterator) + transaction + }, + sender_address: ->(line, sender, _) { + sender.address = LineParsers::Addresses.new(line).address + sender + }, + sender_locality: ->(line, sender, _) { + sender.assign_attributes( + LineParsers::Locality.new(line).attributes + ) + sender + }, + sender_account_start: ->(line, payment, iterator) { + payment.sender_account = SenderAccountParser.call(line, iterator) + payment + }, + sender_account_names: ->(line, sender_account, _) { + sender_account.name = LineParsers::Names.new(line).full_name + sender_account + }, + sender_account_address: ->(line, sender_account, _) { + sender_account.address = LineParsers::Addresses.new(line).address + sender_account + }, + sender_account_locality: ->(line, sender_account, _) { + sender_account.assign_attributes( + LineParsers::Locality.new(line).attributes + ) + sender_account + }, + international: ->(line, transaction, _) { + transaction.international = Document::International.new( + LineParsers::International.new(line).attributes + ) + transaction + }, + deduction_start: ->(line, account, iterator) { + account.deductions << DeductionParser.call(line, iterator) + account + }, + account_end: ->(line, account, _) { + account.assign_attributes( + LineParsers::AccountEnd.new(line).attributes + ) + account + }, + document_end: ->(line, document, _) { + document.number_of_lines = LineParsers::DocumentEnd.new(line).number_of_lines + document + } + }.freeze + + DocumentParser = ->(line_iterator) { + ParseRunner.call( + context: Document.new, + iterator: line_iterator, + parsers: PARSERS.slice(:document_start, :account_start, :document_end) + ) + } + + AccountParser = ->(line, line_iterator) { + account = Document::Account.new(LineParsers::AccountStart.new(line).attributes) + + ParseRunner.call( + context: account, + iterator: line_iterator, + parsers: PARSERS.slice(:payment_start, :deduction_start, :account_end) + ) + } + + PaymentParser = ->(line, line_iterator) { + payment_line = LineParsers::PaymentStart.new(line) + payment = Document::Payment.new(payment_line.attributes) + payment.reference_numbers << payment_line.reference_number if payment_line.reference_number + + ParseRunner.call( + context: payment, + iterator: line_iterator, + parsers: PARSERS.slice( + :reference_numbers, + :messages, + :sender_start, + :sender_account_start, + :international + ) + ) + } + + DeductionParser = ->(line, line_iterator) { + deduction_line = LineParsers::DeductionStart.new(line) + deduction = Document::Deduction.new(deduction_line.attributes) + deduction.reference_numbers << deduction_line.reference_number if deduction_line.reference_number + + ParseRunner.call( + context: deduction, + iterator: line_iterator, + parsers: PARSERS.slice( + :reference_numbers, + :messages, + :sender_start, + :sender_account_start, + :international + ) + ) + } + + SenderParser = ->(line, line_iterator) { + sender = Document::Sender.new(name: LineParsers::Names.new(line).full_name ) + + ParseRunner.call( + context: sender, + iterator: line_iterator, + parsers: PARSERS.slice(:sender_address, :sender_locality) + ) + } + + SenderAccountParser = ->(line, line_iterator) { + sender_account = Document::SenderAccount.new( + LineParsers::SenderAccountStart.new(line).attributes + ) + + ParseRunner.call( + context: sender_account, + iterator: line_iterator, + parsers: PARSERS.slice( + :sender_account_names, + :sender_account_address, + :sender_account_locality + ) + ) + } + + def parse + DocumentParser.call(lines.lazy.map { |l| tokenize_line(l) }) + end + + def result + parse end protected @@ -29,26 +221,22 @@ def lines file.each_line end - private - def validate_file_format - unless FileFormatValidator.new(first_line).valid? - raise InvalidFileFormatError.new validator.errors.join(", ") + validator = FileFormatValidator.new(first_line) + + unless validator.valid? + raise InvalidFileFormatError.new(validator.errors.join(", ")) end end - # Look up a matching handler for the line and process it - # The process method on a handler always returns a Contexts object - def parse_line line, contexts - line = line.encode Encoding::UTF_8 if encode_lines? - - handler = handler_for_line line + def tokenize_line line + line = line.encode(Encoding::UTF_8) if encode_lines? - handler.process line, contexts + [line_type(line), line] end - def handler_for_line line - LineHandlers.mapping.fetch line[0..1] + def line_type line + LINE_TYPES.fetch(line[0..1].to_i) end def encode_lines? diff --git a/spec/total_in/line_parsers/sender_account_spec.rb b/spec/total_in/line_parsers/sender_account_spec.rb index 89f7bf6..4975b41 100644 --- a/spec/total_in/line_parsers/sender_account_spec.rb +++ b/spec/total_in/line_parsers/sender_account_spec.rb @@ -2,9 +2,9 @@ module TotalIn module LineParsers - RSpec.describe SenderAccount do + RSpec.describe SenderAccountStart do let :sender_account do - SenderAccount.new "6098765433 29999999999 " + SenderAccountStart.new "6098765433 29999999999 " end it "parses the account number" do diff --git a/spec/total_in/line_processors/account_end_spec.rb b/spec/total_in/line_processors/account_end_spec.rb deleted file mode 100644 index 7c770e9..0000000 --- a/spec/total_in/line_processors/account_end_spec.rb +++ /dev/null @@ -1,42 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe AccountEnd do - let :line do - double "LineParsers::AccountEnd", attributes: { - number_of_transactions: 1, - amount: 20, - statement_reference: "123" - } - end - - let :account do - Document::Account.new account_number: "213" - end - - let :contexts do - Contexts.new [Document.new, account, Document::Payment.new] - end - - it "moves to the nearest account and assigns the line attributes" do - AccountEnd.call line, contexts - - expect(account.attributes).to eq({ - account_number: "213", - number_of_transactions: 1, - amount: 20, - statement_reference: "123" - }) - end - - it "sets the account as the current context" do - c = AccountEnd.call line, contexts - - expect(c.current).to be account - end - end - end -end - diff --git a/spec/total_in/line_processors/account_start_spec.rb b/spec/total_in/line_processors/account_start_spec.rb deleted file mode 100644 index e1bab1f..0000000 --- a/spec/total_in/line_processors/account_start_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "AccountStart" do - let :line do - double "LineParsers::AccountStart", attributes: { - account_number: "12345", - currency: "SEK", - date: Date.new - } - end - - let :document do - Document.new - end - - let :contexts do - Contexts.new - end - - before do - contexts.add document - end - - it "instantiates a new account with the line attributes" do - c = AccountStart.call line, contexts - account = c.current - - expect(account).to be_a Document::Account - expect(account.attributes).to eq line.attributes - end - - it "adds the account to the document" do - expect(document.accounts).to be_empty - - c = AccountStart.call line, contexts - - expect(document.accounts.size).to eq 1 - expect(document.accounts.first).to eq c.current - end - end - end -end diff --git a/spec/total_in/line_processors/addresses_spec.rb b/spec/total_in/line_processors/addresses_spec.rb deleted file mode 100644 index fdcb550..0000000 --- a/spec/total_in/line_processors/addresses_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe Addresses do - let :line do - double "Line", values: ["one", "two"] - end - - describe "when the current context is a Document::Sender" do - it "sets the address to the sender" do - sender = Document::Sender.new - contexts = Contexts.new sender - - Addresses.new(Document::Sender).call line, contexts - - expect(sender.address).to eq "one two" - end - end - - describe "when the current context is something else" do - let! :sender do - Document::Sender.new - end - - before do - allow(Document::Sender).to receive(:new) { sender } - end - - it "adds a new Document::Sender to the nearest transaction and appends it to the contexts" do - transaction = Document::Transaction.new - contexts = Contexts.new transaction - - new_contexts = Addresses.new(Document::Sender).call line, contexts - - expect(sender.address).to eq "one two" - expect(transaction.sender).to eq sender - expect(new_contexts.current).to be sender - end - end - end - end -end diff --git a/spec/total_in/line_processors/deduction_start_spec.rb b/spec/total_in/line_processors/deduction_start_spec.rb deleted file mode 100644 index f5d328b..0000000 --- a/spec/total_in/line_processors/deduction_start_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "DeductionStart" do - let :line do - double "Line", attributes: {}, reference_number: "1234567890" - end - - let :account do - Document::Account.new - end - - let! :contexts do - Contexts.new [Document.new, account, Document::Deduction.new] - end - - it "adds a new deduction to the nearest account" do - deduction = Document::Deduction.new - allow(Document::Deduction).to receive(:new) { deduction } - - DeductionStart.call line, contexts - - expect(account.deductions).to include deduction - end - - it "sets the deduction as the current context" do - deduction = Document::Deduction.new - allow(Document::Deduction).to receive(:new) { deduction } - - new_contexts = DeductionStart.call line, contexts - - expect(new_contexts.current).to be deduction - end - - it "assigns the line attributes to the account" do - deduction = Document::Deduction.new - allow(Document::Deduction).to receive(:new) { deduction } - - DeductionStart.call line, contexts - - expect(Document::Deduction).to have_received(:new).with(line.attributes) - end - - it "adds the line reference number to the deduction" do - new_contexts = DeductionStart.call line, contexts - - expect(new_contexts.current.reference_numbers).to include "1234567890" - end - end - end -end - diff --git a/spec/total_in/line_processors/document_end_spec.rb b/spec/total_in/line_processors/document_end_spec.rb deleted file mode 100644 index 71bb42d..0000000 --- a/spec/total_in/line_processors/document_end_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "DocumentEnd" do - class Thing - end - - let :line do - double "Line", number_of_lines: 35 - end - - it "moves to the nearest document context" do - document = Document.new - contexts = Contexts.new [Thing.new, document, Thing.new, Thing.new] - - DocumentEnd.call line, contexts - - expect(contexts.current).to eq document - end - - it "sets the number of lines on the document" do - document = Document.new - - DocumentEnd.call line, Contexts.new(document) - - expect(document.number_of_lines).to eq 35 - end - end - end -end diff --git a/spec/total_in/line_processors/document_start_spec.rb b/spec/total_in/line_processors/document_start_spec.rb deleted file mode 100644 index 7da0ce0..0000000 --- a/spec/total_in/line_processors/document_start_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "DocumentStart" do - let :line do - double "Line", attributes: {} - end - - it "instantiates a new document with the line attributes" do - allow(Document).to receive :new - - DocumentStart.call line, Contexts.new - - expect(Document).to have_received(:new).with line.attributes - end - - it "sets the document as the current context" do - fake_document = double "Document" - allow(Document).to receive(:new) { fake_document } - - contexts = DocumentStart.call line, Contexts.new - - expect(contexts.current).to be fake_document - end - end - end -end diff --git a/spec/total_in/line_processors/international_spec.rb b/spec/total_in/line_processors/international_spec.rb deleted file mode 100644 index 8dd71e0..0000000 --- a/spec/total_in/line_processors/international_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "International" do - let :line do - double "LineParsers::International", attributes: { cost: 20, amount: 300 } - end - - let :contexts do - Contexts.new Document::Transaction.new - end - - it "moves to the nearest transaction" do - contexts.add Document::Sender.new - - c = International.call line, contexts - - expect(c.current).to be_a Document::Transaction - end - - it "assigns the transaction a new International with the line's attributes" do - c = International.call line, contexts - international = c.current.international - - expect(international).to be_a Document::International - expect(international.attributes).to eq line.attributes - end - end - end -end diff --git a/spec/total_in/line_processors/locality_spec.rb b/spec/total_in/line_processors/locality_spec.rb deleted file mode 100644 index 7252548..0000000 --- a/spec/total_in/line_processors/locality_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe Locality do - let :line do - double "Line", attributes: {} - end - - describe "when the current context is a Document::Sender" do - it "adds the line values to the sender as name" do - sender = Document::Sender.new - contexts = Contexts.new sender - allow(sender).to receive(:assign_attributes) - - Locality.new(Document::Sender).call line, contexts - - expect(sender).to have_received(:assign_attributes).with line.attributes - end - end - - describe "when the current context is something else" do - let! :sender do - Document::Sender.new - end - - before do - allow(Document::Sender).to receive(:new) { sender } - end - - it "adds a new Document::Sender to the nearest transaction and appends it to the contexts" do - transaction = Document::Transaction.new - contexts = Contexts.new transaction - allow(sender).to receive(:assign_attributes) - - new_contexts = Locality.new(Document::Sender).call line, contexts - - expect(transaction.sender).to eq sender - expect(new_contexts.current).to be sender - expect(sender).to have_received(:assign_attributes).with line.attributes - end - end - end - end -end diff --git a/spec/total_in/line_processors/messages_spec.rb b/spec/total_in/line_processors/messages_spec.rb deleted file mode 100644 index ee59a60..0000000 --- a/spec/total_in/line_processors/messages_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "Names" do - let :line do - double "Line", values: ["one", "two"] - end - - let :current_context do - double "SomeContext", add_message: nil - end - - it "adds the line values to the current context's reference_numbers" do - contexts = Contexts.new current_context - - Messages.call line, contexts - - expect(current_context).to have_received(:add_message).with "one" - expect(current_context).to have_received(:add_message).with "two" - end - end - end -end diff --git a/spec/total_in/line_processors/names_spec.rb b/spec/total_in/line_processors/names_spec.rb deleted file mode 100644 index 21904f5..0000000 --- a/spec/total_in/line_processors/names_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe Names do - let :line do - double "Line", values: ["one", "two"] - end - - describe "when the current context is a Document::Sender" do - it "adds the line values to the sender as name" do - sender = Document::Sender.new - contexts = Contexts.new sender - - Names.new(Document::Sender).call line, contexts - - expect(sender.name).to eq "one two" - end - end - - describe "when the current context is something else" do - let! :sender do - Document::Sender.new - end - - before do - allow(Document::Sender).to receive(:new) { sender } - end - - it "adds a new Document::Sender to the nearest transaction and appends it to the contexts" do - transaction = Document::Transaction.new - contexts = Contexts.new transaction - - new_contexts = Names.new(Document::Sender).call line, contexts - - expect(sender.name).to eq "one two" - expect(transaction.sender).to eq sender - expect(new_contexts.current).to be sender - end - end - end - end -end - diff --git a/spec/total_in/line_processors/payment_start_spec.rb b/spec/total_in/line_processors/payment_start_spec.rb deleted file mode 100644 index 74368f0..0000000 --- a/spec/total_in/line_processors/payment_start_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "PaymentStart" do - let :line do - double "Line", attributes: {}, reference_number: "1234567890" - end - - let :account do - Document::Account.new - end - - let! :contexts do - Contexts.new [Document.new, account, Document::Payment.new] - end - - it "adds a new payment to the nearest account" do - payment = Document::Payment.new - allow(Document::Payment).to receive(:new) { payment } - - PaymentStart.call line, contexts - - expect(account.payments).to include payment - end - - it "sets the payment as the current context" do - payment = Document::Payment.new - allow(Document::Payment).to receive(:new) { payment } - - new_contexts = PaymentStart.call line, contexts - - expect(new_contexts.current).to be payment - end - - it "assigns the line attributes to the account" do - payment = Document::Payment.new - allow(Document::Payment).to receive(:new) { payment } - - PaymentStart.call line, contexts - - expect(Document::Payment).to have_received(:new).with(line.attributes) - end - - it "adds the line reference number to the payment" do - new_contexts = PaymentStart.call line, contexts - - expect(new_contexts.current.reference_numbers).to include "1234567890" - end - end - end -end diff --git a/spec/total_in/line_processors/reference_numbers_spec.rb b/spec/total_in/line_processors/reference_numbers_spec.rb deleted file mode 100644 index 31eec0b..0000000 --- a/spec/total_in/line_processors/reference_numbers_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "ReferenceNumbers" do - let :line do - double "Line", values: ["one", "two"] - end - - let :current_context do - double "SomeContext", reference_numbers: ["original"] - end - - it "adds the line values to the current context's reference_numbers" do - contexts = Contexts.new current_context - - ReferenceNumbers.call line, contexts - - expect(contexts.current.reference_numbers).to eq ["original", "one", "two"] - end - end - end -end diff --git a/spec/total_in/line_processors/sender_account_spec.rb b/spec/total_in/line_processors/sender_account_spec.rb deleted file mode 100644 index 39cd579..0000000 --- a/spec/total_in/line_processors/sender_account_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require "total_in/contexts" -require "total_in/line_processors" - -module TotalIn - module LineProcessors - RSpec.describe "SenderAccount" do - let :line do - double "Line", attributes: {} - end - - describe "when the current context is a Document::SenderAccount" do - it "adds the line values to the sender as name" do - sender_account = Document::SenderAccount.new - contexts = Contexts.new sender_account - allow(sender_account).to receive(:assign_attributes) - - SenderAccount.call line, contexts - - expect(sender_account).to have_received(:assign_attributes).with line.attributes - end - end - - describe "when the current context is something else" do - let! :sender_account do - Document::SenderAccount.new - end - - before do - allow(Document::SenderAccount).to receive(:new) { sender_account } - end - - it "adds a new Document::SenderAccount to the nearest transaction and appends it to the contexts" do - transaction = Document::Transaction.new - contexts = Contexts.new transaction - allow(sender_account).to receive(:assign_attributes) - - new_contexts = SenderAccount.call line, contexts - - expect(transaction.sender_account).to eq sender_account - expect(new_contexts.current).to be sender_account - expect(sender_account).to have_received(:assign_attributes).with line.attributes - end - end - end - end -end diff --git a/total-in.gemspec b/total-in.gemspec index 6500cb5..e1f8c84 100644 --- a/total-in.gemspec +++ b/total-in.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/Oktavilla/total-in-ruby" spec.license = "MIT" - spec.required_ruby_version = "~> 2.0" + spec.required_ruby_version = "~> 2.5" spec.files = `git ls-files -z`.split("\x0") spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } From 90c143cbcc5a3f30f6d017792ca791ec00fae14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Junstr=C3=B6m?= Date: Mon, 25 Jun 2018 09:37:51 +0200 Subject: [PATCH 3/5] Rmeove unused helper --- lib/total_in/document.rb | 1 - lib/total_in/string_helpers.rb | 10 ---------- 2 files changed, 11 deletions(-) delete mode 100644 lib/total_in/string_helpers.rb diff --git a/lib/total_in/document.rb b/lib/total_in/document.rb index ea950fa..82b4705 100644 --- a/lib/total_in/document.rb +++ b/lib/total_in/document.rb @@ -1,4 +1,3 @@ -require "total_in/string_helpers" require "total_in/attribute_methods" module TotalIn diff --git a/lib/total_in/string_helpers.rb b/lib/total_in/string_helpers.rb deleted file mode 100644 index 5566512..0000000 --- a/lib/total_in/string_helpers.rb +++ /dev/null @@ -1,10 +0,0 @@ -module TotalIn - module StringHelpers - def self.underscore word - word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2') - word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') - word.tr!("-", "_") - word.downcase - end - end -end From 2642c7ea1c6a6b0e66dc63a349b2e5e53a69ec5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Junstr=C3=B6m?= Date: Mon, 25 Jun 2018 09:38:07 +0200 Subject: [PATCH 4/5] Correct rubby version in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c10d29f..9ead158 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: ruby rvm: -- 2.2.3 +- 2.5.1 script: bundle exec rspec spec addons: code_climate: From 41cb9ee262500192d04cc63574b25d194a19e390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Junstr=C3=B6m?= Date: Mon, 25 Jun 2018 09:40:36 +0200 Subject: [PATCH 5/5] Remove unused fixture --- spec/fixtures/total_in_full_utf_8.txt | 61 --------------------------- 1 file changed, 61 deletions(-) delete mode 100644 spec/fixtures/total_in_full_utf_8.txt diff --git a/spec/fixtures/total_in_full_utf_8.txt b/spec/fixtures/total_in_full_utf_8.txt deleted file mode 100644 index 0f9f26c..0000000 --- a/spec/fixtures/total_in_full_utf_8.txt +++ /dev/null @@ -1,61 +0,0 @@ -00TI222222 2011102504133012345601TL1TOTALIN -1010181 SEK20111024 -2038952344444 00000000030255022222333334444451 -3038952345678 38952145778 -40FAKTURANR:38952344444 INTERN REF: 9780858 -40FAKTURANR:38952345678 38952145778ABC -601234567 19999999999 -61TESTBOLAGET AB -62GATAN 12 -6312345 TESTSTAD -200000000000000000000000000 00000000042973522222333334444455 -40TACK FÖR LÅNET -50FÖRETAGET AB FRISKVÅRDAVD. -6099999999 -61FÖRETAGET AB -62GATAN 7 -6388888 TESTORTEN -200000000000000000000000000 0000000002109002222233333444446734523455 -40BETALNING FÖR VARA 123 -50TESTFABRIKEN AB -51GATAN 22 -5211111 TESTVIKEN -6098765433 29999999999 -61NORDEA BANK AB -6310571 STOCKHOLM -200000000000000000000000000 00000000014836522222333334444472 -601222211 19999999999 -2038952345555 00000000088000022222333334444423 -40FAKT 38952345555,FAKTURANR -602232567 19999999999 -70000000000000000 000000000100000EUR000000088000 -25987654123 00000000005255022222333334444457 -40FAKTURA NR: 987654123 ABC KUNDNR: 123 -40ÅTERBETALNING -601234567 19999999999 -61TESTBOLAGET AB -62GATAN 12 -6312345 TESTSTAD -90000000060000000000191900020111024001 -109690017 SEK20111024 -200000000000000000000000000 00000000092343411111222223333344 -40BETALNING AVSEENDE KÖP 110902 -601234567 19999999999 -61TESTBOLAGET AB -62GATAN 12 -6312345 TESTSTAD -2038952678900 00000000001050022222333334444477 -50TESTFÖRETAG ENHET 2.A -6054321 19999999999 -61TESTFÖRETAG -62TESTV 55 -6312345 TESTSTAD -2038952678888 00000000002050022222333334444422 -3038952345999 -40FAKTNR=38952348888 OCH FAKTNR=38952345999 -6098765555 19999999999 -61TESTER AB -62VÄGEN 1 -6388888 TESTORTEN -90000000030000000000095443420111024001 -99000000000000061