fortnox-api 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -0
  3. data/.env.template +7 -0
  4. data/.env.test +11 -3
  5. data/.gitignore +7 -1
  6. data/.rubocop.yml +18 -2
  7. data/.tool-versions +1 -0
  8. data/.travis.yml +15 -12
  9. data/CHANGELOG.md +58 -3
  10. data/CONTRIBUTE.md +21 -9
  11. data/DEVELOPER_README.md +72 -0
  12. data/Guardfile +13 -4
  13. data/README.md +226 -64
  14. data/Rakefile +128 -0
  15. data/bin/get_tokens +79 -0
  16. data/bin/renew_tokens +28 -0
  17. data/fortnox-api.gemspec +31 -25
  18. data/lib/fortnox/api/mappers/article.rb +1 -1
  19. data/lib/fortnox/api/mappers/base/from_json.rb +5 -4
  20. data/lib/fortnox/api/mappers/base/to_json.rb +4 -5
  21. data/lib/fortnox/api/mappers/base.rb +3 -3
  22. data/lib/fortnox/api/mappers/customer.rb +1 -1
  23. data/lib/fortnox/api/mappers/default_delivery_types.rb +1 -1
  24. data/lib/fortnox/api/mappers/default_templates.rb +1 -1
  25. data/lib/fortnox/api/mappers/edi_information.rb +1 -1
  26. data/lib/fortnox/api/mappers/email_information.rb +1 -1
  27. data/lib/fortnox/api/mappers/invoice.rb +4 -4
  28. data/lib/fortnox/api/mappers/invoice_row.rb +1 -1
  29. data/lib/fortnox/api/mappers/order.rb +4 -4
  30. data/lib/fortnox/api/mappers/order_row.rb +1 -1
  31. data/lib/fortnox/api/mappers/project.rb +1 -1
  32. data/lib/fortnox/api/mappers/terms_of_payment.rb +1 -1
  33. data/lib/fortnox/api/mappers/unit.rb +1 -1
  34. data/lib/fortnox/api/mappers/value/country_string.rb +1 -1
  35. data/lib/fortnox/api/mappers.rb +18 -18
  36. data/lib/fortnox/api/models/article.rb +2 -2
  37. data/lib/fortnox/api/models/base.rb +23 -21
  38. data/lib/fortnox/api/models/customer.rb +57 -57
  39. data/lib/fortnox/api/models/document.rb +2 -2
  40. data/lib/fortnox/api/models/invoice.rb +2 -2
  41. data/lib/fortnox/api/models/label.rb +3 -3
  42. data/lib/fortnox/api/models/order.rb +2 -2
  43. data/lib/fortnox/api/models/project.rb +2 -2
  44. data/lib/fortnox/api/models/terms_of_payment.rb +2 -2
  45. data/lib/fortnox/api/models/unit.rb +2 -2
  46. data/lib/fortnox/api/models.rb +7 -7
  47. data/lib/fortnox/api/repositories/article.rb +3 -3
  48. data/lib/fortnox/api/repositories/authentication.rb +61 -0
  49. data/lib/fortnox/api/repositories/base/savers.rb +3 -1
  50. data/lib/fortnox/api/repositories/base.rb +25 -38
  51. data/lib/fortnox/api/repositories/customer.rb +3 -3
  52. data/lib/fortnox/api/repositories/invoice.rb +3 -3
  53. data/lib/fortnox/api/repositories/order.rb +3 -3
  54. data/lib/fortnox/api/repositories/project.rb +3 -3
  55. data/lib/fortnox/api/repositories/terms_of_payment.rb +3 -3
  56. data/lib/fortnox/api/repositories/unit.rb +3 -3
  57. data/lib/fortnox/api/repositories.rb +8 -7
  58. data/lib/fortnox/api/request_handling.rb +30 -18
  59. data/lib/fortnox/api/types/default_delivery_types.rb +0 -2
  60. data/lib/fortnox/api/types/default_templates.rb +0 -2
  61. data/lib/fortnox/api/types/document_row.rb +3 -3
  62. data/lib/fortnox/api/types/edi_information.rb +0 -2
  63. data/lib/fortnox/api/types/email_information.rb +0 -2
  64. data/lib/fortnox/api/types/enums.rb +27 -11
  65. data/lib/fortnox/api/types/invoice_row.rb +1 -1
  66. data/lib/fortnox/api/types/model.rb +5 -9
  67. data/lib/fortnox/api/types/nullable.rb +13 -9
  68. data/lib/fortnox/api/types/order_row.rb +1 -1
  69. data/lib/fortnox/api/types/required.rb +3 -3
  70. data/lib/fortnox/api/types/sized.rb +4 -4
  71. data/lib/fortnox/api/types.rb +31 -23
  72. data/lib/fortnox/api/version.rb +1 -1
  73. data/lib/fortnox/api.rb +21 -39
  74. data/spec/fortnox/api/mappers/base/canonical_name_sym_spec.rb +13 -11
  75. data/spec/fortnox/api/mappers/base/from_json_spec.rb +10 -12
  76. data/spec/fortnox/api/mappers/base/to_json_spec.rb +48 -57
  77. data/spec/fortnox/api/mappers/base_spec.rb +4 -7
  78. data/spec/fortnox/api/mappers/contexts/json_conversion.rb +38 -33
  79. data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +1 -1
  80. data/spec/fortnox/api/mappers/examples/mapper.rb +1 -1
  81. data/spec/fortnox/api/mappers/unit_spec.rb +3 -4
  82. data/spec/fortnox/api/models/base_spec.rb +33 -22
  83. data/spec/fortnox/api/models/unit_spec.rb +5 -3
  84. data/spec/fortnox/api/repositories/article_spec.rb +14 -9
  85. data/spec/fortnox/api/repositories/authentication_spec.rb +103 -0
  86. data/spec/fortnox/api/repositories/base_spec.rb +105 -326
  87. data/spec/fortnox/api/repositories/customer_spec.rb +37 -7
  88. data/spec/fortnox/api/repositories/examples/all.rb +0 -1
  89. data/spec/fortnox/api/repositories/examples/find.rb +5 -8
  90. data/spec/fortnox/api/repositories/examples/only.rb +4 -13
  91. data/spec/fortnox/api/repositories/examples/save.rb +32 -18
  92. data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +0 -5
  93. data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +1 -4
  94. data/spec/fortnox/api/repositories/examples/search.rb +4 -7
  95. data/spec/fortnox/api/repositories/invoice_spec.rb +64 -21
  96. data/spec/fortnox/api/repositories/order_spec.rb +11 -9
  97. data/spec/fortnox/api/repositories/project_spec.rb +7 -6
  98. data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +9 -7
  99. data/spec/fortnox/api/repositories/unit_spec.rb +13 -11
  100. data/spec/fortnox/api/types/country_spec.rb +1 -1
  101. data/spec/fortnox/api/types/email_spec.rb +2 -2
  102. data/spec/fortnox/api/types/examples/document_row.rb +3 -3
  103. data/spec/fortnox/api/types/examples/enum.rb +4 -4
  104. data/spec/fortnox/api/types/examples/types.rb +1 -3
  105. data/spec/fortnox/api/types/housework_types_spec.rb +54 -90
  106. data/spec/fortnox/api/types/model_spec.rb +13 -23
  107. data/spec/fortnox/api/types/nullable_spec.rb +30 -10
  108. data/spec/fortnox/api/types/order_row_spec.rb +2 -2
  109. data/spec/fortnox/api/types/required_spec.rb +7 -15
  110. data/spec/fortnox/api/types/sales_account_spec.rb +57 -0
  111. data/spec/fortnox/api_spec.rb +19 -124
  112. data/spec/spec_helper.rb +0 -14
  113. data/spec/support/helpers/configuration_helper.rb +30 -3
  114. data/spec/support/helpers.rb +1 -1
  115. data/spec/support/matchers/type/attribute_matcher.rb +2 -2
  116. data/spec/support/matchers/type/enum_matcher.rb +1 -1
  117. data/spec/support/matchers/type/have_account_number_matcher.rb +1 -1
  118. data/spec/support/matchers/type/have_email_matcher.rb +1 -1
  119. data/spec/support/matchers/type/have_nullable_date_matcher.rb +7 -5
  120. data/spec/support/matchers/type/have_nullable_matcher.rb +1 -1
  121. data/spec/support/matchers/type/have_nullable_string_matcher.rb +5 -5
  122. data/spec/support/matchers/type/require_attribute_matcher.rb +5 -5
  123. data/spec/support/matchers/type/type_matcher.rb +1 -1
  124. data/spec/support/vcr_setup.rb +16 -0
  125. data/spec/vcr_cassettes/articles/all.yml +32 -49
  126. data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +27 -23
  127. data/spec/vcr_cassettes/articles/find_failure.yml +27 -23
  128. data/spec/vcr_cassettes/articles/find_id_1.yml +29 -24
  129. data/spec/vcr_cassettes/articles/find_new.yml +30 -26
  130. data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +29 -25
  131. data/spec/vcr_cassettes/articles/save_new.yml +29 -25
  132. data/spec/vcr_cassettes/articles/save_old.yml +30 -26
  133. data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +29 -25
  134. data/spec/vcr_cassettes/articles/search_by_name.yml +32 -25
  135. data/spec/vcr_cassettes/articles/search_miss.yml +27 -23
  136. data/spec/vcr_cassettes/articles/search_with_special_char.yml +27 -23
  137. data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +29 -36
  138. data/spec/vcr_cassettes/authentication/expired_token.yml +54 -0
  139. data/spec/vcr_cassettes/authentication/invalid_authorization.yml +57 -0
  140. data/spec/vcr_cassettes/authentication/invalid_refresh_token.yml +58 -0
  141. data/spec/vcr_cassettes/authentication/valid_request.yml +63 -0
  142. data/spec/vcr_cassettes/customers/all.yml +35 -136
  143. data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +27 -23
  144. data/spec/vcr_cassettes/customers/find_failure.yml +27 -23
  145. data/spec/vcr_cassettes/customers/find_id_1.yml +30 -25
  146. data/spec/vcr_cassettes/customers/find_new.yml +29 -25
  147. data/spec/vcr_cassettes/customers/find_with_sales_account.yml +63 -0
  148. data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +29 -25
  149. data/spec/vcr_cassettes/customers/save_new.yml +28 -24
  150. data/spec/vcr_cassettes/customers/save_new_with_country_code_SE.yml +28 -24
  151. data/spec/vcr_cassettes/customers/save_new_with_sales_account.yml +63 -0
  152. data/spec/vcr_cassettes/customers/save_old.yml +29 -25
  153. data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +28 -24
  154. data/spec/vcr_cassettes/customers/search_by_name.yml +29 -53
  155. data/spec/vcr_cassettes/customers/search_miss.yml +27 -23
  156. data/spec/vcr_cassettes/customers/search_with_special_char.yml +27 -23
  157. data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +30 -26
  158. data/spec/vcr_cassettes/invoices/all.yml +62 -121
  159. data/spec/vcr_cassettes/invoices/filter_hit.yml +30 -28
  160. data/spec/vcr_cassettes/invoices/filter_invalid.yml +27 -23
  161. data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +27 -23
  162. data/spec/vcr_cassettes/invoices/find_failure.yml +27 -23
  163. data/spec/vcr_cassettes/invoices/find_id_1.yml +31 -26
  164. data/spec/vcr_cassettes/invoices/find_new.yml +32 -28
  165. data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +29 -25
  166. data/spec/vcr_cassettes/invoices/row_description_limit.yml +65 -0
  167. data/spec/vcr_cassettes/invoices/save_new.yml +31 -27
  168. data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +31 -27
  169. data/spec/vcr_cassettes/invoices/save_new_with_country.yml +31 -26
  170. data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +32 -27
  171. data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +31 -26
  172. data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +31 -26
  173. data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +31 -26
  174. data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +32 -27
  175. data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +32 -27
  176. data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +31 -26
  177. data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +31 -26
  178. data/spec/vcr_cassettes/invoices/save_new_with_unsaved_parent.yml +65 -0
  179. data/spec/vcr_cassettes/invoices/save_old.yml +32 -28
  180. data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +32 -28
  181. data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +32 -27
  182. data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +32 -28
  183. data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +32 -27
  184. data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +32 -27
  185. data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +31 -26
  186. data/spec/vcr_cassettes/invoices/search_by_name.yml +29 -31
  187. data/spec/vcr_cassettes/invoices/search_miss.yml +27 -23
  188. data/spec/vcr_cassettes/invoices/search_with_special_char.yml +27 -23
  189. data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +30 -26
  190. data/spec/vcr_cassettes/orders/all.yml +35 -123
  191. data/spec/vcr_cassettes/orders/filter_hit.yml +30 -30
  192. data/spec/vcr_cassettes/orders/filter_invalid.yml +27 -23
  193. data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +27 -23
  194. data/spec/vcr_cassettes/orders/find_failure.yml +27 -23
  195. data/spec/vcr_cassettes/orders/find_id_1.yml +33 -27
  196. data/spec/vcr_cassettes/orders/find_new.yml +32 -28
  197. data/spec/vcr_cassettes/orders/housework_invalid_tax_reduction_type.yml +28 -24
  198. data/spec/vcr_cassettes/orders/housework_othercoses_invalid.yml +28 -24
  199. data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +32 -27
  200. data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +32 -27
  201. data/spec/vcr_cassettes/orders/housework_type_construction.yml +32 -27
  202. data/spec/vcr_cassettes/orders/housework_type_cooking.yml +28 -24
  203. data/spec/vcr_cassettes/orders/housework_type_electricity.yml +32 -27
  204. data/spec/vcr_cassettes/orders/housework_type_gardening.yml +32 -27
  205. data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +32 -27
  206. data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +32 -27
  207. data/spec/vcr_cassettes/orders/housework_type_hvac.yml +32 -27
  208. data/spec/vcr_cassettes/orders/housework_type_itservices.yml +32 -27
  209. data/spec/vcr_cassettes/orders/housework_type_majorappliancerepair.yml +32 -27
  210. data/spec/vcr_cassettes/orders/housework_type_masonry.yml +32 -27
  211. data/spec/vcr_cassettes/orders/housework_type_movingservices.yml +32 -27
  212. data/spec/vcr_cassettes/orders/housework_type_othercare.yml +32 -27
  213. data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +32 -27
  214. data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +32 -27
  215. data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +32 -27
  216. data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +32 -27
  217. data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +28 -24
  218. data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +29 -25
  219. data/spec/vcr_cassettes/orders/save_new.yml +32 -28
  220. data/spec/vcr_cassettes/orders/save_old.yml +32 -28
  221. data/spec/vcr_cassettes/orders/save_with_nested_model.yml +32 -27
  222. data/spec/vcr_cassettes/orders/search_by_name.yml +29 -27
  223. data/spec/vcr_cassettes/orders/search_miss.yml +27 -23
  224. data/spec/vcr_cassettes/orders/search_with_special_char.yml +27 -23
  225. data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +30 -26
  226. data/spec/vcr_cassettes/projects/all.yml +30 -43
  227. data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +27 -23
  228. data/spec/vcr_cassettes/projects/find_failure.yml +27 -23
  229. data/spec/vcr_cassettes/projects/find_id_1.yml +29 -25
  230. data/spec/vcr_cassettes/projects/find_new.yml +30 -26
  231. data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +31 -26
  232. data/spec/vcr_cassettes/projects/save_new.yml +29 -25
  233. data/spec/vcr_cassettes/projects/save_old.yml +30 -26
  234. data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +29 -25
  235. data/spec/vcr_cassettes/termsofpayments/all.yml +32 -32
  236. data/spec/vcr_cassettes/termsofpayments/find_failure.yml +27 -23
  237. data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +29 -26
  238. data/spec/vcr_cassettes/termsofpayments/find_new.yml +29 -25
  239. data/spec/vcr_cassettes/termsofpayments/save_new.yml +29 -25
  240. data/spec/vcr_cassettes/termsofpayments/save_old.yml +29 -25
  241. data/spec/vcr_cassettes/units/all.yml +29 -32
  242. data/spec/vcr_cassettes/units/find_failure.yml +27 -23
  243. data/spec/vcr_cassettes/units/find_id_1.yml +29 -25
  244. data/spec/vcr_cassettes/units/find_new.yml +29 -25
  245. data/spec/vcr_cassettes/units/save_new.yml +29 -25
  246. data/spec/vcr_cassettes/units/save_old.yml +29 -25
  247. data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +29 -25
  248. metadata +130 -261
  249. data/lib/fortnox/api/circular_queue.rb +0 -39
  250. data/spec/fortnox/api/circular_queue_spec.rb +0 -52
  251. data/spec/support/helpers/dummy_class_helper.rb +0 -38
  252. data/spec/support/helpers/when_performing_helper.rb +0 -7
  253. data/spec/vcr_cassettes/invoices/save_new_with_country_KR.yml +0 -61
  254. data/spec/vcr_cassettes/orders/housework_without_tax_reduction_type.yml +0 -57
  255. data/temp.txt +0 -1
