solidus_frontend_devise_token_auth 2.8.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +26 -0
  3. data/README.md +42 -0
  4. data/Rakefile +17 -0
  5. data/app/assets/config/solidus_frontend_manifest.js +4 -0
  6. data/app/assets/images/credit_cards/amex_cid.gif +0 -0
  7. data/app/assets/images/credit_cards/credit_card.gif +0 -0
  8. data/app/assets/images/credit_cards/discover_cid.gif +0 -0
  9. data/app/assets/images/credit_cards/icons/american_express.png +0 -0
  10. data/app/assets/images/credit_cards/icons/cirrus.png +0 -0
  11. data/app/assets/images/credit_cards/icons/delta.png +0 -0
  12. data/app/assets/images/credit_cards/icons/diners_club.png +0 -0
  13. data/app/assets/images/credit_cards/icons/directdebit.png +0 -0
  14. data/app/assets/images/credit_cards/icons/discover.png +0 -0
  15. data/app/assets/images/credit_cards/icons/egold.png +0 -0
  16. data/app/assets/images/credit_cards/icons/maestro.png +0 -0
  17. data/app/assets/images/credit_cards/icons/master.png +0 -0
  18. data/app/assets/images/credit_cards/icons/paypal.png +0 -0
  19. data/app/assets/images/credit_cards/icons/solo.png +0 -0
  20. data/app/assets/images/credit_cards/icons/switch.png +0 -0
  21. data/app/assets/images/credit_cards/icons/visa.png +0 -0
  22. data/app/assets/images/credit_cards/icons/visaelectron.png +0 -0
  23. data/app/assets/images/credit_cards/icons/westernunion.png +0 -0
  24. data/app/assets/images/credit_cards/icons/wirecard.png +0 -0
  25. data/app/assets/images/credit_cards/icons/worldpay.png +0 -0
  26. data/app/assets/images/credit_cards/master_cid.jpg +0 -0
  27. data/app/assets/images/credit_cards/visa_cid.gif +0 -0
  28. data/app/assets/images/favicon.ico +0 -0
  29. data/app/assets/images/icons/add-to-cart.png +0 -0
  30. data/app/assets/images/icons/checkout.png +0 -0
  31. data/app/assets/images/icons/delete.png +0 -0
  32. data/app/assets/images/icons/update.png +0 -0
  33. data/app/assets/images/spinner.gif +0 -0
  34. data/app/assets/images/spree/frontend/cart.png +0 -0
  35. data/app/assets/javascripts/spree/frontend/cart.js +30 -0
  36. data/app/assets/javascripts/spree/frontend/checkout/address.js +127 -0
  37. data/app/assets/javascripts/spree/frontend/checkout/coupon-code.js +41 -0
  38. data/app/assets/javascripts/spree/frontend/checkout/payment.js +55 -0
  39. data/app/assets/javascripts/spree/frontend/checkout.js +24 -0
  40. data/app/assets/javascripts/spree/frontend/locale_selector.js +5 -0
  41. data/app/assets/javascripts/spree/frontend/product.js +81 -0
  42. data/app/assets/javascripts/spree/frontend.js +5 -0
  43. data/app/assets/stylesheets/spree/frontend/_skeleton.scss +242 -0
  44. data/app/assets/stylesheets/spree/frontend/_variables.scss +65 -0
  45. data/app/assets/stylesheets/spree/frontend/screen.css.scss +1387 -0
  46. data/app/assets/stylesheets/spree/frontend.css +5 -0
  47. data/app/controllers/spree/checkout_controller.rb +236 -0
  48. data/app/controllers/spree/content_controller.rb +11 -0
  49. data/app/controllers/spree/home_controller.rb +14 -0
  50. data/app/controllers/spree/locale_controller.rb +20 -0
  51. data/app/controllers/spree/orders_controller.rb +138 -0
  52. data/app/controllers/spree/products_controller.rb +52 -0
  53. data/app/controllers/spree/store_controller.rb +30 -0
  54. data/app/controllers/spree/taxons_controller.rb +31 -0
  55. data/app/helpers/spree/orders_helper.rb +18 -0
  56. data/app/helpers/spree/taxon_filters_helper.rb +13 -0
  57. data/app/models/spree/frontend_configuration.rb +10 -0
  58. data/app/views/spree/address/_form.html.erb +96 -0
  59. data/app/views/spree/address/_form_hidden.html.erb +12 -0
  60. data/app/views/spree/checkout/_address.html.erb +33 -0
  61. data/app/views/spree/checkout/_confirm.html.erb +25 -0
  62. data/app/views/spree/checkout/_coupon_code.html.erb +12 -0
  63. data/app/views/spree/checkout/_delivery.html.erb +108 -0
  64. data/app/views/spree/checkout/_payment.html.erb +67 -0
  65. data/app/views/spree/checkout/_summary.html.erb +76 -0
  66. data/app/views/spree/checkout/_terms_and_conditions.en.html.erb +1 -0
  67. data/app/views/spree/checkout/edit.html.erb +32 -0
  68. data/app/views/spree/checkout/existing_payment/_gateway.html.erb +9 -0
  69. data/app/views/spree/checkout/payment/_check.html.erb +0 -0
  70. data/app/views/spree/checkout/payment/_gateway.html.erb +36 -0
  71. data/app/views/spree/content/cvv.html.erb +13 -0
  72. data/app/views/spree/home/index.html.erb +12 -0
  73. data/app/views/spree/layouts/spree_application.html.erb +36 -0
  74. data/app/views/spree/orders/_adjustment_row.html.erb +8 -0
  75. data/app/views/spree/orders/_adjustments.html.erb +24 -0
  76. data/app/views/spree/orders/_form.html.erb +29 -0
  77. data/app/views/spree/orders/_line_item.html.erb +34 -0
  78. data/app/views/spree/orders/edit.html.erb +47 -0
  79. data/app/views/spree/orders/show.html.erb +22 -0
  80. data/app/views/spree/payments/_payment.html.erb +18 -0
  81. data/app/views/spree/products/_cart_form.html.erb +65 -0
  82. data/app/views/spree/products/_image.html.erb +8 -0
  83. data/app/views/spree/products/_promotions.html.erb +19 -0
  84. data/app/views/spree/products/_properties.html.erb +15 -0
  85. data/app/views/spree/products/_taxons.html.erb +14 -0
  86. data/app/views/spree/products/_thumbnails.html.erb +21 -0
  87. data/app/views/spree/products/index.html.erb +27 -0
  88. data/app/views/spree/products/show.html.erb +51 -0
  89. data/app/views/spree/shared/_address.html.erb +38 -0
  90. data/app/views/spree/shared/_filters.html.erb +27 -0
  91. data/app/views/spree/shared/_footer.html.erb +6 -0
  92. data/app/views/spree/shared/_head.html.erb +14 -0
  93. data/app/views/spree/shared/_header.html.erb +5 -0
  94. data/app/views/spree/shared/_image.html.erb +12 -0
  95. data/app/views/spree/shared/_link_to_cart.html.erb +1 -0
  96. data/app/views/spree/shared/_locale_selector.html.erb +25 -0
  97. data/app/views/spree/shared/_login_bar_items.html.erb +1 -0
  98. data/app/views/spree/shared/_main_nav_bar.html.erb +12 -0
  99. data/app/views/spree/shared/_nav_bar.html.erb +9 -0
  100. data/app/views/spree/shared/_order_details.html.erb +146 -0
  101. data/app/views/spree/shared/_products.html.erb +51 -0
  102. data/app/views/spree/shared/_search.html.erb +11 -0
  103. data/app/views/spree/shared/_shipment_tracking.html.erb +9 -0
  104. data/app/views/spree/shared/_sidebar.html.erb +3 -0
  105. data/app/views/spree/shared/_taxonomies.html.erb +9 -0
  106. data/app/views/spree/shared/unauthorized.html.erb +0 -0
  107. data/app/views/spree/store/cart_link.html.erb +1 -0
  108. data/app/views/spree/taxons/_taxon.html.erb +4 -0
  109. data/app/views/spree/taxons/show.html.erb +20 -0
  110. data/config/initializers/assets.rb +3 -0
  111. data/config/initializers/canonical_rails.rb +16 -0
  112. data/config/routes.rb +33 -0
  113. data/lib/generators/solidus/views/override_generator.rb +49 -0
  114. data/lib/solidus_frontend.rb +3 -0
  115. data/lib/spree/frontend/engine.rb +13 -0
  116. data/lib/spree/frontend/middleware/seo_assist.rb +52 -0
  117. data/lib/spree/frontend.rb +15 -0
  118. data/lib/spree_frontend.rb +3 -0
  119. data/lib/tasks/rake_util.rb +18 -0
  120. data/lib/tasks/taxon.rake +16 -0
  121. data/script/rails +10 -0
  122. data/solidus_frontend.gemspec +35 -0
  123. data/spec/controllers/controller_helpers_spec.rb +30 -0
  124. data/spec/controllers/locale_controller_spec.rb +57 -0
  125. data/spec/controllers/spree/checkout_controller_spec.rb +539 -0
  126. data/spec/controllers/spree/checkout_controller_with_views_spec.rb +37 -0
  127. data/spec/controllers/spree/content_controller_spec.rb +9 -0
  128. data/spec/controllers/spree/current_order_tracking_spec.rb +47 -0
  129. data/spec/controllers/spree/home_controller_spec.rb +29 -0
  130. data/spec/controllers/spree/orders_controller_ability_spec.rb +93 -0
  131. data/spec/controllers/spree/orders_controller_spec.rb +225 -0
  132. data/spec/controllers/spree/orders_controller_transitions_spec.rb +33 -0
  133. data/spec/controllers/spree/products_controller_spec.rb +38 -0
  134. data/spec/controllers/spree/taxons_controller_spec.rb +14 -0
  135. data/spec/features/address_spec.rb +78 -0
  136. data/spec/features/automatic_promotion_adjustments_spec.rb +49 -0
  137. data/spec/features/caching/products_spec.rb +48 -0
  138. data/spec/features/caching/taxons_spec.rb +21 -0
  139. data/spec/features/cart_spec.rb +85 -0
  140. data/spec/features/checkout_spec.rb +690 -0
  141. data/spec/features/checkout_unshippable_spec.rb +37 -0
  142. data/spec/features/coupon_code_spec.rb +266 -0
  143. data/spec/features/currency_spec.rb +20 -0
  144. data/spec/features/free_shipping_promotions_spec.rb +60 -0
  145. data/spec/features/locale_spec.rb +27 -0
  146. data/spec/features/order_spec.rb +73 -0
  147. data/spec/features/products_spec.rb +291 -0
  148. data/spec/features/promotion_code_invalidation_spec.rb +54 -0
  149. data/spec/features/quantity_promotions_spec.rb +130 -0
  150. data/spec/features/taxons_spec.rb +158 -0
  151. data/spec/features/template_rendering_spec.rb +20 -0
  152. data/spec/fixtures/thinking-cat.jpg +0 -0
  153. data/spec/generators/solidus/views/override_generator_spec.rb +50 -0
  154. data/spec/helpers/base_helper_spec.rb +13 -0
  155. data/spec/helpers/order_helper_spec.rb +14 -0
  156. data/spec/helpers/taxon_filters_helper_spec.rb +12 -0
  157. data/spec/spec_helper.rb +106 -0
  158. data/spec/support/features/fill_in_with_force.rb +12 -0
  159. data/spec/support/shared_contexts/checkout_setup.rb +12 -0
  160. data/spec/support/shared_contexts/custom_products.rb +28 -0
  161. data/spec/support/shared_contexts/locales.rb +16 -0
  162. data/spec/views/spree/checkout/_summary_spec.rb +11 -0
  163. metadata +337 -0
