fortnox-api 0.7.2 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -0
  3. data/.rubocop.yml +1 -1
  4. data/.tool-versions +1 -0
  5. data/.travis.yml +5 -10
  6. data/CHANGELOG.md +45 -1
  7. data/README.md +7 -4
  8. data/Rakefile +5 -0
  9. data/fortnox-api.gemspec +22 -17
  10. data/lib/fortnox/api/mappers/article.rb +1 -1
  11. data/lib/fortnox/api/mappers/base/from_json.rb +3 -3
  12. data/lib/fortnox/api/mappers/base/to_json.rb +2 -2
  13. data/lib/fortnox/api/mappers/base.rb +3 -3
  14. data/lib/fortnox/api/mappers/customer.rb +1 -1
  15. data/lib/fortnox/api/mappers/default_delivery_types.rb +1 -1
  16. data/lib/fortnox/api/mappers/default_templates.rb +1 -1
  17. data/lib/fortnox/api/mappers/edi_information.rb +1 -1
  18. data/lib/fortnox/api/mappers/email_information.rb +1 -1
  19. data/lib/fortnox/api/mappers/invoice.rb +4 -4
  20. data/lib/fortnox/api/mappers/invoice_row.rb +1 -1
  21. data/lib/fortnox/api/mappers/order.rb +4 -4
  22. data/lib/fortnox/api/mappers/order_row.rb +1 -1
  23. data/lib/fortnox/api/mappers/project.rb +1 -1
  24. data/lib/fortnox/api/mappers/terms_of_payment.rb +1 -1
  25. data/lib/fortnox/api/mappers/unit.rb +1 -1
  26. data/lib/fortnox/api/mappers/value/country_string.rb +1 -1
  27. data/lib/fortnox/api/mappers.rb +18 -18
  28. data/lib/fortnox/api/models/article.rb +2 -2
  29. data/lib/fortnox/api/models/base.rb +14 -14
  30. data/lib/fortnox/api/models/customer.rb +2 -2
  31. data/lib/fortnox/api/models/document.rb +5 -2
  32. data/lib/fortnox/api/models/invoice.rb +2 -2
  33. data/lib/fortnox/api/models/label.rb +1 -1
  34. data/lib/fortnox/api/models/order.rb +2 -2
  35. data/lib/fortnox/api/models/project.rb +2 -2
  36. data/lib/fortnox/api/models/terms_of_payment.rb +2 -2
  37. data/lib/fortnox/api/models/unit.rb +2 -2
  38. data/lib/fortnox/api/models.rb +7 -7
  39. data/lib/fortnox/api/repositories/article.rb +3 -3
  40. data/lib/fortnox/api/repositories/base.rb +4 -3
  41. data/lib/fortnox/api/repositories/customer.rb +3 -3
  42. data/lib/fortnox/api/repositories/invoice.rb +3 -3
  43. data/lib/fortnox/api/repositories/order.rb +3 -3
  44. data/lib/fortnox/api/repositories/project.rb +3 -3
  45. data/lib/fortnox/api/repositories/terms_of_payment.rb +3 -3
  46. data/lib/fortnox/api/repositories/unit.rb +3 -3
  47. data/lib/fortnox/api/repositories.rb +7 -7
  48. data/lib/fortnox/api/types/default_delivery_types.rb +0 -2
  49. data/lib/fortnox/api/types/default_templates.rb +0 -2
  50. data/lib/fortnox/api/types/edi_information.rb +0 -2
  51. data/lib/fortnox/api/types/email_information.rb +0 -2
  52. data/lib/fortnox/api/types/enums.rb +36 -8
  53. data/lib/fortnox/api/types/invoice_row.rb +1 -1
  54. data/lib/fortnox/api/types/model.rb +4 -6
  55. data/lib/fortnox/api/types/nullable.rb +13 -9
  56. data/lib/fortnox/api/types/order_row.rb +1 -1
  57. data/lib/fortnox/api/types/required.rb +3 -3
  58. data/lib/fortnox/api/types/sized.rb +2 -2
  59. data/lib/fortnox/api/types.rb +23 -23
  60. data/lib/fortnox/api/version.rb +1 -1
  61. data/lib/fortnox/api.rb +18 -16
  62. data/spec/fortnox/api/circular_queue_spec.rb +3 -3
  63. data/spec/fortnox/api/mappers/base/canonical_name_sym_spec.rb +9 -7
  64. data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +1 -1
  65. data/spec/fortnox/api/mappers/examples/mapper.rb +1 -1
  66. data/spec/fortnox/api/models/base_spec.rb +8 -8
  67. data/spec/fortnox/api/repositories/article_spec.rb +2 -2
  68. data/spec/fortnox/api/repositories/base_spec.rb +4 -12
  69. data/spec/fortnox/api/repositories/customer_spec.rb +1 -1
  70. data/spec/fortnox/api/repositories/invoice_spec.rb +13 -19
  71. data/spec/fortnox/api/repositories/project_spec.rb +1 -1
  72. data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +2 -2
  73. data/spec/fortnox/api/repositories/unit_spec.rb +3 -3
  74. data/spec/fortnox/api/types/enums_spec.rb +1 -0
  75. data/spec/fortnox/api/types/housework_types_spec.rb +122 -34
  76. data/spec/fortnox/api/types/model_spec.rb +11 -17
  77. data/spec/fortnox/api/types/nullable_spec.rb +30 -10
  78. data/spec/fortnox/api/types/required_spec.rb +1 -4
  79. data/spec/support/matchers/type/enum_matcher.rb +1 -1
  80. data/spec/support/matchers/type/have_account_number_matcher.rb +1 -1
  81. data/spec/support/matchers/type/have_email_matcher.rb +1 -1
  82. data/spec/support/matchers/type/have_nullable_date_matcher.rb +5 -5
  83. data/spec/support/matchers/type/have_nullable_string_matcher.rb +3 -3
  84. data/spec/vcr_cassettes/articles/all.yml +43 -17
  85. data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +34 -15
  86. data/spec/vcr_cassettes/articles/find_failure.yml +34 -15
  87. data/spec/vcr_cassettes/articles/find_id_1.yml +35 -16
  88. data/spec/vcr_cassettes/articles/find_new.yml +37 -18
  89. data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +34 -15
  90. data/spec/vcr_cassettes/articles/save_new.yml +35 -15
  91. data/spec/vcr_cassettes/articles/save_old.yml +37 -18
  92. data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +35 -15
  93. data/spec/vcr_cassettes/articles/search_by_name.yml +34 -15
  94. data/spec/vcr_cassettes/articles/search_miss.yml +34 -15
  95. data/spec/vcr_cassettes/articles/search_with_special_char.yml +34 -15
  96. data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +38 -18
  97. data/spec/vcr_cassettes/customers/all.yml +36 -17
  98. data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +34 -15
  99. data/spec/vcr_cassettes/customers/find_failure.yml +34 -15
  100. data/spec/vcr_cassettes/customers/find_id_1.yml +34 -15
  101. data/spec/vcr_cassettes/customers/find_new.yml +36 -17
  102. data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +34 -15
  103. data/spec/vcr_cassettes/customers/save_new.yml +34 -14
  104. data/spec/vcr_cassettes/customers/save_new_with_country_code_SE.yml +30 -20
  105. data/spec/vcr_cassettes/customers/save_old.yml +36 -17
  106. data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +34 -14
  107. data/spec/vcr_cassettes/customers/search_by_name.yml +38 -16
  108. data/spec/vcr_cassettes/customers/search_miss.yml +34 -15
  109. data/spec/vcr_cassettes/customers/search_with_special_char.yml +34 -15
  110. data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +34 -15
  111. data/spec/vcr_cassettes/invoices/all.yml +39 -17
  112. data/spec/vcr_cassettes/invoices/filter_hit.yml +34 -15
  113. data/spec/vcr_cassettes/invoices/filter_invalid.yml +33 -13
  114. data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +34 -15
  115. data/spec/vcr_cassettes/invoices/find_failure.yml +34 -15
  116. data/spec/vcr_cassettes/invoices/find_id_1.yml +36 -17
  117. data/spec/vcr_cassettes/invoices/find_new.yml +39 -20
  118. data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +34 -15
  119. data/spec/vcr_cassettes/invoices/save_new.yml +37 -17
  120. data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +37 -17
  121. data/spec/vcr_cassettes/invoices/save_new_with_country.yml +32 -22
  122. data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +33 -23
  123. data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +32 -22
  124. data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +32 -22
  125. data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +32 -22
  126. data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +33 -23
  127. data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +33 -23
  128. data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +32 -22
  129. data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +32 -22
  130. data/spec/vcr_cassettes/invoices/save_old.yml +39 -20
  131. data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +39 -20
  132. data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +34 -25
  133. data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +39 -20
  134. data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +34 -25
  135. data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +36 -16
  136. data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +36 -16
  137. data/spec/vcr_cassettes/invoices/search_by_name.yml +34 -15
  138. data/spec/vcr_cassettes/invoices/search_miss.yml +34 -15
  139. data/spec/vcr_cassettes/invoices/search_with_special_char.yml +34 -15
  140. data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +34 -15
  141. data/spec/vcr_cassettes/orders/all.yml +35 -16
  142. data/spec/vcr_cassettes/orders/filter_hit.yml +34 -15
  143. data/spec/vcr_cassettes/orders/filter_invalid.yml +33 -13
  144. data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +34 -15
  145. data/spec/vcr_cassettes/orders/find_failure.yml +34 -15
  146. data/spec/vcr_cassettes/orders/find_id_1.yml +35 -16
  147. data/spec/vcr_cassettes/orders/find_new.yml +38 -19
  148. data/spec/vcr_cassettes/orders/housework_invalid_tax_reduction_type.yml +63 -0
  149. data/spec/vcr_cassettes/orders/housework_othercoses_invalid.yml +63 -0
  150. data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +37 -17
  151. data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +37 -17
  152. data/spec/vcr_cassettes/orders/housework_type_construction.yml +37 -17
  153. data/spec/vcr_cassettes/orders/housework_type_cooking.yml +34 -14
  154. data/spec/vcr_cassettes/orders/housework_type_electricity.yml +37 -17
  155. data/spec/vcr_cassettes/orders/housework_type_gardening.yml +37 -17
  156. data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +37 -17
  157. data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +37 -17
  158. data/spec/vcr_cassettes/orders/housework_type_hvac.yml +37 -17
  159. data/spec/vcr_cassettes/orders/housework_type_itservices.yml +66 -0
  160. data/spec/vcr_cassettes/orders/housework_type_majorappliancerepair.yml +66 -0
  161. data/spec/vcr_cassettes/orders/housework_type_masonry.yml +37 -17
  162. data/spec/vcr_cassettes/orders/housework_type_movingservices.yml +66 -0
  163. data/spec/vcr_cassettes/orders/housework_type_othercare.yml +37 -17
  164. data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +37 -17
  165. data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +37 -17
  166. data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +37 -17
  167. data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +37 -17
  168. data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +34 -14
  169. data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +34 -15
  170. data/spec/vcr_cassettes/orders/save_new.yml +36 -16
  171. data/spec/vcr_cassettes/orders/save_old.yml +38 -19
  172. data/spec/vcr_cassettes/orders/save_with_nested_model.yml +36 -16
  173. data/spec/vcr_cassettes/orders/search_by_name.yml +34 -15
  174. data/spec/vcr_cassettes/orders/search_miss.yml +34 -15
  175. data/spec/vcr_cassettes/orders/search_with_special_char.yml +34 -15
  176. data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +34 -15
  177. data/spec/vcr_cassettes/projects/all.yml +58 -33
  178. data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +34 -15
  179. data/spec/vcr_cassettes/projects/find_failure.yml +34 -15
  180. data/spec/vcr_cassettes/projects/find_id_1.yml +34 -15
  181. data/spec/vcr_cassettes/projects/find_new.yml +37 -18
  182. data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +36 -17
  183. data/spec/vcr_cassettes/projects/save_new.yml +35 -15
  184. data/spec/vcr_cassettes/projects/save_old.yml +37 -18
  185. data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +36 -17
  186. data/spec/vcr_cassettes/termsofpayments/all.yml +46 -25
  187. data/spec/vcr_cassettes/termsofpayments/find_failure.yml +34 -15
  188. data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +35 -16
  189. data/spec/vcr_cassettes/termsofpayments/find_new.yml +36 -17
  190. data/spec/vcr_cassettes/termsofpayments/save_new.yml +35 -15
  191. data/spec/vcr_cassettes/termsofpayments/save_old.yml +36 -17
  192. data/spec/vcr_cassettes/units/all.yml +45 -22
  193. data/spec/vcr_cassettes/units/find_failure.yml +34 -15
  194. data/spec/vcr_cassettes/units/find_id_1.yml +35 -16
  195. data/spec/vcr_cassettes/units/find_new.yml +36 -17
  196. data/spec/vcr_cassettes/units/save_new.yml +35 -15
  197. data/spec/vcr_cassettes/units/save_old.yml +36 -17
  198. data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +35 -15
  199. metadata +115 -43
  200. data/spec/support/helpers/dummy_class_helper.rb +0 -38
  201. data/spec/vcr_cassettes/invoices/save_new_with_country_KR.yml +0 -57