@@ -7,21 +7,14 @@
7
7
  # Assumes that attribute is a string attribute without restrictions.
8
8
  shared_examples_for '.save' do |attribute, additional_attrs: {}|
9
9
  describe '.save' do
10
- let(:new_hash) { additional_attrs.merge(attribute => value) }
11
- let(:new_model) { described_class::MODEL.new(new_hash) }
12
- let(:save_new) { VCR.use_cassette("#{vcr_dir}/save_new") { repository.save(new_model) } }
13
- let(:entity_wrapper) { repository.mapper.class::JSON_ENTITY_WRAPPER }
14
- let(:value) { 'A value' }
15
-
16
- shared_examples_for 'save' do
17
- before do
18
- if model.saved?
19
- message = 'Test trying to save model, but already marked as saved!'
20
- message << " Model: #{model.inspect}"
21
- raise(message)
22
- end
10
+ let(:new_hash) { additional_attrs.merge(attribute => 'A value') }
11
+ let(:save_new) do
12
+ VCR.use_cassette("#{vcr_dir}/save_new") do
13
+ repository.save(described_class::MODEL.new(new_hash))
23
14
  end
15
+ end
24
16
 
17
+ shared_examples_for 'save' do
25
18
  specify "includes correct #{attribute.inspect}" do
