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,20 @@
1
+ require 'spec_helper'
2
+ require 'fortnox/api'
3
+ require 'fortnox/api/mappers/order'
4
+ require 'fortnox/api/mappers/examples/mapper'
5
+
6
+ describe Fortnox::API::Mapper::Order do
7
+ key_map =
8
+ {
9
+ administration_fee_vat: 'AdministrationFeeVAT',
10
+ freight_vat: 'FreightVAT',
11
+ total_vat: 'TotalVAT',
12
+ vat_included: 'VATIncluded'
13
+ }
14
+ json_entity_type = 'Order'
15
+ json_entity_collection = 'Orders'
16
+
17
+ it_behaves_like 'mapper', key_map, json_entity_type, json_entity_collection do
18
+ let(:mapper){ described_class.new }
19
+ end
20
+ end
@@ -1,12 +1,14 @@
1
1
  require 'spec_helper'
2
2
  require 'fortnox/api/models/base'
3
+ require 'fortnox/api/types'
3
4
 
4
5
  describe Fortnox::API::Model::Base do
5
6
  using_test_classes do
6
7
  class Entity < Fortnox::API::Model::Base
7
- attribute :private, String, writer: :private
8
- attribute :string, String
9
- attribute :number, Integer, default: 42
8
+ attribute :private, Fortnox::API::Types::String.with( read_only: true )
9
+ attribute :string, Fortnox::API::Types::Required::String
10
+ attribute :number, Fortnox::API::Types::Nullable::Integer
11
+ attribute :account, Fortnox::API::Types::AccountNumber
10
12
  end
11
13
  end
12
14
 
@@ -16,7 +18,23 @@ describe Fortnox::API::Model::Base do
16
18
 
17
19
  it{ is_expected.to be_a Entity }
18
20
  it{ is_expected.to be_new }
19
- it{ is_expected.to_not be_saved }
21
+ it{ is_expected.not_to be_saved }
22
+ end
23
+
24
+ context 'without required attribute' do
25
+ subject{ ->{ Entity.new({}) } }
26
+
27
+ it{ is_expected.to raise_error Fortnox::API::Exception }
28
+ it{ is_expected.to raise_error Fortnox::API::MissingAttributeError }
29
+ it{ is_expected.to raise_error Fortnox::API::MissingAttributeError, /Missing attribute :string/ }
30
+ end
31
+
32
+ context 'with invalid attribute value' do
33
+ subject{ ->{ Entity.new({ string: 'Test', account: 13337 }) } }
34
+
35
+ it{ is_expected.to raise_error Fortnox::API::Exception }
36
+ it{ is_expected.to raise_error Fortnox::API::AttributeError }
37
+ it{ is_expected.to raise_error Fortnox::API::AttributeError, /invalid type for :account/ }
20
38
  end
21
39
  end
22
40
 
@@ -24,52 +42,56 @@ describe Fortnox::API::Model::Base do
24
42
  let(:original){ Entity.new( string: 'Test' ) }
25
43
 
26
44
  context 'with new, simple value' do
27
- subject{ original.update( string: 'Variant' ) }
45
+ subject{ updated_model }
46
+
47
+ let(:updated_model){ original.update( string: 'Variant' ) }
48
+
49
+ it{ is_expected.to be_new }
50
+ it{ is_expected.not_to be_saved }
28
51
 
29
52
  it 'returns a new object' do
30
- is_expected.to_not eql( original )
53
+ is_expected.not_to eql( original )
31
54
  end
32
55
 
33
- it 'returns a object of the same class' do
34
- expect( subject.class ).to eql( original.class )
56
+ describe 'updated attribute' do
57
+ subject{ updated_model.string }
58
+ it{ is_expected.to eql( 'Variant' ) }
35
59
  end
36
60
 
37
- it 'returns a object with the new value' do
38
- expect( subject.string ).to eql( 'Variant' )
61
+ describe 'returned class' do
62
+ subject{ updated_model.class }
63
+ it{ is_expected.to eql( original.class ) }
39
64
  end
