fortnox-api 0.1.0 → 0.2.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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +3 -2
  3. data/.env.test +3 -0
  4. data/.rubocop.yml +32 -23
  5. data/.travis.yml +3 -2
  6. data/Guardfile +2 -2
  7. data/LICENSE.txt +165 -22
  8. data/README.md +56 -37
  9. data/fortnox-api.gemspec +9 -6
  10. data/lib/fortnox/api.rb +18 -2
  11. data/lib/fortnox/api/base.rb +5 -3
  12. data/lib/fortnox/api/environment_validation.rb +51 -6
  13. data/lib/fortnox/api/mappers.rb +49 -0
  14. data/lib/fortnox/api/mappers/base.rb +47 -0
  15. data/lib/fortnox/api/mappers/base/from_json.rb +78 -0
  16. data/lib/fortnox/api/mappers/base/to_json.rb +65 -0
  17. data/lib/fortnox/api/mappers/customer.rb +27 -0
  18. data/lib/fortnox/api/mappers/default_delivery_types.rb +13 -0
  19. data/lib/fortnox/api/mappers/default_templates.rb +15 -0
  20. data/lib/fortnox/api/mappers/edi_information.rb +22 -0
  21. data/lib/fortnox/api/mappers/email_information.rb +18 -0
  22. data/lib/fortnox/api/mappers/invoice.rb +27 -0
  23. data/lib/fortnox/api/mappers/invoice_row.rb +20 -0
  24. data/lib/fortnox/api/mappers/order.rb +23 -0
  25. data/lib/fortnox/api/mappers/order_row.rb +16 -0
  26. data/lib/fortnox/api/models.rb +2 -0
  27. data/lib/fortnox/api/models/base.rb +56 -13
  28. data/lib/fortnox/api/models/customer.rb +112 -101
  29. data/lib/fortnox/api/models/document_base.rb +189 -0
  30. data/lib/fortnox/api/models/invoice.rb +29 -195
  31. data/lib/fortnox/api/models/label.rb +17 -0
  32. data/lib/fortnox/api/models/order.rb +27 -0
  33. data/lib/fortnox/api/repositories.rb +2 -0
  34. data/lib/fortnox/api/repositories/base.rb +4 -5
  35. data/lib/fortnox/api/repositories/base/loaders.rb +22 -14
  36. data/lib/fortnox/api/repositories/base/savers.rb +30 -16
  37. data/lib/fortnox/api/repositories/customer.rb +3 -25
  38. data/lib/fortnox/api/repositories/invoice.rb +3 -22
  39. data/lib/fortnox/api/repositories/order.rb +16 -0
  40. data/lib/fortnox/api/request_handling.rb +3 -3
  41. data/lib/fortnox/api/types.rb +44 -0
  42. data/lib/fortnox/api/types/default_delivery_types.rb +20 -0
  43. data/lib/fortnox/api/types/default_templates.rb +23 -0
  44. data/lib/fortnox/api/types/defaulted.rb +11 -0
  45. data/lib/fortnox/api/types/document_row.rb +65 -0
  46. data/lib/fortnox/api/types/edi_information.rb +29 -0
  47. data/lib/fortnox/api/types/email_information.rb +26 -0
  48. data/lib/fortnox/api/types/enums.rb +75 -0
  49. data/lib/fortnox/api/types/invoice_row.rb +19 -0
  50. data/lib/fortnox/api/types/model.rb +40 -0
  51. data/lib/fortnox/api/types/nullable.rb +21 -0
  52. data/lib/fortnox/api/types/order_row.rb +16 -0
  53. data/lib/fortnox/api/types/required.rb +13 -0
  54. data/lib/fortnox/api/types/sized.rb +25 -0
  55. data/lib/fortnox/api/version.rb +1 -1
  56. data/spec/fortnox/api/base_spec.rb +85 -14
  57. data/spec/fortnox/api/mappers/base/from_json_spec.rb +70 -0
  58. data/spec/fortnox/api/mappers/base/to_json_spec.rb +76 -0
  59. data/spec/fortnox/api/mappers/base_spec.rb +156 -0
  60. data/spec/fortnox/api/mappers/contexts/json_conversion.rb +56 -0
  61. data/spec/fortnox/api/mappers/customer_spec.rb +25 -0
  62. data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +12 -0
  63. data/spec/fortnox/api/mappers/edi_information_spec.rb +21 -0
  64. data/spec/fortnox/api/mappers/email_information_spec.rb +17 -0
  65. data/spec/fortnox/api/mappers/examples/mapper.rb +26 -0
  66. data/spec/fortnox/api/mappers/invoice_row_spec.rb +19 -0
  67. data/spec/fortnox/api/mappers/invoice_spec.rb +24 -0
  68. data/spec/fortnox/api/mappers/order_row_spec.rb +14 -0
  69. data/spec/fortnox/api/mappers/order_spec.rb +20 -0
  70. data/spec/fortnox/api/models/base_spec.rb +44 -22
  71. data/spec/fortnox/api/models/customer_spec.rb +9 -0
  72. data/spec/fortnox/api/models/examples/document_base.rb +13 -0
  73. data/spec/fortnox/api/models/examples/model.rb +13 -0
  74. data/spec/fortnox/api/models/invoice_spec.rb +7 -31
  75. data/spec/fortnox/api/models/order_spec.rb +13 -0
  76. data/spec/fortnox/api/repositories/customer_spec.rb +20 -76
  77. data/spec/fortnox/api/repositories/examples/all.rb +17 -0
  78. data/spec/fortnox/api/repositories/examples/find.rb +25 -0
  79. data/spec/fortnox/api/repositories/examples/only.rb +42 -0
  80. data/spec/fortnox/api/repositories/examples/save.rb +69 -0
  81. data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +32 -0
  82. data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +27 -0
  83. data/spec/fortnox/api/repositories/examples/search.rb +31 -0
  84. data/spec/fortnox/api/repositories/invoice_spec.rb +36 -5
  85. data/spec/fortnox/api/repositories/order_spec.rb +35 -0
  86. data/spec/fortnox/api/types/account_number_spec.rb +28 -0
  87. data/spec/fortnox/api/types/default_delivery_types_spec.rb +10 -0
  88. data/spec/fortnox/api/types/edi_information_spec.rb +13 -0
  89. data/spec/fortnox/api/types/email_information_spec.rb +13 -0
  90. data/spec/fortnox/api/types/email_spec.rb +29 -0
  91. data/spec/fortnox/api/types/enums_spec.rb +13 -0
  92. data/spec/fortnox/api/types/examples/document_row.rb +15 -0
  93. data/spec/fortnox/api/types/examples/enum.rb +48 -0
  94. data/spec/fortnox/api/types/examples/types.rb +9 -0
  95. data/spec/fortnox/api/types/house_work_types_spec.rb +60 -0
  96. data/spec/fortnox/api/types/invoice_row_spec.rb +9 -0
  97. data/spec/fortnox/api/types/model_spec.rb +56 -0
  98. data/spec/fortnox/api/types/nullable_spec.rb +57 -0
  99. data/spec/fortnox/api/types/order_row_spec.rb +13 -0
  100. data/spec/fortnox/api/types/required_spec.rb +42 -0
  101. data/spec/fortnox/api/types/sized_spec.rb +74 -0
  102. data/spec/fortnox/api_spec.rb +16 -15
  103. data/spec/spec_helper.rb +19 -9
  104. data/spec/support/helpers/dummy_class_helper.rb +19 -0
  105. data/spec/support/helpers/environment_helper.rb +7 -0
  106. data/spec/support/helpers/repository_helper.rb +8 -0
  107. data/spec/support/helpers/when_performing_helper.rb +5 -0
  108. data/spec/support/matchers.rb +1 -1
  109. data/spec/support/matchers/type.rb +17 -0
  110. data/spec/support/matchers/type/attribute_matcher.rb +39 -0
  111. data/spec/support/matchers/type/enum_matcher.rb +21 -0
  112. data/spec/support/matchers/type/have_account_number_matcher.rb +21 -0
  113. data/spec/support/matchers/type/have_country_code_matcher.rb +13 -0
  114. data/spec/support/matchers/type/have_currency_matcher.rb +7 -0
  115. data/spec/support/matchers/type/have_customer_type_matcher.rb +13 -0
  116. data/spec/support/matchers/type/have_default_delivery_type_matcher.rb +7 -0
  117. data/spec/support/matchers/type/have_discount_type_matcher.rb +7 -0
  118. data/spec/support/matchers/type/have_email_matcher.rb +22 -0
  119. data/spec/support/matchers/type/have_house_work_type_matcher.rb +7 -0
  120. data/spec/support/matchers/type/have_nullable_date_matcher.rb +58 -0
  121. data/spec/support/matchers/type/have_nullable_matcher.rb +52 -0
  122. data/spec/support/matchers/type/have_nullable_string_matcher.rb +49 -0
  123. data/spec/support/matchers/type/have_sized_float_matcher.rb +8 -0
  124. data/spec/support/matchers/type/have_sized_integer_matcher.rb +8 -0
  125. data/spec/support/matchers/type/have_sized_string_matcher.rb +35 -0
  126. data/spec/support/matchers/type/have_vat_type_matcher.rb +7 -0
  127. data/spec/support/matchers/type/numeric_matcher.rb +50 -0
  128. data/spec/support/matchers/type/require_attribute_matcher.rb +69 -0
  129. data/spec/support/matchers/type/type_matcher.rb +38 -0
  130. data/spec/vcr_cassettes/customers/all.yml +119 -9
  131. data/spec/vcr_cassettes/customers/find_id_1.yml +8 -9
  132. data/spec/vcr_cassettes/customers/find_new.yml +46 -0
  133. data/spec/vcr_cassettes/customers/save_new.yml +9 -11
  134. data/spec/vcr_cassettes/customers/save_old.yml +9 -12
  135. data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +45 -0
  136. data/spec/vcr_cassettes/customers/search_by_name.yml +66 -0
  137. data/spec/vcr_cassettes/customers/search_miss.yml +45 -0
  138. data/spec/vcr_cassettes/invoices/all.yml +104 -0
  139. data/spec/vcr_cassettes/invoices/filter_hit.yml +46 -0
  140. data/spec/vcr_cassettes/invoices/filter_invalid.yml +42 -0
  141. data/spec/vcr_cassettes/invoices/find_id_1.yml +47 -0
  142. data/spec/vcr_cassettes/invoices/find_new.yml +49 -0
  143. data/spec/vcr_cassettes/invoices/save_new.yml +48 -0
  144. data/spec/vcr_cassettes/invoices/save_old.yml +49 -0
  145. data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +47 -0
  146. data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +47 -0
  147. data/spec/vcr_cassettes/invoices/search_by_name.yml +48 -0
  148. data/spec/vcr_cassettes/invoices/search_miss.yml +45 -0
  149. data/spec/vcr_cassettes/orders/all.yml +144 -0
  150. data/spec/vcr_cassettes/orders/filter_hit.yml +48 -0
  151. data/spec/vcr_cassettes/orders/filter_invalid.yml +42 -0
  152. data/spec/vcr_cassettes/orders/find_id_1.yml +48 -0
  153. data/spec/vcr_cassettes/orders/find_new.yml +49 -0
  154. data/spec/vcr_cassettes/orders/house_work_type_babysitting.yml +47 -0
  155. data/spec/vcr_cassettes/orders/house_work_type_cleaning.yml +47 -0
  156. data/spec/vcr_cassettes/orders/house_work_type_construction.yml +47 -0
  157. data/spec/vcr_cassettes/orders/house_work_type_cooking.yml +43 -0
  158. data/spec/vcr_cassettes/orders/house_work_type_electricity.yml +47 -0
  159. data/spec/vcr_cassettes/orders/house_work_type_gardening.yml +47 -0
  160. data/spec/vcr_cassettes/orders/house_work_type_glassmetalwork.yml +47 -0
  161. data/spec/vcr_cassettes/orders/house_work_type_grounddrainagework.yml +47 -0
  162. data/spec/vcr_cassettes/orders/house_work_type_hvac.yml +47 -0
  163. data/spec/vcr_cassettes/orders/house_work_type_masonry.yml +47 -0
  164. data/spec/vcr_cassettes/orders/house_work_type_othercare.yml +47 -0
  165. data/spec/vcr_cassettes/orders/house_work_type_othercosts.yml +47 -0
  166. data/spec/vcr_cassettes/orders/house_work_type_paintingwallpapering.yml +47 -0
  167. data/spec/vcr_cassettes/orders/house_work_type_snowplowing.yml +47 -0
  168. data/spec/vcr_cassettes/orders/house_work_type_textileclothing.yml +47 -0
  169. data/spec/vcr_cassettes/orders/house_work_type_tutoring.yml +43 -0
  170. data/spec/vcr_cassettes/orders/save_new.yml +48 -0
  171. data/spec/vcr_cassettes/orders/save_old.yml +49 -0
  172. data/spec/vcr_cassettes/orders/save_with_nested_model.yml +47 -0
  173. data/spec/vcr_cassettes/orders/search_by_name.yml +47 -0
  174. data/spec/vcr_cassettes/orders/search_miss.yml +45 -0
  175. metadata +301 -71
  176. data/lib/fortnox/api/models/attributes/country_code.rb +0 -17
  177. data/lib/fortnox/api/models/attributes/currency.rb +0 -17
  178. data/lib/fortnox/api/models/edi_information.rb +0 -28
  179. data/lib/fortnox/api/models/email_information.rb +0 -25
  180. data/lib/fortnox/api/models/row.rb +0 -82
  181. data/lib/fortnox/api/repositories/base/json_convertion.rb +0 -68
  182. data/lib/fortnox/api/repositories/base/options.rb +0 -33
  183. data/lib/fortnox/api/validators.rb +0 -1
  184. data/lib/fortnox/api/validators/attributes/country_code.rb +0 -42
  185. data/lib/fortnox/api/validators/attributes/currency.rb +0 -38
  186. data/lib/fortnox/api/validators/base.rb +0 -70
  187. data/lib/fortnox/api/validators/constant.rb +0 -21
  188. data/lib/fortnox/api/validators/customer.rb +0 -29
  189. data/lib/fortnox/api/validators/edi_information.rb +0 -11
  190. data/lib/fortnox/api/validators/email_information.rb +0 -19
  191. data/lib/fortnox/api/validators/invoice.rb +0 -33
  192. data/lib/fortnox/api/validators/row.rb +0 -22
  193. data/spec/fortnox/api/models/attributes/country_code_spec.rb +0 -23
  194. data/spec/fortnox/api/models/attributes/currency_spec.rb +0 -23
  195. data/spec/fortnox/api/models/attributes/dummy_model_context.rb +0 -9
  196. data/spec/fortnox/api/models/row_spec.rb +0 -13
  197. data/spec/fortnox/api/repositories/context.rb +0 -10
  198. data/spec/fortnox/api/repositories/examples.rb +0 -16
  199. data/spec/fortnox/api/validators/attributes/country_code_spec.rb +0 -9
  200. data/spec/fortnox/api/validators/attributes/currency_spec.rb +0 -9
  201. data/spec/fortnox/api/validators/attributes/examples_for_validate.rb +0 -29
  202. data/spec/fortnox/api/validators/base_spec.rb +0 -61
  203. data/spec/fortnox/api/validators/constant_spec.rb +0 -12
  204. data/spec/fortnox/api/validators/context.rb +0 -102
  205. data/spec/fortnox/api/validators/customer_spec.rb +0 -31
  206. data/spec/fortnox/api/validators/edi_information_spec.rb +0 -18
  207. data/spec/fortnox/api/validators/email_information_spec.rb +0 -26
  208. data/spec/fortnox/api/validators/invoice_spec.rb +0 -36
  209. data/spec/fortnox/api/validators/row_spec.rb +0 -27
  210. data/spec/fortnox/api/validators/validator_examples.rb +0 -20
  211. data/spec/support/matchers/models.rb +0 -27
  212. data/spec/support/matchers/validators.rb +0 -36
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'dry-struct'
3
+ require 'fortnox/api/types'
4
+
5
+ describe Fortnox::API::Types::Nullable, type: :type do
6
+ subject{ TestStruct }
7
+
8
+ describe 'String' do
9
+ using_test_class do
10
+ class TestStruct < Dry::Struct
11
+ attribute :string, Fortnox::API::Types::Nullable::String
12
+ end
13
+ end
14
+
15
+ it{ is_expected.to have_nullable(:string, 'A simple message', 0, '0') }
16
+ end
17
+
18
+ describe 'Float' do
19
+ using_test_class do
20
+ class TestStruct < Dry::Struct
21
+ attribute :float, Fortnox::API::Types::Nullable::Float
22
+ end
23
+ end
24
+
25
+ it{ is_expected.to have_nullable(:float, 14.0, 'Not a Float!', 0.0) }
26
+ end
27
+
28
+ describe 'Integer' do
29
+ using_test_class do
30
+ class TestStruct < Dry::Struct
31
+ attribute :integer, Fortnox::API::Types::Nullable::Integer
32
+ end
33
+ end
34
+
35
+ it{ is_expected.to have_nullable(:integer, 14, 14.0, 14) }
36
+ end
37
+
38
+ describe 'Boolean' do
39
+ using_test_class do
40
+ class TestStruct < Dry::Struct
41
+ attribute :boolean, Fortnox::API::Types::Nullable::Boolean
42
+ end
43
+ end
44
+
45
+ it{ is_expected.to have_nullable(:boolean, true, 'Not a Boolean!', false) }
46
+ end
47
+
48
+ describe 'Date' do
49
+ using_test_class do
50
+ class TestStruct < Dry::Struct
51
+ attribute :date, Fortnox::API::Types::Nullable::Date
52
+ end
53
+ end
54
+
55
+ it{ is_expected.to have_nullable_date(:date, Date.new(2016, 1, 1), 'Not a Date!') }
56
+ end
57
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'fortnox/api/types/order_row'
3
+ require 'fortnox/api/types/examples/document_row'
4
+
5
+ RSpec.describe Fortnox::API::Types::OrderRow, type: :type do
6
+ valid_hash = { ordered_quantity: 10.5 }
7
+
8
+ subject{ described_class }
9
+
10
+ it{ is_expected.to require_attribute( :ordered_quantity, valid_hash ) }
11
+
12
+ it_behaves_like 'DocumentRow', valid_hash
13
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'fortnox/api/types'
3
+ require 'fortnox/api/types/required'
4
+
5
+ describe Fortnox::API::Types::Required, type: :type do
6
+ using_test_class do
7
+ class TestClass < Dry::Struct
8
+ end
9
+ end
10
+
11
+ shared_examples_for 'required attribute' do |_type|
12
+ subject{ ->{ TestClass.new({}) } }
13
+
14
+ let(:error_message) do
15
+ "[#{ TestClass }.new] #{ :required_attribute.inspect } is missing in Hash input"
16
+ end
17
+
18
+ it 'raises an error' do
19
+ is_expected.to raise_error(Dry::Struct::Error, error_message)
20
+ end
21
+ end
22
+
23
+ describe 'String' do
24
+ before do
25
+ class TestClass
26
+ attribute :required_attribute, Fortnox::API::Types::Required::String
27
+ end
28
+ end
29
+
30
+ include_examples 'required attribute', String
31
+ end
32
+
33
+ describe 'Float' do
34
+ before do
35
+ class TestClass
36
+ attribute :required_attribute, Fortnox::API::Types::Required::Float
37
+ end
38
+ end
39
+
40
+ include_examples 'required attribute', Float
41
+ end
42
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+ require 'fortnox/api/types'
3
+ require 'fortnox/api/types/examples/types'
4
+
5
+ describe Fortnox::API::Types::Sized do
6
+
7
+ shared_examples_for 'Sized Types' do
8
+ context 'created with nil' do
9
+ subject{ klass[ nil ] }
10
+ it{ is_expected.to be_nil }
11
+ end
12
+ end
13
+
14
+ describe 'String' do
15
+ max_size = 5
16
+ let( :klass ){ described_class::String[ max_size ] }
17
+
18
+ it_behaves_like 'Sized Types'
19
+
20
+ context 'created with empty string' do
21
+ include_examples 'equals input', ''
22
+ end
23
+
24
+ context 'created with fewer characters than the limit' do
25
+ include_examples 'equals input', 'a' * (max_size - 1)
26
+ end
27
+
28
+ context 'created with valid string' do
29
+ include_examples 'equals input', 'a' * max_size
30
+ end
31
+
32
+ context 'created with more characters than the limit' do
33
+ include_examples 'raises ConstraintError', 'a' * (max_size + 1)
34
+ end
35
+ end
36
+
37
+ shared_examples_for 'Sized Numeric' do |type, min, max, step|
38
+ let( :klass ){ described_class.const_get(type)[ min, max ] }
39
+
40
+ it_behaves_like 'Sized Types'
41
+
42
+ context 'created with value below the lower limit' do
43
+ include_examples 'raises ConstraintError', min - step
44
+ end
45
+
46
+ context 'created with value at the lower limit' do
47
+ include_examples 'equals input', min
48
+ end
49
+
50
+ context 'created with valid number near lower limit' do
51
+ include_examples 'equals input', min + step
52
+ end
53
+
54
+ context 'created with valid number near upper limit' do
55
+ include_examples 'equals input', max - step
56
+ end
57
+
58
+ context 'created with value at the upper limit' do
59
+ include_examples 'equals input', max
60
+ end
61
+
62
+ context 'created with value above the upper limit' do
63
+ include_examples 'raises ConstraintError', max + step
64
+ end
65
+ end
66
+
67
+ describe 'Float' do
68
+ it_behaves_like 'Sized Numeric', 'Float', 0.0, 100.0, 0.1
69
+ end
70
+
71
+ describe 'Integer' do
72
+ it_behaves_like 'Sized Numeric', 'Integer', 0, 100, 1
73
+ end
74
+ end
@@ -2,16 +2,17 @@ require 'spec_helper'
2
2
  require 'fortnox/api'
