solidus_frontend_devise_token_auth 2.8.0.alpha.2

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 (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