40
-
41
- it{ is_expected.to be_new }
42
- it{ is_expected.to_not be_saved }
43
65
  end
44
66
 
45
67
  context 'with the same, simple value' do
46
- subject{ original.update( string: 'Test' ) }
68
+ subject( :updated_model ){ original.update( string: 'Test' ) }
47
69
 
48
70
  it 'returns the same object' do
49
71
  is_expected.to eql( original )
50
72
  end
51
73
 
52
74
  it 'returns a object with the same value' do
53
- expect( subject.string ).to eql( 'Test' )
75
+ expect( updated_model.string ).to eql( 'Test' )
54
76
  end
55
77
 
56
78
  it{ is_expected.to be_new }
57
- it{ is_expected.to_not be_saved }
79
+ it{ is_expected.not_to be_saved }
58
80
  end
59
81
 
60
82
  context 'a saved entity' do
61
- let( :saved_entry ){ Entity.new( string: 'Saved', new: false, unsaved: false) }
83
+ subject( :updated_entry ){ saved_entry.update( string: 'Updated' ) }
62
84
 
63
- subject{ saved_entry.update( string: 'Updated' ) }
85
+ let( :saved_entry ){ Entity.new( string: 'Saved', new: false, unsaved: false) }
64
86
 
65
87
  before do
66
- expect(saved_entry).to_not be_new
88
+ expect(saved_entry).not_to be_new
67
89
  expect(saved_entry).to be_saved
68
90
  end
69
91
 
70
- specify{ expect(subject.string).to eq( 'Updated' ) }
71
- it{ is_expected.to_not be_new }
72
- it{ is_expected.to_not be_saved }
92
+ specify{ expect(updated_entry.string).to eq( 'Updated' ) }
93
+ it{ is_expected.not_to be_new }
94
+ it{ is_expected.not_to be_saved }
73
95
  end
74
96
  end
75
97
 
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require 'fortnox/api/models/customer'
3
+ require 'fortnox/api/models/examples/model'
4
+
5
+ describe Fortnox::API::Model::Customer, type: :model do
6
+ valid_hash = { name: 'Arthur Dent' }
7
+
8
+ it_behaves_like 'a model', valid_hash, :customer_number, '5'
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'fortnox/api/models/examples/model'
2
+
3
+ shared_examples_for 'DocumentBase Model' do |row_class, row_attribute, valid_hash, valid_row_hash: {}|
4
+ it_behaves_like 'a model', valid_hash, :document_number, 1
5
+
6
+ context "when having a(n) #{ row_class }" do
7
+ it 'returns the correct object' do
8
+ row = row_class.new(valid_row_hash)
9
+ document_base = described_class.new( customer_number: '123', row_attribute => [row] )
10
+ expect(document_base.send(row_attribute)).to eq([row])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ shared_examples_for 'a model' do |valid_hash, unique_id_attribute, value|
2
+ it 'can be initialized' do
3
+ expect{ described_class.new(valid_hash) }.not_to raise_error
4
+ end
5
+
6
+ describe '.unique_id' do
7
+ let( :model ){ described_class.new( valid_hash.merge({ unique_id_attribute => value })) }
8
+
9
+ before{ expect(model.send(unique_id_attribute)).to eq value }
10
+
11
+ it{ expect(model.unique_id).to eq value }
12
+ end
13
+ end
@@ -1,36 +1,12 @@
1
1
  require 'spec_helper'
2
2
  require 'fortnox/api/models/invoice'
3
+ require 'fortnox/api/models/examples/document_base'
3
4
 
4
- describe Fortnox::API::Model::Invoice do
5
- shared_examples 'having value objects' do |value_object_class|
6
- context "when having an #{value_object_class}" do
7
- it "returns the correct object" do
8
- value_object = value_object_class.new
9
- invoice = described_class.new( attribute => value_object )
10
- expect(invoice.send(attribute)).to eq(value_object)
11
- end
12
- end
13
- end
5
+ describe Fortnox::API::Model::Invoice, type: :model do
6
+ valid_hash = { customer_number: '12345' }
14
7
 
