fortnox-api 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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