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
@@ -24,19 +24,19 @@ describe Fortnox::API::Model::Base do
24
24
  end
25
25
 
26
26
  context 'without required attribute' do
27
- subject { -> { entity_class.new({}) } }
28
-
29
- it { is_expected.to raise_error Fortnox::API::Exception }
30
- it { is_expected.to raise_error Fortnox::API::MissingAttributeError }
31
- it { is_expected.to raise_error Fortnox::API::MissingAttributeError, /Missing attribute :string/ }
27
+ it do
28
+ expect do
29
+ entity_class.new({})
30
+ end.to raise_error Fortnox::API::MissingAttributeError, /Missing attribute :string/
31
+ end
32
32
  end
33
33
 
34
34
  context 'with invalid attribute value' do
35
- subject { -> { entity_class.new(string: 'Test', account: 13_337) } }
36
-
37
- it { is_expected.to raise_error Fortnox::API::Exception }
38
- it { is_expected.to raise_error Fortnox::API::AttributeError }
39
- it { is_expected.to raise_error Fortnox::API::AttributeError, /invalid type for :account/ }
35
+ it do
36
+ expect do
37
+ entity_class.new(string: 'Test', account: 13_337)
38
+ end.to raise_error Fortnox::API::AttributeError, /invalid type for :account/
39
+ end
40
40
  end
41
41
  end
42
42
 
@@ -44,15 +44,13 @@ describe Fortnox::API::Model::Base do
44
44
  let(:original) { entity_class.new(string: 'Test') }
45
45
 
46
46
  context 'with new, simple value' do
47
- subject { updated_model }
48
-
49
- let(:updated_model) { original.update(string: 'Variant') }
47
+ subject(:updated_model) { original.update(string: 'Variant') }
50
48
 
51
49
  it { is_expected.to be_new }
52
50
  it { is_expected.not_to be_saved }
53
51
 
54
52
  it 'returns a new object' do
55
- is_expected.not_to eql(original)
53
+ expect(updated_model).not_to eql(original)
56
54
  end
57
55
 
58
56
  describe 'updated attribute' do
@@ -72,7 +70,7 @@ describe Fortnox::API::Model::Base do
72
70
  subject(:updated_model) { original.update(string: 'Test') }
73
71
 
74
72
  it 'returns the same object' do
75
- is_expected.to eql(original)
73
+ expect(updated_model).to eql(original)
76
74
  end
77
75
 
78
76
  it 'returns a object with the same value' do
@@ -83,7 +81,7 @@ describe Fortnox::API::Model::Base do
83
81
  it { is_expected.not_to be_saved }
84
82
  end
85
83
 
86
- context 'when updating' do
84
+ context 'when updating a saved entity' do
87
85
  let(:updated_entity) do
88
86
  saved_entity = entity_class.new(string: 'Saved', new: false, unsaved: false)
89
87
  saved_entity.update(string: 'Updated')
@@ -102,5 +100,18 @@ describe Fortnox::API::Model::Base do
102
100
  it { is_expected.to eq('Updated') }
103
101
  end
104
102
  end
103
+
104
+ context 'when updating a saved entity with nil values' do
105
+ subject(:updated_entity) { original.update(number: nil) }
106
+
107
+ let(:original) { entity_class.new(string: 'Saved', new: false, unsaved: false) }
108
+
109
+ it 'returns the same object' do
110
+ expect(updated_entity).to eql(original)
111
+ end
112
+
113
+ it { is_expected.not_to be_new }
114
+ it { is_expected.to be_saved }
115
+ end
105
116
  end
106
117
  end
@@ -9,9 +9,11 @@ module Fortnox
9
9
  module Model
10
10
  describe Unit, type: :model do
11
11
  context 'when created from empty hash' do
12
- subject { -> { described_class.new } }
13
-
14
- it { is_expected.to raise_error(Fortnox::API::MissingAttributeError, /Missing attribute.*:code/) }
12
+ it {
13
+ expect do
14
+ described_class.new
15
+ end.to raise_error(Fortnox::API::MissingAttributeError, /Missing attribute.*:code/)
16
+ }
15
17
  end
16
18
 
17
19
  context 'when created from stub' do
@@ -10,13 +10,16 @@ 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::Article, order: :defined, integration: true do
13
+ describe Fortnox::API::Repository::Article, integration: true, order: :defined do
14
14
  include Helpers::Configuration
15
-
16
- before { set_api_test_configuration }
15
+ include Helpers::Repositories
17
16
 
18
17
  subject(:repository) { described_class.new }
19
18
 
19
+ before { set_api_test_configuration }
20
+
21
+ # VCR: Requires a Financial Year in Fortnox, otherwise the sales account is not be available.
22
+ # VCR: Update requires that default accounts exists in the chart of accounts
20
23
  include_examples '.save',
21
24
  :description,
22
25
  additional_attrs: { sales_account: 1250 }
@@ -26,18 +29,20 @@ describe Fortnox::API::Repository::Article, order: :defined, integration: true d
26
29
  :ean,
27
30
  '5901234123457'