@@ -27,12 +27,12 @@ describe Fortnox::API::Repository::Article, order: :defined, integration: true d
27
27
  '5901234123457'
28
28
 
29
29
  # When recording new VCR cassettes, expected matches must be increased
30
- include_examples '.all', 26
30
+ include_examples '.all', 33
31
31
 
32
32
  # When recording new VCR cassettes, expected matches must be increased
33
33
  include_examples '.find', '1' do
34
34
  let(:find_by_hash_failure) { { description: 'Not Found' } }
35
- let(:single_param_find_by_hash) { { find_hash: { articlenumber: 1 }, matches: 13 } }
35
+ let(:single_param_find_by_hash) { { find_hash: { articlenumber: 1 }, matches: 14 } }
36
36
 
37
37
  let(:multi_param_find_by_hash) do
38
38
  { find_hash: { articlenumber: 1, description: 'Cykelpump' }, matches: 1 }
@@ -4,19 +4,11 @@ require 'spec_helper'
4
4
  require 'fortnox/api'
5
5
 
6
6
  describe Fortnox::API::Repository::Base do
7
- using_test_class do
8
- module Model
9
- class RepositoryBaseTest
10
- end
11
- end
12
- module Repository
13
- class Test < Fortnox::API::Repository::Base
14
- MODEL = Model::RepositoryBaseTest
15
- end
16
- end
17
- end
18
-
19
7
  before do