3
3
 
4
4
  describe Fortnox::API do
5
+ include Helpers::Environment
5
6
 
6
7
  context 'get access token' do
7
8
  before do
8
- ENV['FORTNOX_API_BASE_URL'] = 'http://api.fortnox.se/3/'
9
- ENV['FORTNOX_API_CLIENT_SECRET'] = 'P5K5vE3Kun'
10
- ENV['FORTNOX_API_ACCESS_TOKEN'] = '3f08d038-f380-4893-94a0-a08f6e60e67a'
11
- ENV['FORTNOX_API_AUTHORIZATION_CODE'] = 'ea3862b0-189c-464b-8e23-1b9702365ea1'
12
- end
9
+ stub_environment(
10
+ 'FORTNOX_API_BASE_URL' => 'http://api.fortnox.se/3/',
11
+ 'FORTNOX_API_CLIENT_SECRET' => 'P5K5vE3Kun',
12
+ 'FORTNOX_API_ACCESS_TOKEN' => '3f08d038-f380-4893-94a0-a08f6e60e67a',
13
+ 'FORTNOX_API_AUTHORIZATION_CODE' => 'ea3862b0-189c-464b-8e23-1b9702365ea1'
14
+ )
13
15
 
14
- it 'works' do
15
16
  stub_request(
16
17
  :get,
17
18
  'http://api.fortnox.se/3/',
@@ -21,16 +22,16 @@ describe Fortnox::API do
21
22
  'Client-Secret' => 'P5K5vE3Kun',
22
23
  'Accept' => 'application/json',
23
24
  }
