fortnox-api 0.1.0 → 0.2.0

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