8
+ stub_const('Model::RepositoryBaseTest', Class.new)
9
+ stub_const('Repository::Test', Class.new(described_class))
10
+ stub_const('Repository::Test::MODEL', Model::RepositoryBaseTest)
11
+
20
12
  Fortnox::API::Registry.register(:repositorybasetest, Model::RepositoryBaseTest)
21
13
  end
22
14
 
@@ -39,7 +39,7 @@ describe Fortnox::API::Repository::Customer, order: :defined, integration: true
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
+ include_examples '.search', :name, 'Test', 33
43
43
 
44
44
  describe 'country reference' do
45
45
  describe 'with valid country code \'SE\'' do
@@ -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', 97
40
+ include_examples '.all', 100
41
41
 
42
42
  include_examples '.find', 1 do
43
43
  let(:find_by_hash_failure) { { yourreference: 'Not found' } }
@@ -89,12 +89,6 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
89
89
  it { is_expected.to eq('GB') }
90
90
  end
91
91
 
92
- describe 'KR' do
93
- subject { save_invoice(country: 'KR').country }
94
-
95
- it { is_expected.to eq('KR') }
96
- end
97
-
98
92
  describe 'VA' do
99
93
  subject { save_invoice(country: 'VA').country }
100
94
 
@@ -129,27 +123,27 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
129
123
 
