solidus_api 1.0.0.pre

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 (202) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/CHANGELOG.md +1 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE +27 -0
  6. data/Rakefile +16 -0
  7. data/app/controllers/spree/api/addresses_controller.rb +43 -0
  8. data/app/controllers/spree/api/base_controller.rb +189 -0
  9. data/app/controllers/spree/api/checkouts_controller.rb +133 -0
  10. data/app/controllers/spree/api/classifications_controller.rb +18 -0
  11. data/app/controllers/spree/api/config_controller.rb +6 -0
  12. data/app/controllers/spree/api/countries_controller.rb +23 -0
  13. data/app/controllers/spree/api/credit_cards_controller.rb +25 -0
  14. data/app/controllers/spree/api/images_controller.rb +47 -0
  15. data/app/controllers/spree/api/inventory_units_controller.rb +52 -0
  16. data/app/controllers/spree/api/line_items_controller.rb +74 -0
  17. data/app/controllers/spree/api/option_types_controller.rb +49 -0
  18. data/app/controllers/spree/api/option_values_controller.rb +58 -0
  19. data/app/controllers/spree/api/orders_controller.rb +155 -0
  20. data/app/controllers/spree/api/payments_controller.rb +81 -0
  21. data/app/controllers/spree/api/product_properties_controller.rb +72 -0
  22. data/app/controllers/spree/api/products_controller.rb +129 -0
  23. data/app/controllers/spree/api/promotions_controller.rb +26 -0
  24. data/app/controllers/spree/api/properties_controller.rb +71 -0
  25. data/app/controllers/spree/api/return_authorizations_controller.rb +71 -0
  26. data/app/controllers/spree/api/shipments_controller.rb +172 -0
  27. data/app/controllers/spree/api/states_controller.rb +35 -0
  28. data/app/controllers/spree/api/stock_items_controller.rb +84 -0
  29. data/app/controllers/spree/api/stock_locations_controller.rb +50 -0
  30. data/app/controllers/spree/api/stock_movements_controller.rb +42 -0
  31. data/app/controllers/spree/api/stock_transfers_controller.rb +19 -0
  32. data/app/controllers/spree/api/store_credit_events_controller.rb +9 -0
  33. data/app/controllers/spree/api/stores_controller.rb +55 -0
  34. data/app/controllers/spree/api/taxonomies_controller.rb +64 -0
  35. data/app/controllers/spree/api/taxons_controller.rb +93 -0
  36. data/app/controllers/spree/api/transfer_items_controller.rb +42 -0
  37. data/app/controllers/spree/api/users_controller.rb +56 -0
  38. data/app/controllers/spree/api/variants_controller.rb +75 -0
  39. data/app/controllers/spree/api/zones_controller.rb +50 -0
  40. data/app/helpers/spree/api/api_helpers.rb +190 -0
  41. data/app/models/spree/api_configuration.rb +5 -0
  42. data/app/models/spree/option_value_decorator.rb +9 -0
  43. data/app/views/spree/api/addresses/show.v1.rabl +10 -0
  44. data/app/views/spree/api/adjustments/show.v1.rabl +4 -0
  45. data/app/views/spree/api/config/money.v1.rabl +2 -0
  46. data/app/views/spree/api/config/show.v1.rabl +2 -0
  47. data/app/views/spree/api/countries/index.v1.rabl +7 -0
  48. data/app/views/spree/api/countries/show.v1.rabl +5 -0
  49. data/app/views/spree/api/credit_cards/index.v1.rabl +7 -0
  50. data/app/views/spree/api/credit_cards/show.v1.rabl +3 -0
  51. data/app/views/spree/api/errors/gateway_error.v1.rabl +2 -0
  52. data/app/views/spree/api/errors/invalid_api_key.v1.rabl +2 -0
  53. data/app/views/spree/api/errors/invalid_resource.v1.rabl +3 -0
  54. data/app/views/spree/api/errors/must_specify_api_key.v1.rabl +2 -0
  55. data/app/views/spree/api/errors/not_found.v1.rabl +2 -0
  56. data/app/views/spree/api/errors/unauthorized.v1.rabl +2 -0
  57. data/app/views/spree/api/errors/variant_not_in_stock_transfer.v1.rabl +2 -0
  58. data/app/views/spree/api/images/index.v1.rabl +4 -0
  59. data/app/views/spree/api/images/show.v1.rabl +6 -0
  60. data/app/views/spree/api/inventory_units/show.rabl +2 -0
  61. data/app/views/spree/api/line_items/new.v1.rabl +3 -0
  62. data/app/views/spree/api/line_items/show.v1.rabl +15 -0
  63. data/app/views/spree/api/option_types/index.v1.rabl +3 -0
  64. data/app/views/spree/api/option_types/show.v1.rabl +5 -0
  65. data/app/views/spree/api/option_values/index.v1.rabl +3 -0
  66. data/app/views/spree/api/option_values/show.v1.rabl +2 -0
  67. data/app/views/spree/api/orders/address.v1.rabl +0 -0
  68. data/app/views/spree/api/orders/canceled.v1.rabl +0 -0
  69. data/app/views/spree/api/orders/cart.v1.rabl +0 -0
  70. data/app/views/spree/api/orders/complete.v1.rabl +0 -0
  71. data/app/views/spree/api/orders/could_not_apply_coupon.v1.rabl +2 -0
  72. data/app/views/spree/api/orders/could_not_transition.v1.rabl +3 -0
  73. data/app/views/spree/api/orders/expected_total_mismatch.v1.rabl +2 -0
  74. data/app/views/spree/api/orders/index.v1.rabl +7 -0
  75. data/app/views/spree/api/orders/invalid_shipping_method.v1.rabl +2 -0
  76. data/app/views/spree/api/orders/mine.v1.rabl +9 -0
  77. data/app/views/spree/api/orders/order.v1.rabl +9 -0
  78. data/app/views/spree/api/orders/payment.v1.rabl +3 -0
  79. data/app/views/spree/api/orders/show.v1.rabl +52 -0
  80. data/app/views/spree/api/payments/credit_over_limit.v1.rabl +2 -0
  81. data/app/views/spree/api/payments/index.v1.rabl +7 -0
  82. data/app/views/spree/api/payments/new.v1.rabl +5 -0
  83. data/app/views/spree/api/payments/show.v1.rabl +2 -0
  84. data/app/views/spree/api/payments/update_forbidden.v1.rabl +2 -0
  85. data/app/views/spree/api/product_properties/index.v1.rabl +7 -0
  86. data/app/views/spree/api/product_properties/new.v1.rabl +2 -0
  87. data/app/views/spree/api/product_properties/show.v1.rabl +2 -0
  88. data/app/views/spree/api/products/index.v1.rabl +9 -0
  89. data/app/views/spree/api/products/new.v1.rabl +3 -0
  90. data/app/views/spree/api/products/product.v1.rabl +1 -0
  91. data/app/views/spree/api/products/show.v1.rabl +31 -0
  92. data/app/views/spree/api/promotions/handler.v1.rabl +5 -0
  93. data/app/views/spree/api/promotions/show.v1.rabl +2 -0
  94. data/app/views/spree/api/properties/index.v1.rabl +7 -0
  95. data/app/views/spree/api/properties/new.v1.rabl +2 -0
  96. data/app/views/spree/api/properties/show.v1.rabl +2 -0
  97. data/app/views/spree/api/return_authorizations/index.v1.rabl +7 -0
  98. data/app/views/spree/api/return_authorizations/new.v1.rabl +3 -0
  99. data/app/views/spree/api/return_authorizations/show.v1.rabl +2 -0
  100. data/app/views/spree/api/shared/stock_location_required.v1.rabl +2 -0
  101. data/app/views/spree/api/shipments/big.v1.rabl +48 -0
  102. data/app/views/spree/api/shipments/cannot_ready_shipment.v1.rabl +2 -0
  103. data/app/views/spree/api/shipments/mine.v1.rabl +9 -0
  104. data/app/views/spree/api/shipments/show.v1.rabl +32 -0
  105. data/app/views/spree/api/shipments/small.v1.rabl +37 -0
  106. data/app/views/spree/api/shipping_rates/show.v1.rabl +2 -0
  107. data/app/views/spree/api/states/index.v1.rabl +14 -0
  108. data/app/views/spree/api/states/show.v1.rabl +2 -0
  109. data/app/views/spree/api/stock_items/index.v1.rabl +7 -0
  110. data/app/views/spree/api/stock_items/show.v1.rabl +5 -0
  111. data/app/views/spree/api/stock_locations/index.v1.rabl +7 -0
  112. data/app/views/spree/api/stock_locations/show.v1.rabl +8 -0
  113. data/app/views/spree/api/stock_movements/index.v1.rabl +7 -0
  114. data/app/views/spree/api/stock_movements/show.v1.rabl +5 -0
  115. data/app/views/spree/api/stock_transfers/receive.v1.rabl +5 -0
  116. data/app/views/spree/api/store_credit_events/mine.v1.rabl +10 -0
  117. data/app/views/spree/api/stores/index.v1.rabl +4 -0
  118. data/app/views/spree/api/stores/show.v1.rabl +2 -0
  119. data/app/views/spree/api/taxonomies/index.v1.rabl +7 -0
  120. data/app/views/spree/api/taxonomies/jstree.rabl +8 -0
  121. data/app/views/spree/api/taxonomies/nested.v1.rabl +11 -0
  122. data/app/views/spree/api/taxonomies/new.v1.rabl +3 -0
  123. data/app/views/spree/api/taxonomies/show.v1.rabl +15 -0
  124. data/app/views/spree/api/taxons/index.v1.rabl +12 -0
  125. data/app/views/spree/api/taxons/jstree.rabl +8 -0
  126. data/app/views/spree/api/taxons/new.v1.rabl +3 -0
  127. data/app/views/spree/api/taxons/show.v1.rabl +6 -0
  128. data/app/views/spree/api/taxons/taxons.v1.rabl +5 -0
  129. data/app/views/spree/api/transfer_items/show.v1.rabl +6 -0
  130. data/app/views/spree/api/users/index.v1.rabl +7 -0
  131. data/app/views/spree/api/users/new.v1.rabl +3 -0
  132. data/app/views/spree/api/users/show.v1.rabl +10 -0
  133. data/app/views/spree/api/variants/big.v1.rabl +17 -0
  134. data/app/views/spree/api/variants/index.v1.rabl +9 -0
  135. data/app/views/spree/api/variants/new.v1.rabl +2 -0
  136. data/app/views/spree/api/variants/show.v1.rabl +3 -0
  137. data/app/views/spree/api/variants/small.v1.rabl +17 -0
  138. data/app/views/spree/api/zones/index.v1.rabl +7 -0
  139. data/app/views/spree/api/zones/show.v1.rabl +6 -0
  140. data/config/initializers/metal_load_paths.rb +1 -0
  141. data/config/locales/en.yml +29 -0
  142. data/config/routes.rb +139 -0
  143. data/db/migrate/20100107141738_add_api_key_to_spree_users.rb +7 -0
  144. data/db/migrate/20120411123334_resize_api_key_field.rb +7 -0
  145. data/db/migrate/20120530054546_rename_api_key_to_spree_api_key.rb +7 -0
  146. data/db/migrate/20131017162334_add_index_to_user_spree_api_key.rb +7 -0
  147. data/lib/solidus_api.rb +1 -0
  148. data/lib/spree/api/engine.rb +38 -0
  149. data/lib/spree/api/responders/rabl_template.rb +31 -0
  150. data/lib/spree/api/responders.rb +11 -0
  151. data/lib/spree/api/testing_support/caching.rb +10 -0
  152. data/lib/spree/api/testing_support/helpers.rb +44 -0
  153. data/lib/spree/api/testing_support/setup.rb +16 -0
  154. data/lib/spree/api.rb +10 -0
  155. data/lib/spree_api.rb +3 -0
  156. data/script/rails +9 -0
  157. data/solidus_api.gemspec +21 -0
  158. data/spec/controllers/spree/api/addresses_controller_spec.rb +56 -0
  159. data/spec/controllers/spree/api/base_controller_spec.rb +164 -0
  160. data/spec/controllers/spree/api/checkouts_controller_spec.rb +386 -0
  161. data/spec/controllers/spree/api/classifications_controller_spec.rb +48 -0
  162. data/spec/controllers/spree/api/config_controller_spec.rb +23 -0
  163. data/spec/controllers/spree/api/countries_controller_spec.rb +48 -0
  164. data/spec/controllers/spree/api/credit_cards_controller_spec.rb +80 -0
  165. data/spec/controllers/spree/api/images_controller_spec.rb +93 -0
  166. data/spec/controllers/spree/api/inventory_units_controller_spec.rb +50 -0
  167. data/spec/controllers/spree/api/line_items_controller_spec.rb +186 -0
  168. data/spec/controllers/spree/api/option_types_controller_spec.rb +116 -0
  169. data/spec/controllers/spree/api/option_values_controller_spec.rb +135 -0
  170. data/spec/controllers/spree/api/orders_controller_spec.rb +759 -0
  171. data/spec/controllers/spree/api/payments_controller_spec.rb +254 -0
  172. data/spec/controllers/spree/api/product_properties_controller_spec.rb +116 -0
  173. data/spec/controllers/spree/api/products_controller_spec.rb +454 -0
  174. data/spec/controllers/spree/api/promotion_application_spec.rb +50 -0
  175. data/spec/controllers/spree/api/promotions_controller_spec.rb +64 -0
  176. data/spec/controllers/spree/api/properties_controller_spec.rb +102 -0
  177. data/spec/controllers/spree/api/return_authorizations_controller_spec.rb +173 -0
  178. data/spec/controllers/spree/api/shipments_controller_spec.rb +252 -0
  179. data/spec/controllers/spree/api/states_controller_spec.rb +82 -0
  180. data/spec/controllers/spree/api/stock_items_controller_spec.rb +307 -0
  181. data/spec/controllers/spree/api/stock_locations_controller_spec.rb +172 -0
  182. data/spec/controllers/spree/api/stock_movements_controller_spec.rb +84 -0
  183. data/spec/controllers/spree/api/stock_transfers_controller_spec.rb +83 -0
  184. data/spec/controllers/spree/api/store_credit_events_controller_spec.rb +68 -0
  185. data/spec/controllers/spree/api/stores_controller_spec.rb +133 -0
  186. data/spec/controllers/spree/api/taxonomies_controller_spec.rb +114 -0
  187. data/spec/controllers/spree/api/taxons_controller_spec.rb +177 -0
  188. data/spec/controllers/spree/api/transfer_items_controller_spec.rb +152 -0
  189. data/spec/controllers/spree/api/unauthenticated_products_controller_spec.rb +26 -0
  190. data/spec/controllers/spree/api/users_controller_spec.rb +153 -0
  191. data/spec/controllers/spree/api/variants_controller_spec.rb +235 -0
  192. data/spec/controllers/spree/api/zones_controller_spec.rb +115 -0
  193. data/spec/features/checkout_spec.rb +187 -0
  194. data/spec/fixtures/thinking-cat.jpg +0 -0
  195. data/spec/models/spree/legacy_user_spec.rb +45 -0
  196. data/spec/requests/rabl_cache_spec.rb +32 -0
  197. data/spec/shared_examples/protect_product_actions.rb +17 -0
  198. data/spec/spec_helper.rb +60 -0
  199. data/spec/support/controller_hacks.rb +38 -0
  200. data/spec/support/database_cleaner.rb +14 -0
  201. data/spec/support/have_attributes_matcher.rb +13 -0
  202. metadata +334 -0
