fortnox-api 0.8.2 → 0.9.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/.env.template +7 -0
- data/.env.test +11 -3
- data/.gitignore +7 -1
- data/.rubocop.yml +17 -1
- data/.travis.yml +10 -9
- data/CHANGELOG.md +22 -8
- data/CONTRIBUTE.md +21 -9
- data/DEVELOPER_README.md +72 -0
- data/Guardfile +13 -4
- data/README.md +226 -64
- data/Rakefile +128 -0
- data/bin/get_tokens +79 -0
- data/bin/renew_tokens +28 -0
- data/fortnox-api.gemspec +10 -9
- data/lib/fortnox/api/mappers/base/from_json.rb +4 -3
- data/lib/fortnox/api/mappers/base/to_json.rb +2 -3
- data/lib/fortnox/api/models/base.rb +12 -10
- data/lib/fortnox/api/models/customer.rb +55 -55
- data/lib/fortnox/api/models/label.rb +2 -2
- data/lib/fortnox/api/repositories/authentication.rb +61 -0
- data/lib/fortnox/api/repositories/base/savers.rb +3 -1
- data/lib/fortnox/api/repositories/base.rb +21 -35
- data/lib/fortnox/api/repositories.rb +1 -0
- data/lib/fortnox/api/request_handling.rb +30 -18
- data/lib/fortnox/api/types/document_row.rb +3 -3
- data/lib/fortnox/api/types/enums.rb +27 -11
- data/lib/fortnox/api/types/model.rb +1 -4
- data/lib/fortnox/api/types/sized.rb +2 -2
- data/lib/fortnox/api/types.rb +14 -1
- data/lib/fortnox/api/version.rb +1 -1
- data/lib/fortnox/api.rb +12 -32
- data/spec/fortnox/api/mappers/base/canonical_name_sym_spec.rb +4 -4
- data/spec/fortnox/api/mappers/base/from_json_spec.rb +10 -12
- data/spec/fortnox/api/mappers/base/to_json_spec.rb +48 -57
- data/spec/fortnox/api/mappers/base_spec.rb +4 -7
- data/spec/fortnox/api/mappers/contexts/json_conversion.rb +38 -33
- data/spec/fortnox/api/mappers/unit_spec.rb +3 -4
- data/spec/fortnox/api/models/base_spec.rb +27 -16
- data/spec/fortnox/api/models/unit_spec.rb +5 -3
- data/spec/fortnox/api/repositories/article_spec.rb +14 -9
- data/spec/fortnox/api/repositories/authentication_spec.rb +103 -0
- data/spec/fortnox/api/repositories/base_spec.rb +106 -319
- data/spec/fortnox/api/repositories/customer_spec.rb +37 -7
- data/spec/fortnox/api/repositories/examples/all.rb +0 -1
- data/spec/fortnox/api/repositories/examples/find.rb +5 -8
- data/spec/fortnox/api/repositories/examples/only.rb +4 -13
- data/spec/fortnox/api/repositories/examples/save.rb +32 -18
- data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +0 -5
- data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +1 -4
- data/spec/fortnox/api/repositories/examples/search.rb +4 -7
- data/spec/fortnox/api/repositories/invoice_spec.rb +64 -15
- data/spec/fortnox/api/repositories/order_spec.rb +11 -9
- data/spec/fortnox/api/repositories/project_spec.rb +7 -6
- data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +9 -7
- data/spec/fortnox/api/repositories/unit_spec.rb +13 -11
- data/spec/fortnox/api/types/country_spec.rb +1 -1
- data/spec/fortnox/api/types/email_spec.rb +2 -2
- data/spec/fortnox/api/types/examples/document_row.rb +3 -3
- data/spec/fortnox/api/types/examples/enum.rb +4 -4
- data/spec/fortnox/api/types/examples/types.rb +1 -3
- data/spec/fortnox/api/types/housework_types_spec.rb +54 -61
- data/spec/fortnox/api/types/model_spec.rb +3 -27
- data/spec/fortnox/api/types/order_row_spec.rb +2 -2
- data/spec/fortnox/api/types/required_spec.rb +6 -11
- data/spec/fortnox/api/types/sales_account_spec.rb +57 -0
- data/spec/fortnox/api_spec.rb +19 -124
- data/spec/spec_helper.rb +0 -14
- data/spec/support/helpers/configuration_helper.rb +30 -3
- data/spec/support/helpers.rb +1 -1
- data/spec/support/matchers/type/attribute_matcher.rb +2 -2
- data/spec/support/matchers/type/have_nullable_date_matcher.rb +6 -4
- data/spec/support/matchers/type/have_nullable_matcher.rb +1 -1
- data/spec/support/matchers/type/have_nullable_string_matcher.rb +5 -5
- data/spec/support/matchers/type/require_attribute_matcher.rb +5 -5
- data/spec/support/matchers/type/type_matcher.rb +1 -1
- data/spec/support/vcr_setup.rb +16 -0
- data/spec/vcr_cassettes/articles/all.yml +16 -43
- data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +10 -12
- data/spec/vcr_cassettes/articles/find_failure.yml +10 -12
- data/spec/vcr_cassettes/articles/find_id_1.yml +13 -14
- data/spec/vcr_cassettes/articles/find_new.yml +14 -16
- data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +13 -15
- data/spec/vcr_cassettes/articles/save_new.yml +13 -15
- data/spec/vcr_cassettes/articles/save_old.yml +14 -16
- data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +13 -15
- data/spec/vcr_cassettes/articles/search_by_name.yml +16 -15
- data/spec/vcr_cassettes/articles/search_miss.yml +10 -12
- data/spec/vcr_cassettes/articles/search_with_special_char.yml +10 -12
- data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +13 -27
- data/spec/vcr_cassettes/authentication/expired_token.yml +54 -0
- data/spec/vcr_cassettes/authentication/invalid_authorization.yml +57 -0
- data/spec/vcr_cassettes/authentication/invalid_refresh_token.yml +58 -0
- data/spec/vcr_cassettes/authentication/valid_request.yml +63 -0
- data/spec/vcr_cassettes/customers/all.yml +20 -127
- data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +10 -12
- data/spec/vcr_cassettes/customers/find_failure.yml +10 -12
- data/spec/vcr_cassettes/customers/find_id_1.yml +14 -15
- data/spec/vcr_cassettes/customers/find_new.yml +13 -15
- data/spec/vcr_cassettes/customers/find_with_sales_account.yml +63 -0
- data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +13 -15
- data/spec/vcr_cassettes/customers/save_new.yml +12 -14
- data/spec/vcr_cassettes/customers/save_new_with_country_code_SE.yml +12 -14
- data/spec/vcr_cassettes/customers/save_new_with_sales_account.yml +63 -0
- data/spec/vcr_cassettes/customers/save_old.yml +13 -15
- data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +12 -14
- data/spec/vcr_cassettes/customers/search_by_name.yml +13 -45
- data/spec/vcr_cassettes/customers/search_miss.yml +10 -12
- data/spec/vcr_cassettes/customers/search_with_special_char.yml +10 -12
- data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +14 -16
- data/spec/vcr_cassettes/invoices/all.yml +47 -112
- data/spec/vcr_cassettes/invoices/filter_hit.yml +14 -18
- data/spec/vcr_cassettes/invoices/filter_invalid.yml +10 -12
- data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +10 -12
- data/spec/vcr_cassettes/invoices/find_failure.yml +10 -12
- data/spec/vcr_cassettes/invoices/find_id_1.yml +15 -16
- data/spec/vcr_cassettes/invoices/find_new.yml +16 -18
- data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +13 -15
- data/spec/vcr_cassettes/invoices/row_description_limit.yml +65 -0
- data/spec/vcr_cassettes/invoices/save_new.yml +14 -16
- data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +14 -16
- data/spec/vcr_cassettes/invoices/save_new_with_country.yml +14 -15
- data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +15 -16
- data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +14 -15
- data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +14 -15
- data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +14 -15
- data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +15 -16
- data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +15 -16
- data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +14 -15
- data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +14 -15
- data/spec/vcr_cassettes/invoices/save_new_with_unsaved_parent.yml +65 -0
- data/spec/vcr_cassettes/invoices/save_old.yml +16 -18
- data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +16 -18
- data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +16 -17
- data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +16 -18
- data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +16 -17
- data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +15 -16
- data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +14 -15
- data/spec/vcr_cassettes/invoices/search_by_name.yml +13 -21
- data/spec/vcr_cassettes/invoices/search_miss.yml +10 -12
- data/spec/vcr_cassettes/invoices/search_with_special_char.yml +10 -12
- data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +14 -16
- data/spec/vcr_cassettes/orders/all.yml +19 -113
- data/spec/vcr_cassettes/orders/filter_hit.yml +14 -20
- data/spec/vcr_cassettes/orders/filter_invalid.yml +10 -12
- data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +10 -12
- data/spec/vcr_cassettes/orders/find_failure.yml +10 -12
- data/spec/vcr_cassettes/orders/find_id_1.yml +17 -17
- data/spec/vcr_cassettes/orders/find_new.yml +16 -18
- data/spec/vcr_cassettes/orders/housework_invalid_tax_reduction_type.yml +11 -13
- data/spec/vcr_cassettes/orders/housework_othercoses_invalid.yml +11 -13
- data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_construction.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_cooking.yml +11 -13
- data/spec/vcr_cassettes/orders/housework_type_electricity.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_gardening.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_hvac.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_itservices.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_majorappliancerepair.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_masonry.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_movingservices.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_othercare.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +15 -16
- data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +11 -13
- data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +13 -15
- data/spec/vcr_cassettes/orders/save_new.yml +16 -18
- data/spec/vcr_cassettes/orders/save_old.yml +16 -18
- data/spec/vcr_cassettes/orders/save_with_nested_model.yml +15 -16
- data/spec/vcr_cassettes/orders/search_by_name.yml +13 -17
- data/spec/vcr_cassettes/orders/search_miss.yml +10 -12
- data/spec/vcr_cassettes/orders/search_with_special_char.yml +10 -12
- data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +14 -16
- data/spec/vcr_cassettes/projects/all.yml +14 -37
- data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +10 -12
- data/spec/vcr_cassettes/projects/find_failure.yml +10 -12
- data/spec/vcr_cassettes/projects/find_id_1.yml +13 -15
- data/spec/vcr_cassettes/projects/find_new.yml +14 -16
- data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +15 -16
- data/spec/vcr_cassettes/projects/save_new.yml +13 -15
- data/spec/vcr_cassettes/projects/save_old.yml +14 -16
- data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +12 -14
- data/spec/vcr_cassettes/termsofpayments/all.yml +16 -23
- data/spec/vcr_cassettes/termsofpayments/find_failure.yml +10 -12
- data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +13 -16
- data/spec/vcr_cassettes/termsofpayments/find_new.yml +12 -14
- data/spec/vcr_cassettes/termsofpayments/save_new.yml +12 -14
- data/spec/vcr_cassettes/termsofpayments/save_old.yml +12 -14
- data/spec/vcr_cassettes/units/all.yml +13 -24
- data/spec/vcr_cassettes/units/find_failure.yml +10 -12
- data/spec/vcr_cassettes/units/find_id_1.yml +13 -15
- data/spec/vcr_cassettes/units/find_new.yml +12 -14
- data/spec/vcr_cassettes/units/save_new.yml +12 -14
- data/spec/vcr_cassettes/units/save_old.yml +12 -14
- data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +12 -14
- metadata +39 -230
- data/lib/fortnox/api/circular_queue.rb +0 -39
- data/spec/fortnox/api/circular_queue_spec.rb +0 -52
- data/spec/support/helpers/when_performing_helper.rb +0 -7
- data/temp.txt +0 -1
@@ -7,98 +7,94 @@ require 'fortnox/api/repositories/order'
|
|
7
7
|
require 'fortnox/api/models/order'
|
8
8
|
require 'fortnox/api/types/order_row'
|
9
9
|
|
10
|
-
# rubocop:disable RSpec/DescribeClass
|
11
10
|
describe 'HouseworkTypes', integration: true do
|
12
11
|
include Helpers::Configuration
|
12
|
+
include Helpers::Repositories
|
13
13
|
|
14
|
-
before
|
14
|
+
before do
|
15
|
+
set_api_test_configuration
|
16
|
+
stub_const('TYPE_ROT', Fortnox::API::Types::TaxReductionTypes['rot'])
|
17
|
+
stub_const('TYPE_RUT', Fortnox::API::Types::TaxReductionTypes['rut'])
|
18
|
+
end
|
15
19
|
|
16
20
|
let(:repository) { Fortnox::API::Repository::Order.new }
|
17
21
|
|
18
22
|
shared_examples_for 'housework type' do |type, tax_reduction_type, legacy: false, housework: true|
|
19
|
-
subject do
|
20
|
-
cassette = "orders/housework_type_#{type.downcase}"
|
21
|
-
-> { VCR.use_cassette(cassette) { repository.save(document) } }
|
22
|
-
end
|
23
|
-
|
24
23
|
let(:document) do
|
25
24
|
Fortnox::API::Model::Order.new(
|
26
25
|
customer_number: '1',
|
27
|
-
tax_reduction_type: tax_reduction_type,
|
26
|
+
tax_reduction_type: Object.const_get(tax_reduction_type),
|
28
27
|
order_rows: [
|
29
28
|
Fortnox::API::Types::OrderRow.new(
|
30
29
|
ordered_quantity: 1,
|
31
|
-
article_number: '
|
30
|
+
article_number: '101',
|
32
31
|
housework_type: Fortnox::API::Types::HouseworkTypes[type],
|
33
32
|
housework: housework
|
34
33
|
)
|
35
34
|
]
|
36
35
|
)
|
37
36
|
end
|
37
|
+
let(:save) do
|
38
|
+
-> { VCR.use_cassette("orders/housework_type_#{type.downcase}") { repository.save(document) } }
|
39
|
+
end
|
38
40
|
|
39
41
|
context "when creating an OrderRow with housework_type set to #{type}" do
|
40
42
|
if legacy
|
41
|
-
let(:error_message) {
|
43
|
+
let(:error_message) { /Skattereduktion för den valda typen av husarbete har upphört/ }
|
42
44
|
|
43
|
-
|
44
|
-
is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
|
45
|
-
end
|
45
|
+
specify { expect { save.call }.to raise_error(Fortnox::API::RemoteServerError, error_message) }
|
46
46
|
else
|
47
|
-
|
47
|
+
specify { expect { save.call }.not_to raise_error }
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
it_behaves_like 'housework type', '
|
56
|
-
it_behaves_like 'housework type', '
|
57
|
-
it_behaves_like 'housework type', '
|
58
|
-
it_behaves_like 'housework type', '
|
59
|
-
it_behaves_like 'housework type', '
|
60
|
-
|
61
|
-
it_behaves_like 'housework type', '
|
62
|
-
it_behaves_like 'housework type', '
|
63
|
-
|
64
|
-
it_behaves_like 'housework type', '
|
65
|
-
it_behaves_like 'housework type', '
|
66
|
-
it_behaves_like 'housework type', '
|
67
|
-
it_behaves_like 'housework type', '
|
68
|
-
it_behaves_like 'housework type', '
|
69
|
-
it_behaves_like 'housework type', '
|
70
|
-
it_behaves_like 'housework type', '
|
71
|
-
|
72
|
-
|
73
|
-
it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_RUT, housework: false
|
74
|
-
|
52
|
+
it_behaves_like 'housework type', 'CONSTRUCTION', 'TYPE_ROT'
|
53
|
+
it_behaves_like 'housework type', 'ELECTRICITY', 'TYPE_ROT'
|
54
|
+
it_behaves_like 'housework type', 'GLASSMETALWORK', 'TYPE_ROT'
|
55
|
+
it_behaves_like 'housework type', 'GROUNDDRAINAGEWORK', 'TYPE_ROT'
|
56
|
+
it_behaves_like 'housework type', 'MASONRY', 'TYPE_ROT'
|
57
|
+
it_behaves_like 'housework type', 'PAINTINGWALLPAPERING', 'TYPE_ROT'
|
58
|
+
it_behaves_like 'housework type', 'HVAC', 'TYPE_ROT'
|
59
|
+
it_behaves_like 'housework type', 'OTHERCOSTS', 'TYPE_ROT', housework: false
|
60
|
+
|
61
|
+
it_behaves_like 'housework type', 'MAJORAPPLIANCEREPAIR', 'TYPE_RUT'
|
62
|
+
it_behaves_like 'housework type', 'MOVINGSERVICES', 'TYPE_RUT'
|
63
|
+
it_behaves_like 'housework type', 'ITSERVICES', 'TYPE_RUT'
|
64
|
+
it_behaves_like 'housework type', 'CLEANING', 'TYPE_RUT'
|
65
|
+
it_behaves_like 'housework type', 'TEXTILECLOTHING', 'TYPE_RUT'
|
66
|
+
it_behaves_like 'housework type', 'SNOWPLOWING', 'TYPE_RUT'
|
67
|
+
it_behaves_like 'housework type', 'GARDENING', 'TYPE_RUT'
|
68
|
+
it_behaves_like 'housework type', 'BABYSITTING', 'TYPE_RUT'
|
69
|
+
it_behaves_like 'housework type', 'OTHERCARE', 'TYPE_RUT'
|
70
|
+
it_behaves_like 'housework type', 'OTHERCOSTS', 'TYPE_RUT', housework: false
|
71
|
+
|
72
|
+
# rubocop:disable RSpec/RepeatedExample
|
75
73
|
# rubocop:disable RSpec/RepeatedDescription
|
76
|
-
|
77
|
-
|
74
|
+
it 'will soon be added' do
|
75
|
+
pending 'todo'
|
76
|
+
raise StandardError, 'Will be supported 2021-01-01'
|
78
77
|
# it_behaves_like 'housework type', 'HOMEMAINTENANCE', TYPE_RUT
|
79
78
|
# it_behaves_like 'housework type', 'FURNISHING', TYPE_RUT
|
80
79
|
# it_behaves_like 'housework type', 'TRANSPORTATIONSERVICES', TYPE_RUT
|
81
80
|
# it_behaves_like 'housework type', 'WASHINGANDCAREOFCLOTHING', TYPE_RUT
|
82
81
|
end
|
83
82
|
|
84
|
-
|
85
|
-
|
83
|
+
it 'will soon be added' do
|
84
|
+
pending 'todo'
|
85
|
+
raise StandardError, 'Will be supported 2021-01-01'
|
86
86
|
# it_behaves_like 'housework type', 'SOLARCELLS', TYPE_GREEN
|
87
87
|
# it_behaves_like 'housework type', 'STORAGESELFPRODUCEDELECTRICTY', TYPE_GREEN
|
88
88
|
# it_behaves_like 'housework type', 'CHARGINGSTATIONELECTRICVEHICLE', TYPE_GREEN
|
89
89
|
# it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_GREEN
|
90
90
|
end
|
91
|
+
# rubocop:enable RSpec/RepeatedExample
|
91
92
|
# rubocop:enable RSpec/RepeatedDescription
|
92
93
|
|
93
|
-
it_behaves_like 'housework type', 'COOKING', TYPE_RUT, legacy: true
|
94
|
-
it_behaves_like 'housework type', 'TUTORING', TYPE_RUT, legacy: true
|
94
|
+
it_behaves_like 'housework type', 'COOKING', 'TYPE_RUT', legacy: true
|
95
|
+
it_behaves_like 'housework type', 'TUTORING', 'TYPE_RUT', legacy: true
|
95
96
|
|
96
97
|
describe 'with OTHERCOSTS' do
|
97
|
-
subject do
|
98
|
-
cassette = 'orders/housework_othercoses_invalid'
|
99
|
-
-> { VCR.use_cassette(cassette) { repository.save(document) } }
|
100
|
-
end
|
101
|
-
|
102
98
|
let(:document) do
|
103
99
|
Fortnox::API::Model::Order.new(
|
104
100
|
customer_number: '1',
|
@@ -106,7 +102,7 @@ describe 'HouseworkTypes', integration: true do
|
|
106
102
|
order_rows: [
|
107
103
|
Fortnox::API::Types::OrderRow.new(
|
108
104
|
ordered_quantity: 1,
|
109
|
-
article_number: '
|
105
|
+
article_number: '101',
|
110
106
|
housework_type: Fortnox::API::Types::HouseworkTypes['OTHERCOSTS'],
|
111
107
|
housework: true
|
112
108
|
)
|
@@ -114,19 +110,16 @@ describe 'HouseworkTypes', integration: true do
|
|
114
110
|
)
|
115
111
|
end
|
116
112
|
|
117
|
-
let(:error_message) {
|
113
|
+
let(:error_message) { /Kan inte sätta typen övrig kostnad på en rad markerad som husarbete/ }
|
118
114
|
|
119
115
|
it "can't have housework set to true" do
|
120
|
-
|
116
|
+
expect do
|
117
|
+
VCR.use_cassette('orders/housework_othercoses_invalid') { repository.save(document) }
|
118
|
+
end.to raise_error(Fortnox::API::RemoteServerError, error_message)
|
121
119
|
end
|
122
120
|
end
|
123
121
|
|
124
122
|
describe 'with wrong tax reduction type' do
|
125
|
-
subject do
|
126
|
-
cassette = 'orders/housework_invalid_tax_reduction_type'
|
127
|
-
-> { VCR.use_cassette(cassette) { repository.save(document) } }
|
128
|
-
end
|
129
|
-
|
130
123
|
let(:type) { 'CONSTRUCTION' }
|
131
124
|
let(:document) do
|
132
125
|
Fortnox::API::Model::Order.new(
|
@@ -135,7 +128,7 @@ describe 'HouseworkTypes', integration: true do
|
|
135
128
|
order_rows: [
|
136
129
|
Fortnox::API::Types::OrderRow.new(
|
137
130
|
ordered_quantity: 1,
|
138
|
-
article_number: '
|
131
|
+
article_number: '101',
|
139
132
|
housework_type: Fortnox::API::Types::HouseworkTypes[type],
|
140
133
|
housework: true
|
141
134
|
)
|
@@ -144,13 +137,13 @@ describe 'HouseworkTypes', integration: true do
|
|
144
137
|
end
|
145
138
|
|
146
139
|
let(:error_message) do
|
147
|
-
|
148
|
-
"får inte innehålla rader med husarbetestypen '#{type}'."
|
140
|
+
/Dokument med skattereduktionstypen '#{TYPE_RUT}' får inte innehålla rader med husarbetestypen '#{type}'/
|
149
141
|
end
|
150
142
|
|
151
143
|
it 'raises an error' do
|
152
|
-
|
144
|
+
expect do
|
145
|
+
VCR.use_cassette('orders/housework_invalid_tax_reduction_type') { repository.save(document) }
|
146
|
+
end.to raise_error(Fortnox::API::RemoteServerError, error_message)
|
153
147
|
end
|
154
148
|
end
|
155
149
|
end
|
156
|
-
# rubocop:enable RSpec/DescribeClass
|
@@ -17,9 +17,7 @@ RSpec.describe Fortnox::API::Types::Model do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
describe "User inheriting from #{described_class}" do
|
20
|
-
|
21
|
-
|
22
|
-
it { is_expected.to raise_error(error) }
|
20
|
+
specify { expect { TypesModelUser.new(args) }.to raise_error(error) }
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
@@ -30,8 +28,6 @@ RSpec.describe Fortnox::API::Types::Model do
|
|
30
28
|
end
|
31
29
|
|
32
30
|
context 'when omitting optional keys' do
|
33
|
-
subject { -> { User.new } }
|
34
|
-
|
35
31
|
before do
|
36
32
|
stub_const('Types::Nullable::String', Dry::Types['strict.string'].optional)
|
37
33
|
|
@@ -42,32 +38,12 @@ RSpec.describe Fortnox::API::Types::Model do
|
|
42
38
|
stub_const('User', user_class)
|
43
39
|
end
|
44
40
|
|
45
|
-
|
41
|
+
specify { expect { User.new }.not_to raise_error }
|
46
42
|
|
47
43
|
describe 'optional attribute' do
|
48
44
|
subject { User.new.optional_string }
|
49
45
|
|
50
|
-
it { is_expected.to
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'with required keys' do
|
55
|
-
before do
|
56
|
-
stub_const('Types::Age', Dry::Types['strict.integer'].constrained(gt: 18).is(:required))
|
57
|
-
|
58
|
-
test_class = Class.new(Fortnox::API::Types::Model) do
|
59
|
-
attribute :age, Types::Age
|
60
|
-
end
|
61
|
-
|
62
|
-
stub_const('Model', test_class)
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'does not raise error' do
|
66
|
-
expect { Model.new(age: 20) }.not_to raise_error
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'supports string keys' do
|
70
|
-
expect { Model.new('age' => 20) }.not_to raise_error
|
46
|
+
it { is_expected.to be_nil }
|
71
47
|
end
|
72
48
|
end
|
73
49
|
end
|
@@ -5,10 +5,10 @@ require 'fortnox/api/types/order_row'
|
|
5
5
|
require 'fortnox/api/types/examples/document_row'
|
6
6
|
|
7
7
|
RSpec.describe Fortnox::API::Types::OrderRow, type: :type do
|
8
|
-
valid_hash = { ordered_quantity: 10.5 }
|
9
|
-
|
10
8
|
subject { described_class }
|
11
9
|
|
10
|
+
valid_hash = { ordered_quantity: 10.5 }
|
11
|
+
|
12
12
|
it { is_expected.to require_attribute(:ordered_quantity, valid_hash) }
|
13
13
|
|
14
14
|
it_behaves_like 'DocumentRow', valid_hash
|
@@ -8,22 +8,16 @@ describe Fortnox::API::Types::Required, type: :type do
|
|
8
8
|
before { stub_const('TestClass', Class.new(Dry::Struct)) }
|
9
9
|
|
10
10
|
shared_examples_for 'required attribute' do |_type|
|
11
|
-
|
12
|
-
|
13
|
-
let(:error_message) do
|
14
|
-
"[#{TestClass}.new] #{:required_attribute.inspect} is missing in Hash input"
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'raises an error' do
|
18
|
-
is_expected.to raise_error(Dry::Struct::Error, error_message)
|
19
|
-
end
|
11
|
+
let(:error_message) { "[#{TestClass}.new] #{:required_attribute.inspect} is missing in Hash input" }
|
12
|
+
specify { expect { TestClass.new({}) }.to raise_error(Dry::Struct::Error, error_message) }
|
20
13
|
end
|
21
14
|
|
22
15
|
describe 'String' do
|
23
16
|
before do
|
24
|
-
|
17
|
+
test_class = Class.new(TestClass) do
|
25
18
|
attribute :required_attribute, Fortnox::API::Types::Required::String
|
26
19
|
end
|
20
|
+
stub_const('TestClass', test_class)
|
27
21
|
end
|
28
22
|
|
29
23
|
include_examples 'required attribute', String
|
@@ -31,9 +25,10 @@ describe Fortnox::API::Types::Required, type: :type do
|
|
31
25
|
|
32
26
|
describe 'Float' do
|
33
27
|
before do
|
34
|
-
|
28
|
+
test_class = Class.new(TestClass) do
|
35
29
|
attribute :required_attribute, Fortnox::API::Types::Required::Float
|
36
30
|
end
|
31
|
+
stub_const('TestClass', test_class)
|
37
32
|
end
|
38
33
|
|
39
34
|
include_examples 'required attribute', Float
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'fortnox/api/types'
|
5
|
+
require 'fortnox/api/types/examples/types'
|
6
|
+
|
7
|
+
describe Fortnox::API::Types do
|
8
|
+
let(:klass) { Fortnox::API::Types::SalesAccount }
|
9
|
+
|
10
|
+
describe 'SalesAccount' do
|
11
|
+
context 'when created with nil' do
|
12
|
+
subject { klass[nil] }
|
13
|
+
|
14
|
+
it { is_expected.to be_nil }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when created with empty string' do
|
18
|
+
subject { klass[''] }
|
19
|
+
|
20
|
+
it { is_expected.to be_nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
[-12_345, -1_234, -123, -1, 0, 1, 12, 123, 1_234.0, 12_345].each do |invalid_number|
|
24
|
+
context "with #{invalid_number}" do
|
25
|
+
it 'raises ConstraintError' do
|
26
|
+
expect { klass[invalid_number] }.to raise_error(Dry::Types::ConstraintError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with 4 digits' do
|
32
|
+
subject { klass[1_234] }
|
33
|
+
|
34
|
+
it { is_expected.to eq('1234') }
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when created with valid string' do
|
38
|
+
include_examples 'equals input', '1234'
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when created with a too many digits' do
|
42
|
+
include_examples 'raises ConstraintError', '12345'
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when created with too few digits' do
|
46
|
+
include_examples 'raises ConstraintError', '123'
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when created with a negative number' do
|
50
|
+
include_examples 'raises ConstraintError', '-1234'
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when created with characters' do
|
54
|
+
include_examples 'raises ConstraintError', 'abcd'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/spec/fortnox/api_spec.rb
CHANGED
@@ -4,14 +4,7 @@ require 'spec_helper'
|
|
4
4
|
require 'fortnox/api'
|
5
5
|
|
6
6
|
describe Fortnox::API do
|
7
|
-
before
|
8
|
-
module Fortnox
|
9
|
-
module API
|
10
|
-
class TestBase
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
7
|
+
before { stub_const('Fortnox::API::TestBase', Class.new) }
|
15
8
|
|
16
9
|
describe 'configuration defaults' do
|
17
10
|
subject(:config_value) { described_class.config[config_key] }
|
@@ -21,37 +14,13 @@ describe Fortnox::API do
|
|
21
14
|
describe 'base_url' do
|
22
15
|
let(:config_key) { :base_url }
|
23
16
|
|
24
|
-
it { is_expected.to
|
25
|
-
end
|
26
|
-
|
27
|
-
describe 'client_secret' do
|
28
|
-
let(:config_key) { :client_secret }
|
29
|
-
|
30
|
-
it { is_expected.to be_nil }
|
31
|
-
end
|
32
|
-
|
33
|
-
describe 'access_token' do
|
34
|
-
let(:config_key) { :access_token }
|
35
|
-
|
36
|
-
it { is_expected.to be_nil }
|
37
|
-
end
|
38
|
-
|
39
|
-
describe 'access_tokens' do
|
40
|
-
let(:config_key) { :access_tokens }
|
41
|
-
|
42
|
-
it { is_expected.to be_nil }
|
17
|
+
it { is_expected.to eq 'https://api.fortnox.se/3/' }
|
43
18
|
end
|
44
19
|
|
45
|
-
describe '
|
46
|
-
let(:config_key) { :
|
47
|
-
|
48
|
-
it { is_expected.to eql({}) }
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'debugging' do
|
52
|
-
let(:config_key) { :debugging }
|
20
|
+
describe 'token_url' do
|
21
|
+
let(:config_key) { :token_url }
|
53
22
|
|
54
|
-
it { is_expected.to
|
23
|
+
it { is_expected.to eq 'https://apps.fortnox.se/oauth-v1/token' }
|
55
24
|
end
|
56
25
|
|
57
26
|
describe 'logger' do
|
@@ -67,104 +36,30 @@ describe Fortnox::API do
|
|
67
36
|
end
|
68
37
|
end
|
69
38
|
|
70
|
-
describe 'access_token' do
|
71
|
-
context 'when set to a String' do
|
72
|
-
subject { described_class.config.access_token }
|
73
|
-
|
74
|
-
before { described_class.configure { |config| config.access_token = value } }
|
75
|
-
let(:value) { '12345' }
|
76
|
-
|
77
|
-
it { is_expected.to eql value }
|
78
|
-
end
|
79
|
-
|
80
|
-
shared_examples_for 'invalid argument' do
|
81
|
-
subject { -> { described_class.configure { |config| config.access_token = value } } }
|
82
|
-
|
83
|
-
it { is_expected.to raise_error(ArgumentError, /expected a String/) }
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'when set to a Hash' do
|
87
|
-
include_examples 'invalid argument' do
|
88
|
-
let(:value) { { a: '123' } }
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'when set to an Array' do
|
93
|
-
include_examples 'invalid argument' do
|
94
|
-
let(:value) { %w[123 456] }
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
describe 'access_tokens' do
|
100
|
-
context 'when set to a String' do
|
101
|
-
subject { -> { described_class.configure { |config| config.access_tokens = '12345' } } }
|
102
|
-
|
103
|
-
it { is_expected.to raise_error(ArgumentError, /expected a Hash or an Array/) }
|
104
|
-
end
|
105
|
-
|
106
|
-
shared_examples_for 'valid argument' do
|
107
|
-
subject { described_class.config.access_tokens }
|
108
|
-
|
109
|
-
before { described_class.configure { |config| config.access_tokens = value } }
|
110
|
-
|
111
|
-
it { is_expected.to eql(value) }
|
112
|
-
end
|
113
|
-
|
114
|
-
context 'when set to a Hash' do
|
115
|
-
include_examples 'valid argument' do
|
116
|
-
let(:value) { { a: '123', b: '456' } }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context 'when set to an Array' do
|
121
|
-
include_examples 'valid argument' do
|
122
|
-
let(:value) { %w[123 456] }
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
describe 'token_store' do
|
128
|
-
subject { described_class.config[:token_store] }
|
129
|
-
|
130
|
-
context 'when access_token set' do
|
131
|
-
before { described_class.configure { |config| config.access_token = access_token } }
|
132
|
-
let(:access_token) { '12345' }
|
133
|
-
|
134
|
-
it { is_expected.to eql(default: access_token) }
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'when access_tokens is' do
|
138
|
-
before { described_class.configure { |config| config.access_tokens = access_tokens } }
|
139
|
-
|
140
|
-
describe 'a Hash' do
|
141
|
-
let(:access_tokens) { { a: '123', b: '456' } }
|
142
|
-
|
143
|
-
it { is_expected.to eql(access_tokens) }
|
144
|
-
end
|
145
|
-
|
146
|
-
describe 'an Array' do
|
147
|
-
let(:access_tokens) { %w[123 456] }
|
148
|
-
|
149
|
-
it { is_expected.to eql(default: access_tokens) }
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
39
|
describe 'readers for' do
|
155
40
|
describe 'debugging' do
|
156
|
-
subject { described_class.debugging }
|
41
|
+
subject(:debugging) { described_class.debugging }
|
157
42
|
|
158
43
|
it 'is available' do
|
159
|
-
|
44
|
+
expect(debugging).to be false
|
160
45
|
end
|
161
46
|
end
|
162
47
|
|
163
48
|
describe 'logger' do
|
164
|
-
subject { described_class.logger }
|
49
|
+
subject(:logger) { described_class.logger }
|
165
50
|
|
166
51
|
it 'is available' do
|
167
|
-
|
52
|
+
expect(logger).to be_a Logger
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#access_token' do
|
58
|
+
context 'when token is set' do
|
59
|
+
before { described_class.access_token = 'an_access_token' }
|
60
|
+
|
61
|
+
it 'returns the token' do
|
62
|
+
expect(described_class.access_token).to eq('an_access_token')
|
168
63
|
end
|
169
64
|
end
|
170
65
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -20,26 +20,12 @@ RSpec.configure do |config|
|
|
20
20
|
config.extend Helpers # Allow access to helpers in describe and context blocks
|
21
21
|
config.include Helpers # Allow access to helpers in it and let blocks
|
22
22
|
|
23
|
-
config.include Helpers::Repositories, integration: true
|
24
23
|
config.include Matchers::Type, type: :type
|
25
24
|
|
26
25
|
config.order = 'random'
|
27
26
|
|
28
27
|
WebMock.disable_net_connect!(allow: 'codeclimate.com')
|
29
28
|
|
30
|
-
config.before do
|
31
|
-
module Test
|
32
|
-
def self.remove_constants
|
33
|
-
constants.each { |const| remove_const(const) }
|
34
|
-
self
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
config.after do
|
40
|
-
Object.send(:remove_const, Test.remove_constants.name)
|
41
|
-
end
|
42
|
-
|
43
29
|
# Reset configuration after each test run
|
44
30
|
config.after do
|
45
31
|
Fortnox::API::DEFAULT_CONFIGURATION.each do |key, value|
|
@@ -1,12 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'dotenv'
|
4
|
+
require 'jwt'
|
5
|
+
|
6
|
+
DOTENV_FILE_NAME = '.env.test'
|
7
|
+
Dotenv.load(DOTENV_FILE_NAME)
|
8
|
+
|
9
|
+
DEBUG = ENV.fetch('DEBUG', false) == true
|
10
|
+
|
3
11
|
module Helpers
|
4
12
|
module Configuration
|
5
|
-
def set_api_test_configuration
|
13
|
+
def set_api_test_configuration # rubocop:disable Metrics/MethodLength
|
6
14
|
Fortnox::API.configure do |config|
|
7
|
-
config.
|
8
|
-
|
15
|
+
config.debugging = DEBUG
|
16
|
+
|
17
|
+
if DEBUG
|
18
|
+
config.logger = lambda {
|
19
|
+
logger = Logger.new($stdout)
|
20
|
+
logger.level = Logger::DEBUG
|
21
|
+
return logger
|
22
|
+
}.call
|
23
|
+
end
|
9
24
|
end
|
25
|
+
|
26
|
+
Fortnox::API.access_token = ENV.fetch('FORTNOX_API_ACCESS_TOKEN')
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_to_registry(symbol, klass)
|
30
|
+
unless Fortnox::API::Registry.key? symbol
|
31
|
+
# Only register the key once...
|
32
|
+
Fortnox::API::Registry.register(symbol) { klass }
|
33
|
+
end
|
34
|
+
|
35
|
+
# ... but stub the value each test run
|
36
|
+
Fortnox::API::Registry.stub(symbol, klass)
|
10
37
|
end
|
11
38
|
end
|
12
39
|
end
|
data/spec/support/helpers.rb
CHANGED
@@ -19,7 +19,7 @@ module Matchers
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def failure_message
|
22
|
-
"Expected class to have attribute #{@attribute.inspect} defined as #{@attribute_type}, "\
|
22
|
+
"Expected class to have attribute #{@attribute.inspect} defined as #{@attribute_type}, " \
|
23
23
|
"but got following errors:
|
24
24
|
#{@errors}"
|
25
25
|
end
|
@@ -29,7 +29,7 @@ module Matchers
|
|
29
29
|
def expect_error(msg)
|
30
30
|
yield
|
31
31
|
|
32
|
-
@errors
|
32
|
+
@errors = @errors += msg
|
33
33
|
false # Fail test since expected error not thrown
|
34
34
|
rescue Dry::Struct::Error
|
35
35
|
# TODO: check if error message is correct
|
@@ -14,6 +14,8 @@ module Matchers
|
|
14
14
|
@expected_error = Fortnox::API::AttributeError
|
15
15
|
@expected_error_message = 'invalid date'
|
16
16
|
@failure_description = ''
|
17
|
+
|
18
|
+
super(attribute, valid_value, invalid_value, nil)
|
17
19
|
end
|
18
20
|
|
19
21
|
def matches?(klass)
|
@@ -46,11 +48,11 @@ module Matchers
|
|
46
48
|
|
47
49
|
@failure_description << " (Expected #{@expected_error}, but got none)"
|
48
50
|
false
|
49
|
-
rescue @expected_error =>
|
50
|
-
return true if
|
51
|
+
rescue @expected_error => exception
|
52
|
+
return true if exception.message == @expected_error_message
|
51
53
|
|
52
|
-
fail_message = "Expected error message to include #{@expected_error_message.inspect}, "\
|
53
|
-
"but was #{
|
54
|
+
fail_message = "Expected error message to include #{@expected_error_message.inspect}, " \
|
55
|
+
"but was #{exception.message.inspect}"
|
54
56
|
raise(fail_message)
|
55
57
|
end
|
56
58
|
end
|
@@ -45,7 +45,7 @@ module Matchers
|
|
45
45
|
value = model.send(@attribute)
|
46
46
|
return true if value == @default_value
|
47
47
|
|
48
|
-
@failure_description << " (Expected #{@invalid_value.inspect} to default to "\
|
48
|
+
@failure_description << " (Expected #{@invalid_value.inspect} to default to " \
|
49
49
|
"#{@default_value.inspect}), but got #{value.inspect}"
|
50
50
|
false
|
51
51
|
end
|