130
124
  before { persisted_invoice }
131
125
 
132
- context 'by setting value to nil' do
126
+ context 'when setting value to nil' do
127
+ subject { updated_persisted_invoice.comments }
128
+
133
129
  let(:updated_persisted_invoice) do
134
130
  VCR.use_cassette("#{vcr_dir}/save_old_with_nil_comments") do
135
131
  repository.save(persisted_invoice.update(comments: nil))
136
132
  end
137
133
  end
138
134
 
139
- subject { updated_persisted_invoice.comments }
140
-
141
135
  pending { is_expected.to eq(nil) }
142
136
  end
143
137
 
144
- context 'by setting value to empty string' do
138
+ context 'when setting value to empty string' do
139
+ subject { updated_persisted_invoice.comments }
140
+
145
141
  let(:updated_persisted_invoice) do
146
142
  VCR.use_cassette("#{vcr_dir}/save_old_with_empty_comments") do
147
143
  repository.save(persisted_invoice.update(comments: ''))
148
144
  end
149
145
  end
150
146
 
151
- subject { updated_persisted_invoice.comments }
152
-
153
147
  it 'does not reset the value' do
154
148
  is_expected.to eq('A comment to be reset')
155
149
  end
@@ -169,7 +163,9 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
169
163
 
170
164
  before { persisted_invoice }
171
165
 
172
- context 'by setting value to nil' do
166
+ context 'when setting value to nil' do
167
+ subject { updated_persisted_invoice.country }
168
+
173
169
  let(:updated_persisted_invoice) do
174
170
  # TODO: This VCR cassette needs to be re-recorded again
175
171
  # when the we fix #172.
@@ -178,20 +174,18 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
178
174
  end
179
175
  end
180
176
 
181
- subject { updated_persisted_invoice.country }
182
-
183
177
  pending { is_expected.to eq(nil) }
184
178
  end
185
179
 
186
- context 'by setting value to empty string' do
180
+ context 'when setting value to empty string' do
181
+ subject { updated_persisted_invoice.country }
182
+
187
183
  let(:updated_persisted_invoice) do
188
184
  VCR.use_cassette("#{vcr_dir}/save_old_with_empty_country") do
189
185
  repository.save(persisted_invoice.update(country: ''))
190
186
  end
191
187
  end
192
188
 
193
- subject { updated_persisted_invoice.country }
194
-
195
189
  it 'does not reset the country' do
196
190
  is_expected.to eq('SE')
197
191
  end
@@ -22,7 +22,7 @@ describe Fortnox::API::Repository::Project, order: :defined, integration: true d
22
22
  # It is not yet possible to delete Projects. Therefore, expected nr of
23
23
  # Projects when running .all will continue to increase
24
24
  # (until 100, which is max by default).
25
- include_examples '.all', 31
25
+ include_examples '.all', 37
26
26
 
27
27
  include_examples '.find', '1' do
28
28
  let(:find_by_hash_failure) { { offset: 10_000 } }