26
19
  saved_entity = send_request
27
20
  expect(saved_entity.send(attribute)).to eql(value)
@@ -31,8 +24,9 @@ shared_examples_for '.save' do |attribute, additional_attrs: {}|
31
24
  describe 'new' do
32
25
  context 'when not saved' do
33
26
  include_examples 'save' do
34
- let(:model) { new_model }
27
+ let(:model) { described_class::MODEL.new(new_hash) }
35
28
  let(:send_request) { save_new }
29
+ let(:value) { 'A value' }
36
30
  end
37
31
  end
38
32
 
@@ -45,13 +39,34 @@ shared_examples_for '.save' do |attribute, additional_attrs: {}|
45
39
  end
46
40
 
47
41
  describe 'old (update existing)' do
42
+ let(:find_new_cassette) { "#{vcr_dir}/find_new" }
43
+
48
44
  include_examples 'save' do
49
45
  let(:value) { "Updated #{attribute}" }
46
+
50
47
  let(:model) do
51
- new_id = save_new.unique_id
52
- new_record = VCR.use_cassette("#{vcr_dir}/find_new") { repository.find(new_id) }
53
- new_record.update(attribute => value)
48
+ existing_model = VCR.use_cassette(find_new_cassette) do
49
+ repository.find(save_new.unique_id)
50
+ end
51
+
52
+ updated_model = existing_model.update(attribute => value)
53
+
54
+ if updated_model.saved?
55
+ raise(
56
+ "We are trying to update the :#{attribute} attribute with " \
57
+ "#{value} on an existing record, but that record " \
58
+ 'loaded from Fortnox ' \
59
+ "already has this attribute set to that value:\n" \
60
+ "#{existing_model.inspect}\nHave a look at the VCR cassette " \
61
+ "\"#{find_new_cassette}\" which should load the record with the " \
62
+ "attribute :#{attribute} set to something else than " \
63
+ 'the value we want to set. ' \
64
+ )
65
+ end
66
+
67
+ updated_model
54
68
  end