28
31
 
29
- # When recording new VCR cassettes, expected matches must be increased
30
- include_examples '.all', 33
32
+ # VCR: expected matches must be increased
33
+ include_examples '.all', 6
31
34
 
32
- # When recording new VCR cassettes, expected matches must be increased
35
+ # VCR: Expected matches must be increased
36
+ # VCR: Create the searched Articles manually in Fortnox
33
37
  include_examples '.find', '1' do
34
38
  let(:find_by_hash_failure) { { description: 'Not Found' } }
35
- let(:single_param_find_by_hash) { { find_hash: { articlenumber: 1 }, matches: 14 } }
39
+ let(:single_param_find_by_hash) { { find_hash: { articlenumber: 101 }, matches: 1 } }
36
40
 
37
41
  let(:multi_param_find_by_hash) do
38
- { find_hash: { articlenumber: 1, description: 'Cykelpump' }, matches: 1 }
42
+ { find_hash: { articlenumber: 101, description: 'Hammer' }, matches: 1 }
39
43
  end
40
44
  end
41
45
 
42
- include_examples '.search', :description, 'Testartikel', 2
46
+ # VCR: Expected mathes must be updated
47
+ include_examples '.search', :description, 'Test article', 3
43
48
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'fortnox/api'
5
+ require 'fortnox/api/repositories/authentication'
6
+
7
+ describe Fortnox::API::Repository::Authentication, integration: true do
8
+ include Helpers::Configuration
9
+
10
+ subject(:repository) { described_class.new }
11
+
12
+ before { set_api_test_configuration }
13
+
14
+ let(:vcr_dir) { 'authentication' }
15
+
16
+ let(:valid_response) do
17
+ VCR.use_cassette("#{vcr_dir}/valid_request") do
18
+ repository.renew_tokens(
19
+ refresh_token: ENV.fetch('FORTNOX_API_REFRESH_TOKEN'),
20
+ client_id: ENV.fetch('FORTNOX_API_CLIENT_ID'),
21
+ client_secret: ENV.fetch('FORTNOX_API_CLIENT_SECRET')
22
+ )
23
+ end
24
+ end
25
+
26
+ describe '#renew_tokens' do
27
+ context 'with invalid authorization' do
28
+ let(:request_with_nonsense_credentials) do
29
+ VCR.use_cassette("#{vcr_dir}/invalid_authorization") do
30
+ repository.renew_tokens(
31
+ refresh_token: ENV.fetch('FORTNOX_API_REFRESH_TOKEN'),
32
+ client_id: 'nonsense_id',
33
+ client_secret: 'nonsense_secret'
34
+ )
35
+ end
36
+ end
37
+
38
+ it 'raises an error' do
39
+ expect { request_with_nonsense_credentials }.to(
40
+ raise_error(Fortnox::API::RemoteServerError, /Unauthorized request(.)*Error:(.)*invalid_client/)
41
+ )
42
+ end
43
+ end
44
+
45
+ context 'with invalid refresh token' do
46
+ let(:request_with_invalid_refresh_token) do
47
+ VCR.use_cassette("#{vcr_dir}/invalid_refresh_token") do
48
+ repository.renew_tokens(
49
+ refresh_token: 'invalid_refresh_token',
50
+ client_id: ENV.fetch('FORTNOX_API_CLIENT_ID'),
51
+ client_secret: ENV.fetch('FORTNOX_API_CLIENT_SECRET')
52
+ )
53
+ end
54
+ end
55
+
56
+ it 'raises an error' do
57
+ expect { request_with_invalid_refresh_token }.to(
58
+ raise_error(Fortnox::API::RemoteServerError, /Bad request(.)*Error:(.)*Invalid refresh token/)
59
+ )
60
+ end
61
+ end
62
+
63
+ describe 'returned hash' do
64
+ subject { valid_response }
65
+
66
+ it { is_expected.to include(:access_token, :refresh_token, :expires_in, :token_type, :scope) }
67
+ end
68
+
69
+ describe 'access_token' do
70
+ subject { valid_response[:access_token] }
71
+
72
+ it { is_expected.to be_a(String) }
73
+ it { is_expected.not_to be_empty }
74
+ end
75
+
76
+ describe 'refresh_token' do
77
+ subject { valid_response[:refresh_token] }
78
+
79
+ it { is_expected.to be_a(String) }
80
+ it { is_expected.not_to be_empty }
81
+ end
82
+
83
+ describe 'expires_in' do
84
+ subject { valid_response[:expires_in] }
85
+
86
+ it { is_expected.to be_a(Integer) }
87
+ end
88
+
89
+ describe 'token_type' do
90
+ subject { valid_response[:token_type] }
91
+
92
+ it { is_expected.to be_a(String) }
93
+ it { is_expected.not_to be_empty }
94
+ end
95
+
96
+ describe 'scope' do
97
+ subject { valid_response[:scope] }
98
+
99
+ it { is_expected.to be_a(String) }
100
+ it { is_expected.not_to be_empty }
101
+ end
102
+ end
103
+ end