@@ -18,12 +18,12 @@ describe Fortnox::API::Repository::TermsOfPayment, order: :defined, integration:
18
18
  before { set_api_test_configuration }
19
19
 
20
20
  # When recording new VCR cassettes, code must be changed to a new unique one
21
- required_hash = { code: '18DAYS' }
21
+ required_hash = { code: '20DAYS' }
22
22
 
23
23
  include_examples '.save', :description, additional_attrs: required_hash
24
24
 
25
25
  # When recording new VCR cassettes, expected matches needs to be increased
26
- include_examples '.all', 12
26
+ include_examples '.all', 14
27
27
 
28
28
  include_examples '.find', '15DAYS', find_by_hash: false do
29
29
  let(:find_by_hash_failure) { { code: '15days' } }
@@ -19,16 +19,16 @@ describe Fortnox::API::Repository::Unit, order: :defined, integration: true do
19
19
  # When recording new VCR cassettes, code needs to be changed to a unique value
20
20
  include_examples '.save',
21
21
  :description,
22
- additional_attrs: { code: 'blarg4' }
22
+ additional_attrs: { code: 'blarg7' }
23
23
 
24
24
  # When recording new VCR cassettes, code needs to be changed to a unique value
25
25
  include_examples '.save with specially named attribute',
26
26
  { description: 'Happy clouds' },
27
27
  :code,
28
- 'woooh4'
28
+ 'woooh6'
29
29
 
30
30
  # When recording new VCR cassettes, expected number must be updated
31
- include_examples '.all', 12
31
+ include_examples '.all', 16
32
32
 
33
33
  include_examples '.find', 'blarg', find_by_hash: false do
34
34
  let(:find_by_hash_failure) { { code: 'notfound' } }
@@ -13,4 +13,5 @@ describe Fortnox::API::Types do
13
13
  it_behaves_like 'enum', 'VATType', 'VATTypes'
14
14
  it_behaves_like 'enum', 'DefaultDeliveryType', 'DefaultDeliveryTypeValues'
15
15
  it_behaves_like 'enum', 'ProjectStatusType', 'ProjectStatusTypes'
16
+ it_behaves_like 'enum', 'TaxReductionType', 'TaxReductionTypes'
16
17
  end
@@ -14,29 +14,32 @@ describe 'HouseworkTypes', integration: true do
14
14
  before { set_api_test_configuration }
15
15
 
16
16
  let(:repository) { Fortnox::API::Repository::Order.new }
17
- let(:valid_model) do
18
- Fortnox::API::Model::Order.new(customer_number: '1', order_rows: [order_row])
19
- end
20
- let(:order_row) do
21
- Fortnox::API::Types::OrderRow.new(ordered_quantity: 1,
22
- article_number: '0000',
23
- housework_type: housework_type)
24
- end
25
17
 
26
- shared_examples_for 'housework type' do |type, legacy: false|
18
+ shared_examples_for 'housework type' do |type, tax_reduction_type, legacy: false, housework: true|
27
19
  subject do
28
- lambda do
29
- VCR.use_cassette("orders/housework_type_#{type.downcase}") do
30
- repository.save(valid_model)
31
- end
32
- end
20
+ cassette = "orders/housework_type_#{type.downcase}"
21
+ -> { VCR.use_cassette(cassette) { repository.save(document) } }
33
22
  end
34
23
 
35
- let(:error_message) { 'Skattereduktion för den valda typen av husarbete har upphört.' }
36
- let(:housework_type) { Fortnox::API::Types::HouseworkTypes[type] }
24
+ let(:document) do
25
+ Fortnox::API::Model::Order.new(
26
+ customer_number: '1',
27
+ tax_reduction_type: tax_reduction_type,
28
+ order_rows: [
29
+ Fortnox::API::Types::OrderRow.new(
30
+ ordered_quantity: 1,
31
+ article_number: '0000',
32
+ housework_type: Fortnox::API::Types::HouseworkTypes[type],
33
+ housework: housework
34
+ )
35
+ ]
36
+ )
37
+ end
37
38
 
38
39
  context "when creating an OrderRow with housework_type set to #{type}" do
39
40
  if legacy
41
+ let(:error_message) { 'Skattereduktion för den valda typen av husarbete har upphört.' }
42
+
40
43
  it 'raises an error' do
41
44
  is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
42
45
  end
@@ -46,23 +49,108 @@ describe 'HouseworkTypes', integration: true do
46
49
  end
47
50
  end
48
51
 