69
+
55
70
  let(:send_request) do
56
71
  VCR.use_cassette("#{vcr_dir}/save_old") { repository.save(model) }
57
72
  end
@@ -59,4 +74,3 @@ shared_examples_for '.save' do |attribute, additional_attrs: {}|
59
74
  end
60
75
  end
61
76
  end
62
- # rubocop:enable RSpec/DescribeClass
@@ -15,10 +15,6 @@ shared_examples_for '.save with nested model' do |required_hash, nested_model_ke
15
15
  end
16
16
  end
17
17
 
18
- it 'does not raise any errors' do
19
- expect { response }.not_to raise_error
20
- end
21
-
22
18
  describe 'returned entity\'s nested model' do
23
19
  subject(:returned_nested_model) { response.send(nested_model_key).first }
24
20
 
@@ -30,4 +26,3 @@ shared_examples_for '.save with nested model' do |required_hash, nested_model_ke
30
26
  end
31
27
  end
32
28
  end
33
- # rubocop:enable RSpec/DescribeClass
@@ -7,8 +7,6 @@
7
7
  shared_examples_for '.save with specially named attribute' do |required_hash, attribute, value|
8
8
  describe '.save' do
9
9
  context 'with specially named attribute' do
10
- subject { -> { save_model } }
11
-
12
10
  let(:new_model) { described_class::MODEL.new(required_hash.merge(attribute => value)) }