24
- ).to_return(
25
- status: 200,
26
- body: { 'Authorisation' => { 'AccessToken' => '3f08d038-f380-4893-94a0-a08f6e60e67a' } }.to_json,
27
- headers: { 'Content-Type' => 'application/json' },
28
- )
25
+ ).to_return(
26
+ status: 200,
27
+ body: { 'Authorisation' => { 'AccessToken' => '3f08d038-f380-4893-94a0-a08f6e60e67a' } }.to_json,
28
+ headers: { 'Content-Type' => 'application/json' },
29
+ )
30
+ end
29
31
 
30
- response = Fortnox::API.get_access_token
31
32
 
32
- expect( response).to eql( "3f08d038-f380-4893-94a0-a08f6e60e67a" )
33
- end
34
- end
33
+ subject{ described_class.get_access_token }
35
34
 
35
+ it{ is_expected.to eql( "3f08d038-f380-4893-94a0-a08f6e60e67a" ) }
36
+ end
36
37
  end
@@ -1,31 +1,41 @@
1
1
  ENV['RUBY_ENV'] = 'test'
2
2
 
3
+ require 'rspec/collection_matchers'
3
4
  require 'webmock/rspec'
4
5
  require 'pry'
5
6
  require "codeclimate-test-reporter"
6
7
  require 'support/matchers'