15
- describe 'association with Fortnox::API::Model::Row' do
16
- context 'when having an Invoice Row' do
17
- it 'returns the correct Row' do
18
- row = Fortnox::API::Model::Row.new
19
- invoice = described_class.new( invoice_rows: [row] )
20
- expect(invoice.invoice_rows).to eq([row])
21
- end
22
- end
23
- end
24
-
25
- describe 'association with Fortnox::API::Model::EmailInformation' do
26
- include_examples 'having value objects', Fortnox::API::Model::EmailInformation do
27
- let( :attribute ){ :email_information }
28
- end
29
- end
30
-
31
- describe 'association with Fortnox::API::Model::EDIInformation' do
32
- include_examples 'having value objects', Fortnox::API::Model::EDIInformation do
33
- let( :attribute ){ :edi_information }
34
- end
35
- end
8
+ it_behaves_like 'DocumentBase Model',
9
+ Fortnox::API::Types::InvoiceRow,
10
+ :invoice_rows,
11
+ valid_hash
36
12
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'fortnox/api/models/order'
3
+ require 'fortnox/api/models/examples/document_base'
4
+
5
+ describe Fortnox::API::Model::Order, type: :model do
6
+ valid_hash = { customer_number: '12345' }
7
+
8
+ it_behaves_like 'DocumentBase Model',
9
+ Fortnox::API::Types::OrderRow,
10
+ :order_rows,
11
+ valid_hash,
12
+ valid_row_hash: { ordered_quantity: 1.1 }
13
+ end
@@ -1,85 +1,29 @@
1
1
  require 'spec_helper'
2
- require 'fortnox/api/repositories/context'
2
+ require 'fortnox/api'
3
+ require 'fortnox/api/mappers'
3
4
  require 'fortnox/api/repositories/customer'
4
- require 'fortnox/api/models/customer'
5
+ require 'fortnox/api/repositories/examples/all'
6
+ require 'fortnox/api/repositories/examples/find'
7
+ require 'fortnox/api/repositories/examples/save'
8
+ require 'fortnox/api/repositories/examples/save_with_specially_named_attribute'
9
+ require 'fortnox/api/repositories/examples/search'
5
10
 
6
- describe Fortnox::API::Repository::Customer do
7
- include_context 'repository context'
11
+ describe Fortnox::API::Repository::Customer, order: :defined, integration: true do
12
+ subject(:repository){ described_class.new }
8
13
 
9
- subject{ described_class.new }
14
+ include_examples '.save', :name
10
15
 
11
- it_behaves_like 'repositories', Fortnox::API::Model::Customer
16
+ include_examples '.save with specially named attribute',
17
+ { name: 'Test customer' },
18
+ :email_invoice_cc,
19
+ 'test@example.com'
12
20
 
13
- let( :find_id ){ 1 }
14
- let( :find_customer_1 ) do
15
- VCR.use_cassette( 'customers/find_id_1' ){ subject.find( find_id ) }
16
- end
21
+ # It is not yet possible to delete Customers. Therefore, expected nr of
22
+ # Customers when running .all will continue to increase
23
+ # (until 100, which is max by default).
24
+ include_examples '.all', 100
17
25
 
18
- describe '.all' do
19
- let(:response) do
20
- VCR.use_cassette( 'customers/all' ){ subject.all }
21
- end
26
+ include_examples '.find', '1'
22
27
 