13
11
  let(:save_model) do
14
12
  VCR.use_cassette("#{vcr_dir}/save_with_specially_named_attribute") do
@@ -16,7 +14,7 @@ shared_examples_for '.save with specially named attribute' do |required_hash, at
16
14
  end
17
15
  end
18
16
 
19
- it { is_expected.not_to raise_error }
17
+ it { expect { save_model }.not_to raise_error }
20
18
 
21
19
  describe 'response' do
22
20
  subject { save_model.send(attribute) }
@@ -26,4 +24,3 @@ shared_examples_for '.save with specially named attribute' do |required_hash, at
26
24
  end
27
25
  end
28
26
  end
29
- # rubocop:enable RSpec/DescribeClass
@@ -26,17 +26,14 @@ shared_examples_for '.search' do |attribute_hash_key_name, value, matches|
26
26
  end
27
27
 
28
28
  context 'with special characters' do
29
- subject do
30
- when_performing do
31
- VCR.use_cassette("#{vcr_dir}/search_with_special_char") do
32
- repository.search(attribute_hash_key_name => 'special char å')
33
- end
29
+ let(:search_with_special_char) do
30
+ VCR.use_cassette("#{vcr_dir}/search_with_special_char") do
31
+ repository.search(attribute_hash_key_name => 'special char å')
34
32
  end
35
33
  end
36
34
 
37
- it { is_expected.not_to raise_error }
35
+ specify { expect { search_with_special_char }.not_to raise_error }
38
36
  end
39
37
  end
40
38
  end
41
39
  end
42
- # rubocop:enable RSpec/DescribeClass
@@ -12,18 +12,36 @@ require 'fortnox/api/repositories/examples/save_with_nested_model'
12
12
  require 'fortnox/api/repositories/examples/save_with_specially_named_attribute'
13
13
  require 'fortnox/api/repositories/examples/only'
14
14
 
15
- describe Fortnox::API::Repository::Invoice, order: :defined, integration: true do
15
+ describe Fortnox::API::Repository::Invoice, integration: true, order: :defined do
16
16
  include Helpers::Configuration
17
-
18
- before { set_api_test_configuration }
17
+ include Helpers::Repositories
19
18
 
20
19
  subject(:repository) { described_class.new }
21
20
 
21
+ before { set_api_test_configuration }
22
+
22
23
  required_hash = { customer_number: '1' }
23
24
 
24
25
  include_examples '.save', :comments, additional_attrs: required_hash
25
26
 
26
- nested_model_hash = { price: 10, article_number: '0000' }
27
+ describe '#save' do
28
+ context 'with unsaved parent' do
29
+ subject(:saved_child) do
30
+ parent_invoice = Fortnox::API::Model::Invoice.new(customer_number: '1')
31
+ child_invoice = parent_invoice.update(due_date: '2023-01-01')
32
+
33
+ VCR.use_cassette("#{vcr_dir}/save_new_with_unsaved_parent") do
34
+ described_class.new.save(child_invoice)
35
+ end
36
+ end
37
+
38
+ it 'sets attribute from parent when saved' do
39
+ expect(saved_child.customer_number).to eq '1'
40
+ end
41
+ end
42
+ end
43
+
44
+ nested_model_hash = { price: 10, article_number: '101' }
27
45
  include_examples '.save with nested model',
28
46
  required_hash,
29
47
  :invoice_rows,
@@ -37,8 +55,9 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
37
55
 
38
56
  # It is not possible to delete Invoces. Therefore, expected nr of Orders
39
57
  # when running .all will continue to increase (until 100, which is max by default).
40
- include_examples '.all', 100
58
+ include_examples '.all', 34
41
59
 
60
+ # VCR: Models needs to be created manually in Fortnox
42
61
  include_examples '.find', 1 do