@@ -0,0 +1,539 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::CheckoutController, type: :controller do
6
+ let(:token) { 'some_token' }
7
+ let(:user) { create(:user) }
8
+ let(:order) { FactoryBot.create(:order_with_totals) }
9
+
10
+ let(:address_params) do
11
+ address = FactoryBot.build(:address)
12
+ address.attributes.except("created_at", "updated_at")
13
+ end
14
+
15
+ before do
16
+ allow(controller).to receive_messages try_spree_current_user: user
17
+ allow(controller).to receive_messages spree_current_user: user
18
+ allow(controller).to receive_messages current_order: order
19
+ end
20
+
21
+ context "#edit" do
22
+ it 'should check if the user is authorized for :edit' do
23
+ expect(controller).to receive(:authorize!).with(:edit, order, token)
24
+ request.cookie_jar.signed[:guest_token] = token
25
+ get :edit, params: { state: 'address' }
26
+ end
27
+
28
+ it "should redirect to the cart path unless checkout_allowed?" do
29
+ allow(order).to receive_messages checkout_allowed?: false
30
+ get :edit, params: { state: "delivery" }
31
+ expect(response).to redirect_to(spree.cart_path)
32
+ end
33
+
34
+ it "should redirect to the cart path if current_order is nil" do
35
+ allow(controller).to receive(:current_order).and_return(nil)
36
+ get :edit, params: { state: "delivery" }
37
+ expect(response).to redirect_to(spree.cart_path)
38
+ end
39
+
40
+ it "should redirect to cart if order is completed" do
41
+ allow(order).to receive_messages(completed?: true)
42
+ get :edit, params: { state: "address" }
43
+ expect(response).to redirect_to(spree.cart_path)
44
+ end
45
+
46
+ # Regression test for https://github.com/spree/spree/issues/2280
47
+ it "should redirect to current step trying to access a future step" do
48
+ order.update_column(:state, "address")
49
+ get :edit, params: { state: "delivery" }
50
+ expect(response).to redirect_to spree.checkout_state_path("address")
51
+ end
52
+
53
+ context "when entering the checkout" do
54
+ before do
55
+ # The first step for checkout controller is address
56
+ # Transitioning into this state first is required
57
+ order.update_column(:state, "address")
58
+ end
59
+
60
+ it "should associate the order with a user" do
61
+ order.update_column :user_id, nil
62
+ expect(order).to receive(:associate_user!).with(user)
63
+ get :edit
64
+ end
65
+ end
66
+ end
67
+
68
+ context "#update" do
69
+ it 'should check if the user is authorized for :edit' do
70
+ expect(controller).to receive(:authorize!).with(:edit, order, token)
71
+ request.cookie_jar.signed[:guest_token] = token
72
+ post :update, params: { state: 'address' }
73
+ end
74
+
75
+ context "save successful" do
76
+ def post_address
77
+ post :update, params: {
78
+ state: "address",
79
+ order: {
80
+ bill_address_attributes: address_params,
81
+ use_billing: true
82
+ }
83
+ }
84
+ end
85
+
86
+ let!(:payment_method) { create(:payment_method) }
87
+ before do
88
+ # Must have *a* shipping method and a payment method so updating from address works
89
+ allow(order).to receive_messages ensure_available_shipping_rates: true
90
+ order.line_items << FactoryBot.create(:line_item)
91
+ end
92
+
93
+ context "with the order in the cart state" do
94
+ before do
95
+ order.update_attributes! user: user
96
+ order.update_column(:state, "cart")
97
+ end
98
+
99
+ it "should assign order" do
100
+ post :update, params: { state: "address" }
101
+ expect(assigns[:order]).not_to be_nil
102
+ end
103
+
104
+ it "should advance the state" do
105
+ post_address
106
+ expect(order.reload.state).to eq("delivery")
107
+ end
108
+
109
+ it "should redirect the next state" do
110
+ post_address
111
+ expect(response).to redirect_to spree.checkout_state_path("delivery")
112
+ end
113
+
114
+ context "current_user respond to save address method" do
115
+ it "calls persist order address on user" do
116
+ expect(user).to receive(:persist_order_address)
117
+ post :update, params: {
118
+ state: "address",
119
+ order: {
120
+ bill_address_attributes: address_params,
121
+ use_billing: true
122
+ },
123
+ save_user_address: "1"
124
+ }
125
+ end
126
+ end
127
+
128
+ context "current_user doesnt respond to persist_order_address" do
129
+ it "doesnt raise any error" do
130
+ post :update, params: {
131
+ state: "address",
132
+ order: {
133
+ bill_address_attributes: address_params,
134
+ use_billing: true
135
+ },
136
+ save_user_address: "1"
137
+ }
138
+ end
139
+ end
140
+ end
141
+
142
+ context "with the order in the address state" do
143
+ before do
144
+ order.update_attributes! user: user
145
+ order.update_columns(ship_address_id: create(:address).id, state: "address")
146
+ end
147
+
148
+ context 'landing to address page' do
149
+ it "tries to associate user addresses to order" do
150
+ expect(order).to receive(:assign_default_user_addresses)
151
+ get :edit
152
+ end
153
+ end
154
+
155
+ context "with a billing and shipping address" do
156
+ subject do
157
+ post :update, params: {
158
+ state: "address",
159
+ order: {
160
+ bill_address_attributes: order.bill_address.attributes.except("created_at", "updated_at").compact,
161
+ ship_address_attributes: order.ship_address.attributes.except("created_at", "updated_at").compact,
162
+ use_billing: false
163
+ }
164
+ }
165
+ end
166
+
167
+ it "doesn't change bill address" do
168
+ expect {
169
+ subject
170
+ }.not_to change { order.reload.ship_address.id }
171
+ end
172
+
173
+ it "doesn't change ship address" do
174
+ expect {
175
+ subject
176
+ }.not_to change { order.reload.bill_address.id }
177
+ end
178
+ end
179
+ end
180
+
181
+ # This is the only time that we need the 'set_payment_parameters_amount'
182
+ # controller code, because otherwise the transition to 'confirm' will
183
+ # trigger the 'add_store_credit_payments' transition code which will do
184
+ # the same thing here.
185
+ # Perhaps we can just remove 'set_payment_parameters_amount' entirely at
186
+ # some point?
187
+ context "when there is a checkout step between payment and confirm" do
188
+ before do
189
+ @old_checkout_flow = Spree::Order.checkout_flow
190
+ Spree::Order.class_eval do
191
+ insert_checkout_step :new_step, after: :payment
192
+ end
193
+ end
194
+
195
+ after do
196
+ Spree::Order.checkout_flow(&@old_checkout_flow)
197
+ end
198
+
199
+ let(:order) { create(:order_with_line_items) }
200
+ let(:payment_method) { create(:credit_card_payment_method) }
201
+
202
+ let(:params) do
203
+ {
204
+ state: 'payment',
205
+ order: {
206
+ payments_attributes: [
207
+ {
208
+ payment_method_id: payment_method.id.to_s,
209
+ source_attributes: attributes_for(:credit_card)
210
+ }
211
+ ]
212
+ }
213
+ }
214
+ end
215
+
216
+ before do
217
+ order.update_attributes! user: user
218
+ 3.times { order.next! } # should put us in the payment state
219
+ end
220
+
221
+ it 'sets the payment amount' do
222
+ post :update, params: params
223
+ order.reload
224
+ expect(order.state).to eq('new_step')
225
+ expect(order.payments.size).to eq(1)
226
+ expect(order.payments.first.amount).to eq(order.total)
227
+ end
228
+ end
229
+
230
+ context "when in the payment state" do
231
+ let(:order) { create(:order_with_line_items) }
232
+ let(:payment_method) { create(:credit_card_payment_method) }
233
+
234
+ let(:params) do
235
+ {
236
+ state: 'payment',
237
+ order: {
238
+ payments_attributes: [
239
+ {
240
+ payment_method_id: payment_method.id.to_s,
241
+ source_attributes: attributes_for(:credit_card)
242
+ }
243
+ ]
244
+ }
245
+ }
246
+ end
247
+
248
+ before do
249
+ order.update_attributes! user: user
250
+ 3.times { order.next! } # should put us in the payment state
251
+ end
252
+
253
+ context 'with a permitted payment method' do
254
+ it 'sets the payment amount' do
255
+ post :update, params: params
256
+ order.reload
257
+ expect(order.state).to eq('confirm')
258
+ expect(order.payments.size).to eq(1)
259
+ expect(order.payments.first.amount).to eq(order.total)
260
+ end
261
+ end
262
+
263
+ context 'with an unpermitted payment method' do
264
+ before { payment_method.update!(available_to_users: false) }
265
+
266
+ it 'sets the payment amount' do
267
+ expect {
268
+ post :update, params: params
269
+ }.to raise_error(ActiveRecord::RecordNotFound)
270
+
271
+ expect(order.state).to eq('payment')
272
+ expect(order.payments).to be_empty
273
+ end
274
+ end
275
+ end
276
+
277
+ context "when in the confirm state" do
278
+ before do
279
+ order.update_attributes! user: user
280
+ order.update_column(:state, "confirm")
281
+ # An order requires a payment to reach the complete state
282
+ # This is because payment_required? is true on the order
283
+ create(:payment, amount: order.total, order: order)
284
+ order.create_proposed_shipments
285
+ order.payments.reload
286
+ end
287
+
288
+ # This inadvertently is a regression test for https://github.com/spree/spree/issues/2694
289
+ it "should redirect to the order view" do
290
+ post :update, params: { state: "confirm" }
291
+ expect(response).to redirect_to spree.order_path(order)
292
+ end
293
+
294
+ it "should populate the flash message" do
295
+ post :update, params: { state: "confirm" }
296
+ expect(flash.notice).to eq(I18n.t('spree.order_processed_successfully'))
297
+ end
298
+
299
+ it "should remove completed order from current_order" do
300
+ post :update, params: { state: "confirm" }
301
+ expect(assigns(:current_order)).to be_nil
302
+ expect(assigns(:order)).to eql controller.current_order
303
+ end
304
+ end
305
+ end
306
+
307
+ context "save unsuccessful" do
308
+ before do
309
+ order.update_attributes! user: user
310
+ allow(order).to receive_messages valid?: false
311
+ end
312
+
313
+ it "should not assign order" do
314
+ post :update, params: { state: "address", email: '' }
315
+ expect(assigns[:order]).not_to be_nil
316
+ end
317
+
318
+ it "should not change the order state" do
319
+ post :update, params: { state: 'address' }
320
+ end
321
+
322
+ it "should render the edit template" do
323
+ post :update, params: { state: 'address' }
324
+ expect(response).to render_template :edit
325
+ end
326
+ end
327
+
328
+ context "when current_order is nil" do
329
+ before { allow(controller).to receive_messages current_order: nil }
330
+
331
+ it "should not change the state if order is completed" do
332
+ expect(order).not_to receive(:update_attribute)
333
+ post :update, params: { state: "confirm" }
334
+ end
335
+
336
+ it "should redirect to the cart_path" do
337
+ post :update, params: { state: "confirm" }
338
+ expect(response).to redirect_to spree.cart_path
339
+ end
340
+ end
341
+
342
+ context "Spree::Core::GatewayError" do
343
+ before do
344
+ order.update_attributes! user: user
345
+ allow(order).to receive(:next).and_raise(Spree::Core::GatewayError.new("Invalid something or other."))
346
+ post :update, params: { state: "address" }
347
+ end
348
+
349
+ it "should render the edit template and display exception message" do
350
+ expect(response).to render_template :edit
351
+ expect(flash.now[:error]).to eq(I18n.t('spree.spree_gateway_error_flash_for_checkout'))
352
+ expect(assigns(:order).errors[:base]).to include("Invalid something or other.")
353
+ end
354
+ end
355
+
356
+ context "fails to transition from address" do
357
+ let(:order) do
358
+ FactoryBot.create(:order_with_line_items).tap do |order|
359
+ order.next!
360
+ expect(order.state).to eq('address')
361
+ end
362
+ end
363
+
364
+ before do
365
+ allow(controller).to receive_messages current_order: order
366
+ allow(controller).to receive_messages check_authorization: true
367
+ end
368
+
369
+ context "when the order is invalid" do
370
+ before do
371
+ allow(order).to receive_messages valid?: true, next: nil
372
+ order.errors.add :base, 'Base error'
373
+ order.errors.add :adjustments, 'error'
374
+ end
375
+
376
+ it "due to the order having errors" do
377
+ put :update, params: { state: order.state, order: {} }
378
+ expect(flash[:error]).to eq("Base error\nAdjustments error")
379
+ expect(response).to redirect_to(spree.checkout_state_path('address'))
380
+ end
381
+ end
382
+
383
+ context "when the country is not a shippable country" do
384
+ let(:foreign_address) { create(:address, country_iso_code: "CA") }
385
+
386
+ before do
387
+ order.update(shipping_address: foreign_address)
388
+ end
389
+
390
+ it "due to no available shipping rates for any of the shipments" do
391
+ put :update, params: { state: "address", order: {} }
392
+ expect(flash[:error]).to eq(I18n.t('spree.items_cannot_be_shipped'))
393
+ expect(response).to redirect_to(spree.checkout_state_path('address'))
394
+ end
395
+ end
396
+ end
397
+
398
+ context "when GatewayError is raised" do
399
+ let(:order) do
400
+ FactoryBot.create(:order_with_line_items).tap do |order|
401
+ until order.state == 'payment'
402
+ order.next!
403
+ end
404
+ # So that the confirmation step is skipped and we get straight to the action.
405
+ payment_method = FactoryBot.create(:simple_credit_card_payment_method)
406
+ payment = FactoryBot.create(:payment, payment_method: payment_method, amount: order.total)
407
+ order.payments << payment
408
+ order.next!
409
+ end
410
+ end
411
+
412
+ before do
413
+ allow(controller).to receive_messages current_order: order
414
+ allow(controller).to receive_messages check_authorization: true
415
+ end
416
+
417
+ it "fails to transition from payment to complete" do
418
+ allow_any_instance_of(Spree::Payment).to receive(:process!).and_raise(Spree::Core::GatewayError.new(I18n.t('spree.payment_processing_failed')))
419
+ put :update, params: { state: order.state, order: {} }
420
+ expect(flash[:error]).to eq(I18n.t('spree.payment_processing_failed'))
421
+ end
422
+ end
423
+ end
424
+
425
+ context "When last inventory item has been purchased" do
426
+ let(:product) { mock_model(Spree::Product, name: "Amazing Object") }
427
+ let(:variant) { mock_model(Spree::Variant) }
428
+ let(:line_item) { mock_model Spree::LineItem, insufficient_stock?: true, amount: 0, name: "Amazing Item" }
429
+ let(:order) { create(:order) }
430
+
431
+ before do
432
+ allow(order).to receive_messages(line_items: [line_item], state: "payment")
433
+
434
+ configure_spree_preferences do |config|
435
+ config.track_inventory_levels = true
436
+ end
437
+ end
438
+
439
+ context "and back orders are not allowed" do
440
+ before do
441
+ post :update, params: { state: "payment" }
442
+ end
443
+
444
+ it "should redirect to cart" do
445
+ expect(response).to redirect_to spree.cart_path
446
+ end
447
+
448
+ it "should set flash message for no inventory" do
449
+ expect(flash[:error]).to eq("Amazing Item became unavailable.")
450
+ end
451
+ end
452
+ end
453
+
454
+ context "order doesn't have a delivery step" do
455
+ before do
456
+ allow(order).to receive_messages(checkout_steps: ["cart", "address", "payment"])
457
+ allow(order).to receive_messages state: "address"
458
+ allow(controller).to receive_messages check_authorization: true
459
+ end
460
+
461
+ it "doesn't set shipping address on the order" do
462
+ expect(order).to_not receive(:ship_address=)
463
+ post :update, params: { state: order.state }
464
+ end
465
+
466
+ it "doesn't remove unshippable items before payment" do
467
+ expect {
468
+ post :update, params: { state: "payment" }
469
+ }.to_not change { order.line_items }
470
+ end
471
+ end
472
+
473
+ it "does remove unshippable items before payment" do
474
+ allow(order).to receive_messages payment_required?: true
475
+ allow(controller).to receive_messages check_authorization: true
476
+
477
+ expect {
478
+ post :update, params: { state: "payment" }
479
+ }.to change { order.line_items.to_a.size }.from(1).to(0)
480
+ end
481
+
482
+ context 'trying to apply a coupon code' do
483
+ let(:order) { create(:order_with_line_items, state: 'payment', guest_token: 'a token') }
484
+ let(:coupon_code) { "coupon_code" }
485
+
486
+ before { cookies.signed[:guest_token] = order.guest_token }
487
+
488
+ context "when coupon code is empty" do
489
+ let(:coupon_code) { "" }
490
+
491
+ it 'does not try to apply coupon code' do
492
+ expect(Spree::PromotionHandler::Coupon).not_to receive :new
493
+
494
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
495
+
496
+ expect(response).to redirect_to(spree.checkout_state_path('confirm'))
497
+ end
498
+ end
499
+
500
+ context "when coupon code is applied" do
501
+ let(:promotion_handler) { instance_double('Spree::PromotionHandler::Coupon', error: nil, success: 'Coupon Applied!') }
502
+
503
+ it "continues checkout flow normally" do
504
+ expect(Spree::PromotionHandler::Coupon)
505
+ .to receive_message_chain(:new, :apply)
506
+ .and_return(promotion_handler)
507
+
508
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
509
+
510
+ expect(response).to render_template :edit
511
+ expect(flash.now[:success]).to eq('Coupon Applied!')
512
+ end
513
+
514
+ context "when coupon code is not applied" do
515
+ let(:promotion_handler) { instance_double('Spree::PromotionHandler::Coupon', error: 'Some error', success: false) }
516
+
517
+ it "setups the current step correctly before rendering" do
518
+ expect(Spree::PromotionHandler::Coupon)
519
+ .to receive_message_chain(:new, :apply)
520
+ .and_return(promotion_handler)
521
+ expect(controller).to receive(:setup_for_current_state)
522
+
523
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
524
+ end
525
+
526
+ it "render cart with coupon error" do
527
+ expect(Spree::PromotionHandler::Coupon)
528
+ .to receive_message_chain(:new, :apply)
529
+ .and_return(promotion_handler)
530
+
531
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
532
+
533
+ expect(response).to render_template :edit
534
+ expect(flash.now[:error]).to eq('Some error')
535
+ end
536
+ end
537
+ end
538
+ end
539
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ # This spec is useful for when we just want to make sure a view is rendering correctly
6
+ # Walking through the entire checkout process is rather tedious, don't you think?
7
+ describe Spree::CheckoutController, type: :controller do
8
+ render_views
9
+ let(:token) { 'some_token' }
10
+ let(:user) { stub_model(Spree::LegacyUser) }
11
+
12
+ before do
13
+ allow(controller).to receive_messages try_spree_current_user: user
14
+ end
15
+
16
+ # Regression test for https://github.com/spree/spree/issues/3246
17
+ context "when using GBP" do
18
+ before do
19
+ Spree::Config[:currency] = "GBP"
20
+ end
21
+
22
+ context "when order is in delivery" do
23
+ before do
24
+ # Using a let block won't acknowledge the currency setting
25
+ # Therefore we just do it like this...
26
+ order = Spree::TestingSupport::OrderWalkthrough.up_to(:address)
27
+ allow(controller).to receive_messages current_order: order
28
+ end
29
+
30
+ it "displays rate cost in correct currency" do
31
+ get :edit
32
+ html = Nokogiri::HTML(response.body)
33
+ expect(html.css('.rate-cost').text).to eq "£10.00"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ describe Spree::ContentController, type: :controller do
5
+ it "should display CVV page" do
6
+ get :cvv
7
+ expect(response.response_code).to eq(200)
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'current order tracking', type: :controller do
6
+ let!(:store) { create(:store) }
7
+ let(:user) { create(:user) }
8
+
9
+ controller(Spree::StoreController) do
10
+ def index
11
+ head :ok
12
+ end
13
+ end
14
+
15
+ let(:order) { FactoryBot.create(:order) }
16
+
17
+ it 'automatically tracks who the order was created by & IP address' do
18
+ allow(controller).to receive_messages(try_spree_current_user: user)
19
+ get :index
20
+ expect(controller.current_order(create_order_if_necessary: true).created_by).to eq controller.try_spree_current_user
21
+ expect(controller.current_order.last_ip_address).to eq "0.0.0.0"
22
+ end
23
+
24
+ context "current order creation" do
25
+ before { allow(controller).to receive_messages(try_spree_current_user: user) }
26
+
27
+ it "doesn't create a new order out of the blue" do
28
+ expect {
29
+ get :index
30
+ }.not_to change { Spree::Order.count }
31
+ end
32
+ end
33
+ end
34
+
35
+ describe Spree::OrdersController, type: :controller do
36
+ let(:user) { create(:user) }
37
+
38
+ before { allow(controller).to receive_messages(try_spree_current_user: user) }
39
+
40
+ describe Spree::OrdersController do
41
+ it "doesn't create a new order out of the blue" do
42
+ expect {
43
+ get :edit
44
+ }.not_to change { Spree::Order.count }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::HomeController, type: :controller do
6
+ it "provides current user to the searcher class" do
7
+ user = mock_model(Spree.user_class, last_incomplete_spree_order: nil)
8
+ allow(controller).to receive_messages try_spree_current_user: user
9
+ expect_any_instance_of(Spree::Config.searcher_class).to receive(:current_user=).with(user)
10
+ get :index
11
+ expect(response.status).to eq(200)
12
+ end
13
+
14
+ context "layout" do
15
+ it "renders default layout" do
16
+ get :index
17
+ expect(response).to render_template(layout: 'spree/layouts/spree_application')
18
+ end
19
+
20
+ context "different layout specified in config" do
21
+ before { Spree::Config.layout = 'layouts/application' }
22
+
23
+ it "renders specified layout" do
24
+ get :index
25
+ expect(response).to render_template(layout: 'layouts/application')
26
+ end
27
+ end
28
+ end
29
+ end