7
8
  require 'support/helpers'
8
9
  require 'support/vcr_setup'
10
+ require 'dotenv'
9
11
 
10
12
  CodeClimate::TestReporter.start
13
+ Dotenv.load('.env.test')
11
14
 
12
15
  RSpec.configure do |config|
13
16
  config.run_all_when_everything_filtered = true
14
17
  config.filter_run :focus
15
18
 
16
- config.extend Helpers
19
+ config.extend Helpers # Allow access to helpers in describe and context blocks
20
+ config.include Helpers # Allow access to helpers in it and let blocks
21
+
22
+ config.include Helpers::Repositories, integration: true
23
+ config.include Matchers::Type, type: :type
17
24
 
18
- # Run specs in random order to surface order dependencies. If you find an
19
- # order dependency and want to debug it, you can fix the order by providing
20
- # the seed, which is printed after each run.
21
- # --seed 1234
22
25
  config.order = 'random'
23
26
 
24
27
  WebMock.disable_net_connect!( allow: 'codeclimate.com' )
25
28
 
26
- config.after( :each ) do
27
- ENV['FORTNOX_API_BASE_URL'] = nil
28
- ENV['FORTNOX_API_CLIENT_SECRET'] = nil
29
- ENV['FORTNOX_API_ACCESS_TOKEN'] = nil
29
+ config.before do
30
+ module Test
31
+ def self.remove_constants
32
+ constants.each{ |const| remove_const(const) }
33
+ self
34
+ end
35
+ end
36
+ end
37
+
38
+ config.after do
39
+ Object.send(:remove_const, Test.remove_constants.name)
30
40
  end