49
- it_behaves_like 'housework type', 'CONSTRUCTION'
50
- it_behaves_like 'housework type', 'ELECTRICITY'
51
- it_behaves_like 'housework type', 'GLASSMETALWORK'
52
- it_behaves_like 'housework type', 'GROUNDDRAINAGEWORK'
53
- it_behaves_like 'housework type', 'MASONRY'
54
- it_behaves_like 'housework type', 'PAINTINGWALLPAPERING'
55
- it_behaves_like 'housework type', 'HVAC'
56
- it_behaves_like 'housework type', 'CLEANING'
57
- it_behaves_like 'housework type', 'TEXTILECLOTHING'
58
- it_behaves_like 'housework type', 'CLEANING'
59
- it_behaves_like 'housework type', 'SNOWPLOWING'
60
- it_behaves_like 'housework type', 'GARDENING'
61
- it_behaves_like 'housework type', 'BABYSITTING'
62
- it_behaves_like 'housework type', 'OTHERCARE'
63
- it_behaves_like 'housework type', 'OTHERCOSTS'
64
-
65
- it_behaves_like 'housework type', 'COOKING', legacy: true
66
- it_behaves_like 'housework type', 'TUTORING', legacy: true
52
+ TYPE_ROT = Fortnox::API::Types::TaxReductionTypes['rot']
53
+ TYPE_RUT = Fortnox::API::Types::TaxReductionTypes['rut']
54
+
55
+ it_behaves_like 'housework type', 'CONSTRUCTION', TYPE_ROT
56
+ it_behaves_like 'housework type', 'ELECTRICITY', TYPE_ROT
57
+ it_behaves_like 'housework type', 'GLASSMETALWORK', TYPE_ROT
58
+ it_behaves_like 'housework type', 'GROUNDDRAINAGEWORK', TYPE_ROT
59
+ it_behaves_like 'housework type', 'MASONRY', TYPE_ROT
60
+ it_behaves_like 'housework type', 'PAINTINGWALLPAPERING', TYPE_ROT
61
+ it_behaves_like 'housework type', 'HVAC', TYPE_ROT
62
+ it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_ROT, housework: false
63
+
64
+ it_behaves_like 'housework type', 'MAJORAPPLIANCEREPAIR', TYPE_RUT
65
+ it_behaves_like 'housework type', 'MOVINGSERVICES', TYPE_RUT
66
+ it_behaves_like 'housework type', 'ITSERVICES', TYPE_RUT
67
+ it_behaves_like 'housework type', 'CLEANING', TYPE_RUT
68
+ it_behaves_like 'housework type', 'TEXTILECLOTHING', TYPE_RUT
69
+ it_behaves_like 'housework type', 'SNOWPLOWING', TYPE_RUT
70
+ it_behaves_like 'housework type', 'GARDENING', TYPE_RUT
71
+ it_behaves_like 'housework type', 'BABYSITTING', TYPE_RUT
72
+ it_behaves_like 'housework type', 'OTHERCARE', TYPE_RUT
73
+ it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_RUT, housework: false
74
+
75
+ # rubocop:disable RSpec/RepeatedDescription
76
+ pending 'to be added' do
77
+ raise Exception, 'Will be supported 2021-01-01'
78
+ # it_behaves_like 'housework type', 'HOMEMAINTENANCE', TYPE_RUT
79
+ # it_behaves_like 'housework type', 'FURNISHING', TYPE_RUT
80
+ # it_behaves_like 'housework type', 'TRANSPORTATIONSERVICES', TYPE_RUT
81
+ # it_behaves_like 'housework type', 'WASHINGANDCAREOFCLOTHING', TYPE_RUT
82
+ end
83
+
84
+ pending 'to be added' do
85
+ raise Exception, 'Will be supported 2021-01-01'
86
+ # it_behaves_like 'housework type', 'SOLARCELLS', TYPE_GREEN
87
+ # it_behaves_like 'housework type', 'STORAGESELFPRODUCEDELECTRICTY', TYPE_GREEN
88
+ # it_behaves_like 'housework type', 'CHARGINGSTATIONELECTRICVEHICLE', TYPE_GREEN
89
+ # it_behaves_like 'housework type', 'OTHERCOSTS', TYPE_GREEN
90
+ end
91
+ # rubocop:enable RSpec/RepeatedDescription
92
+
93
+ it_behaves_like 'housework type', 'COOKING', TYPE_RUT, legacy: true
94
+ it_behaves_like 'housework type', 'TUTORING', TYPE_RUT, legacy: true
95
+
96
+ 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
+ let(:document) do
103
+ Fortnox::API::Model::Order.new(
104
+ customer_number: '1',
105
+ tax_reduction_type: TYPE_ROT,
106
+ order_rows: [
107
+ Fortnox::API::Types::OrderRow.new(
108
+ ordered_quantity: 1,
109
+ article_number: '0000',
110
+ housework_type: Fortnox::API::Types::HouseworkTypes['OTHERCOSTS'],
111
+ housework: true
112
+ )
113
+ ]
114
+ )
115
+ end
116
+
117
+ let(:error_message) { 'Kan inte sätta typen övrig kostnad på en rad markerad som husarbete.' }
118
+
119
+ it "can't have housework set to true" do
120
+ is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
121
+ end
122
+ end
123
+
124
+ 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
+ let(:type) { 'CONSTRUCTION' }
131
+ let(:document) do
132
+ Fortnox::API::Model::Order.new(
133
+ customer_number: '1',
134
+ tax_reduction_type: TYPE_RUT,
135
+ order_rows: [
136
+ Fortnox::API::Types::OrderRow.new(
137
+ ordered_quantity: 1,
138
+ article_number: '0000',
139
+ housework_type: Fortnox::API::Types::HouseworkTypes[type],
140
+ housework: true
141
+ )
142
+ ]
143
+ )
144
+ end
145
+
146
+ let(:error_message) do
147
+ "Dokument med skattereduktionstypen '#{TYPE_RUT}' " \
148
+ "får inte innehålla rader med husarbetestypen '#{type}'."
149
+ end
150
+
151
+ it 'raises an error' do
152
+ is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
153
+ end
154
+ end
67
155
  end
