fortnox-api 0.6.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +4 -0
- data/.travis.yml +20 -15
- data/CHANGELOG.md +18 -0
- data/README.md +11 -19
- data/fortnox-api.gemspec +6 -6
- data/lib/fortnox/api/mappers.rb +5 -38
- data/lib/fortnox/api/mappers/base.rb +2 -24
- data/lib/fortnox/api/mappers/base/canonical_name_sym.rb +21 -0
- data/lib/fortnox/api/mappers/value/array.rb +18 -0
- data/lib/fortnox/api/mappers/value/country_code_string.rb +24 -0
- data/lib/fortnox/api/mappers/value/date.rb +11 -0
- data/lib/fortnox/api/mappers/value/hash.rb +16 -0
- data/lib/fortnox/api/mappers/value/identity.rb +18 -0
- data/lib/fortnox/api/models/document.rb +1 -1
- data/lib/fortnox/api/models/invoice.rb +1 -1
- data/lib/fortnox/api/models/order.rb +1 -1
- data/lib/fortnox/api/repositories/base.rb +9 -11
- data/lib/fortnox/api/request_handling.rb +0 -1
- data/lib/fortnox/api/types.rb +19 -3
- data/lib/fortnox/api/types/enums.rb +0 -23
- data/lib/fortnox/api/types/shim/country_code_string.rb +10 -0
- data/lib/fortnox/api/types/sized.rb +3 -16
- data/lib/fortnox/api/version.rb +1 -1
- data/spec/fortnox/api/circular_queue_spec.rb +52 -0
- data/spec/fortnox/api/mappers/base/canonical_name_sym_spec.rb +34 -0
- data/spec/fortnox/api/mappers/base_spec.rb +33 -43
- data/spec/fortnox/api/mappers/contexts/json_conversion.rb +1 -1
- data/spec/fortnox/api/repositories/article_spec.rb +4 -2
- data/spec/fortnox/api/repositories/base_spec.rb +28 -8
- data/spec/fortnox/api/repositories/customer_spec.rb +2 -1
- data/spec/fortnox/api/repositories/invoice_spec.rb +147 -3
- data/spec/fortnox/api/repositories/order_spec.rb +2 -2
- data/spec/fortnox/api/repositories/project_spec.rb +1 -1
- data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +4 -2
- data/spec/fortnox/api/repositories/unit_spec.rb +6 -3
- data/spec/fortnox/api/types/country_code_spec.rb +76 -0
- data/spec/fortnox/api/types/email_spec.rb +8 -7
- data/spec/fortnox/api/types/enums_spec.rb +0 -1
- data/spec/fortnox/api/types/examples/document_row.rb +1 -1
- data/spec/fortnox/api_spec.rb +3 -1
- data/spec/vcr_cassettes/articles/all.yml +22 -8
- data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +6 -6
- data/spec/vcr_cassettes/articles/find_failure.yml +6 -6
- data/spec/vcr_cassettes/articles/find_id_1.yml +7 -7
- data/spec/vcr_cassettes/articles/find_new.yml +9 -9
- data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +6 -6
- data/spec/vcr_cassettes/articles/save_new.yml +8 -8
- data/spec/vcr_cassettes/articles/save_old.yml +9 -9
- data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +8 -8
- data/spec/vcr_cassettes/articles/search_by_name.yml +6 -6
- data/spec/vcr_cassettes/articles/search_miss.yml +6 -6
- data/spec/vcr_cassettes/articles/search_with_special_char.yml +6 -6
- data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +18 -8
- data/spec/vcr_cassettes/customers/all.yml +9 -9
- data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +6 -6
- data/spec/vcr_cassettes/customers/find_failure.yml +6 -6
- data/spec/vcr_cassettes/customers/find_id_1.yml +7 -7
- data/spec/vcr_cassettes/customers/find_new.yml +9 -9
- data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +5 -5
- data/spec/vcr_cassettes/customers/save_new.yml +7 -7
- data/spec/vcr_cassettes/customers/save_old.yml +8 -8
- data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +7 -7
- data/spec/vcr_cassettes/customers/search_by_name.yml +16 -8
- data/spec/vcr_cassettes/customers/search_miss.yml +6 -6
- data/spec/vcr_cassettes/customers/search_with_special_char.yml +6 -6
- data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +7 -7
- data/spec/vcr_cassettes/invoices/all.yml +100 -65
- data/spec/vcr_cassettes/invoices/filter_hit.yml +11 -8
- data/spec/vcr_cassettes/invoices/filter_invalid.yml +6 -6
- data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +6 -6
- data/spec/vcr_cassettes/invoices/find_failure.yml +6 -6
- data/spec/vcr_cassettes/invoices/find_id_1.yml +7 -7
- data/spec/vcr_cassettes/invoices/find_new.yml +11 -12
- data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +8 -8
- data/spec/vcr_cassettes/invoices/save_new.yml +9 -10
- data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country.yml +46 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_KR.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +46 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +46 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +46 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +46 -0
- data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +46 -0
- data/spec/vcr_cassettes/invoices/save_old.yml +10 -11
- data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +48 -0
- data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +48 -0
- data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +9 -10
- data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +9 -10
- data/spec/vcr_cassettes/invoices/search_by_name.yml +13 -9
- data/spec/vcr_cassettes/invoices/search_miss.yml +6 -6
- data/spec/vcr_cassettes/invoices/search_with_special_char.yml +6 -6
- data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +9 -9
- data/spec/vcr_cassettes/orders/all.yml +105 -105
- data/spec/vcr_cassettes/orders/filter_hit.yml +13 -10
- data/spec/vcr_cassettes/orders/filter_invalid.yml +6 -6
- data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +6 -6
- data/spec/vcr_cassettes/orders/find_failure.yml +6 -6
- data/spec/vcr_cassettes/orders/find_id_1.yml +8 -8
- data/spec/vcr_cassettes/orders/find_new.yml +11 -12
- data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_construction.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_cooking.yml +6 -6
- data/spec/vcr_cassettes/orders/housework_type_electricity.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_gardening.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_hvac.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_masonry.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_othercare.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +9 -9
- data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +6 -6
- data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +7 -7
- data/spec/vcr_cassettes/orders/save_new.yml +9 -10
- data/spec/vcr_cassettes/orders/save_old.yml +10 -11
- data/spec/vcr_cassettes/orders/save_with_nested_model.yml +9 -10
- data/spec/vcr_cassettes/orders/search_by_name.yml +9 -8
- data/spec/vcr_cassettes/orders/search_miss.yml +6 -6
- data/spec/vcr_cassettes/orders/search_with_special_char.yml +6 -6
- data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +8 -8
- data/spec/vcr_cassettes/projects/all.yml +18 -8
- data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +6 -6
- data/spec/vcr_cassettes/projects/find_failure.yml +6 -6
- data/spec/vcr_cassettes/projects/find_id_1.yml +6 -6
- data/spec/vcr_cassettes/projects/find_new.yml +9 -9
- data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +7 -7
- data/spec/vcr_cassettes/projects/save_new.yml +8 -8
- data/spec/vcr_cassettes/projects/save_old.yml +8 -8
- data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +7 -7
- data/spec/vcr_cassettes/termsofpayments/all.yml +10 -7
- data/spec/vcr_cassettes/termsofpayments/find_failure.yml +6 -6
- data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +6 -6
- data/spec/vcr_cassettes/termsofpayments/find_new.yml +8 -8
- data/spec/vcr_cassettes/termsofpayments/save_new.yml +8 -8
- data/spec/vcr_cassettes/termsofpayments/save_old.yml +8 -8
- data/spec/vcr_cassettes/units/all.yml +14 -10
- data/spec/vcr_cassettes/units/find_failure.yml +6 -6
- data/spec/vcr_cassettes/units/find_id_1.yml +6 -6
- data/spec/vcr_cassettes/units/find_new.yml +8 -10
- data/spec/vcr_cassettes/units/save_new.yml +8 -10
- data/spec/vcr_cassettes/units/save_old.yml +8 -10
- data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +8 -10
- data/temp.txt +1 -0
- metadata +71 -13
data/lib/fortnox/api/types.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'dry-struct'
|
4
4
|
require 'dry-types'
|
5
|
+
require 'countries'
|
6
|
+
require 'fortnox/api/types/shim/country_code_string'
|
5
7
|
|
6
8
|
module Dry
|
7
9
|
module Types
|
@@ -24,6 +26,7 @@ module Fortnox
|
|
24
26
|
module API
|
25
27
|
module Types
|
26
28
|
include Dry::Types.module
|
29
|
+
ISO3166.configure { |config| config.locales = %i[en sv] }
|
27
30
|
|
28
31
|
THE_TRUTH = { true => true, 'true' => true, false => false, 'false' => false }.freeze
|
29
32
|
|
@@ -45,9 +48,22 @@ module Fortnox
|
|
45
48
|
.constructor(EnumConstructors.default)
|
46
49
|
|
47
50
|
CountryCode = Strict::String
|
48
|
-
.constrained(included_in: CountryCodes.values)
|
49
51
|
.optional
|
50
|
-
.constructor
|
52
|
+
.constructor do |value|
|
53
|
+
next value if value.nil? || value == ''
|
54
|
+
|
55
|
+
# Fortnox only supports Swedish translation of Sweden
|
56
|
+
next CountryCodeString.new('SE') if value =~ /^s(e$|we|ve)/i
|
57
|
+
|
58
|
+
country = ::ISO3166::Country[value] ||
|
59
|
+
::ISO3166::Country.find_country_by_name(value) ||
|
60
|
+
::ISO3166::Country.find_country_by_translated_names(value)
|
61
|
+
|
62
|
+
raise Dry::Types::ConstraintError.new('value violates constraints', value) if country.nil?
|
63
|
+
|
64
|
+
CountryCodeString.new(country.alpha2)
|
65
|
+
end
|
66
|
+
|
51
67
|
Currency = Strict::String
|
52
68
|
.constrained(included_in: Currencies.values)
|
53
69
|
.optional
|
@@ -63,7 +79,7 @@ module Fortnox
|
|
63
79
|
.constructor(EnumConstructors.default)
|
64
80
|
|
65
81
|
Email = Strict::String
|
66
|
-
.constrained(max_size: 1024, format: /^$|\A[
|
82
|
+
.constrained(max_size: 1024, format: /^$|\A[[[:alnum:]]+-_.]+@[\w+-_.]+\.[a-z]+\z/i)
|
67
83
|
.optional
|
68
84
|
.constructor { |v| v.to_s.downcase unless v.nil? }
|
69
85
|
|
@@ -35,29 +35,6 @@ module Fortnox
|
|
35
35
|
HouseworkTypes = Types::Strict::String.enum(
|
36
36
|
*(CURRENT_HOUSEWORK_TYPES + LEGACY_HOUSEWORK_TYPES)
|
37
37
|
)
|
38
|
-
CountryCodes = Types::Strict::String.enum(
|
39
|
-
'AF', 'AX', 'AL', 'DZ', 'AS', 'AD', 'AO', 'AI', 'AQ', 'AG', 'AR', 'AM',
|
40
|
-
'AW', 'AU', 'AT', 'AZ', 'BS', 'BH', 'BD', 'BB', 'BY', 'BE', 'BZ', 'BJ',
|
41
|
-
'BM', 'BT', 'BO', 'BQ', 'BA', 'BW', 'BV', 'BR', 'IO', 'BN', 'BG', 'BF',
|
42
|
-
'BI', 'CV', 'KH', 'CM', 'CA', 'KY', 'CF', 'TD', 'CL', 'CN', 'CX', 'CC',
|
43
|
-
'CO', 'KM', 'CG', 'CD', 'CK', 'CR', 'CI', 'HR', 'CU', 'CW', 'CY', 'CZ',
|
44
|
-
'DK', 'DJ', 'DM', 'DO', 'EC', 'EG', 'SV', 'GQ', 'ER', 'EE', 'ET', 'FK',
|
45
|
-
'FO', 'FJ', 'FI', 'FR', 'GF', 'PF', 'TF', 'GA', 'GM', 'GE', 'DE', 'GH',
|
46
|
-
'GI', 'GR', 'GL', 'GD', 'GP', 'GU', 'GT', 'GG', 'GN', 'GW', 'GY', 'HT',
|
47
|
-
'HM', 'VA', 'HN', 'HK', 'HU', 'IS', 'IN', 'ID', 'IR', 'IQ', 'IE', 'IM',
|
48
|
-
'IL', 'IT', 'JM', 'JP', 'JE', 'JO', 'KZ', 'KE', 'KI', 'KP', 'KR', 'KW',
|
49
|
-
'KG', 'LA', 'LV', 'LB', 'LS', 'LR', 'LY', 'LI', 'LT', 'LU', 'MO', 'MK',
|
50
|
-
'MG', 'MW', 'MY', 'MV', 'ML', 'MT', 'MH', 'MQ', 'MR', 'MU', 'YT', 'MX',
|
51
|
-
'FM', 'MD', 'MC', 'MN', 'ME', 'MS', 'MA', 'MZ', 'MM', 'NA', 'NR', 'NP',
|
52
|
-
'NL', 'NC', 'NZ', 'NI', 'NE', 'NG', 'NU', 'NF', 'MP', 'NO', 'OM', 'PK',
|
53
|
-
'PW', 'PS', 'PA', 'PG', 'PY', 'PE', 'PH', 'PN', 'PL', 'PT', 'PR', 'QA',
|
54
|
-
'RE', 'RO', 'RU', 'RW', 'BL', 'SH', 'KN', 'LC', 'MF', 'PM', 'VC', 'WS',
|
55
|
-
'SM', 'ST', 'SA', 'SN', 'RS', 'SC', 'SL', 'SG', 'SX', 'SK', 'SI', 'SB',
|
56
|
-
'SO', 'ZA', 'GS', 'SS', 'ES', 'LK', 'SD', 'SR', 'SJ', 'SZ', 'SE', 'CH',
|
57
|
-
'SY', 'TW', 'TJ', 'TZ', 'TH', 'TL', 'TG', 'TK', 'TO', 'TT', 'TN', 'TR',
|
58
|
-
'TM', 'TC', 'TV', 'UG', 'UA', 'AE', 'GB', 'US', 'UM', 'UY', 'UZ', 'VU',
|
59
|
-
'VE', 'VN', 'VG', 'VI', 'WF', 'EH', 'YE', 'ZM', 'ZW'
|
60
|
-
)
|
61
38
|
Currencies = Types::Strict::String.enum(
|
62
39
|
'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN',
|
63
40
|
'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV',
|
@@ -21,22 +21,9 @@ module Fortnox
|
|
21
21
|
end
|
22
22
|
|
23
23
|
module Float
|
24
|
-
def self.[](low
|
25
|
-
|
26
|
-
|
27
|
-
Types::Strict::Float.constrained(gteq: low, lteq: high).optional.constructor do |value|
|
28
|
-
value.to_f unless value.nil?
|
29
|
-
end
|
30
|
-
elsif range
|
31
|
-
# Legacy
|
32
|
-
Types::Strict::Float.constrained(gteq: low, lteq: high).optional.constructor do |value|
|
33
|
-
value.to_f unless value.nil?
|
34
|
-
end
|
35
|
-
else
|
36
|
-
# Legacy
|
37
|
-
Types::Strict::Float.constrained(gteq: low, lteq: high).optional.constructor do |value|
|
38
|
-
value.to_f unless value.nil?
|
39
|
-
end
|
24
|
+
def self.[](low, high)
|
25
|
+
Types::Strict::Float.constrained(gteq: low, lteq: high).optional.constructor do |value|
|
26
|
+
value.to_f unless value.nil?
|
40
27
|
end
|
41
28
|
end
|
42
29
|
end
|
data/lib/fortnox/api/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'fortnox/api/circular_queue'
|
5
|
+
|
6
|
+
describe Fortnox::API::CircularQueue do
|
7
|
+
describe 'start index' do
|
8
|
+
context 'when running several times' do
|
9
|
+
let(:test_array) { (0..99).to_a }
|
10
|
+
let(:samples) { Array.new(100) { described_class.new(*test_array).next } }
|
11
|
+
|
12
|
+
subject { Set.new(samples).size }
|
13
|
+
|
14
|
+
# NOTE: This test is not perfect. We are testing that a random generator
|
15
|
+
# with 100 items to choose from does not choose the same item 100 times in a row.
|
16
|
+
# Yes, the possibility is low, but I thought I should just mention it :)
|
17
|
+
it 'does not start with the same item each time' do
|
18
|
+
is_expected.to be > 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#next' do
|
24
|
+
context 'when several items in queue' do
|
25
|
+
let(:queue) { described_class.new(1,2,3) }
|
26
|
+
let(:first_round) { Array.new(3) { queue.next } }
|
27
|
+
let(:second_round) { Array.new(3) { queue.next } }
|
28
|
+
|
29
|
+
it 'circulates the items' do
|
30
|
+
first_round
|
31
|
+
expect(first_round[0]).to eq(queue.next)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'circulates the items in the same order each time' do
|
35
|
+
expect(first_round).to eq(second_round)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'circulates through given input' do
|
39
|
+
expect(first_round.sort).to eq([1, 2, 3])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when only one item in queue' do
|
44
|
+
let(:queue) { described_class.new(1) }
|
45
|
+
|
46
|
+
it 'circulates the item' do
|
47
|
+
first_item = queue.next
|
48
|
+
expect(first_item).to eq(queue.next)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'fortnox/api/mappers/base/canonical_name_sym'
|
5
|
+
|
6
|
+
describe Fortnox::API::Mapper::CanonicalNameSym do
|
7
|
+
describe '.canonical_name_sym' do
|
8
|
+
context 'with simple class' do
|
9
|
+
using_test_class do
|
10
|
+
class TestClass
|
11
|
+
extend Fortnox::API::Mapper::CanonicalNameSym
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
subject { TestClass.canonical_name_sym }
|
16
|
+
|
17
|
+
it { is_expected.to eq(:testclass) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when class included in module' do
|
21
|
+
using_test_class do
|
22
|
+
module Something
|
23
|
+
class Test
|
24
|
+
extend Fortnox::API::Mapper::CanonicalNameSym
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
subject { Something::Test.canonical_name_sym }
|
30
|
+
|
31
|
+
it { is_expected.to eq(:test) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -35,6 +35,12 @@ describe Fortnox::API::Mapper::Base do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
describe 'integer' do
|
39
|
+
include_examples 'identity mapper', :integer do
|
40
|
+
let(:value) { Fortnox::API::Types::Nullable::Integer[1337] }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
38
44
|
describe 'float' do
|
39
45
|
include_examples 'identity mapper', :float do
|
40
46
|
let(:value) { Fortnox::API::Types::Nullable::Float[13.37] }
|
@@ -111,57 +117,41 @@ describe Fortnox::API::Mapper::Base do
|
|
111
117
|
end
|
112
118
|
end
|
113
119
|
|
114
|
-
describe 'AccountNumber' do
|
115
|
-
include_examples 'identity mapper', :account_number do
|
116
|
-
let(:value) { Fortnox::API::Types::AccountNumber[1234] }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
120
|
describe 'CountryCode' do
|
121
|
-
|
122
|
-
let(:value) { Fortnox::API::Types::CountryCode['SE'] }
|
123
|
-
end
|
124
|
-
end
|
121
|
+
subject { mapper.call('GB') }
|
125
122
|
|
126
|
-
|
127
|
-
include_examples 'identity mapper', :currency do
|
128
|
-
let(:value) { Fortnox::API::Types::Currency['SEK'] }
|
129
|
-
end
|
130
|
-
end
|
123
|
+
let(:mapper) { Fortnox::API::Registry[:countrycodestring] }
|
131
124
|
|
132
|
-
|
133
|
-
include_examples 'identity mapper', :customer_type do
|
134
|
-
let(:value) { Fortnox::API::Types::CustomerType['PRIVATE'] }
|
135
|
-
end
|
136
|
-
end
|
125
|
+
it { is_expected.to eq('United Kingdom') }
|
137
126
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
142
|
-
end
|
127
|
+
describe 'special cases' do
|
128
|
+
context 'with SE' do
|
129
|
+
subject { mapper.call('SE') }
|
143
130
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end
|
131
|
+
it 'translates code to country name in Swedish' do
|
132
|
+
is_expected.to eq('Sverige')
|
133
|
+
end
|
134
|
+
end
|
149
135
|
|
150
|
-
|
151
|
-
|
152
|
-
let(:value) { Fortnox::API::Types::HouseworkType['CONSTRUCTION'] }
|
153
|
-
end
|
154
|
-
end
|
136
|
+
context 'with nil value' do
|
137
|
+
subject { mapper.call(nil) }
|
155
138
|
|
156
|
-
|
157
|
-
|
158
|
-
let(:value) { Fortnox::API::Types::VATType['SEVAT'] }
|
159
|
-
end
|
160
|
-
end
|
139
|
+
it { is_expected.to eq(nil) }
|
140
|
+
end
|
161
141
|
|
162
|
-
|
163
|
-
|
142
|
+
context 'with empty string' do
|
143
|
+
subject { mapper.call('') }
|
144
|
+
|
145
|
+
it { is_expected.to eq('') }
|
146
|
+
end
|
164
147
|
|
165
|
-
|
148
|
+
context 'with nonsense' do
|
149
|
+
subject { -> { mapper.call('nonsense') } }
|
150
|
+
|
151
|
+
it 'is not supported (since input is sanitised) and therefore blows up' do
|
152
|
+
raise_error(NoMethodError)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
166
156
|
end
|
167
157
|
end
|
@@ -40,7 +40,7 @@ shared_context 'with JSON conversion' do
|
|
40
40
|
attribute :url, 'strict.string'
|
41
41
|
attribute :name, 'strict.string'
|
42
42
|
attribute :vat, 'strict.float'
|
43
|
-
attribute :categories, Dry::Types['coercible.array'].
|
43
|
+
attribute :categories, Dry::Types['coercible.array'].of(Test::Category)
|
44
44
|
attribute :designer, Test::ProductDesigner
|
45
45
|
end
|
46
46
|
end
|
@@ -26,11 +26,13 @@ describe Fortnox::API::Repository::Article, order: :defined, integration: true d
|
|
26
26
|
:ean,
|
27
27
|
'5901234123457'
|
28
28
|
|
29
|
-
|
29
|
+
# When recording new VCR cassettes, expected matches must be increased
|
30
|
+
include_examples '.all', 26
|
30
31
|
|
32
|
+
# When recording new VCR cassettes, expected matches must be increased
|
31
33
|
include_examples '.find', '1' do
|
32
34
|
let(:find_by_hash_failure) { { description: 'Not Found' } }
|
33
|
-
let(:single_param_find_by_hash) { { find_hash: { articlenumber: 1 }, matches:
|
35
|
+
let(:single_param_find_by_hash) { { find_hash: { articlenumber: 1 }, matches: 13 } }
|
34
36
|
|
35
37
|
let(:multi_param_find_by_hash) do
|
36
38
|
{ find_hash: { articlenumber: 1, description: 'Cykelpump' }, matches: 1 }
|
@@ -6,18 +6,25 @@ require 'fortnox/api'
|
|
6
6
|
describe Fortnox::API::Repository::Base do
|
7
7
|
using_test_class do
|
8
8
|
module Model
|
9
|
-
class
|
9
|
+
class RepositoryBaseTest
|
10
10
|
end
|
11
11
|
end
|
12
12
|
module Repository
|
13
13
|
class Test < Fortnox::API::Repository::Base
|
14
|
-
MODEL = Model::
|
14
|
+
MODEL = Model::RepositoryBaseTest
|
15
15
|
end
|
16
16
|
end
|
17
|
+
end
|
18
|
+
|
19
|
+
before do
|
20
|
+
Fortnox::API::Registry.register(:repositorybasetest, Model::RepositoryBaseTest)
|
21
|
+
end
|
17
22
|
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
after do
|
24
|
+
# HACK: Currently, there is no way to remove keys from the Dry::Container#register.
|
25
|
+
# We could move the register call to a before(:all) hook, but that registered key
|
26
|
+
# would then leak into other tests. Instead, we can simply delete it with this little hack :)
|
27
|
+
Fortnox::API::Registry._container.delete('repositorybasetest')
|
21
28
|
end
|
22
29
|
|
23
30
|
let(:access_token) { '3f08d038-f380-4893-94a0-a08f6e60e67a' }
|
@@ -36,7 +43,7 @@ describe Fortnox::API::Repository::Base do
|
|
36
43
|
|
37
44
|
describe 'creation' do
|
38
45
|
shared_examples_for 'missing configuration' do
|
39
|
-
subject { -> {
|
46
|
+
subject { -> { Repository::Test.new(token_store: :store1).get('nonsense') } }
|
40
47
|
|
41
48
|
let(:error) { Fortnox::API::MissingConfiguration }
|
42
49
|
|
@@ -45,14 +52,27 @@ describe Fortnox::API::Repository::Base do
|
|
45
52
|
|
46
53
|
context 'without base url' do
|
47
54
|
include_examples 'missing configuration' do
|
48
|
-
before
|
55
|
+
before do
|
56
|
+
Fortnox::API.configure do |config|
|
57
|
+
config.base_url = nil
|
58
|
+
config.client_secret = client_secret
|
59
|
+
config.access_tokens = { store1: access_token }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
49
63
|
let(:message) { 'have to provide a base url' }
|
50
64
|
end
|
51
65
|
end
|
52
66
|
|
53
67
|
context 'without client secret' do
|
54
68
|
include_examples 'missing configuration' do
|
55
|
-
before
|
69
|
+
before do
|
70
|
+
Fortnox::API.configure do |config|
|
71
|
+
config.client_secret = nil
|
72
|
+
config.access_tokens = { store1: access_token }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
56
76
|
let(:message) { 'have to provide your client secret' }
|
57
77
|
end
|
58
78
|
end
|
@@ -38,5 +38,6 @@ describe Fortnox::API::Repository::Customer, order: :defined, integration: true
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
# When recording new VCR casettes, expected matches must be increased
|
42
|
+
include_examples '.search', :name, 'Test', 30
|
42
43
|
end
|
@@ -37,7 +37,7 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
|
|
37
37
|
|
38
38
|
# It is not possible to delete Invoces. Therefore, expected nr of Orders
|
39
39
|
# when running .all will continue to increase (until 100, which is max by default).
|
40
|
-
include_examples '.all',
|
40
|
+
include_examples '.all', 97
|
41
41
|
|
42
42
|
include_examples '.find', 1 do
|
43
43
|
let(:find_by_hash_failure) { { yourreference: 'Not found' } }
|
@@ -51,7 +51,151 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
include_examples '.search', :customername, 'Test',
|
54
|
+
include_examples '.search', :customername, 'Test', 7
|
55
55
|
|
56
|
-
include_examples '.only', :fullypaid,
|
56
|
+
include_examples '.only', :fullypaid, 4
|
57
|
+
|
58
|
+
describe 'country attribute' do
|
59
|
+
def new_invoice(country:)
|
60
|
+
described_class::MODEL.new(customer_number: 1, country: country)
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'with valid country' do
|
64
|
+
def save_invoice(country:, vcr_cassette: country)
|
65
|
+
VCR.use_cassette("#{vcr_dir}/save_new_with_country_#{vcr_cassette}") do
|
66
|
+
repository.save(new_invoice(country: country))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'accepts English country names' do
|
71
|
+
expect(save_invoice(country: 'Norway').country).to eq('NO')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'translates Swedish country names to English' do
|
75
|
+
expect(save_invoice(country: 'Norge').country).to eq('NO')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'skips nil values' do
|
79
|
+
expect(save_invoice(country: nil, vcr_cassette: 'nil').country).to eq('')
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'skips empty string values' do
|
83
|
+
expect(save_invoice(country: '', vcr_cassette: 'empty_string').country).to eq('')
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'GB' do
|
87
|
+
subject { save_invoice(country: 'GB').country }
|
88
|
+
|
89
|
+
it { is_expected.to eq('GB') }
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'KR' do
|
93
|
+
subject { save_invoice(country: 'KR').country }
|
94
|
+
|
95
|
+
it { is_expected.to eq('KR') }
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'VA' do
|
99
|
+
subject { save_invoice(country: 'VA').country }
|
100
|
+
|
101
|
+
it { is_expected.to eq('VA') }
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'VI' do
|
105
|
+
subject { save_invoice(country: 'VI').country }
|
106
|
+
|
107
|
+
it { is_expected.to eq('VI') }
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'special cases Sverige' do
|
111
|
+
subject { save_invoice(country: 'Sverige').country }
|
112
|
+
|
113
|
+
it { is_expected.to eq('SE') }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'resetting values in Fortnox' do
|
119
|
+
context 'with String values' do
|
120
|
+
def new_invoice(comments:)
|
121
|
+
described_class::MODEL.new(customer_number: 1, comments: comments)
|
122
|
+
end
|
123
|
+
|
124
|
+
let(:persisted_invoice) do
|
125
|
+
VCR.use_cassette("#{vcr_dir}/save_new_with_comments") do
|
126
|
+
repository.save(new_invoice(comments: 'A comment to be reset'))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
before { persisted_invoice }
|
131
|
+
|
132
|
+
context 'by setting value to nil' do
|
133
|
+
let(:updated_persisted_invoice) do
|
134
|
+
VCR.use_cassette("#{vcr_dir}/save_old_with_nil_comments") do
|
135
|
+
repository.save(persisted_invoice.update(comments: nil))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
subject { updated_persisted_invoice.comments }
|
140
|
+
|
141
|
+
pending { is_expected.to eq(nil) }
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'by setting value to empty string' do
|
145
|
+
let(:updated_persisted_invoice) do
|
146
|
+
VCR.use_cassette("#{vcr_dir}/save_old_with_empty_comments") do
|
147
|
+
repository.save(persisted_invoice.update(comments: ''))
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
subject { updated_persisted_invoice.comments }
|
152
|
+
|
153
|
+
it 'does not reset the value' do
|
154
|
+
is_expected.to eq('A comment to be reset')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'with other values' do
|
160
|
+
def new_invoice(country:)
|
161
|
+
described_class::MODEL.new(customer_number: 1, country: country)
|
162
|
+
end
|
163
|
+
|
164
|
+
let(:persisted_invoice) do
|
165
|
+
VCR.use_cassette("#{vcr_dir}/save_new_with_country") do
|
166
|
+
repository.save(new_invoice(country: 'Sverige'))
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
before { persisted_invoice }
|
171
|
+
|
172
|
+
context 'by setting value to nil' do
|
173
|
+
let(:updated_persisted_invoice) do
|
174
|
+
# TODO: This VCR cassette needs to be re-recorded again
|
175
|
+
# when the we fix #172.
|
176
|
+
VCR.use_cassette("#{vcr_dir}/save_old_with_nil_country") do
|
177
|
+
repository.save(persisted_invoice.update(country: nil))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
subject { updated_persisted_invoice.country }
|
182
|
+
|
183
|
+
pending { is_expected.to eq(nil) }
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'by setting value to empty string' do
|
187
|
+
let(:updated_persisted_invoice) do
|
188
|
+
VCR.use_cassette("#{vcr_dir}/save_old_with_empty_country") do
|
189
|
+
repository.save(persisted_invoice.update(country: ''))
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
subject { updated_persisted_invoice.country }
|
194
|
+
|
195
|
+
it 'does not reset the country' do
|
196
|
+
is_expected.to eq('SE')
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
57
201
|
end
|