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,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Spree
6
+ describe OrdersController, type: :controller do
7
+ ORDER_TOKEN = 'ORDER_TOKEN'
8
+
9
+ let!(:store) { create(:store) }
10
+ let(:user) { create(:user) }
11
+ let(:guest_user) { create(:user) }
12
+ let(:order) { Spree::Order.create }
13
+ let(:variant) { create(:variant) }
14
+
15
+ it 'should understand order routes with token' do
16
+ expect(spree.token_order_path('R123456', 'ABCDEF')).to eq('/orders/R123456/token/ABCDEF')
17
+ end
18
+
19
+ context 'when an order exists in the cookies.signed' do
20
+ let(:token) { 'some_token' }
21
+
22
+ before do
23
+ allow(controller).to receive_messages current_order: order
24
+ allow(controller).to receive_messages spree_current_user: user
25
+ end
26
+
27
+ context '#populate' do
28
+ it 'should check if user is authorized for :update' do
29
+ expect(controller).to receive(:authorize!).with(:update, order, token)
30
+ post :populate, params: { variant_id: variant.id, token: token }
31
+ end
32
+ end
33
+
34
+ context '#edit' do
35
+ it 'should check if user is authorized for :read' do
36
+ expect(controller).to receive(:authorize!).with(:read, order, token)
37
+ get :edit, params: { token: token }
38
+ end
39
+ end
40
+
41
+ context '#update' do
42
+ it 'should check if user is authorized for :update' do
43
+ allow(order).to receive :update_attributes
44
+ expect(controller).to receive(:authorize!).with(:update, order, token)
45
+ post :update, params: { order: { email: "foo@bar.com" }, token: token }
46
+ end
47
+ end
48
+
49
+ context '#empty' do
50
+ it 'should check if user is authorized for :update' do
51
+ expect(controller).to receive(:authorize!).with(:update, order, token)
52
+ post :empty, params: { token: token }
53
+ end
54
+ end
55
+
56
+ context "#show" do
57
+ let(:specified_order) { create(:order) }
58
+
59
+ it "should check against the specified order" do
60
+ expect(controller).to receive(:authorize!).with(:read, specified_order, token)
61
+ get :show, params: { id: specified_order.number, token: token }
62
+ end
63
+ end
64
+ end
65
+
66
+ context 'when no authenticated user' do
67
+ let(:order) { create(:order, number: 'R123') }
68
+
69
+ context '#show' do
70
+ context 'when token parameter present' do
71
+ it 'always ooverride existing token when passing a new one' do
72
+ cookies.signed[:guest_token] = "soo wrong"
73
+ get :show, params: { id: 'R123', token: order.guest_token }
74
+ expect(cookies.signed[:guest_token]).to eq(order.guest_token)
75
+ end
76
+
77
+ it 'should store as guest_token in session' do
78
+ get :show, params: { id: 'R123', token: order.guest_token }
79
+ expect(cookies.signed[:guest_token]).to eq(order.guest_token)
80
+ end
81
+ end
82
+
83
+ context 'when no token present' do
84
+ it 'should respond with 404' do
85
+ expect {
86
+ get :show, params: { id: 'R123' }
87
+ }.to raise_error(ActiveRecord::RecordNotFound)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::OrdersController, type: :controller do
6
+ let!(:store) { create(:store) }
7
+ let(:user) { create(:user) }
8
+
9
+ context "Order model mock" do
10
+ let(:order) do
11
+ Spree::Order.create!
12
+ end
13
+ let(:variant) { create(:variant) }
14
+
15
+ before do
16
+ allow(controller).to receive_messages(try_spree_current_user: user)
17
+ end
18
+
19
+ context "#populate" do
20
+ it "should create a new order when none specified" do
21
+ post :populate, params: { variant_id: variant.id }
22
+ expect(response).to be_redirect
23
+ expect(cookies.signed[:guest_token]).not_to be_blank
24
+
25
+ order_by_token = Spree::Order.find_by(guest_token: cookies.signed[:guest_token])
26
+ assigned_order = assigns[:order]
27
+
28
+ expect(assigned_order).to eq order_by_token
29
+ expect(assigned_order).to be_persisted
30
+ end
31
+
32
+ context "with Variant" do
33
+ it "should handle population" do
34
+ expect do
35
+ post :populate, params: { variant_id: variant.id, quantity: 5 }
36
+ end.to change { user.orders.count }.by(1)
37
+ order = user.orders.last
38
+ expect(response).to redirect_to spree.cart_path
39
+ expect(order.line_items.size).to eq(1)
40
+ line_item = order.line_items.first
41
+ expect(line_item.variant_id).to eq(variant.id)
42
+ expect(line_item.quantity).to eq(5)
43
+ end
44
+
45
+ it "shows an error when population fails" do
46
+ request.env["HTTP_REFERER"] = spree.root_path
47
+ allow_any_instance_of(Spree::LineItem).to(
48
+ receive(:valid?).and_return(false)
49
+ )
50
+ allow_any_instance_of(Spree::LineItem).to(
51
+ receive_message_chain(:errors, :full_messages).
52
+ and_return(["Order population failed"])
53
+ )
54
+
55
+ post :populate, params: { variant_id: variant.id, quantity: 5 }
56
+
57
+ expect(response).to redirect_to(spree.root_path)
58
+ expect(flash[:error]).to eq("Order population failed")
59
+ end
60
+
61
+ it "shows an error when quantity is invalid" do
62
+ request.env["HTTP_REFERER"] = spree.root_path
63
+
64
+ post(
65
+ :populate,
66
+ params: { variant_id: variant.id, quantity: -1 }
67
+ )
68
+
69
+ expect(response).to redirect_to(spree.root_path)
70
+ expect(flash[:error]).to eq(
71
+ I18n.t('spree.please_enter_reasonable_quantity')
72
+ )
73
+ end
74
+
75
+ context "when quantity is empty string" do
76
+ it "should populate order with 1 of given variant" do
77
+ expect do
78
+ post :populate, params: { variant_id: variant.id, quantity: '' }
79
+ end.to change { Spree::Order.count }.by(1)
80
+ order = Spree::Order.last
81
+ expect(response).to redirect_to spree.cart_path
82
+ expect(order.line_items.size).to eq(1)
83
+ line_item = order.line_items.first
84
+ expect(line_item.variant_id).to eq(variant.id)
85
+ expect(line_item.quantity).to eq(1)
86
+ end
87
+ end
88
+
89
+ context "when quantity is nil" do
90
+ it "should populate order with 1 of given variant" do
91
+ expect do
92
+ post :populate, params: { variant_id: variant.id, quantity: nil }
93
+ end.to change { Spree::Order.count }.by(1)
94
+ order = Spree::Order.last
95
+ expect(response).to redirect_to spree.cart_path
96
+ expect(order.line_items.size).to eq(1)
97
+ line_item = order.line_items.first
98
+ expect(line_item.variant_id).to eq(variant.id)
99
+ expect(line_item.quantity).to eq(1)
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ context "#update" do
106
+ context "with authorization" do
107
+ before do
108
+ allow(controller).to receive :authorize!
109
+ allow(controller).to receive_messages current_order: order
110
+ end
111
+
112
+ it "should render the edit view (on failure)" do
113
+ # email validation is only after address state
114
+ order.update_column(:state, "delivery")
115
+ put :update, params: { order: { email: "" } }
116
+ expect(response).to render_template :edit
117
+ end
118
+
119
+ it "should redirect to cart path (on success)" do
120
+ allow(order).to receive(:update_attributes).and_return true
121
+ put :update
122
+ expect(response).to redirect_to(spree.cart_path)
123
+ end
124
+
125
+ it "should advance the order if :checkout button is pressed" do
126
+ allow(order).to receive(:update_attributes).and_return true
127
+ expect(order).to receive(:next)
128
+ put :update, params: { checkout: true }
129
+ expect(response).to redirect_to checkout_state_path('address')
130
+ end
131
+
132
+ context 'trying to apply a coupon code' do
133
+ let(:order) { create(:order_with_line_items, state: 'cart') }
134
+ let(:coupon_code) { "coupon_code" }
135
+
136
+ context "when coupon code is empty" do
137
+ let(:coupon_code) { "" }
138
+
139
+ it 'does not try to apply coupon code' do
140
+ expect(Spree::PromotionHandler::Coupon).not_to receive :new
141
+
142
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
143
+
144
+ expect(response).to redirect_to(spree.cart_path)
145
+ end
146
+ end
147
+
148
+ context "when coupon code is applied" do
149
+ let(:promotion_handler) { instance_double('Spree::PromotionHandler::Coupon', error: nil, success: 'Coupon Applied!') }
150
+
151
+ it "continues checkout flow normally" do
152
+ expect(Spree::PromotionHandler::Coupon)
153
+ .to receive_message_chain(:new, :apply)
154
+ .and_return(promotion_handler)
155
+
156
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
157
+
158
+ expect(response).to redirect_to(spree.cart_path)
159
+ expect(flash.now[:success]).to eq('Coupon Applied!')
160
+ end
161
+
162
+ context "when coupon code is not applied" do
163
+ let(:promotion_handler) { instance_double('Spree::PromotionHandler::Coupon', error: 'Some error', success: false) }
164
+
165
+ it "render cart with coupon error" do
166
+ expect(Spree::PromotionHandler::Coupon)
167
+ .to receive_message_chain(:new, :apply)
168
+ .and_return(promotion_handler)
169
+
170
+ put :update, params: { state: order.state, order: { coupon_code: coupon_code } }
171
+
172
+ expect(response).to render_template :edit
173
+ expect(flash.now[:error]).to eq('Some error')
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ context "#empty" do
182
+ before do
183
+ allow(controller).to receive :authorize!
184
+ end
185
+
186
+ it "should destroy line items in the current order" do
187
+ allow(controller).to receive(:current_order).and_return(order)
188
+ expect(order).to receive(:empty!)
189
+ put :empty
190
+ expect(response).to redirect_to(spree.cart_path)
191
+ end
192
+ end
193
+
194
+ # Regression test for https://github.com/spree/spree/issues/2750
195
+ context "#update" do
196
+ before do
197
+ allow(user).to receive :last_incomplete_spree_order
198
+ allow(controller).to receive :set_current_order
199
+ end
200
+
201
+ it "cannot update a blank order" do
202
+ put :update, params: { order: { email: "foo" } }
203
+ expect(flash[:error]).to eq(I18n.t('spree.order_not_found'))
204
+ expect(response).to redirect_to(spree.root_path)
205
+ end
206
+ end
207
+ end
208
+
209
+ context "line items quantity is 0" do
210
+ let(:order) { Spree::Order.create(store: store) }
211
+ let(:variant) { create(:variant) }
212
+ let!(:line_item) { order.contents.add(variant, 1) }
213
+
214
+ before do
215
+ allow(controller).to receive :authorize!
216
+ allow(controller).to receive_messages(current_order: order)
217
+ end
218
+
219
+ it "removes line items on update" do
220
+ expect(order.line_items.count).to eq 1
221
+ put :update, params: { order: { line_items_attributes: { "0" => { id: line_item.id, quantity: 0 } } } }
222
+ expect(order.reload.line_items.count).to eq 0
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ Spree::Order.class_eval do
6
+ attr_accessor :did_transition
7
+ end
8
+
9
+ module Spree
10
+ describe OrdersController, type: :controller do
11
+ # Regression test for https://github.com/spree/spree/issues/2004
12
+ context "with a transition callback on first state" do
13
+ let(:order) { Spree::Order.new }
14
+
15
+ before do
16
+ allow(controller).to receive_messages current_order: order
17
+ expect(controller).to receive(:authorize!).at_least(:once).and_return(true)
18
+
19
+ first_state, = Spree::Order.checkout_steps.first
20
+ Spree::Order.state_machine.after_transition to: first_state do |order|
21
+ order.did_transition = true
22
+ end
23
+ end
24
+
25
+ it "correctly calls the transition callback" do
26
+ expect(order.did_transition).to be_nil
27
+ order.line_items << FactoryBot.create(:line_item)
28
+ put :update, params: { checkout: "checkout" }
29
+ expect(order.did_transition).to be true
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::ProductsController, type: :controller do
6
+ let!(:product) { create(:product, available_on: 1.year.from_now) }
7
+
8
+ # Regression test for https://github.com/spree/spree/issues/1390
9
+ it "allows admins to view non-active products" do
10
+ allow(controller).to receive_messages spree_current_user: mock_model(Spree.user_class, has_spree_role?: true, last_incomplete_spree_order: nil)
11
+ get :show, params: { id: product.to_param }
12
+ expect(response.status).to eq(200)
13
+ end
14
+
15
+ it "cannot view non-active products" do
16
+ expect {
17
+ get :show, params: { id: product.to_param }
18
+ }.to raise_error(ActiveRecord::RecordNotFound)
19
+ end
20
+
21
+ it "should provide the current user to the searcher class" do
22
+ user = mock_model(Spree.user_class, last_incomplete_spree_order: nil)
23
+ allow(controller).to receive_messages spree_current_user: user
24
+ expect_any_instance_of(Spree::Config.searcher_class).to receive(:current_user=).with(user)
25
+ get :index
26
+ expect(response.status).to eq(200)
27
+ end
28
+
29
+ # Regression test for https://github.com/spree/spree/issues/2249
30
+ it "doesn't error when given an invalid referer" do
31
+ current_user = mock_model(Spree.user_class, has_spree_role?: true, last_incomplete_spree_order: nil)
32
+ allow(controller).to receive_messages spree_current_user: current_user
33
+ request.env['HTTP_REFERER'] = "not|a$url"
34
+
35
+ # Previously a URI::InvalidURIError exception was being thrown
36
+ get :show, params: { id: product.to_param }
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::TaxonsController, type: :controller do
6
+ it "should provide the current user to the searcher class" do
7
+ taxon = create(:taxon, permalink: "test")
8
+ user = mock_model(Spree.user_class, last_incomplete_spree_order: nil)
9
+ allow(controller).to receive_messages spree_current_user: user
10
+ expect_any_instance_of(Spree::Config.searcher_class).to receive(:current_user=).with(user)
11
+ get :show, params: { id: taxon.permalink }
12
+ expect(response.status).to eq(200)
13
+ end
14
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Address", type: :feature, inaccessible: true do
6
+ let!(:product) { create(:product, name: "RoR Mug") }
7
+ let!(:order) { create(:order_with_totals, state: 'cart') }
8
+
9
+ stub_authorization!
10
+
11
+ before do
12
+ visit spree.root_path
13
+
14
+ click_link "RoR Mug"
15
+ click_button "add-to-cart-button"
16
+
17
+ address = "order_bill_address_attributes"
18
+ @country_css = "#{address}_country_id"
19
+ @state_select_css = "##{address}_state_id"
20
+ @state_name_css = "##{address}_state_name"
21
+ end
22
+
23
+ context "country requires state", js: true, focus: true do
24
+ let!(:canada) { create(:country, name: "Canada", states_required: true, iso: "CA") }
25
+ let!(:uk) { create(:country, name: "United Kingdom", states_required: true, iso: "GB") }
26
+
27
+ before { Spree::Config[:default_country_iso] = uk.iso }
28
+
29
+ context "but has no state" do
30
+ it "shows the state input field" do
31
+ click_button "Checkout"
32
+
33
+ select canada.name, from: @country_css
34
+ expect(page).to have_no_css(@state_select_css)
35
+ expect(page).to have_css("#{@state_name_css}.required")
36
+ end
37
+ end
38
+
39
+ context "and has state" do
40
+ before { create(:state, name: "Ontario", country: canada) }
41
+
42
+ it "shows the state collection selection" do
43
+ click_button "Checkout"
44
+
45
+ select canada.name, from: @country_css
46
+ expect(page).to have_no_css(@state_name_css)
47
+ expect(page).to have_css("#{@state_select_css}.required")
48
+ end
49
+ end
50
+
51
+ context "user changes to country without states required" do
52
+ let!(:france) { create(:country, name: "France", states_required: false, iso: "FR") }
53
+
54
+ it "clears the state name" do
55
+ click_button "Checkout"
56
+ select canada.name, from: @country_css
57
+ page.find(@state_name_css).set("Toscana")
58
+
59
+ select france.name, from: @country_css
60
+
61
+ expect(page).to have_no_css(@state_name_css)
62
+ expect(page).to have_no_css(@state_select_css)
63
+ end
64
+ end
65
+ end
66
+
67
+ context "country does not require state", js: true do
68
+ let!(:france) { create(:country, name: "France", states_required: false, iso: "FR") }
69
+
70
+ it "shows a disabled state input field" do
71
+ click_button "Checkout"
72
+
73
+ select france.name, from: @country_css
74
+ expect(page).to have_no_css(@state_name_css)
75
+ expect(page).to have_css("#{@state_select_css}[disabled]", visible: false)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Automatic promotions", type: :feature, js: true do
6
+ let!(:store) { create(:store) }
7
+ let!(:country) { create(:country, name: "United States of America", states_required: true) }
8
+ let!(:state) { create(:state, name: "Alabama", country: country) }
9
+ let!(:zone) { create(:zone) }
10
+ let!(:shipping_method) { create(:shipping_method) }
11
+ let!(:payment_method) { create(:check_payment_method) }
12
+ let!(:product) { create(:product, name: "RoR Mug", price: 20) }
13
+
14
+ let!(:promotion) do
15
+ promotion = Spree::Promotion.create!(name: "$10 off when you spend more than $100", apply_automatically: true)
16
+
17
+ calculator = Spree::Calculator::FlatRate.new
18
+ calculator.preferred_amount = 10
19
+
20
+ rule = Spree::Promotion::Rules::ItemTotal.create
21
+ rule.preferred_amount = 100
22
+ rule.save
23
+
24
+ promotion.rules << rule
25
+
26
+ action = Spree::Promotion::Actions::CreateAdjustment.create
27
+ action.calculator = calculator
28
+ action.save
29
+
30
+ promotion.actions << action
31
+ end
32
+
33
+ context "on the cart page" do
34
+ before do
35
+ visit spree.root_path
36
+ click_link product.name
37
+ click_button "add-to-cart-button"
38
+ end
39
+
40
+ it "automatically applies the promotion once the order crosses the threshold" do
41
+ fill_in "order_line_items_attributes_0_quantity", with: 10
42
+ click_button "Update"
43
+ expect(page).to have_content("Promotion ($10 off when you spend more than $100) -$10.00")
44
+ fill_in "order_line_items_attributes_0_quantity", with: 1
45
+ click_button "Update"
46
+ expect(page).not_to have_content("Promotion ($10 off when you spend more than $100) -$10.00")
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'products', type: :feature, caching: true do
6
+ let!(:product) { create(:product) }
7
+ let!(:product2) { create(:product) }
8
+ let!(:taxonomy) { create(:taxonomy) }
9
+ let!(:taxon) { create(:taxon, taxonomy: taxonomy) }
10
+
11
+ before do
12
+ product2.update_column(:updated_at, 1.day.ago)
13
+ # warm up the cache
14
+ visit spree.root_path
15
+
16
+ clear_cache_events
17
+ end
18
+
19
+ it "reads from cache upon a second viewing" do
20
+ visit spree.root_path
21
+ expect(cache_writes.count).to eq(0)
22
+ end
23
+
24
+ it "busts the cache when a product is updated" do
25
+ product.update_column(:updated_at, 1.day.from_now)
26
+ visit spree.root_path
27
+ expect(cache_writes.count).to eq(2)
28
+ end
29
+
30
+ it "busts the cache when all products are soft-deleted" do
31
+ product.discard
32
+ product2.discard
33
+ visit spree.root_path
34
+ expect(cache_writes.count).to eq(1)
35
+ end
36
+
37
+ it "busts the cache when the newest product is soft-deleted" do
38
+ product.discard
39
+ visit spree.root_path
40
+ expect(cache_writes.count).to eq(1)
41
+ end
42
+
43
+ it "busts the cache when an older product is soft-deleted" do
44
+ product2.discard
45
+ visit spree.root_path
46
+ expect(cache_writes.count).to eq(1)
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'taxons', type: :feature, caching: true do
6
+ let!(:taxonomy) { create(:taxonomy) }
7
+ let!(:taxon) { create(:taxon, taxonomy: taxonomy) }
8
+
9
+ before do
10
+ # warm up the cache
11
+ visit spree.root_path
12
+
13
+ clear_cache_events
14
+ end
15
+
16
+ it "busts the cache when max_level_in_taxons_menu conf changes" do
17
+ Spree::Config[:max_level_in_taxons_menu] = 5
18
+ visit spree.root_path
19
+ expect(cache_writes.count).to eq(1)
20
+ end
21
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Cart", type: :feature, inaccessible: true do
6
+ before { create(:store) }
7
+
8
+ it "shows cart icon on non-cart pages" do
9
+ visit spree.root_path
10
+ expect(page).to have_selector("li#link-to-cart a", visible: true)
11
+ end
12
+
13
+ it "prevents double clicking the remove button on cart", js: true do
14
+ @product = create(:product, name: "RoR Mug")
15
+
16
+ visit spree.root_path
17
+ click_link "RoR Mug"
18
+ click_button "add-to-cart-button"
19
+
20
+ # prevent form submit to verify button is disabled
21
+ page.execute_script("$('#update-cart').submit(function(){return false;})")
22
+
23
+ expect(page).not_to have_selector('button#update-button[disabled]')
24
+ page.find(:css, '.delete img').click
25
+ expect(page).to have_selector('button#update-button[disabled]')
26
+ end
27
+
28
+ # Regression test for https://github.com/spree/spree/issues/2006
29
+ it "does not error out with a 404 when GET'ing to /orders/populate" do
30
+ visit '/orders/populate'
31
+ within(".error") do
32
+ expect(page).to have_content(I18n.t('spree.populate_get_error'))
33
+ end
34
+ end
35
+
36
+ it 'allows you to remove an item from the cart', js: true do
37
+ create(:product, name: "RoR Mug")
38
+ visit spree.root_path
39
+ click_link "RoR Mug"
40
+ click_button "add-to-cart-button"
41
+ find('.cart-item-delete .delete').click
42
+ expect(page).not_to have_content("Line items quantity must be an integer")
43
+ expect(page).not_to have_content("RoR Mug")
44
+ expect(page).to have_content("Your cart is empty")
45
+
46
+ within "#link-to-cart" do
47
+ expect(page).to have_content("EMPTY")
48
+ end
49
+ end
50
+
51
+ it 'allows you to empty the cart', js: true do
52
+ create(:product, name: "RoR Mug")
53
+ visit spree.root_path
54
+ click_link "RoR Mug"
55
+ click_button "add-to-cart-button"
56
+
57
+ expect(page).to have_content("RoR Mug")
58
+ click_on "Empty Cart"
59
+ expect(page).to have_content("Your cart is empty")
60
+
61
+ within "#link-to-cart" do
62
+ expect(page).to have_content("EMPTY")
63
+ end
64
+ end
65
+
66
+ # regression for https://github.com/spree/spree/issues/2276
67
+ context "product contains variants but no option values" do
68
+ let(:variant) { create(:variant) }
69
+ let(:product) { variant.product }
70
+
71
+ before { variant.option_values.destroy_all }
72
+
73
+ it "still adds product to cart", inaccessible: true do
74
+ visit spree.product_path(product)
75
+ click_button "add-to-cart-button"
76
+
77
+ visit spree.cart_path
78
+ expect(page).to have_content(product.name)
79
+ end
80
+ end
81
+ it "should have a surrounding element with data-hook='cart_container'" do
82
+ visit spree.cart_path
83
+ expect(page).to have_selector("div[data-hook='cart_container']")
84
+ end
85
+ end