43
62
  let(:find_by_hash_failure) { { yourreference: 'Not found' } }
44
63
 
@@ -51,9 +70,10 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
51
70
  end
52
71
  end
53
72
 
54
- include_examples '.search', :customername, 'Test', 7
73
+ include_examples '.search', :customername, 'Test', 1
55
74
 
56
- include_examples '.only', :fullypaid, 4
75
+ # VCR: Need to be set manually in Fortnox
76
+ include_examples '.only', :fullypaid, 2
57
77
 
58
78
  describe 'country attribute' do
59
79
  def new_invoice(country:)
@@ -89,12 +109,6 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
89
109
  it { is_expected.to eq('GB') }
90
110
  end
91
111
 
92
- describe 'KR' do
93
- subject { save_invoice(country: 'KR').country }
94
-
95
- it { is_expected.to eq('KR') }
96
- end
97
-
98
112
  describe 'VA' do
99
113
  subject { save_invoice(country: 'VA').country }
100
114
 
@@ -130,7 +144,7 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
130
144
  before { persisted_invoice }
131
145
 
132
146
  context 'when setting value to nil' do
133
- subject { updated_persisted_invoice.comments }
147
+ subject(:comments) { updated_persisted_invoice.comments }
134
148
 
135
149
  let(:updated_persisted_invoice) do
136
150
  VCR.use_cassette("#{vcr_dir}/save_old_with_nil_comments") do
@@ -138,11 +152,14 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
138
152
  end
139
153
  end
140
154
 
141
- pending { is_expected.to eq(nil) }
155
+ it do
156
+ pending "test to rerecord VCR cassette, maybe it's working now"
157
+ expect(comments).to be_nil
158
+ end
142
159
  end
143
160
 
144
161
  context 'when setting value to empty string' do
145
- subject { updated_persisted_invoice.comments }
162
+ subject(:comments) { updated_persisted_invoice.comments }
146
163
 
147
164
  let(:updated_persisted_invoice) do
148
165
  VCR.use_cassette("#{vcr_dir}/save_old_with_empty_comments") do
@@ -151,7 +168,7 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
151
168
  end
152
169
 
153
170
  it 'does not reset the value' do
154
- is_expected.to eq('A comment to be reset')
171
+ expect(comments).to eq('A comment to be reset')
155
172
  end
156
173
  end
157
174
  end
@@ -170,7 +187,7 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
170
187
  before { persisted_invoice }
171
188
 
172
189
  context 'when setting value to nil' do
173
- subject { updated_persisted_invoice.country }
190
+ subject(:country) { updated_persisted_invoice.country }
174
191
 
175
192
  let(:updated_persisted_invoice) do
176
193
  # TODO: This VCR cassette needs to be re-recorded again
@@ -180,11 +197,14 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
180
197
  end
181
198
  end
182
199
 
183
- pending { is_expected.to eq(nil) }
200
+ it 'is nil' do
201
+ pending 'see comment above'
202
+ expect(country).to be_nil
203
+ end
184
204
  end
185
205
 
186
206
  context 'when setting value to empty string' do
187
- subject { updated_persisted_invoice.country }
207
+ subject(:country) { updated_persisted_invoice.country }
188
208
 
189
209
  let(:updated_persisted_invoice) do
190
210
  VCR.use_cassette("#{vcr_dir}/save_old_with_empty_country") do
@@ -193,9 +213,32 @@ describe Fortnox::API::Repository::Invoice, order: :defined, integration: true d
193
213
  end
194
214
 
195
215
  it 'does not reset the country' do
196
- is_expected.to eq('SE')
216
+ expect(country).to eq('SE')
197
217
  end
198
218
  end
199
219
  end
200
220
  end
221
+
222
+ describe 'limits for invoice_row' do
223
+ describe 'description' do
224
+ let(:model) do
225
+ described_class::MODEL.new(
226
+ customer_number: '1',
227
+ invoice_rows: [
228
+ {
229
+ article_number: '101',
230
+ description: 'a' * 255
231
+ }
232
+ ]
233
+ )
234
+ end
235
+ let(:saving_with_max_row_description) do
236
+ VCR.use_cassette("#{vcr_dir}/row_description_limit") { repository.save(model) }
237
+ end
238
+
239
+ it 'allows 255 characters' do
240
+ expect { saving_with_max_row_description }.not_to raise_error
241
+ end
242
+ end
243
+ end
201
244
  end
@@ -11,28 +11,29 @@ require 'fortnox/api/repositories/examples/save'
11
11
  require 'fortnox/api/repositories/examples/save_with_nested_model'
12
12
  require 'fortnox/api/repositories/examples/search'
13
13
 
14
- describe Fortnox::API::Repository::Order, order: :defined, integration: true do
14
+ describe Fortnox::API::Repository::Order, integration: true, order: :defined do
15
15
  include Helpers::Configuration
16
-
17
- before { set_api_test_configuration }
16
+ include Helpers::Repositories
18
17
 
19
18
  subject(:repository) { described_class.new }
20
19
 
20
+ before { set_api_test_configuration }
21
+
21
22
  required_hash = { customer_number: '1' }
22
23
 
23
24
  include_examples '.save', :comments, additional_attrs: required_hash
24
25
 