23
- specify 'returns correct number of records' do
24
- expect( response.size ).to be 1
25
- end
26
-
27
- specify 'returns correct class' do
28
- expect( response.first.class ).to be Fortnox::API::Model::Customer
29
- end
30
- end
31
-
32
- describe '.find' do
33
- specify 'returns correct class' do
34
- expect( find_customer_1.class ).to be Fortnox::API::Model::Customer
35
- end
36
-
37
- specify 'returns correct Customer' do
38
- expect( find_customer_1.customer_number.to_i ).to eq( find_id )
39
- end
40
-
41
- specify 'returned Customer is marked as saved' do
42
- expect( find_customer_1 ).to be_saved
43
- end
44
-
45
- specify 'returned Customer is not markes as new' do
46
- expect( find_customer_1 ).to_not be_new
47
- end
48
- end
49
-
50
- describe '.save' do
51
- shared_examples_for 'save' do |attribute|
52
- specify "include updated #{attribute.inspect}" do
53
- send_request
54
- expect( response['Customer'][attribute] ).to eql( updated_attribute )
55
- end
56
- end
57
-
58
- describe 'new' do
59
- include_examples 'save', 'Name' do
60
- let( :updated_attribute ){ 'A customer' }
61
- let( :model ) do
62
- Fortnox::API::Model::Customer.new( name: updated_attribute )
63
- end
64
-
65
- let( :send_request ) do
66
- VCR.use_cassette( 'customers/save_new' ){ subject.save( model ) }
67
- end
68
-
69
- let( :response ){ send_request }
70
- end
71
- end
72
-
73
- describe 'old (update existing)' do
74
- include_examples 'save', 'Name' do
75
- let( :updated_attribute ){ 'Updated customer' }
76
- let( :model ){ find_customer_1.update( name: updated_attribute ) }
77
-
78
- let( :send_request ) do
79
- VCR.use_cassette( 'customers/save_old' ){ subject.save( model ) }
80
- end
81
- let( :response ){ send_request }
82
- end
83
- end
84
- end
28
+ include_examples '.search', :name, 'Test', 23
85
29
  end
