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.
Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/.env.template +7 -0
  3. data/.env.test +11 -3
  4. data/.gitignore +7 -1
  5. data/.rubocop.yml +17 -1
  6. data/.travis.yml +10 -9
  7. data/CHANGELOG.md +22 -8
  8. data/CONTRIBUTE.md +21 -9
  9. data/DEVELOPER_README.md +72 -0
  10. data/Guardfile +13 -4
  11. data/README.md +226 -64
  12. data/Rakefile +128 -0
  13. data/bin/get_tokens +79 -0
  14. data/bin/renew_tokens +28 -0
  15. data/fortnox-api.gemspec +10 -9
  16. data/lib/fortnox/api/mappers/base/from_json.rb +4 -3
  17. data/lib/fortnox/api/mappers/base/to_json.rb +2 -3
  18. data/lib/fortnox/api/models/base.rb +12 -10
  19. data/lib/fortnox/api/models/customer.rb +55 -55
  20. data/lib/fortnox/api/models/label.rb +2 -2
  21. data/lib/fortnox/api/repositories/authentication.rb +61 -0
  22. data/lib/fortnox/api/repositories/base/savers.rb +3 -1
  23. data/lib/fortnox/api/repositories/base.rb +21 -35
  24. data/lib/fortnox/api/repositories.rb +1 -0
  25. data/lib/fortnox/api/request_handling.rb +30 -18
  26. data/lib/fortnox/api/types/document_row.rb +3 -3
  27. data/lib/fortnox/api/types/enums.rb +27 -11
  28. data/lib/fortnox/api/types/model.rb +1 -4
  29. data/lib/fortnox/api/types/sized.rb +2 -2
  30. data/lib/fortnox/api/types.rb +14 -1
  31. data/lib/fortnox/api/version.rb +1 -1
  32. data/lib/fortnox/api.rb +12 -32
  33. data/spec/fortnox/api/mappers/base/canonical_name_sym_spec.rb +4 -4
  34. data/spec/fortnox/api/mappers/base/from_json_spec.rb +10 -12
  35. data/spec/fortnox/api/mappers/base/to_json_spec.rb +48 -57
  36. data/spec/fortnox/api/mappers/base_spec.rb +4 -7
  37. data/spec/fortnox/api/mappers/contexts/json_conversion.rb +38 -33
  38. data/spec/fortnox/api/mappers/unit_spec.rb +3 -4
  39. data/spec/fortnox/api/models/base_spec.rb +27 -16
  40. data/spec/fortnox/api/models/unit_spec.rb +5 -3
  41. data/spec/fortnox/api/repositories/article_spec.rb +14 -9
  42. data/spec/fortnox/api/repositories/authentication_spec.rb +103 -0
  43. data/spec/fortnox/api/repositories/base_spec.rb +106 -319
  44. data/spec/fortnox/api/repositories/customer_spec.rb +37 -7
  45. data/spec/fortnox/api/repositories/examples/all.rb +0 -1
  46. data/spec/fortnox/api/repositories/examples/find.rb +5 -8
  47. data/spec/fortnox/api/repositories/examples/only.rb +4 -13
  48. data/spec/fortnox/api/repositories/examples/save.rb +32 -18
  49. data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +0 -5
  50. data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +1 -4
  51. data/spec/fortnox/api/repositories/examples/search.rb +4 -7
  52. data/spec/fortnox/api/repositories/invoice_spec.rb +64 -15
  53. data/spec/fortnox/api/repositories/order_spec.rb +11 -9
  54. data/spec/fortnox/api/repositories/project_spec.rb +7 -6
  55. data/spec/fortnox/api/repositories/terms_of_payment_spec.rb +9 -7
  56. data/spec/fortnox/api/repositories/unit_spec.rb +13 -11
  57. data/spec/fortnox/api/types/country_spec.rb +1 -1
  58. data/spec/fortnox/api/types/email_spec.rb +2 -2
  59. data/spec/fortnox/api/types/examples/document_row.rb +3 -3
  60. data/spec/fortnox/api/types/examples/enum.rb +4 -4
  61. data/spec/fortnox/api/types/examples/types.rb +1 -3
  62. data/spec/fortnox/api/types/housework_types_spec.rb +54 -61
  63. data/spec/fortnox/api/types/model_spec.rb +3 -27
  64. data/spec/fortnox/api/types/order_row_spec.rb +2 -2
  65. data/spec/fortnox/api/types/required_spec.rb +6 -11
  66. data/spec/fortnox/api/types/sales_account_spec.rb +57 -0
  67. data/spec/fortnox/api_spec.rb +19 -124
  68. data/spec/spec_helper.rb +0 -14
  69. data/spec/support/helpers/configuration_helper.rb +30 -3
  70. data/spec/support/helpers.rb +1 -1
  71. data/spec/support/matchers/type/attribute_matcher.rb +2 -2
  72. data/spec/support/matchers/type/have_nullable_date_matcher.rb +6 -4
  73. data/spec/support/matchers/type/have_nullable_matcher.rb +1 -1
  74. data/spec/support/matchers/type/have_nullable_string_matcher.rb +5 -5
  75. data/spec/support/matchers/type/require_attribute_matcher.rb +5 -5
  76. data/spec/support/matchers/type/type_matcher.rb +1 -1
  77. data/spec/support/vcr_setup.rb +16 -0
  78. data/spec/vcr_cassettes/articles/all.yml +16 -43
  79. data/spec/vcr_cassettes/articles/find_by_hash_failure.yml +10 -12
  80. data/spec/vcr_cassettes/articles/find_failure.yml +10 -12
  81. data/spec/vcr_cassettes/articles/find_id_1.yml +13 -14
  82. data/spec/vcr_cassettes/articles/find_new.yml +14 -16
  83. data/spec/vcr_cassettes/articles/multi_param_find_by_hash.yml +13 -15
  84. data/spec/vcr_cassettes/articles/save_new.yml +13 -15
  85. data/spec/vcr_cassettes/articles/save_old.yml +14 -16
  86. data/spec/vcr_cassettes/articles/save_with_specially_named_attribute.yml +13 -15
  87. data/spec/vcr_cassettes/articles/search_by_name.yml +16 -15
  88. data/spec/vcr_cassettes/articles/search_miss.yml +10 -12
  89. data/spec/vcr_cassettes/articles/search_with_special_char.yml +10 -12
  90. data/spec/vcr_cassettes/articles/single_param_find_by_hash.yml +13 -27
  91. data/spec/vcr_cassettes/authentication/expired_token.yml +54 -0
  92. data/spec/vcr_cassettes/authentication/invalid_authorization.yml +57 -0
  93. data/spec/vcr_cassettes/authentication/invalid_refresh_token.yml +58 -0
  94. data/spec/vcr_cassettes/authentication/valid_request.yml +63 -0
  95. data/spec/vcr_cassettes/customers/all.yml +20 -127
  96. data/spec/vcr_cassettes/customers/find_by_hash_failure.yml +10 -12
  97. data/spec/vcr_cassettes/customers/find_failure.yml +10 -12
  98. data/spec/vcr_cassettes/customers/find_id_1.yml +14 -15
  99. data/spec/vcr_cassettes/customers/find_new.yml +13 -15
  100. data/spec/vcr_cassettes/customers/find_with_sales_account.yml +63 -0
  101. data/spec/vcr_cassettes/customers/multi_param_find_by_hash.yml +13 -15
  102. data/spec/vcr_cassettes/customers/save_new.yml +12 -14
  103. data/spec/vcr_cassettes/customers/save_new_with_country_code_SE.yml +12 -14
  104. data/spec/vcr_cassettes/customers/save_new_with_sales_account.yml +63 -0
  105. data/spec/vcr_cassettes/customers/save_old.yml +13 -15
  106. data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +12 -14
  107. data/spec/vcr_cassettes/customers/search_by_name.yml +13 -45
  108. data/spec/vcr_cassettes/customers/search_miss.yml +10 -12
  109. data/spec/vcr_cassettes/customers/search_with_special_char.yml +10 -12
  110. data/spec/vcr_cassettes/customers/single_param_find_by_hash.yml +14 -16
  111. data/spec/vcr_cassettes/invoices/all.yml +47 -112
  112. data/spec/vcr_cassettes/invoices/filter_hit.yml +14 -18
  113. data/spec/vcr_cassettes/invoices/filter_invalid.yml +10 -12
  114. data/spec/vcr_cassettes/invoices/find_by_hash_failure.yml +10 -12
  115. data/spec/vcr_cassettes/invoices/find_failure.yml +10 -12
  116. data/spec/vcr_cassettes/invoices/find_id_1.yml +15 -16
  117. data/spec/vcr_cassettes/invoices/find_new.yml +16 -18
  118. data/spec/vcr_cassettes/invoices/multi_param_find_by_hash.yml +13 -15
  119. data/spec/vcr_cassettes/invoices/row_description_limit.yml +65 -0
  120. data/spec/vcr_cassettes/invoices/save_new.yml +14 -16
  121. data/spec/vcr_cassettes/invoices/save_new_with_comments.yml +14 -16
  122. data/spec/vcr_cassettes/invoices/save_new_with_country.yml +14 -15
  123. data/spec/vcr_cassettes/invoices/save_new_with_country_GB.yml +15 -16
  124. data/spec/vcr_cassettes/invoices/save_new_with_country_Norge.yml +14 -15
  125. data/spec/vcr_cassettes/invoices/save_new_with_country_Norway.yml +14 -15
  126. data/spec/vcr_cassettes/invoices/save_new_with_country_Sverige.yml +14 -15
  127. data/spec/vcr_cassettes/invoices/save_new_with_country_VA.yml +15 -16
  128. data/spec/vcr_cassettes/invoices/save_new_with_country_VI.yml +15 -16
  129. data/spec/vcr_cassettes/invoices/save_new_with_country_empty_string.yml +14 -15
  130. data/spec/vcr_cassettes/invoices/save_new_with_country_nil.yml +14 -15
  131. data/spec/vcr_cassettes/invoices/save_new_with_unsaved_parent.yml +65 -0
  132. data/spec/vcr_cassettes/invoices/save_old.yml +16 -18
  133. data/spec/vcr_cassettes/invoices/save_old_with_empty_comments.yml +16 -18
  134. data/spec/vcr_cassettes/invoices/save_old_with_empty_country.yml +16 -17
  135. data/spec/vcr_cassettes/invoices/save_old_with_nil_comments.yml +16 -18
  136. data/spec/vcr_cassettes/invoices/save_old_with_nil_country.yml +16 -17
  137. data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +15 -16
  138. data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +14 -15
  139. data/spec/vcr_cassettes/invoices/search_by_name.yml +13 -21
  140. data/spec/vcr_cassettes/invoices/search_miss.yml +10 -12
  141. data/spec/vcr_cassettes/invoices/search_with_special_char.yml +10 -12
  142. data/spec/vcr_cassettes/invoices/single_param_find_by_hash.yml +14 -16
  143. data/spec/vcr_cassettes/orders/all.yml +19 -113
  144. data/spec/vcr_cassettes/orders/filter_hit.yml +14 -20
  145. data/spec/vcr_cassettes/orders/filter_invalid.yml +10 -12
  146. data/spec/vcr_cassettes/orders/find_by_hash_failure.yml +10 -12
  147. data/spec/vcr_cassettes/orders/find_failure.yml +10 -12
  148. data/spec/vcr_cassettes/orders/find_id_1.yml +17 -17
  149. data/spec/vcr_cassettes/orders/find_new.yml +16 -18
  150. data/spec/vcr_cassettes/orders/housework_invalid_tax_reduction_type.yml +11 -13
  151. data/spec/vcr_cassettes/orders/housework_othercoses_invalid.yml +11 -13
  152. data/spec/vcr_cassettes/orders/housework_type_babysitting.yml +15 -16
  153. data/spec/vcr_cassettes/orders/housework_type_cleaning.yml +15 -16
  154. data/spec/vcr_cassettes/orders/housework_type_construction.yml +15 -16
  155. data/spec/vcr_cassettes/orders/housework_type_cooking.yml +11 -13
  156. data/spec/vcr_cassettes/orders/housework_type_electricity.yml +15 -16
  157. data/spec/vcr_cassettes/orders/housework_type_gardening.yml +15 -16
  158. data/spec/vcr_cassettes/orders/housework_type_glassmetalwork.yml +15 -16
  159. data/spec/vcr_cassettes/orders/housework_type_grounddrainagework.yml +15 -16
  160. data/spec/vcr_cassettes/orders/housework_type_hvac.yml +15 -16
  161. data/spec/vcr_cassettes/orders/housework_type_itservices.yml +15 -16
  162. data/spec/vcr_cassettes/orders/housework_type_majorappliancerepair.yml +15 -16
  163. data/spec/vcr_cassettes/orders/housework_type_masonry.yml +15 -16
  164. data/spec/vcr_cassettes/orders/housework_type_movingservices.yml +15 -16
  165. data/spec/vcr_cassettes/orders/housework_type_othercare.yml +15 -16
  166. data/spec/vcr_cassettes/orders/housework_type_othercosts.yml +15 -16
  167. data/spec/vcr_cassettes/orders/housework_type_paintingwallpapering.yml +15 -16
  168. data/spec/vcr_cassettes/orders/housework_type_snowplowing.yml +15 -16
  169. data/spec/vcr_cassettes/orders/housework_type_textileclothing.yml +15 -16
  170. data/spec/vcr_cassettes/orders/housework_type_tutoring.yml +11 -13
  171. data/spec/vcr_cassettes/orders/multi_param_find_by_hash.yml +13 -15
  172. data/spec/vcr_cassettes/orders/save_new.yml +16 -18
  173. data/spec/vcr_cassettes/orders/save_old.yml +16 -18
  174. data/spec/vcr_cassettes/orders/save_with_nested_model.yml +15 -16
  175. data/spec/vcr_cassettes/orders/search_by_name.yml +13 -17
  176. data/spec/vcr_cassettes/orders/search_miss.yml +10 -12
  177. data/spec/vcr_cassettes/orders/search_with_special_char.yml +10 -12
  178. data/spec/vcr_cassettes/orders/single_param_find_by_hash.yml +14 -16
  179. data/spec/vcr_cassettes/projects/all.yml +14 -37
  180. data/spec/vcr_cassettes/projects/find_by_hash_failure.yml +10 -12
  181. data/spec/vcr_cassettes/projects/find_failure.yml +10 -12
  182. data/spec/vcr_cassettes/projects/find_id_1.yml +13 -15
  183. data/spec/vcr_cassettes/projects/find_new.yml +14 -16
  184. data/spec/vcr_cassettes/projects/multi_param_find_by_hash.yml +15 -16
  185. data/spec/vcr_cassettes/projects/save_new.yml +13 -15
  186. data/spec/vcr_cassettes/projects/save_old.yml +14 -16
  187. data/spec/vcr_cassettes/projects/single_param_find_by_hash.yml +12 -14
  188. data/spec/vcr_cassettes/termsofpayments/all.yml +16 -23
  189. data/spec/vcr_cassettes/termsofpayments/find_failure.yml +10 -12
  190. data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +13 -16
  191. data/spec/vcr_cassettes/termsofpayments/find_new.yml +12 -14
  192. data/spec/vcr_cassettes/termsofpayments/save_new.yml +12 -14
  193. data/spec/vcr_cassettes/termsofpayments/save_old.yml +12 -14
  194. data/spec/vcr_cassettes/units/all.yml +13 -24
  195. data/spec/vcr_cassettes/units/find_failure.yml +10 -12
  196. data/spec/vcr_cassettes/units/find_id_1.yml +13 -15
  197. data/spec/vcr_cassettes/units/find_new.yml +12 -14
  198. data/spec/vcr_cassettes/units/save_new.yml +12 -14
  199. data/spec/vcr_cassettes/units/save_old.yml +12 -14
  200. data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +12 -14
  201. metadata +39 -230
  202. data/lib/fortnox/api/circular_queue.rb +0 -39
  203. data/spec/fortnox/api/circular_queue_spec.rb +0 -52
  204. data/spec/support/helpers/when_performing_helper.rb +0 -7
  205. 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 { set_api_test_configuration }
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: '0000',
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) { 'Skattereduktion för den valda typen av husarbete har upphört.' }
43
+ let(:error_message) { /Skattereduktion för den valda typen av husarbete har upphört/ }
42
44
 