68
156
  # rubocop:enable RSpec/DescribeClass
@@ -6,16 +6,14 @@ require 'fortnox/api/types/model'
6
6
 
7
7
  RSpec.describe Fortnox::API::Types::Model do
8
8
  shared_examples_for 'raises error' do |error|
9
- using_test_classes do
10
- module Types
11
- include Dry::Types.module
9
+ before do
10
+ stub_const('Types::Age', Dry::Types['strict.integer'].constrained(gt: 18).is(:required))
12
11
 
13
- Age = Int.constrained(gt: 18).is(:required)
14
- end
15
-
16
- class TypesModelUser < Fortnox::API::Types::Model
12
+ types_model_user_class = Class.new(Fortnox::API::Types::Model) do
17
13
  attribute :age, Types::Age
18
14
  end
15
+
16
+ stub_const('TypesModelUser', types_model_user_class)
19
17
  end
20
18
 
21
19
  describe "User inheriting from #{described_class}" do
@@ -32,21 +30,17 @@ RSpec.describe Fortnox::API::Types::Model do
32
30
  end
33
31
 
34
32
  context 'when omitting optional keys' do
35
- using_test_class do
36
- module Types
37
- include Dry::Types.module
33
+ subject { -> { User.new } }
38
34
 
39
- module Nullable
40
- String = Types::Strict::String.optional
41
- end
42
- end
35
+ before do
36
+ stub_const('Types::Nullable::String', Dry::Types['strict.string'].optional)
43
37
 
44
- class User < Fortnox::API::Types::Model
38
+ user_class = Class.new(Fortnox::API::Types::Model) do
45
39
  attribute :optional_string, Types::Nullable::String
46
40
  end
47
- end
48
41
 
49
- subject { -> { User.new } }
42
+ stub_const('User', user_class)
43
+ end
50
44
 
51
45
  it { is_expected.not_to raise_error }
52
46
 
@@ -8,52 +8,72 @@ describe Fortnox::API::Types::Nullable, type: :type do
8
8
  subject { TestStruct }
9
9
 
10
10
  describe 'String' do
11
- using_test_class do
12
- class TestStruct < Dry::Struct
11
+ before do
12
+ test_struct_class = Class.new(Dry::Struct) do
13
13
  attribute :string, Fortnox::API::Types::Nullable::String
14
14
  end
15
+
16
+ stub_const('TestStruct', test_struct_class)
15
17
  end
16
18
 
17
19
  it { is_expected.to have_nullable(:string, 'A simple message', 0, '0') }
18
20
  end
19
21
 
20
22
  describe 'Float' do
21
- using_test_class do
22
- class TestStruct < Dry::Struct
23
+ before do
24
+ test_struct_class = Class.new(Dry::Struct) do
23
25
  attribute :float, Fortnox::API::Types::Nullable::Float
24
26
  end
27
+
28
+ stub_const('TestStruct', test_struct_class)
25
29
  end
26
30
 
27
31
  it { is_expected.to have_nullable(:float, 14.0, 'Not a Float!', 0.0) }
28
32
  end
29
33
 
30
34
  describe 'Integer' do
31
- using_test_class do
32
- class TestStruct < Dry::Struct
35
+ before do
36
+ test_struct_class = Class.new(Dry::Struct) do
33
37
  attribute :integer, Fortnox::API::Types::Nullable::Integer
34
38
  end
39
+
40
+ stub_const('TestStruct', test_struct_class)
35
41
  end
36
42
 
37
43
  it { is_expected.to have_nullable(:integer, 14, 14.0, 14) }
38
44
  end
39
45
 
40
46
  describe 'Boolean' do
41
- using_test_class do
42
- class TestStruct < Dry::Struct
47
+ before do
48
+ test_struct_class = Class.new(Dry::Struct) do
43
49
  attribute :boolean, Fortnox::API::Types::Nullable::Boolean
