fortnox-api 0.6.3 → 0.7.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 +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
|