norma43_parser 2.1.1 → 3.1.0
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 +4 -4
- data/.github/workflows/ci.yml +22 -0
- data/.github/workflows/release.yml +33 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +26 -10
- data/Gemfile +2 -2
- data/Gemfile.lock +51 -51
- data/README.md +2 -0
- data/lib/norma43/models/account/spanish_iban.rb +107 -0
- data/lib/norma43/models/account.rb +63 -0
- data/lib/norma43/models/additional_currency.rb +22 -0
- data/lib/norma43/models/additional_item.rb +20 -0
- data/lib/norma43/models/document.rb +42 -0
- data/lib/norma43/models/mixins/attributes_assignment.rb +33 -0
- data/lib/norma43/models/transaction.rb +51 -0
- data/lib/norma43/models.rb +0 -78
- data/lib/norma43/version.rb +1 -1
- data/norma43_parser.gemspec +3 -6
- data/spec/example1_parse_spec.rb +1 -1
- data/spec/norma43/line_processors/account_end_spec.rb +1 -4
- data/spec/norma43/line_processors/account_start_spec.rb +3 -3
- data/spec/norma43/line_processors/additional_currency_spec.rb +3 -3
- data/spec/norma43/line_processors/{additional_items_spec.rb → additional_item_spec.rb} +3 -3
- data/spec/norma43/line_processors/document_end_spec.rb +3 -6
- data/spec/norma43/line_processors/document_start_spec.rb +3 -3
- data/spec/norma43/line_processors/transaction_spec.rb +3 -3
- data/spec/norma43/models/account/spanish_iban_spec.rb +107 -0
- data/spec/norma43/models/account_spec.rb +54 -0
- data/spec/norma43/models/document_spec.rb +35 -0
- data/spec/norma43/models/transaction_spec.rb +25 -0
- data/spec/norma43_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -0
- data/spec/support/shared_examples_for_models.rb +61 -0
- metadata +29 -37
data/lib/norma43/models.rb
CHANGED
@@ -1,86 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "virtus"
|
4
|
-
|
5
3
|
module Norma43
|
6
4
|
module Models
|
7
|
-
# forward declarations
|
8
|
-
class Account; end
|
9
|
-
class Transaction; end
|
10
|
-
class AdditionalItem; end
|
11
|
-
class AdditionalCurrency; end
|
12
5
|
DEBIT_CODE = 1
|
13
6
|
CREDIT_CODE = 2
|
14
|
-
|
15
|
-
class Document
|
16
|
-
include Virtus.model
|
17
|
-
|
18
|
-
attribute :id
|
19
|
-
attribute :created_at
|
20
|
-
attribute :delivery_number
|
21
|
-
attribute :file_type
|
22
|
-
attribute :name
|
23
|
-
attribute :number_of_lines
|
24
|
-
attribute :accounts, Array[Account]
|
25
|
-
|
26
|
-
def transaction_date
|
27
|
-
accounts.map(&:date).compact.first
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Account
|
32
|
-
include Virtus.model
|
33
|
-
|
34
|
-
attribute :bank_code
|
35
|
-
attribute :branch_code
|
36
|
-
attribute :account_number
|
37
|
-
attribute :start_date
|
38
|
-
attribute :end_date
|
39
|
-
attribute :balance_code
|
40
|
-
attribute :balance_amount
|
41
|
-
attribute :currency_code
|
42
|
-
attribute :information_mode_code
|
43
|
-
attribute :abbreviated_name
|
44
|
-
attribute :debit_entries
|
45
|
-
attribute :debit_amount
|
46
|
-
attribute :credit_entries
|
47
|
-
attribute :credit_amount
|
48
|
-
attribute :transactions, Array[Transaction]
|
49
|
-
end
|
50
|
-
|
51
|
-
class Transaction
|
52
|
-
include Virtus.model
|
53
|
-
|
54
|
-
attribute :origin_branch_code
|
55
|
-
attribute :transaction_date
|
56
|
-
attribute :value_date
|
57
|
-
attribute :shared_item
|
58
|
-
attribute :own_item
|
59
|
-
attribute :amount_code
|
60
|
-
attribute :amount
|
61
|
-
attribute :document_number
|
62
|
-
attribute :reference_1
|
63
|
-
attribute :reference_2
|
64
|
-
attribute :additional_items, Array[AdditionalItem]
|
65
|
-
attribute :additional_currency, AdditionalCurrency
|
66
|
-
def debit?; self.amount_code == DEBIT_CODE end
|
67
|
-
end
|
68
|
-
|
69
|
-
class AdditionalItem
|
70
|
-
include Virtus.model
|
71
|
-
|
72
|
-
attribute :data_code
|
73
|
-
attribute :item_1
|
74
|
-
attribute :item_2
|
75
|
-
end
|
76
|
-
|
77
|
-
class AdditionalCurrency
|
78
|
-
include Virtus.model
|
79
|
-
|
80
|
-
attribute :data_code
|
81
|
-
attribute :currency_code
|
82
|
-
attribute :amount
|
83
|
-
attribute :free
|
84
|
-
end
|
85
7
|
end
|
86
8
|
end
|
data/lib/norma43/version.rb
CHANGED
data/norma43_parser.gemspec
CHANGED
@@ -13,17 +13,14 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/sequra/norma43_parser"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.required_ruby_version = "
|
16
|
+
spec.required_ruby_version = ">= 3.0"
|
17
17
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0")
|
19
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
20
|
spec.require_paths = ["lib"]
|
22
21
|
|
23
|
-
spec.add_runtime_dependency "virtus", "~> 1.0"
|
24
22
|
spec.add_runtime_dependency "zeitwerk", "~> 2.0"
|
25
23
|
|
26
|
-
spec.add_development_dependency "
|
27
|
-
spec.add_development_dependency "
|
28
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
29
26
|
end
|
data/spec/example1_parse_spec.rb
CHANGED
@@ -3,10 +3,7 @@
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
5
|
RSpec.describe AccountEnd do
|
6
|
-
let
|
7
|
-
double "Line", attributes: {}
|
8
|
-
end
|
9
|
-
|
6
|
+
let(:line) { instance_double(LineParsers::AccountEnd, attributes: {}) }
|
10
7
|
let(:account) { Norma43::Models::Account.new }
|
11
8
|
let(:contexts) { Norma43::Utils::Contexts.new(
|
12
9
|
[
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
|
-
RSpec.describe
|
6
|
-
let(:line) {
|
5
|
+
RSpec.describe AccountStart do
|
6
|
+
let(:line) { instance_double(LineParsers::AccountStart, attributes: {}) }
|
7
7
|
let(:document) { Norma43::Models::Document.new }
|
8
8
|
let(:contexts) { Norma43::Utils::Contexts.new }
|
9
9
|
|
@@ -20,7 +20,7 @@ module Norma43
|
|
20
20
|
end
|
21
21
|
|
22
22
|
context "when AccountStart is called" do
|
23
|
-
let(:fake_account) {
|
23
|
+
let(:fake_account) { instance_double(Norma43::Models::Account) }
|
24
24
|
before do
|
25
25
|
allow(Norma43::Models::Account).to receive(:new) { fake_account }
|
26
26
|
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
|
-
RSpec.describe
|
6
|
-
let(:line) {
|
5
|
+
RSpec.describe AdditionalCurrency do
|
6
|
+
let(:line) { instance_double(LineParsers::AdditionalCurrency, attributes: {}) }
|
7
7
|
let(:transaction) { Norma43::Models::Transaction.new }
|
8
8
|
let(:contexts) { Norma43::Utils::Contexts.new(
|
9
9
|
[
|
@@ -22,7 +22,7 @@ module Norma43
|
|
22
22
|
end
|
23
23
|
|
24
24
|
context "when AdditionalCurrency is called" do
|
25
|
-
let(:fake_additional_currency) {
|
25
|
+
let(:fake_additional_currency) { instance_double(Models::AdditionalCurrency) }
|
26
26
|
before do
|
27
27
|
allow(Models::AdditionalCurrency).to receive(:new) { fake_additional_currency }
|
28
28
|
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
|
-
RSpec.describe
|
6
|
-
let(:line) {
|
5
|
+
RSpec.describe AdditionalItem do
|
6
|
+
let(:line) { instance_double(LineParsers::AdditionalItem, attributes: {}) }
|
7
7
|
let(:transaction) { Norma43::Models::Transaction.new }
|
8
8
|
let(:contexts) { Norma43::Utils::Contexts.new(
|
9
9
|
[
|
@@ -22,7 +22,7 @@ module Norma43
|
|
22
22
|
end
|
23
23
|
|
24
24
|
context "when AdditionalItem is called" do
|
25
|
-
let(:fake_additional_item) {
|
25
|
+
let(:fake_additional_item) { instance_double(Models::AdditionalItem) }
|
26
26
|
before do
|
27
27
|
allow(Models::AdditionalItem).to receive(:new) { fake_additional_item }
|
28
28
|
end
|
@@ -2,15 +2,12 @@
|
|
2
2
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
|
-
RSpec.describe
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
let(:line) { double "Line", record_number: 35 }
|
5
|
+
RSpec.describe DocumentEnd do
|
6
|
+
let(:line) { instance_double(LineParsers::DocumentEnd, record_number: 35) }
|
10
7
|
|
11
8
|
it "moves to the nearest document context" do
|
12
9
|
document = Norma43::Models::Document.new
|
13
|
-
contexts = Norma43::Utils::Contexts.new [
|
10
|
+
contexts = Norma43::Utils::Contexts.new [anything, document, anything, anything]
|
14
11
|
|
15
12
|
DocumentEnd.call line, contexts
|
16
13
|
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
|
-
RSpec.describe
|
6
|
-
let
|
5
|
+
RSpec.describe DocumentStart do
|
6
|
+
let(:line) { instance_double(LineParsers::DocumentStart, attributes: {}) }
|
7
7
|
|
8
8
|
it "instantiates a new document with the line attributes" do
|
9
9
|
allow(Models::Document).to receive :new
|
@@ -14,7 +14,7 @@ module Norma43
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "sets the document as the current context" do
|
17
|
-
fake_document =
|
17
|
+
fake_document = instance_double(Models::Document)
|
18
18
|
allow(Models::Document).to receive(:new) { fake_document }
|
19
19
|
|
20
20
|
contexts = DocumentStart.call line, Norma43::Utils::Contexts.new
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Norma43
|
4
4
|
module LineProcessors
|
5
|
-
RSpec.describe
|
6
|
-
let(:line) {
|
5
|
+
RSpec.describe Transaction do
|
6
|
+
let(:line) { instance_double(LineParsers::Transaction, attributes: {}) }
|
7
7
|
let(:account) { Norma43::Models::Account.new }
|
8
8
|
let(:contexts) { Norma43::Utils::Contexts.new(
|
9
9
|
[
|
@@ -22,7 +22,7 @@ module Norma43
|
|
22
22
|
end
|
23
23
|
|
24
24
|
context "when Transaction is called" do
|
25
|
-
let(:fake_transaction) {
|
25
|
+
let(:fake_transaction) { instance_double(Models::Transaction) }
|
26
26
|
before do
|
27
27
|
allow(Models::Transaction).to receive(:new) { fake_transaction }
|
28
28
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Norma43
|
4
|
+
module Models
|
5
|
+
class Account
|
6
|
+
RSpec.describe SpanishIban do
|
7
|
+
def build_account(**attributes)
|
8
|
+
instance_double(Account, **attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".from_account" do
|
12
|
+
subject(:iban) { described_class.from_account(account) }
|
13
|
+
|
14
|
+
context "with the example in the documentation" do
|
15
|
+
let(:account) { build_account(bank_code: 81, branch_code: 54, account_number: 1234567) }
|
16
|
+
it { is_expected.to eq("ES5400810054180001234567") }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with the account from the example1.n43 fixture" do
|
20
|
+
let(:account) {
|
21
|
+
file.seek 2
|
22
|
+
bank_code = file.read(4).to_i
|
23
|
+
branch_code = file.read(4).to_i
|
24
|
+
account_number = file.read(10).to_i
|
25
|
+
|
26
|
+
build_account(bank_code: bank_code, branch_code: branch_code, account_number: account_number)
|
27
|
+
}
|
28
|
+
let(:file) { File.open(File.join(__dir__, "../../../fixtures/example1.n43"), encoding: "iso-8859-1") }
|
29
|
+
|
30
|
+
it { is_expected.to eq("ES1799991111710123456789") }
|
31
|
+
|
32
|
+
after { file.close }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with minimal edge-case" do
|
36
|
+
let(:account) { build_account(bank_code: 3, branch_code: 0, account_number: 0) }
|
37
|
+
it { is_expected.to eq("ES8700030000300000000000") }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with extreme edge-case" do
|
41
|
+
let(:account) { build_account(bank_code: 9000, branch_code: 9999, account_number: 9999999999) }
|
42
|
+
it { is_expected.to eq("ES3790009999309999999999") }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#to_s" do
|
47
|
+
subject { described_class.new(bank_code: 0, branch_code: 0, account_number: 0) }
|
48
|
+
|
49
|
+
it { is_expected.to(respond_to(:to_s)) }
|
50
|
+
|
51
|
+
context "with incorrect account values" do
|
52
|
+
subject { described_class.new(bank_code: bank_code, branch_code: branch_code, account_number: account_number).to_s }
|
53
|
+
|
54
|
+
let(:bank_code) { 9999 }
|
55
|
+
let(:branch_code) { 1111 }
|
56
|
+
let(:account_number) { 123456789 }
|
57
|
+
|
58
|
+
context "with missing bank code" do
|
59
|
+
let(:bank_code) { nil }
|
60
|
+
it { is_expected.to be_empty }
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with missing branch code" do
|
64
|
+
let(:branch_code) { nil }
|
65
|
+
it { is_expected.to be_empty }
|
66
|
+
end
|
67
|
+
|
68
|
+
context "with missing account number" do
|
69
|
+
let(:account_number) { nil }
|
70
|
+
it { is_expected.to be_empty }
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with negative bank code" do
|
74
|
+
let(:bank_code) { -3 }
|
75
|
+
it { is_expected.to be_empty }
|
76
|
+
end
|
77
|
+
|
78
|
+
context "with negative branch code" do
|
79
|
+
let(:bank_code) { -1 }
|
80
|
+
it { is_expected.to be_empty }
|
81
|
+
end
|
82
|
+
|
83
|
+
context "with negative account number" do
|
84
|
+
let(:account_number) { -123456789 }
|
85
|
+
it { is_expected.to be_empty }
|
86
|
+
end
|
87
|
+
|
88
|
+
context "with more than 4 digits in the bank code" do
|
89
|
+
let(:bank_code) { 99990 }
|
90
|
+
it { is_expected.to be_empty }
|
91
|
+
end
|
92
|
+
|
93
|
+
context "with more than 4 digits in the branch code" do
|
94
|
+
let(:bank_code) { 11110 }
|
95
|
+
it { is_expected.to be_empty }
|
96
|
+
end
|
97
|
+
|
98
|
+
context "with more than 10 digits in the account number" do
|
99
|
+
let(:account_number) { 12345678900 }
|
100
|
+
it { is_expected.to be_empty }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Norma43
|
4
|
+
module Models
|
5
|
+
RSpec.describe Account do
|
6
|
+
it_behaves_like "a model"
|
7
|
+
|
8
|
+
describe "#iban" do
|
9
|
+
it { is_expected.to respond_to(:iban) }
|
10
|
+
|
11
|
+
context "with the example in the documentation" do
|
12
|
+
it "returns the correct IBAN string" do
|
13
|
+
account = subject
|
14
|
+
account.account_number = 1234567
|
15
|
+
account.bank_code = 81
|
16
|
+
account.branch_code = 54
|
17
|
+
|
18
|
+
expect(account.iban).to eq("ES5400810054180001234567")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with missing bank data" do
|
23
|
+
subject { described_class.new.iban }
|
24
|
+
it { is_expected.to be_nil }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with missing bank code" do
|
28
|
+
subject { described_class.new(bank_code: nil, branch_code: 1234, account_number: 1234).iban }
|
29
|
+
it { is_expected.to be_nil }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with missing branch code" do
|
33
|
+
subject { described_class.new(bank_code: 1234, branch_code: nil, account_number: 1234).iban }
|
34
|
+
it { is_expected.to be_nil }
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with missing account number" do
|
38
|
+
subject { described_class.new(bank_code: 1234, branch_code: 1234, account_number: nil).iban }
|
39
|
+
it { is_expected.to be_nil }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with negative account number" do
|
43
|
+
subject { described_class.new(bank_code: 1234, branch_code: 1234, account_number: -1234).iban }
|
44
|
+
it { is_expected.to be_nil }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with an account number which is too large" do
|
48
|
+
subject { described_class.new(bank_code: 1234, branch_code: 1234, account_number: 1*10**10).iban }
|
49
|
+
it { is_expected.to be_nil }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Norma43
|
4
|
+
module Models
|
5
|
+
RSpec.describe Document do
|
6
|
+
it_behaves_like "a model"
|
7
|
+
|
8
|
+
describe "#transaction_date" do
|
9
|
+
it { is_expected.to respond_to(:transaction_date) }
|
10
|
+
|
11
|
+
context "when there are no accounts" do
|
12
|
+
subject(:document) { described_class.new({ accounts: [] }) }
|
13
|
+
|
14
|
+
it { expect(document.transaction_date).to be_nil }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when there are accounts" do
|
18
|
+
subject(:document) { described_class.new({ accounts: [account] }) }
|
19
|
+
|
20
|
+
let(:account) {
|
21
|
+
Account.new(transactions: [
|
22
|
+
nil,
|
23
|
+
Transaction.new(transaction_date: nil),
|
24
|
+
Transaction.new(transaction_date: Date.parse("2024-01-23")),
|
25
|
+
])
|
26
|
+
}
|
27
|
+
|
28
|
+
it "returns the date of the first account with a transaction date" do
|
29
|
+
expect(document.transaction_date).to eq(Date.parse("2024-01-23"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Norma43
|
4
|
+
module Models
|
5
|
+
RSpec.describe Transaction do
|
6
|
+
it_behaves_like "a model"
|
7
|
+
|
8
|
+
describe "#debit?" do
|
9
|
+
it { is_expected.to respond_to(:debit?) }
|
10
|
+
|
11
|
+
context "when amount code is code for debits" do
|
12
|
+
subject(:transaction) { described_class.new(amount_code: 1) }
|
13
|
+
|
14
|
+
it { expect(transaction.debit?).to be_truthy }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when amount code is code for credits" do
|
18
|
+
subject(:transaction) { described_class.new(amount_code: 2) }
|
19
|
+
|
20
|
+
it { expect(transaction.debit?).to be_falsey }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/spec/norma43_spec.rb
CHANGED
@@ -6,7 +6,7 @@ RSpec.describe Norma43 do
|
|
6
6
|
describe "#parse" do
|
7
7
|
it "returns the parser results" do
|
8
8
|
text = "some total-in text"
|
9
|
-
parser =
|
9
|
+
parser = instance_double(Norma43::Parser, result: "result")
|
10
10
|
expect(Norma43::Parser).to receive(:new).with(text) { parser }
|
11
11
|
|
12
12
|
expect(Norma43.parse(text)).to eq "result"
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "norma43"
|
4
|
+
|
3
5
|
RSpec.configure do |config|
|
4
6
|
config.order = :random
|
5
7
|
Kernel.srand config.seed
|
@@ -11,6 +13,7 @@ RSpec.configure do |config|
|
|
11
13
|
config.mock_with :rspec do |mocks|
|
12
14
|
mocks.syntax = :expect
|
13
15
|
mocks.verify_partial_doubles = true
|
16
|
+
mocks.verify_doubled_constant_names = true
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_examples "a model" do
|
4
|
+
it { is_expected.to respond_to(:attributes) }
|
5
|
+
it { is_expected.to respond_to(:attributes=) }
|
6
|
+
it { is_expected.to respond_to(:to_h) }
|
7
|
+
it { is_expected.to respond_to(:to_hash) }
|
8
|
+
|
9
|
+
describe "#new" do
|
10
|
+
subject(:model) { described_class.new(attributes) }
|
11
|
+
|
12
|
+
context "when instantiated with an empty hash" do
|
13
|
+
let(:attributes) { {} }
|
14
|
+
|
15
|
+
it "accepts it without failing" do
|
16
|
+
expect { model }.not_to raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#attributes" do
|
22
|
+
subject { described_class.new.attributes }
|
23
|
+
|
24
|
+
it { is_expected.not_to be_empty }
|
25
|
+
it { is_expected.to respond_to(:each_pair) }
|
26
|
+
it { is_expected.to respond_to(:to_h) }
|
27
|
+
it { is_expected.to respond_to(:to_hash) }
|
28
|
+
it { is_expected.to respond_to(:keys) }
|
29
|
+
|
30
|
+
describe "#attributes.keys" do
|
31
|
+
subject { super().keys }
|
32
|
+
|
33
|
+
it { is_expected.not_to be_empty }
|
34
|
+
it { is_expected.to all(be_a(Symbol)) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#attributes=" do
|
39
|
+
subject { described_class.new.attributes=(attributes) }
|
40
|
+
|
41
|
+
context "when passed an empty hash" do
|
42
|
+
let(:attributes) { {} }
|
43
|
+
|
44
|
+
it "accepts it without failing" do
|
45
|
+
expect { subject }.not_to raise_error
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when passed a hash with unknown attribute names" do
|
50
|
+
let(:attributes) { { potato: nil } }
|
51
|
+
|
52
|
+
it "accepts it without failing" do
|
53
|
+
expect { subject }.not_to raise_error
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not set any new method" do
|
57
|
+
expect { subject.potato }.to raise_error(NoMethodError, /undefined method.+potato/i)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|