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,690 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Checkout", type: :feature, inaccessible: true do
6
+ include_context 'checkout setup'
7
+
8
+ context "visitor makes checkout as guest without registration" do
9
+ before(:each) do
10
+ stock_location.stock_items.update_all(count_on_hand: 1)
11
+ end
12
+
13
+ context "defaults to use billing address" do
14
+ before do
15
+ add_mug_to_cart
16
+ Spree::Order.last.update_column(:email, "test@example.com")
17
+ click_button "Checkout"
18
+ end
19
+
20
+ it "should default checkbox to checked", inaccessible: true do
21
+ expect(find('input#order_use_billing')).to be_checked
22
+ end
23
+
24
+ it "should remain checked when used and visitor steps back to address step", js: true do
25
+ fill_in_address
26
+ expect(find('input#order_use_billing')).to be_checked
27
+ end
28
+ end
29
+
30
+ # Regression test for https://github.com/spree/spree/issues/4079
31
+ context "persists state when on address page" do
32
+ before do
33
+ add_mug_to_cart
34
+ click_button "Checkout"
35
+ end
36
+
37
+ specify do
38
+ expect(Spree::Order.count).to eq(1)
39
+ expect(Spree::Order.last.state).to eq("address")
40
+ end
41
+ end
42
+
43
+ # Regression test for https://github.com/spree/spree/issues/1596
44
+ context "full checkout" do
45
+ before do
46
+ shipping_method.calculator.update!(preferred_amount: 10)
47
+ mug.shipping_category = shipping_method.shipping_categories.first
48
+ mug.save!
49
+ end
50
+
51
+ it "does not break the per-item shipping method calculator", js: true do
52
+ add_mug_to_cart
53
+ click_button "Checkout"
54
+
55
+ fill_in "order_email", with: "test@example.com"
56
+ fill_in_address
57
+
58
+ click_button "Save and Continue"
59
+ expect(page).not_to have_content("undefined method `promotion'")
60
+ click_button "Save and Continue"
61
+ expect(page).to have_content("Shipping total: $10.00")
62
+ end
63
+ end
64
+
65
+ # Regression test for https://github.com/spree/spree/issues/4306
66
+ context "free shipping" do
67
+ before do
68
+ add_mug_to_cart
69
+ click_button "Checkout"
70
+ end
71
+
72
+ it "should not show 'Free Shipping' when there are no shipments" do
73
+ within("#checkout-summary") do
74
+ expect(page).to_not have_content('Free Shipping')
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ context "displays default user addresses on address step" do
81
+ before do
82
+ stock_location.stock_items.update_all(count_on_hand: 1)
83
+ end
84
+
85
+ context "when user is logged in" do
86
+ let!(:user) do
87
+ create(:user, bill_address: saved_bill_address, ship_address: saved_ship_address)
88
+ end
89
+
90
+ let!(:order) do
91
+ order = Spree::Order.create!(
92
+ email: "spree@example.com",
93
+ store: Spree::Store.first || FactoryBot.create(:store)
94
+ )
95
+
96
+ order.reload
97
+ order.user = user
98
+ order.recalculate
99
+ order
100
+ end
101
+
102
+ before do
103
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
104
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
105
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
106
+
107
+ add_mug_to_cart
108
+ click_button "Checkout"
109
+ # We need an order reload here to get newly associated addresses.
110
+ # Then we go back to address where we are supposed to be redirected.
111
+ order.reload
112
+ visit spree.checkout_state_path(:address)
113
+ end
114
+
115
+ context "when user has default addresses saved" do
116
+ let(:saved_bill_address) { create(:address, firstname: 'Bill') }
117
+ let(:saved_ship_address) { create(:address, firstname: 'Steve') }
118
+
119
+ it "shows the saved addresses" do
120
+ within("#billing") do
121
+ expect(find_field('First Name').value).to eq 'Bill'
122
+ end
123
+
124
+ within("#shipping") do
125
+ expect(find_field('First Name').value).to eq 'Steve'
126
+ end
127
+ end
128
+ end
129
+
130
+ context "when user does not have default addresses saved" do
131
+ let(:saved_bill_address) { nil }
132
+ let(:saved_ship_address) { nil }
133
+
134
+ it 'shows an empty address' do
135
+ within("#billing") do
136
+ expect(find_field('First Name').value).to be_nil
137
+ end
138
+
139
+ within("#shipping") do
140
+ expect(find_field('First Name').value).to be_nil
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ context "when user is not logged in" do
147
+ context "and proceeds with guest checkout" do
148
+ it 'shows empty addresses' do
149
+ add_mug_to_cart
150
+ click_button "Checkout"
151
+
152
+ within("#billing") do
153
+ expect(find_field('First Name').value).to be_nil
154
+ end
155
+
156
+ within("#shipping") do
157
+ expect(find_field('First Name').value).to be_nil
158
+ end
159
+ end
160
+ end
161
+
162
+ context "and proceeds logging in" do
163
+ let!(:user) do
164
+ create(:user, bill_address: saved_bill_address, ship_address: saved_ship_address)
165
+ end
166
+
167
+ before do
168
+ add_mug_to_cart
169
+ click_button "Checkout"
170
+
171
+ # Simulate user login
172
+ Spree::Order.last.associate_user!(user)
173
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
174
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
175
+
176
+ # Simulate redirect back to address after login
177
+ visit spree.checkout_state_path(:address)
178
+ end
179
+
180
+ context "when does not have saved addresses" do
181
+ let(:saved_bill_address) { nil }
182
+ let(:saved_ship_address) { nil }
183
+
184
+ it 'shows empty addresses' do
185
+ within("#billing") do
186
+ expect(find_field('First Name').value).to be_nil
187
+ end
188
+
189
+ within("#shipping") do
190
+ expect(find_field('First Name').value).to be_nil
191
+ end
192
+ end
193
+ end
194
+
195
+ # Regression test for https://github.com/solidusio/solidus/issues/1811
196
+ context "when does have saved addresses" do
197
+ let(:saved_bill_address) { create(:address, firstname: 'Bill') }
198
+ let(:saved_ship_address) { create(:address, firstname: 'Steve') }
199
+
200
+ it 'shows empty addresses' do
201
+ within("#billing") do
202
+ expect(find_field('First Name').value).to eq 'Bill'
203
+ end
204
+
205
+ within("#shipping") do
206
+ expect(find_field('First Name').value).to eq 'Steve'
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ # Regression test for https://github.com/spree/spree/issues/2694 and https://github.com/spree/spree/issues/4117
215
+ context "doesn't allow bad credit card numbers" do
216
+ let!(:payment_method) { create(:credit_card_payment_method) }
217
+ before(:each) do
218
+ order = Spree::TestingSupport::OrderWalkthrough.up_to(:delivery)
219
+
220
+ user = create(:user)
221
+ order.user = user
222
+ order.recalculate
223
+
224
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
225
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
226
+ end
227
+
228
+ it "redirects to payment page", inaccessible: true do
229
+ visit spree.checkout_state_path(:delivery)
230
+ click_button "Save and Continue"
231
+ choose "Credit Card"
232
+ fill_in "Card Number", with: '123'
233
+ fill_in "card_expiry", with: '04 / 20'
234
+ fill_in "Card Code", with: '123'
235
+ click_button "Save and Continue"
236
+ click_button "Place Order"
237
+ expect(page).to have_content("Bogus Gateway: Forced failure")
238
+ expect(page.current_url).to include("/checkout/payment")
239
+ end
240
+ end
241
+
242
+ context "and likes to double click buttons" do
243
+ let!(:user) { create(:user) }
244
+
245
+ let!(:order) do
246
+ order = Spree::TestingSupport::OrderWalkthrough.up_to(:delivery)
247
+
248
+ order.reload
249
+ order.user = user
250
+ order.recalculate
251
+ order
252
+ end
253
+
254
+ before(:each) do
255
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
256
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
257
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(skip_state_validation?: true)
258
+ end
259
+
260
+ it "prevents double clicking the payment button on checkout", js: true do
261
+ visit spree.checkout_state_path(:payment)
262
+
263
+ # prevent form submit to verify button is disabled
264
+ page.execute_script("$('#checkout_form_payment').submit(function(){return false;})")
265
+
266
+ expect(page).not_to have_selector('input.button[disabled]')
267
+ click_button "Save and Continue"
268
+ expect(page).to have_selector('input.button[disabled]')
269
+ end
270
+
271
+ it "prevents double clicking the confirm button on checkout", js: true do
272
+ order.payments << create(:payment)
273
+ visit spree.checkout_state_path(:confirm)
274
+
275
+ # prevent form submit to verify button is disabled
276
+ page.execute_script("$('#checkout_form_confirm').submit(function(){return false;})")
277
+
278
+ expect(page).not_to have_selector('input.button[disabled]')
279
+ click_button "Place Order"
280
+ expect(page).to have_selector('input.button[disabled]')
281
+ end
282
+ end
283
+
284
+ context "when several payment methods are available" do
285
+ let(:credit_cart_payment) { create(:credit_card_payment_method) }
286
+ let(:check_payment) { create(:check_payment_method) }
287
+
288
+ after do
289
+ Capybara.ignore_hidden_elements = true
290
+ end
291
+
292
+ before do
293
+ Capybara.ignore_hidden_elements = false
294
+ order = Spree::TestingSupport::OrderWalkthrough.up_to(:delivery)
295
+ allow(order).to receive_messages(available_payment_methods: [check_payment, credit_cart_payment])
296
+ order.user = create(:user)
297
+ order.recalculate
298
+
299
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
300
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: order.user)
301
+
302
+ visit spree.checkout_state_path(:payment)
303
+ end
304
+
305
+ it "the first payment method should be selected", js: true do
306
+ payment_method_css = "#order_payments_attributes__payment_method_id_"
307
+ expect(find("#{payment_method_css}#{check_payment.id}")).to be_checked
308
+ expect(find("#{payment_method_css}#{credit_cart_payment.id}")).not_to be_checked
309
+ end
310
+
311
+ it "the fields for the other payment methods should be hidden", js: true do
312
+ payment_method_css = "#payment_method_"
313
+ expect(find("#{payment_method_css}#{check_payment.id}")).to be_visible
314
+ expect(find("#{payment_method_css}#{credit_cart_payment.id}")).not_to be_visible
315
+ end
316
+ end
317
+
318
+ context "user has payment sources", js: true do
319
+ before { Spree::PaymentMethod.all.each(&:really_destroy!) }
320
+ let!(:bogus) { create(:credit_card_payment_method) }
321
+ let(:user) { create(:user) }
322
+
323
+ let!(:credit_card) do
324
+ create(:credit_card, user_id: user.id, payment_method: bogus, gateway_customer_profile_id: "BGS-WEFWF")
325
+ end
326
+
327
+ before do
328
+ user.wallet.add(credit_card)
329
+ order = Spree::TestingSupport::OrderWalkthrough.up_to(:delivery)
330
+
331
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
332
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
333
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
334
+
335
+ visit spree.checkout_state_path(:payment)
336
+ end
337
+
338
+ it "selects first source available and customer moves on" do
339
+ expect(find("#use_existing_card_yes")).to be_checked
340
+
341
+ expect {
342
+ click_on "Save and Continue"
343
+ }.not_to change { Spree::CreditCard.count }
344
+
345
+ click_on "Place Order"
346
+ expect(page).to have_current_path(spree.order_path(Spree::Order.last))
347
+ end
348
+
349
+ it "allows user to enter a new source" do
350
+ choose "use_existing_card_no"
351
+
352
+ fill_in "Name on card", with: 'Spree Commerce'
353
+ fill_in_with_force "Card Number", with: '4111 1111 1111 1111'
354
+ fill_in "card_expiry", with: '04 / 20'
355
+ fill_in "Card Code", with: '123'
356
+
357
+ expect {
358
+ click_on "Save and Continue"
359
+ }.to change { Spree::CreditCard.count }.by 1
360
+
361
+ expect(Spree::CreditCard.last.address).to be_present
362
+
363
+ click_on "Place Order"
364
+ expect(page).to have_current_path(spree.order_path(Spree::Order.last))
365
+ end
366
+ end
367
+
368
+ # regression for https://github.com/spree/spree/issues/2921
369
+ context "goes back from payment to add another item", js: true do
370
+ let!(:store) { FactoryBot.create(:store) }
371
+ let!(:bag) { create(:product, name: "RoR Bag") }
372
+
373
+ it "transit nicely through checkout steps again" do
374
+ add_mug_to_cart
375
+ click_on "Checkout"
376
+ fill_in "order_email", with: "test@example.com"
377
+ fill_in_address
378
+ click_on "Save and Continue"
379
+ click_on "Save and Continue"
380
+ expect(page).to have_current_path(spree.checkout_state_path("payment"))
381
+
382
+ visit spree.root_path
383
+ click_link bag.name
384
+ click_button "add-to-cart-button"
385
+
386
+ click_on "Checkout"
387
+ # edit an address field
388
+ fill_in "order_bill_address_attributes_firstname", with: "Ryann"
389
+ click_on "Save and Continue"
390
+ click_on "Save and Continue"
391
+ click_on "Save and Continue"
392
+ click_on "Place Order"
393
+
394
+ expect(page).to have_current_path(spree.order_path(Spree::Order.last))
395
+ end
396
+ end
397
+
398
+ context "from payment step customer goes back to cart", js: true do
399
+ before do
400
+ add_mug_to_cart
401
+ click_on "Checkout"
402
+ fill_in "order_email", with: "test@example.com"
403
+ fill_in_address
404
+ click_on "Save and Continue"
405
+ click_on "Save and Continue"
406
+ expect(page).to have_current_path(spree.checkout_state_path("payment"))
407
+ end
408
+
409
+ context "and updates line item quantity and try to reach payment page" do
410
+ before do
411
+ visit spree.cart_path
412
+ within ".cart-item-quantity" do
413
+ fill_in first("input")["name"], with: 3
414
+ end
415
+
416
+ click_on "Update"
417
+ end
418
+
419
+ it "redirects user back to address step" do
420
+ visit spree.checkout_state_path("payment")
421
+ expect(page).to have_current_path(spree.checkout_state_path("address"))
422
+ end
423
+
424
+ it "updates shipments properly through step address -> delivery transitions" do
425
+ visit spree.checkout_state_path("payment")
426
+ click_on "Save and Continue"
427
+ click_on "Save and Continue"
428
+
429
+ expect(Spree::InventoryUnit.count).to eq 3
430
+ end
431
+ end
432
+
433
+ context "and adds new product to cart and try to reach payment page" do
434
+ let!(:bag) { create(:product, name: "RoR Bag") }
435
+
436
+ before do
437
+ visit spree.root_path
438
+ click_link bag.name
439
+ click_button "add-to-cart-button"
440
+ end
441
+
442
+ it "redirects user back to address step" do
443
+ visit spree.checkout_state_path("payment")
444
+ expect(page).to have_current_path(spree.checkout_state_path("address"))
445
+ end
446
+
447
+ it "updates shipments properly through step address -> delivery transitions" do
448
+ visit spree.checkout_state_path("payment")
449
+ click_on "Save and Continue"
450
+ click_on "Save and Continue"
451
+
452
+ expect(Spree::InventoryUnit.count).to eq 2
453
+ end
454
+ end
455
+ end
456
+
457
+ context "Coupon promotions", js: true do
458
+ let!(:promotion) { create(:promotion, name: "Huhuhu", code: "huhu") }
459
+ let!(:calculator) { Spree::Calculator::FlatPercentItemTotal.create(preferred_flat_percent: "10") }
460
+ let!(:action) { Spree::Promotion::Actions::CreateItemAdjustments.create(calculator: calculator) }
461
+
462
+ before do
463
+ promotion.actions << action
464
+
465
+ add_mug_to_cart
466
+ click_on "Checkout"
467
+
468
+ fill_in "order_email", with: "test@example.com"
469
+ fill_in_address
470
+ click_on "Save and Continue"
471
+
472
+ click_on "Save and Continue"
473
+ expect(page).to have_current_path(spree.checkout_state_path("payment"))
474
+ end
475
+
476
+ it "applies them & refreshes the page on user clicking the Apply Code button" do
477
+ fill_in "Coupon Code", with: promotion.codes.first.value
478
+ click_on "Apply Code"
479
+
480
+ expect(page).to have_content(promotion.name)
481
+ expect(page).to have_content("-$2.00")
482
+ end
483
+
484
+ context "with invalid coupon" do
485
+ it "doesnt apply the promotion" do
486
+ fill_in "Coupon Code", with: 'invalid'
487
+ click_on "Apply Code"
488
+
489
+ expect(page).to have_content(I18n.t('spree.coupon_code_not_found'))
490
+ end
491
+ end
492
+
493
+ context "doesn't fill in coupon code input" do
494
+ it "advances just fine" do
495
+ click_on "Save and Continue"
496
+ expect(page).to have_current_path(spree.checkout_state_path("confirm"))
497
+ end
498
+ end
499
+ end
500
+
501
+ context "order has only payment step" do
502
+ before do
503
+ create(:credit_card_payment_method)
504
+ @old_checkout_flow = Spree::Order.checkout_flow
505
+ Spree::Order.class_eval do
506
+ checkout_flow do
507
+ go_to_state :payment
508
+ go_to_state :confirm
509
+ end
510
+ end
511
+
512
+ allow_any_instance_of(Spree::Order).to receive_messages email: "spree@commerce.com"
513
+
514
+ add_mug_to_cart
515
+ click_on "Checkout"
516
+ end
517
+
518
+ after do
519
+ Spree::Order.checkout_flow(&@old_checkout_flow)
520
+ end
521
+
522
+ it "goes right payment step and place order just fine" do
523
+ expect(page).to have_current_path(spree.checkout_state_path('payment'))
524
+
525
+ choose "Credit Card"
526
+ fill_in "Name on card", with: 'Spree Commerce'
527
+ fill_in "Card Number", with: '4111 1111 1111 1111'
528
+ fill_in "card_expiry", with: '04 / 20'
529
+ fill_in "Card Code", with: '123'
530
+ click_button "Save and Continue"
531
+
532
+ expect(current_path).to eq spree.checkout_state_path('confirm')
533
+ click_button "Place Order"
534
+ end
535
+ end
536
+
537
+ context "save my address" do
538
+ before do
539
+ stock_location.stock_items.update_all(count_on_hand: 1)
540
+ add_mug_to_cart
541
+ end
542
+
543
+ context 'as a guest' do
544
+ before do
545
+ Spree::Order.last.update_column(:email, "test@example.com")
546
+ click_button "Checkout"
547
+ end
548
+
549
+ it 'should not be displayed' do
550
+ expect(page).to_not have_css("[data-hook=save_user_address]")
551
+ end
552
+ end
553
+
554
+ context 'as a User' do
555
+ before do
556
+ user = create(:user)
557
+ Spree::Order.last.update_column :user_id, user.id
558
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
559
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
560
+ click_button "Checkout"
561
+ end
562
+
563
+ it 'should be displayed' do
564
+ expect(page).to have_css("[data-hook=save_user_address]")
565
+ end
566
+ end
567
+ end
568
+
569
+ context "when order is completed" do
570
+ let!(:user) { create(:user) }
571
+ let!(:order) { Spree::TestingSupport::OrderWalkthrough.up_to(:delivery) }
572
+
573
+ before(:each) do
574
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
575
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
576
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
577
+
578
+ visit spree.checkout_state_path(:delivery)
579
+ click_button "Save and Continue"
580
+ click_button "Save and Continue"
581
+ click_button "Place Order"
582
+ end
583
+
584
+ it "displays a thank you message" do
585
+ expect(page).to have_content(I18n.t('spree.thank_you_for_your_order'))
586
+ end
587
+
588
+ it "does not display a thank you message on that order future visits" do
589
+ visit spree.order_path(order)
590
+ expect(page).to_not have_content(I18n.t('spree.thank_you_for_your_order'))
591
+ end
592
+ end
593
+
594
+ context "with attempted XSS", js: true do
595
+ shared_examples "safe from XSS" do
596
+ # We need a country with states required but no states so that we have
597
+ # access to the state_name input
598
+ let!(:canada) { create(:country, name: 'Canada', iso: "CA", states_required: true) }
599
+ before do
600
+ canada.states.destroy_all
601
+ zone.members.create!(zoneable: canada)
602
+ end
603
+
604
+ it "displays the entered state name without evaluating" do
605
+ add_mug_to_cart
606
+ visit spree.checkout_state_path(:address)
607
+ fill_in_address
608
+
609
+ state_name_css = "order_bill_address_attributes_state_name"
610
+
611
+ select "Canada", from: "order_bill_address_attributes_country_id"
612
+ fill_in 'Customer E-Mail', with: 'test@example.com'
613
+ fill_in state_name_css, with: xss_string
614
+ fill_in "Zip", with: "H0H0H0"
615
+
616
+ click_on 'Save and Continue'
617
+ visit spree.checkout_state_path(:address)
618
+
619
+ expect(page).to have_field(state_name_css, with: xss_string)
620
+ end
621
+ end
622
+
623
+ let(:xss_string) { %(<script>throw("XSS")</script>) }
624
+ include_examples "safe from XSS"
625
+
626
+ context "escaped XSS string" do
627
+ let(:xss_string) { '\x27\x3e\x3cscript\x3ethrow(\x27XSS\x27)\x3c/script\x3e' }
628
+ include_examples "safe from XSS"
629
+ end
630
+ end
631
+
632
+ context "using credit card" do
633
+ let!(:payment_method) { create(:credit_card_payment_method) }
634
+
635
+ # Regression test for https://github.com/solidusio/solidus/issues/1421
636
+ it "works with card number 1", js: true do
637
+ add_mug_to_cart
638
+
639
+ click_on "Checkout"
640
+ fill_in "order_email", with: "test@example.com"
641
+ fill_in_address
642
+ click_on "Save and Continue"
643
+ click_on "Save and Continue"
644
+
645
+ fill_in_credit_card(number: "1")
646
+ click_on "Save and Continue"
647
+
648
+ expect(page).to have_current_path("/checkout/confirm")
649
+ end
650
+
651
+ it "works with card number 4111111111111111", js: true do
652
+ add_mug_to_cart
653
+
654
+ click_on "Checkout"
655
+ fill_in "order_email", with: "test@example.com"
656
+ fill_in_address
657
+ click_on "Save and Continue"
658
+ click_on "Save and Continue"
659
+
660
+ fill_in_credit_card(number: "4111 1111 1111 1111")
661
+ click_on "Save and Continue"
662
+
663
+ expect(page).to have_current_path("/checkout/confirm")
664
+ end
665
+ end
666
+
667
+ def fill_in_credit_card(number:)
668
+ fill_in "Card Number", with: number
669
+ fill_in "Expiration", with: "12 / 24"
670
+ fill_in "Card Code", with: "123"
671
+ end
672
+
673
+ def fill_in_address
674
+ address = "order_bill_address_attributes"
675
+ fill_in "#{address}_firstname", with: "Ryan"
676
+ fill_in "#{address}_lastname", with: "Bigg"
677
+ fill_in "#{address}_address1", with: "143 Swan Street"
678
+ fill_in "#{address}_city", with: "Richmond"
679
+ select "United States of America", from: "#{address}_country_id"
680
+ select "Alabama", from: "#{address}_state_id"
681
+ fill_in "#{address}_zipcode", with: "12345"
682
+ fill_in "#{address}_phone", with: "(555) 555-5555"
683
+ end
684
+
685
+ def add_mug_to_cart
686
+ visit spree.root_path
687
+ click_link mug.name
688
+ click_button "add-to-cart-button"
689
+ end
690
+ end