@@ -0,0 +1,307 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::StockItemsController, :type => :controller do
5
+ render_views
6
+
7
+ let!(:stock_location) { create(:stock_location_with_items) }
8
+ let!(:stock_item) { stock_location.stock_items.order(:id).first }
9
+ let!(:attributes) { [:id, :count_on_hand, :backorderable,
10
+ :stock_location_id, :variant_id] }
11
+
12
+ before do
13
+ stub_authentication!
14
+ end
15
+
16
+ context "as a normal user" do
17
+ describe "#index" do
18
+ it "can list stock items for an active stock location" do
19
+ api_get :index, stock_location_id: stock_location.to_param
20
+ expect(response).to be_success
21
+ json_response['stock_items'].first.should have_attributes(attributes)
22
+ json_response['stock_items'].first['variant']['sku'].should match /\ASKU-\d+\z/
23
+ end
24
+
25
+ it "cannot list stock items for an inactive stock location" do
26
+ stock_location.update_attributes!(active: false)
27
+ api_get :index, stock_location_id: stock_location.to_param
28
+ expect(response).to be_not_found
29
+ end
30
+ end
31
+
32
+ describe "#show" do
33
+ it "can see a stock item for an active stock location" do
34
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
35
+ json_response.should have_attributes(attributes)
36
+ json_response['count_on_hand'].should eq stock_item.count_on_hand
37
+ end
38
+
39
+ it "cannot see a stock item for an inactive stock location" do
40
+ stock_location.update_attributes!(active: false)
41
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
42
+ response.status.should == 404
43
+ end
44
+ end
45
+
46
+ describe "#create" do
47
+ it "cannot create a stock item" do
48
+ variant = create(:variant)
49
+ params = {
50
+ stock_location_id: stock_location.to_param,
51
+ stock_item: {
52
+ variant_id: variant.id,
53
+ count_on_hand: '20'
54
+ }
55
+ }
56
+
57
+ api_post :create, params
58
+ response.status.should == 404
59
+ end
60
+ end
61
+
62
+ describe "#update" do
63
+ it "cannot update a stock item" do
64
+ api_put :update, stock_location_id: stock_location.to_param, id: stock_item.to_param
65
+ response.status.should == 404
66
+ end
67
+ end
68
+
69
+ describe "#destroy" do
70
+ it "cannot destroy a stock item" do
71
+ api_delete :destroy, stock_location_id: stock_location.to_param, id: stock_item.to_param
72
+ response.status.should == 404
73
+ end
74
+ end
75
+ end
76
+
77
+ context "as an admin" do
78
+ sign_in_as_admin!
79
+
80
+ it 'cannot list of stock items' do
81
+ api_get :index, stock_location_id: stock_location.to_param
82
+ expect(json_response['stock_items'].first).to have_attributes(attributes)
83
+ expect(json_response['stock_items'].first['variant']['sku']).to include 'SKU'
84
+ end
85
+
86
+ it 'requires a stock_location_id to be passed as a parameter' do
87
+ api_get :index
88
+ expect(json_response['error']).to match(/stock_location_id parameter must be provided/)
89
+ expect(response.status).to eq(422)
90
+ end
91
+
92
+ it 'can control the page size through a parameter' do
93
+ api_get :index, stock_location_id: stock_location.to_param, per_page: 1
94
+ expect(json_response['count']).to eq(1)
95
+ expect(json_response['current_page']).to eq(1)
96
+ end
97
+
98
+ it 'can query the results through a paramter' do
99
+ stock_item.update_column(:count_on_hand, 30)
100
+ api_get :index, stock_location_id: stock_location.to_param, q: { count_on_hand_eq: '30' }
101
+ expect(json_response['count']).to eq(1)
102
+ expect(json_response['stock_items'].first['count_on_hand']).to eq 30
103
+ end
104
+
105
+ it 'gets a stock item' do
106
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
107
+ expect(json_response).to have_attributes(attributes)
108
+ expect(json_response['count_on_hand']).to eq stock_item.count_on_hand
109
+ end
110
+
111
+ context 'creating a stock item' do
112
+ let!(:variant) do
113
+ variant = create(:variant)
114
+ # Creating a variant also creates stock items.
115
+ # We don't want any to exist (as they would conflict with what we're about to create)
116
+ StockItem.delete_all
117
+ variant
118
+ end
119
+ let(:count_on_hand) { '20' }
120
+ let(:params) do
121
+ {
122
+ stock_location_id: stock_location.to_param,
123
+ stock_item: {
124
+ variant_id: variant.id,
125
+ count_on_hand: count_on_hand
126
+ }
127
+ }
128
+ end
129
+
130
+ subject { api_post :create, params }
131
+
132
+ it 'can create a new stock item' do
133
+ subject
134
+ expect(response.status).to eq 201
135
+ expect(json_response).to have_attributes(attributes)
136
+ end
137
+
138
+ it 'creates a stock movement' do
139
+ expect { subject }.to change { Spree::StockMovement.count }.by(1)
140
+ expect(assigns(:stock_movement).quantity).to eq 20
141
+ end
142
+
143
+ context 'variant tracks inventory' do
144
+ before do
145
+ expect(variant.track_inventory).to eq true
146
+ end
147
+
148
+ it "sets the stock item's count_on_hand" do
149
+ subject
150
+ expect(assigns(:stock_item).count_on_hand).to eq 20
151
+ end
152
+ end
153
+
154
+ context 'variant does not track inventory' do
155
+ before do
156
+ variant.update_attributes(track_inventory: false)
157
+ end
158
+
159
+ it "doesn't set the stock item's count_on_hand" do
160
+ subject
161
+ expect(assigns(:stock_item).count_on_hand).to eq 0
162
+ end
163
+ end
164
+
165
+ context "attempting to set negative inventory" do
166
+ let(:count_on_hand) { '-1' }
167
+
168
+ it "does not allow negative inventory for the stock item" do
169
+ subject
170
+ expect(response.status).to eq 422
171
+ expect(response.body).to match Spree.t(:stock_not_below_zero)
172
+ expect(assigns(:stock_item).count_on_hand).to eq 0
173
+ end
174
+ end
175
+ end
176
+
177
+ context 'updating a stock item' do
178
+ before do
179
+ expect(stock_item.count_on_hand).to eq 10
180
+ end
181
+
182
+ subject { api_put :update, params }
183
+
184
+ context 'adjusting count_on_hand' do
185
+ let(:count_on_hand) { 40 }
186
+ let(:params) do
187
+ {
188
+ id: stock_item.to_param,
189
+ stock_item: {
190
+ count_on_hand: count_on_hand,
191
+ backorderable: true
192
+ }
193
+ }
194
+ end
195
+
196
+ it 'can update a stock item to add new inventory' do
197
+ subject
198
+ expect(response.status).to eq 200
199
+ expect(json_response['count_on_hand']).to eq 50
200
+ expect(json_response['backorderable']).to eq true
201
+ end
202
+
203
+ it 'creates a stock movement for the adjusted quantity' do
204
+ expect { subject }.to change { Spree::StockMovement.count }.by(1)
205
+ expect(Spree::StockMovement.last.quantity).to eq 40
206
+ end
207
+
208
+ context 'tracking inventory' do
209
+ before do
210
+ expect(stock_item.should_track_inventory?).to eq true
211
+ end
212
+
213
+ it "sets the stock item's count_on_hand" do
214
+ subject
215
+ expect(assigns(:stock_item).count_on_hand).to eq 50
216
+ end
217
+ end
218
+
219
+ context 'not tracking inventory' do
220
+ before do
221
+ stock_item.variant.update_attributes(track_inventory: false)
222
+ end
223
+
224
+ it "doesn't set the stock item's count_on_hand" do
225
+ subject
226
+ expect(assigns(:stock_item).count_on_hand).to eq 10
227
+ end
228
+ end
229
+
230
+ context "attempting to set negative inventory" do
231
+ let(:count_on_hand) { '-11' }
232
+
233
+ it "does not allow negative inventory for the stock item" do
234
+ subject
235
+ expect(response.status).to eq 422
236
+ expect(response.body).to match Spree.t(:stock_not_below_zero)
237
+ expect(assigns(:stock_item).count_on_hand).to eq 10
238
+ end
239
+ end
240
+ end
241
+
242
+ context 'setting count_on_hand' do
243
+ let(:count_on_hand) { 40 }
244
+ let(:params) do
245
+ {
246
+ id: stock_item.to_param,
247
+ stock_item: {
248
+ count_on_hand: count_on_hand,
249
+ force: true,
250
+ }
251
+ }
252
+ end
253
+
254
+ it 'can set a stock item to modify the current inventory' do
255
+ subject
256
+ expect(response.status).to eq 200
257
+ expect(json_response['count_on_hand']).to eq 40
258
+ end
259
+
260
+ it 'creates a stock movement for the adjusted quantity' do
261
+ expect { subject }.to change { Spree::StockMovement.count }.by(1)
262
+ expect(assigns(:stock_movement).quantity).to eq 30
263
+ end
264
+
265
+ context 'tracking inventory' do
266
+ before do
267
+ expect(stock_item.should_track_inventory?).to eq true
268
+ end
269
+
270
+ it "updates the stock item's count_on_hand" do
271
+ subject
272
+ expect(assigns(:stock_item).count_on_hand).to eq 40
273
+ end
274
+ end
275
+
276
+ context 'not tracking inventory' do
277
+ before do
278
+ stock_item.variant.update_attributes(track_inventory: false)
279
+ end
280
+
281
+ it "doesn't update the stock item's count_on_hand" do
282
+ subject
283
+ expect(assigns(:stock_item).count_on_hand).to eq 10
284
+ end
285
+ end
286
+
287
+ context "attempting to set negative inventory" do
288
+ let(:count_on_hand) { '-1' }
289
+
290
+ it "does not allow negative inventory for the stock item" do
291
+ subject
292
+ expect(response.status).to eq 422
293
+ expect(response.body).to match Spree.t(:stock_not_below_zero)
294
+ expect(assigns(:stock_item).count_on_hand).to eq 10
295
+ end
296
+ end
297
+ end
298
+ end
299
+
300
+ it 'can delete a stock item' do
301
+ api_delete :destroy, id: stock_item.to_param
302
+ expect(response.status).to eq(204)
303
+ expect { Spree::StockItem.find(stock_item.id) }.to raise_error(ActiveRecord::RecordNotFound)
304
+ end
305
+ end
306
+ end
307
+ end
@@ -0,0 +1,172 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::StockLocationsController, :type => :controller do
5
+ render_views
6
+
7
+ let!(:stock_location) { create(:stock_location) }
8
+ let!(:attributes) { [:id, :name, :address1, :address2, :city, :state_id, :state_name, :country_id, :zipcode, :phone, :active] }
9
+
10
+ before do
11
+ stub_authentication!
12
+ end
13
+
14
+ context "as a user" do
15
+ describe "#index" do
16
+ it "can see active stock locations" do
17
+ api_get :index
18
+ expect(response).to be_success
19
+ stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
20
+ expect(stock_locations).to include stock_location.name
21
+ end
22
+
23
+ it "cannot see inactive stock locations" do
24
+ stock_location.update_attributes!(active: false)
25
+ api_get :index
26
+ expect(response).to be_success
27
+ stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
28
+ expect(stock_locations).not_to include stock_location.name
29
+ end
30
+ end
31
+
32
+ describe "#show" do
33
+ it "can see active stock locations" do
34
+ api_get :show, id: stock_location.id
35
+ expect(response).to be_success
36
+ expect(json_response['name']).to eq stock_location.name
37
+ end
38
+
39
+ it "cannot see inactive stock locations" do
40
+ stock_location.update_attributes!(active: false)
41
+ api_get :show, id: stock_location.id
42
+ expect(response).to be_not_found
43
+ end
44
+ end
45
+
46
+ describe "#create" do
47
+ it "cannot create a new stock location" do
48
+ params = {
49
+ stock_location: {
50
+ name: "North Pole",
51
+ active: true
52
+ }
53
+ }
54
+
55
+ api_post :create, params
56
+ response.status.should == 401
57
+ end
58
+ end
59
+
60
+ describe "#update" do
61
+ it "cannot update a stock location" do
62
+ api_put :update, :stock_location => { :name => "South Pole" }, :id => stock_location.to_param
63
+ response.status.should == 401
64
+ end
65
+ end
66
+
67
+ describe "#destroy" do
68
+ it "cannot delete a stock location" do
69
+ api_put :destroy, :id => stock_location.to_param
70
+ response.status.should == 401
71
+ end
72
+ end
73
+ end
74
+
75
+ context "as an admin" do
76
+ sign_in_as_admin!
77
+
78
+ describe "#index" do
79
+ it "can see active stock locations" do
80
+ api_get :index
81
+ expect(response).to be_success
82
+ stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
83
+ expect(stock_locations).to include stock_location.name
84
+ end
85
+
86
+ it "can see inactive stock locations" do
87
+ stock_location.update_attributes!(active: false)
88
+ api_get :index
89
+ expect(response).to be_success
90
+ stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
91
+ expect(stock_locations).to include stock_location.name
92
+ end
93
+
94
+ it "gets stock location information" do
95
+ api_get :index
96
+ json_response['stock_locations'].first.should have_attributes(attributes)
97
+ json_response['stock_locations'].first['country'].should_not be_nil
98
+ json_response['stock_locations'].first['state'].should_not be_nil
99
+ end
100
+
101
+ it 'can control the page size through a parameter' do
102
+ create(:stock_location)
103
+ api_get :index, per_page: 1
104
+ json_response['count'].should == 1
105
+ json_response['current_page'].should == 1
106
+ json_response['pages'].should == 2
107
+ end
108
+
109
+ it 'can query the results through a paramter' do
110
+ expected_result = create(:stock_location, name: 'South America')
111
+ api_get :index, q: { name_cont: 'south' }
112
+ json_response['count'].should == 1
113
+ json_response['stock_locations'].first['name'].should eq expected_result.name
114
+ end
115
+
116
+ end
117
+
118
+ describe "#show" do
119
+ it "can see active stock locations" do
120
+ api_get :show, id: stock_location.id
121
+ expect(response).to be_success
122
+ expect(json_response['name']).to eq stock_location.name
123
+ end
124
+
125
+ it "can see inactive stock locations" do
126
+ stock_location.update_attributes!(active: false)
127
+ api_get :show, id: stock_location.id
128
+ expect(response).to be_success
129
+ expect(json_response['name']).to eq stock_location.name
130
+ end
131
+ end
132
+
133
+ describe "#create" do
134
+ it "can create a new stock location" do
135
+ params = {
136
+ stock_location: {
137
+ name: "North Pole",
138
+ active: true
139
+ }
140
+ }
141
+
142
+ api_post :create, params
143
+ response.status.should == 201
144
+ json_response.should have_attributes(attributes)
145
+ end
146
+ end
147
+
148
+ describe "#update" do
149
+ it "can update a stock location" do
150
+ params = {
151
+ id: stock_location.to_param,
152
+ stock_location: {
153
+ name: "South Pole"
154
+ }
155
+ }
156
+
157
+ api_put :update, params
158
+ response.status.should == 200
159
+ json_response['name'].should eq 'South Pole'
160
+ end
161
+ end
162
+
163
+ describe "#destroy" do
164
+ it "can delete a stock location" do
165
+ api_delete :destroy, id: stock_location.to_param
166
+ response.status.should == 204
167
+ lambda { stock_location.reload }.should raise_error(ActiveRecord::RecordNotFound)
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::StockMovementsController, :type => :controller do
5
+ render_views
6
+
7
+ let!(:stock_location) { create(:stock_location_with_items) }
8
+ let!(:stock_item) { stock_location.stock_items.order(:id).first }
9
+ let!(:stock_movement) { create(:stock_movement, stock_item: stock_item) }
10
+ let!(:attributes) { [:id, :quantity, :stock_item_id] }
11
+
12
+ before do
13
+ stub_authentication!
14
+ end
15
+
16
+ context 'as a user' do
17
+ it 'cannot see a list of stock movements' do
18
+ api_get :index, stock_location_id: stock_location.to_param
19
+ expect(response.status).to eq(401)
20
+ end
21
+
22
+ it 'cannot see a stock movement' do
23
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.id
24
+ expect(response.status).to eq(404)
25
+ end
26
+
27
+ it 'cannot create a stock movement' do
28
+ params = {
29
+ stock_location_id: stock_location.to_param,
30
+ stock_movement: {
31
+ stock_item_id: stock_item.to_param
32
+ }
33
+ }
34
+
35
+ api_post :create, params
36
+ expect(response.status).to eq(401)
37
+ end
38
+ end
39
+
40
+ context 'as an admin' do
41
+ sign_in_as_admin!
42
+
43
+ it 'gets list of stock movements' do
44
+ api_get :index, stock_location_id: stock_location.to_param
45
+ expect(json_response['stock_movements'].first).to have_attributes(attributes)
46
+ expect(json_response['stock_movements'].first['stock_item']['count_on_hand']).to eq 11
47
+ end
48
+
49
+ it 'can control the page size through a parameter' do
50
+ create(:stock_movement, stock_item: stock_item)
51
+ api_get :index, stock_location_id: stock_location.to_param, per_page: 1
52
+ expect(json_response['count']).to eq(1)
53
+ expect(json_response['current_page']).to eq(1)
54
+ expect(json_response['pages']).to eq(2)
55
+ end
56
+
57
+ it 'can query the results through a paramter' do
58
+ expected_result = create(:stock_movement, :received, quantity: 10, stock_item: stock_item)
59
+ api_get :index, stock_location_id: stock_location.to_param, q: { quantity_eq: '10' }
60
+ expect(json_response['count']).to eq(1)
61
+ end
62
+
63
+ it 'gets a stock movement' do
64
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.to_param
65
+ expect(json_response).to have_attributes(attributes)
66
+ expect(json_response['stock_item_id']).to eq stock_movement.stock_item_id
67
+ end
68
+
69
+ it 'can create a new stock movement' do
70
+ params = {
71
+ stock_location_id: stock_location.to_param,
72
+ stock_movement: {
73
+ stock_item_id: stock_item.to_param
74
+ }
75
+ }
76
+
77
+ api_post :create, params
78
+ expect(response.status).to eq(201)
79
+ expect(json_response).to have_attributes(attributes)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::StockTransfersController do
5
+ render_views
6
+
7
+ let!(:stock_transfer) { create(:stock_transfer_with_items) }
8
+ let(:transfer_item) { stock_transfer.transfer_items.first }
9
+
10
+ before do
11
+ stub_authentication!
12
+ end
13
+
14
+ context "as a normal user" do
15
+ describe "#receive" do
16
+ it "cannot receive transfer items from a stock transfer" do
17
+ api_post :receive, id: stock_transfer.to_param, variant_id: transfer_item.variant.to_param
18
+ expect(response.status).to eq 401
19
+ end
20
+ end
21
+ end
22
+
23
+ context "as an admin" do
24
+ sign_in_as_admin!
25
+
26
+ describe "#receive" do
27
+ subject do
28
+ api_post :receive, id: stock_transfer.to_param, variant_id: variant_id
29
+ end
30
+
31
+ context "valid parameters" do
32
+ let(:variant_id) { transfer_item.variant.to_param }
33
+
34
+ it "can receive a transfer items from a stock transfer" do
35
+ subject
36
+ expect(response.status).to eq 200
37
+ end
38
+
39
+ it "increments the received quantity for the transfer_item" do
40
+ expect { subject }.to change { transfer_item.reload.received_quantity }.by(1)
41
+ end
42
+
43
+ it "returns the received transfer item in the response" do
44
+ subject
45
+ expect(JSON.parse(response.body)["received_item"]["id"]).to eq transfer_item.id
46
+ end
47
+ end
48
+
49
+ context "transfer item has been fully received" do
50
+ let(:variant_id) { transfer_item.variant.to_param }
51
+
52
+ before do
53
+ transfer_item.update_attributes!(expected_quantity: 1, received_quantity: 1)
54
+ end
55
+
56
+ it "returns a 422" do
57
+ subject
58
+ expect(response.status).to eq 422
59
+ end
60
+
61
+ it "returns a specific error message" do
62
+ subject
63
+ expect(JSON.parse(response.body)["errors"]["received_quantity"]).to eq ["must be less than or equal to 1"]
64
+ end
65
+ end
66
+
67
+ context "variant is not in the transfer order" do
68
+ let(:variant_id) { create(:variant).to_param }
69
+
70
+ it "returns a 422" do
71
+ subject
72
+ expect(response.status).to eq 422
73
+ end
74
+
75
+ it "returns a specific error message" do
76
+ subject
77
+ expect(JSON.parse(response.body)["error"]).to eq Spree.t(:item_not_in_stock_transfer)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end