44
50
  end
51
+
52
+ stub_const('TestStruct', test_struct_class)
45
53
  end
46
54
 
47
55
  it { is_expected.to have_nullable(:boolean, true, 'Not a Boolean!', false) }
48
56
  end
49
57
 
50
58
  describe 'Date' do
51
- using_test_class do
52
- class TestStruct < Dry::Struct
59
+ before do
60
+ test_struct_class = Class.new(Dry::Struct) do
53
61
  attribute :date, Fortnox::API::Types::Nullable::Date
54
62
  end
63
+
64
+ stub_const('TestStruct', test_struct_class)
55
65
  end
56
66
 
57
67
  it { is_expected.to have_nullable_date(:date, Date.new(2016, 1, 1), 'Not a Date!') }
68
+
69
+ context 'with empty string' do
70
+ subject { TestStruct.new(date: '').date }
71
+
72
+ it { is_expected.to be_nil }
73
+ end
74
+
75
+ context 'with invalid date' do
76
+ it { expect { TestStruct.new(date: 'Not a Date!') }.to raise_error(Fortnox::API::AttributeError, /invalid date/) }
77
+ end
58
78
  end
59
79
  end
@@ -5,10 +5,7 @@ require 'fortnox/api/types'
5
5
  require 'fortnox/api/types/required'
6
6
 
7
7
  describe Fortnox::API::Types::Required, type: :type do
8
- using_test_class do
9
- class TestClass < Dry::Struct
10
- end
11
- end
8
+ before { stub_const('TestClass', Class.new(Dry::Struct)) }
12
9
 
13
10
  shared_examples_for 'required attribute' do |_type|
14
11
  subject { -> { TestClass.new({}) } }
@@ -15,7 +15,7 @@ module Matchers
15
15
  private
16
16
 
17
17
  def expected_type?
18
- @actual_type = @klass.schema[@attribute]
18
+ @actual_type = @klass.schema.keys.find { |x| x.name == @attribute }&.type
19
19
  @actual_type == @enum_type
20
20
  end
21
21
  end
@@ -15,7 +15,7 @@ module Matchers
15
15
  private
16
16
 
17
17
  def expected_type?
18
- @actual_type = @klass.schema[@attribute]
18
+ @actual_type = @klass.schema.keys.find { |x| x.name == @attribute }&.type
19
19
  @actual_type == Fortnox::API::Types::AccountNumber
20
20
  end
21
21
  end
@@ -16,7 +16,7 @@ module Matchers
16
16
  private
17
17
 
18
18
  def expected_type?
19
- @actual_type = @klass.schema[@attribute]
19
+ @actual_type = @klass.schema.keys.find { |x| x.name == @attribute }&.type
20
20
  @actual_type == Fortnox::API::Types::Email
21
21
  end
22
22
  end
@@ -11,7 +11,7 @@ module Matchers
11
11
  @attribute = attribute
12
12
  @valid_value = valid_value
13
13
  @invalid_value = invalid_value
14
- @expected_error = ArgumentError
14
+ @expected_error = Fortnox::API::AttributeError
15
15
  @expected_error_message = 'invalid date'
16
16
  @failure_description = ''
17
17
  end
@@ -46,11 +46,11 @@ module Matchers
46
46
 
47
47
  @failure_description << " (Expected #{@expected_error}, but got none)"
48
48
  false
49
- rescue @expected_error => error
50
- return true if error.message == @expected_error_message
49
+ rescue @expected_error => e
50
+ return true if e.message == @expected_error_message
51
51
 
52
- fail_message = "Expected error message to include #{expected_message.inspect}, "\
53
- "but was #{error.message.inspect}"
52
+ fail_message = "Expected error message to include #{@expected_error_message.inspect}, "\
53
+ "but was #{e.message.inspect}"
54
54
  raise(fail_message)
55
55
  end
56
56
  end
@@ -33,13 +33,13 @@ module Matchers
33
33
  def rejects_non_string?
34
34
  non_string = 10.0
35
35
  @klass.new(@valid_hash.merge(@attribute => non_string))
36
- rescue Fortnox::API::InvalidAttributeValueError => error
36
+ rescue Fortnox::API::AttributeError => e
37
37
  expected_message = "#{non_string.inspect} (#{non_string.class}) "\
38
38
  "has invalid type for #{@attribute.inspect}"
39
- return true if error.message.include?(expected_message)
39
+ return true if e.message.include?(expected_message)
40
40
 
41
41
  fail_message = "Expected error message to include #{expected_message.inspect}, "\
42
- "but was #{error.message.inspect}"
42
+ "but was #{e.message.inspect}"
43
43
  raise(fail_message)
44
44
  end
45
45
  end