31
41
  end
@@ -1,8 +1,12 @@
1
+ require 'dry-types'
2
+
1
3
  module Helpers
2
4
  def using_test_classes
3
5
  around( :all ) do |example|
4
6
  classes_before_examples = Object.constants
5
7
 
8
+ save_dry_types_state
9
+
6
10
  yield
7
11
 
8
12
  classes_after_examples = Object.constants
@@ -10,6 +14,8 @@ module Helpers
10
14
 
11
15
  example.run
12
16
 
17
+ clean_up_dry_types
18
+
13
19
  classes_created_by_block.each do |klass|
14
20
  Object.send(:remove_const, klass)
15
21
  end
@@ -17,4 +23,17 @@ module Helpers
17
23
  end
18
24
 
19
25
  alias_method :using_test_class, :using_test_classes
26
+
27
+ private
28
+
29
+ def save_dry_types_state
30
+ @types = Dry::Types.container._container.keys
31
+ end
32
+
33
+ def clean_up_dry_types
34
+ container = Dry::Types.container._container
35
+ (container.keys - @types).each{ |key| container.delete(key) }
36
+ Dry::Types.instance_variable_set('@type_map', Concurrent::Map.new)
37
+ end
38
+
20
39
  end
@@ -0,0 +1,7 @@
1
+ module Helpers
2
+ module Environment
3
+ def stub_environment( hash )
4
+ stub_const( 'ENV', ENV.to_hash.merge( hash ))
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Helpers
2
+ module Repositories
3
+ # Returns directory for VCR.
4
+ def vcr_dir
5
+ described_class::MAPPER::JSON_COLLECTION_WRAPPER.downcase
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Helpers
2
+ def when_performing &block
3
+ block.to_proc
4
+ end
5
+ end
@@ -1 +1 @@
1
- Dir[File.expand_path('spec/support/matchers/*.rb')].each{ |file| require file }
1
+ require 'support/matchers/type'
@@ -0,0 +1,17 @@
1
+ require 'support/matchers/type/attribute_matcher'
2
+ require 'support/matchers/type/type_matcher'
3
+ require 'support/matchers/type/have_nullable_matcher'
4
+ require 'support/matchers/type/enum_matcher'
5
+ require 'support/matchers/type/numeric_matcher'
6
+
7
+ require 'support/matchers/type/have_nullable_date_matcher'
8
+ require 'support/matchers/type/require_attribute_matcher'
9
+ require 'support/matchers/type/have_email_matcher'
10
+ require 'support/matchers/type/have_sized_string_matcher'
11
+ require 'support/matchers/type/have_default_delivery_type_matcher'
12
+ require 'support/matchers/type/have_nullable_string_matcher'
13
+ require 'support/matchers/type/have_sized_float_matcher'
14
+ require 'support/matchers/type/have_house_work_type_matcher'
15
+ require 'support/matchers/type/have_account_number_matcher'
16
+ require 'support/matchers/type/have_discount_type_matcher'
17
+ require 'support/matchers/type/have_sized_integer_matcher'
@@ -0,0 +1,39 @@
1
+ module Matchers
2
+ module Type
3
+ class AttributeMatcher
4
+ def initialize( attribute, valid_hash, attribute_type )
5
+ @attribute = attribute
6
+ @valid_hash = valid_hash.dup
7
+ @attribute_type = attribute_type
8
+ @errors = ''
9
+ end
10
+
11
+ def matches? ( klass )
12
+ @klass = klass
13
+ end
14
+
15
+ def description
16
+ "have #{ @attribute_type } attribute #{ @attribute.inspect }"
17
+ end
18
+
19
+ def failure_message
20
+ "Expected class to have attribute #{ @attribute.inspect } defined as #{ @attribute_type }, "\
21
+ "but got following errors:
22
+ #{ @errors }"
23
+ end
24
+
25
+ protected
26
+
27
+ def expect_error(msg)
28
+ yield
29
+
30
+ @errors << msg
31
+ false # Fail test since expected error not thrown
32
+ rescue Dry::Struct::Error
33
+ # TODO: check if error message is correct
34
+ true
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ module Matchers
2
+ module Type
3
+ class EnumMatcher < TypeMatcher
4
+ def initialize( attribute, valid_hash, enum_type, enum_types, nonsense_value: 'NONSENSE'.freeze )
5
+ valid_value = Fortnox::API::Types.const_get(enum_types).values.first
6
+
7
+ super( attribute, valid_hash, enum_type, valid_value, nonsense_value )
8
+
9
+ @enum_type = Fortnox::API::Types.const_get(enum_type)
10
+ @expected_error = "Exception missing for nonsense value #{ @invalid_value.inspect }"
11
+ end
12
+
13
+ private
14
+
15
+ def expected_type?
16
+ @actual_type = @klass.schema[@attribute]
17
+ @actual_type == @enum_type
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Matchers
2
+ module Type
3
+ def have_account_number( attribute, valid_hash = {} )
4
+ HaveAccountNumberMatcher.new( attribute, valid_hash )
5
+ end
6
+
7
+ class HaveAccountNumberMatcher < TypeMatcher
8
+ def initialize( attribute, valid_hash )
9
+ super( attribute, valid_hash, 'account number', 1000, -1 )
10
+ @expected_error = "Exception missing for invalid value #{ @invalid_value.inspect }".freeze
11
+ end
12
+
13
+ private
14
+
15
+ def expected_type?
16
+ @actual_type = @klass.schema[@attribute]
17
+ @actual_type == Fortnox::API::Types::AccountNumber
18
+ end
19
+ end
20
+ end
21
+ end