25
- nested_model_hash = { price: 10, article_number: '0000', ordered_quantity: 1 }
26
+ nested_model_hash = { price: -9_999_999_999, article_number: '101', ordered_quantity: 1 }
26
27
  include_examples '.save with nested model',
27
28
  required_hash,
28
29
  :order_rows,
29
30
  nested_model_hash,
30
31
  [Fortnox::API::Types::OrderRow.new(nested_model_hash)]
31
32
 
32
- # It is not possible to delete Orders. Therefore, expected nr of Orders
33
- # when running .all will continue to increase (until 100, which is max by default).
34
- include_examples '.all', 100
33
+ # VCR: Update expected result
34
+ include_examples '.all', 7
35
35
 
36
+ # VCR: Searched Orders needs to be created manually in Fortnox
36
37
  include_examples '.find', 1 do
37
38
  let(:find_by_hash_failure) { { ourreference: 'Not found' } }
38
39
 
@@ -45,7 +46,8 @@ describe Fortnox::API::Repository::Order, order: :defined, integration: true do
45
46
  end
46
47
  end
47
48
 
48
- include_examples '.search', :customername, 'A customer', 3
49
+ # VCR: Searched Order needs to be created manually
50
+ include_examples '.search', :customername, 'A customer', 1
49
51
 
50
- include_examples '.only', :cancelled, 6
52
+ include_examples '.only', :cancelled, 2
51
53
  end
@@ -8,28 +8,29 @@ require 'fortnox/api/repositories/examples/all'
8
8
  require 'fortnox/api/repositories/examples/find'
9
9
  require 'fortnox/api/repositories/examples/save'
10
10
 
11
- describe Fortnox::API::Repository::Project, order: :defined, integration: true do
11
+ describe Fortnox::API::Repository::Project, integration: true, order: :defined do
12
12
  include Helpers::Configuration
13
-
14
- before { set_api_test_configuration }
13
+ include Helpers::Repositories
15
14
 
16
15
  subject(:repository) { described_class.new }
17
16
 
17
+ before { set_api_test_configuration }
18
+
18
19
  include_examples '.save',
19
20
  :comments,
20
21
  additional_attrs: { description: 'Some important project' }
21
22
 
22
- # It is not yet possible to delete Projects. Therefore, expected nr of
23
+ # VCR: It is not yet possible to delete Projects. Therefore, expected nr of
23
24
  # Projects when running .all will continue to increase
24
25
  # (until 100, which is max by default).
25
- include_examples '.all', 33
26
+ include_examples '.all', 2
26
27
 
27
28
  include_examples '.find', '1' do
28
29
  let(:find_by_hash_failure) { { offset: 10_000 } }
29
30
  let(:single_param_find_by_hash) { { find_hash: { limit: 1 }, matches: 1 } }
30
31
 
31
32
  let(:multi_param_find_by_hash) do
32
- { find_hash: { limit: 2, offset: 2 }, matches: 2 }
33
+ { find_hash: { limit: 2, offset: 0 }, matches: 2 }
33
34
  end
34
35
  end
35
36
  end
@@ -10,23 +10,25 @@ require 'fortnox/api/repositories/examples/save'
10
10
  require 'fortnox/api/repositories/examples/save_with_specially_named_attribute'
11
11
  require 'fortnox/api/repositories/examples/search'
12
12
 
13
- describe Fortnox::API::Repository::TermsOfPayment, order: :defined, integration: true do
13
+ describe Fortnox::API::Repository::TermsOfPayment, integration: true, order: :defined do
14
14
  include Helpers::Configuration
15
+ include Helpers::Repositories
15
16
 
16
17
  subject(:repository) { described_class.new }
17
18
 
18
19
  before { set_api_test_configuration }
19
20
 
20
- # When recording new VCR cassettes, code must be changed to a new unique one
21
- required_hash = { code: '19DAYS' }
21
+ # VCR: code must be changed to a new unique one
22
+ required_hash = { code: '21DAYS' }
22
23
 
23
24
  include_examples '.save', :description, additional_attrs: required_hash
24
25
 
25
- # When recording new VCR cassettes, expected matches needs to be increased
26
- include_examples '.all', 13
26
+ # VCR: expected matches needs to be increased
27
+ include_examples '.all', 10
27
28
 
28
- include_examples '.find', '15DAYS', find_by_hash: false do
29
- let(:find_by_hash_failure) { { code: '15days' } }
29
+ # VCR: The terms of payment searched here needs to be created manually in Fortnox
30
+ include_examples '.find', '19DAYS', find_by_hash: false do
31
+ let(:find_by_hash_failure) { { code: '19days' } }
30
32
  let(:single_param_find_by_hash) { { find_hash: { code: '30days' }, matches: 1 } }
31
33
  end
32
34
  end
@@ -9,29 +9,31 @@ require 'fortnox/api/repositories/examples/find'
9
9
  require 'fortnox/api/repositories/examples/save'
10
10
  require 'fortnox/api/repositories/examples/save_with_specially_named_attribute'
11
11
 
12
- describe Fortnox::API::Repository::Unit, order: :defined, integration: true do
12
+ describe Fortnox::API::Repository::Unit, integration: true, order: :defined do
13
13
  include Helpers::Configuration