@@ -0,0 +1,17 @@
1
+ # rubocop:disable RSpec/DescribeClass
2
+ RSpec.shared_examples_for '.all' do |count|
3
+ describe '.all' do
4
+ let(:response) do
5
+ VCR.use_cassette( "#{ vcr_dir }/all" ){ subject.all }
6
+ end
7
+
8
+ specify 'returns correct number of records' do
9
+ expect( response.size ).to be count
10
+ end
11
+
12
+ specify 'returns correct class' do
13
+ expect( response.first.class ).to be described_class::MODEL
14
+ end
15
+ end
16
+ end
17
+ # rubocop:enable RSpec/DescribeClass
@@ -0,0 +1,25 @@
1
+ # rubocop:disable RSpec/DescribeClass
2
+ shared_examples_for '.find' do |searched_entity_id|
3
+ describe '.find' do
4
+ let( :find_id_1 ) do
5
+ VCR.use_cassette( "#{ vcr_dir }/find_id_1" ){ repository.find( searched_entity_id ) }
6
+ end
7
+
8
+ specify 'returns correct class' do
9
+ expect( find_id_1.class ).to be described_class::MODEL
10
+ end
11
+
12
+ specify 'returns correct Customer' do
13
+ expect( find_id_1.unique_id ).to eq( searched_entity_id )
14
+ end
15
+
16
+ specify 'returned Customer is marked as saved' do
17
+ expect( find_id_1 ).to be_saved
18
+ end
19
+
20
+ specify 'returned Customer is not markes as new' do
21
+ expect( find_id_1 ).not_to be_new
22
+ end
23
+ end
24
+ end
25
+ # rubocop:enable RSpec/DescribeClass
@@ -0,0 +1,42 @@
1
+ # rubocop:disable RSpec/DescribeClass
2
+ shared_examples_for '.only' do |matching_filter, expected_matches, missing_filter: nil|
3
+ describe '.only' do
4
+ def repository_only(repository, vcr_cassette, filter)
5
+ VCR.use_cassette( "#{ vcr_dir }/#{ vcr_cassette }" ) do
6
+ repository.only( filter )
7
+ end
8
+ end
9
+
10
+ shared_examples '.only response' do |vcr_cassette, expected_entries|
11
+ subject{ repository_only( repository, vcr_cassette, filter ) }
12
+
13
+ it{ is_expected.to be_instance_of( Array ) }
14
+ it{ is_expected.to have(expected_entries).entries }
15
+ end
16
+
17
+ unless missing_filter.nil?
18
+ context "with no matches" do
19
+ include_examples '.only response', 'filter_miss', 0 do
20
+ let(:filter){ missing_filter }
21
+ end
22
+ end
23
+ end
24
+
25
+ context "with matches" do
26
+ include_examples '.only response', 'filter_hit', expected_matches do
27
+ let(:filter){ matching_filter }
28
+ end
29
+ end
30
+
31
+ context "with invalid filter" do
32
+ subject do
33
+ when_performing do
34
+ repository_only( repository, 'filter_invalid', 'doesntexist' )
35
+ end
36
+ end
37
+
38
+ it{ is_expected.to raise_error( Fortnox::API::RemoteServerError, /ogiltigt filter/ ) }
39
+ end
40
+ end
41
+ end
42
+ # rubocop:enable RSpec/DescribeClass
@@ -0,0 +1,69 @@
1
+ # rubocop:disable RSpec/DescribeClass
2
+ #######################################
3
+ # SPEC IS DEPENDENT ON DEFINED ORDER!
4
+ #######################################
5
+ #
6
+ # Assumes that attribute is a string attribute without restrictions.
7
+ shared_examples_for '.save' do |attribute, required_attributes = {}|
8
+ describe '.save' do
9
+ let( :new_hash ) do
10
+ required_attributes.merge( attribute => value )
11
+ end
12
+ let( :new_model ){ described_class::MODEL.new( new_hash ) }
13
+ let( :save_new ){ VCR.use_cassette( "#{ vcr_dir }/save_new" ){ repository.save( new_model ) } }
14
+ let( :entity_wrapper ){ repository.mapper.class::JSON_ENTITY_WRAPPER }
15
+ let( :value ){ 'A value' }
16
+
17
+ shared_examples_for 'save' do
18
+ before do
19
+ if model.saved?
20
+ message = 'Test trying to save model, but already marked as saved!'
21
+ message << " Model: #{ model.inspect }"
22
+ fail(message)
23
+ end
24
+ end
25
+
26
+ specify "includes correct #{ attribute.inspect }" do
27
+ saved_entity = send_request
28
+ expect( saved_entity.send(attribute) ).to eql( value )
29
+ end
30
+ end
31
+
32
+ describe 'new' do
33
+ context 'when not saved' do
34
+ include_examples 'save' do
35
+ let( :model ){ new_model }
36
+ let( :send_request ){ save_new }
37
+ end
38
+ end
39
+
40
+ context "saved #{ described_class::MODEL }" do
41
+ let( :hash ){ { unsaved: false }.merge(new_hash) }
42
+ let( :model ){ described_class::MODEL.new( hash ) }
43
+
44
+ before do
45
+ # Should not make an API request in test!
46
+ expect( repository ).not_to receive( :save_new )
47
+ expect( repository ).not_to receive( :update_existing )
48
+ end
49
+
50
+ specify{ expect( repository.save( model )).to be( true ) }
51
+ end
52
+ end
53
+
54
+ describe 'old (update existing)' do
55
+ include_examples 'save' do
56
+ let( :value ){ "Updated #{ attribute }" }
57
+ let( :model ) do
58
+ new_id = save_new.unique_id
59
+ new_record = VCR.use_cassette( "#{ vcr_dir }/find_new" ){ repository.find( new_id ) }
60
+ new_record.update( attribute => value )
61
+ end
62
+ let( :send_request ) do
63
+ VCR.use_cassette( "#{ vcr_dir }/save_old" ){ repository.save( model ) }
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ # rubocop:enable RSpec/DescribeClass