43
- it 'raises an error' do
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
- it { is_expected.not_to raise_error }
47
+ specify { expect { save.call }.not_to raise_error }
48
48
  end
49
49
  end
50
50
  end
51
51
 
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
-
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
- pending 'to be added' do
77
- raise Exception, 'Will be supported 2021-01-01'
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
- pending 'to be added' do
85
- raise Exception, 'Will be supported 2021-01-01'
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: '0000',
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) { 'Kan inte sätta typen övrig kostnad på en rad markerad som husarbete.' }
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
- is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
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: '0000',
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
- "Dokument med skattereduktionstypen '#{TYPE_RUT}' " \
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
- is_expected.to raise_error(Fortnox::API::RemoteServerError, error_message)
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
- subject { -> { TypesModelUser.new(args) } }
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
- it { is_expected.not_to raise_error }
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 be nil }
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
- subject { -> { TestClass.new({}) } }
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
- class TestClass
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
- class TestClass
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
@@ -4,14 +4,7 @@ require 'spec_helper'
4
4
  require 'fortnox/api'
5
5
 
6
6
  describe Fortnox::API do
7
- before do
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 eql 'https://api.fortnox.se/3/' }
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 'token_store' do
46
- let(:config_key) { :token_store }
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 be false }
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
- is_expected.to be false
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
- is_expected.to be_a Logger
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.client_secret = '9aBA8ZgsvR'
8
- config.access_tokens = ['ccaef817-d5d8-4b1c-a316-54f3e55c5c54']
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
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Dir[File.expand_path('spec/support/helpers/*.rb')].each { |file| require file }
3
+ Dir[File.expand_path('spec/support/helpers/*.rb')].sort.each { |file| require file }
@@ -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 << msg
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 => e
50
- return true if e.message == @expected_error_message
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 #{e.message.inspect}"
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