14
-
15
- before { set_api_test_configuration }
14
+ include Helpers::Repositories
16
15
 
17
16
  subject(:repository) { described_class.new }
18
17
 
19
- # When recording new VCR cassettes, code needs to be changed to a unique value
18
+ before { set_api_test_configuration }
19
+
20
+ # VCR: code needs to be changed to a unique value
20
21
  include_examples '.save',
21
22
  :description,
22
- additional_attrs: { code: 'blarg5' }
23
+ additional_attrs: { code: 'blarg9' }
23
24
 
24
- # When recording new VCR cassettes, code needs to be changed to a unique value
25
+ # VCR: code needs to be changed to a unique value
25
26
  include_examples '.save with specially named attribute',
26
27
  { description: 'Happy clouds' },
27
28
  :code,
28
- 'woooh5'
29
+ 'woooh7'
29
30
 
30
- # When recording new VCR cassettes, expected number must be updated
31
- include_examples '.all', 14
31
+ # VCR: expected number must be updated
32
+ include_examples '.all', 7
32
33
 
33
- include_examples '.find', 'blarg', find_by_hash: false do
34
+ # VCR: code must be updated
35
+ include_examples '.find', 'blarg7', find_by_hash: false do
34
36
  let(:find_by_hash_failure) { { code: 'notfound' } }
35
- let(:single_param_find_by_hash) { { find_hash: { code: 'blarg' }, matches: 1 } }
37
+ let(:single_param_find_by_hash) { { find_hash: { code: 'blarg7' }, matches: 1 } }
36
38
  end
37
39
  end
@@ -45,7 +45,7 @@ describe Fortnox::API::Types::Country do
45
45
  expect(described_class['SV']).to eq 'SV'
46
46
  end
47
47
 
48
- it 'translated Switzerland to ' do
48
+ it 'translated Switzerland to' do
49
49
  expect(described_class['Switzerland']).to eq 'CH'
50
50
  end
51
51
  end
@@ -36,8 +36,8 @@ describe Fortnox::API::Types::Email do
36
36
  end
37
37
 
38
38
  context 'when created with more than 1024 characters' do
39
- legal_characters = 'abcdefghijklmnopqrstuvwxyz0123456789.-_+'.split('')
40
- too_long_email = (legal_characters * 35).shuffle.join + '@example.com'
39
+ legal_characters = 'abcdefghijklmnopqrstuvwxyz0123456789.-_+'.chars
40
+ too_long_email = "#{(legal_characters * 35).shuffle.join}@example.com"
41
41
  include_examples 'raises ConstraintError', too_long_email
42
42
  end
43
43
  end
@@ -4,7 +4,7 @@ shared_examples_for 'DocumentRow' do |valid_hash|
4
4
  it { is_expected.to have_account_number(:account_number, valid_hash) }
5
5
 
6
6
  it { is_expected.to have_sized_string(:article_number, 50, valid_hash) }
7
- it { is_expected.to have_sized_string(:description, 50, valid_hash) }
7
+ it { is_expected.to have_sized_string(:description, 255, valid_hash) }
8
8
 
9
9
  it { is_expected.to have_discount_type(:discount_type, valid_hash) }
10
10
 
@@ -12,10 +12,10 @@ shared_examples_for 'DocumentRow' do |valid_hash|
12
12
 
13
13
  it { is_expected.to have_housework_type(:housework_type, valid_hash) }
14
14
 
15
- it { is_expected.to have_sized_float(:price, 0.0, 99_999_999_999.9, valid_hash) }
15
+ it { is_expected.to have_sized_float(:price, -9_999_999_999, 99_999_999_999.9, valid_hash) }
16
16
 
17
17
  it do # rubocop:disable RSpec/ExampleLength
18
- is_expected.to have_sized_float(
18
+ expect(subject).to have_sized_float(
19
19
  :delivered_quantity,
20
20
  -9_999_999_999_999.9,
21
21
  9_999_999_999_999.9,
@@ -36,14 +36,14 @@ shared_examples_for 'enum' do |name, values, auto_crop: false|
36
36
  end
37
37
 
38
38
  context 'with a string that starts like a random member from the enum' do
39
- let(:input) { enum_value.downcase + 'more string' }
39
+ let(:input) { "#{enum_value.downcase}more string" }
40
40
 
41
41
  if auto_crop
42
42
  it { is_expected.to eq enum_value }
43
43
  else
44
- subject { -> { klass[input] } }
45
-
46
- it { is_expected.to raise_error(Dry::Types::ConstraintError) }
44
+ it do
45
+ expect { klass[input] }.to raise_error(Dry::Types::ConstraintError)
46
+ end
47
47
  end
48
48
  end
49
49
  end
@@ -7,7 +7,5 @@ shared_examples_for 'equals input' do |input|
7
7
  end
8
8
 
9
9
  shared_examples_for 'raises ConstraintError' do |input|
10
- subject { -> { klass[input] } }
11
-
12
- it { is_expected.to raise_error(Dry::Types::ConstraintError) }
10
+ specify { expect { klass[input] }.to raise_error(Dry::Types::ConstraintError) }
13
11
  end