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.
- checksums.yaml +7 -0
- data/LICENSE +26 -0
- data/README.md +42 -0
- data/Rakefile +17 -0
- data/app/assets/config/solidus_frontend_manifest.js +4 -0
- data/app/assets/images/credit_cards/amex_cid.gif +0 -0
- data/app/assets/images/credit_cards/credit_card.gif +0 -0
- data/app/assets/images/credit_cards/discover_cid.gif +0 -0
- data/app/assets/images/credit_cards/icons/american_express.png +0 -0
- data/app/assets/images/credit_cards/icons/cirrus.png +0 -0
- data/app/assets/images/credit_cards/icons/delta.png +0 -0
- data/app/assets/images/credit_cards/icons/diners_club.png +0 -0
- data/app/assets/images/credit_cards/icons/directdebit.png +0 -0
- data/app/assets/images/credit_cards/icons/discover.png +0 -0
- data/app/assets/images/credit_cards/icons/egold.png +0 -0
- data/app/assets/images/credit_cards/icons/maestro.png +0 -0
- data/app/assets/images/credit_cards/icons/master.png +0 -0
- data/app/assets/images/credit_cards/icons/paypal.png +0 -0
- data/app/assets/images/credit_cards/icons/solo.png +0 -0
- data/app/assets/images/credit_cards/icons/switch.png +0 -0
- data/app/assets/images/credit_cards/icons/visa.png +0 -0
- data/app/assets/images/credit_cards/icons/visaelectron.png +0 -0
- data/app/assets/images/credit_cards/icons/westernunion.png +0 -0
- data/app/assets/images/credit_cards/icons/wirecard.png +0 -0
- data/app/assets/images/credit_cards/icons/worldpay.png +0 -0
- data/app/assets/images/credit_cards/master_cid.jpg +0 -0
- data/app/assets/images/credit_cards/visa_cid.gif +0 -0
- data/app/assets/images/favicon.ico +0 -0
- data/app/assets/images/icons/add-to-cart.png +0 -0
- data/app/assets/images/icons/checkout.png +0 -0
- data/app/assets/images/icons/delete.png +0 -0
- data/app/assets/images/icons/update.png +0 -0
- data/app/assets/images/spinner.gif +0 -0
- data/app/assets/images/spree/frontend/cart.png +0 -0
- data/app/assets/javascripts/spree/frontend/cart.js +30 -0
- data/app/assets/javascripts/spree/frontend/checkout/address.js +127 -0
- data/app/assets/javascripts/spree/frontend/checkout/coupon-code.js +41 -0
- data/app/assets/javascripts/spree/frontend/checkout/payment.js +55 -0
- data/app/assets/javascripts/spree/frontend/checkout.js +24 -0
- data/app/assets/javascripts/spree/frontend/locale_selector.js +5 -0
- data/app/assets/javascripts/spree/frontend/product.js +81 -0
- data/app/assets/javascripts/spree/frontend.js +5 -0
- data/app/assets/stylesheets/spree/frontend/_skeleton.scss +242 -0
- data/app/assets/stylesheets/spree/frontend/_variables.scss +65 -0
- data/app/assets/stylesheets/spree/frontend/screen.css.scss +1387 -0
- data/app/assets/stylesheets/spree/frontend.css +5 -0
- data/app/controllers/spree/checkout_controller.rb +236 -0
- data/app/controllers/spree/content_controller.rb +11 -0
- data/app/controllers/spree/home_controller.rb +14 -0
- data/app/controllers/spree/locale_controller.rb +20 -0
- data/app/controllers/spree/orders_controller.rb +138 -0
- data/app/controllers/spree/products_controller.rb +52 -0
- data/app/controllers/spree/store_controller.rb +30 -0
- data/app/controllers/spree/taxons_controller.rb +31 -0
- data/app/helpers/spree/orders_helper.rb +18 -0
- data/app/helpers/spree/taxon_filters_helper.rb +13 -0
- data/app/models/spree/frontend_configuration.rb +10 -0
- data/app/views/spree/address/_form.html.erb +96 -0
- data/app/views/spree/address/_form_hidden.html.erb +12 -0
- data/app/views/spree/checkout/_address.html.erb +33 -0
- data/app/views/spree/checkout/_confirm.html.erb +25 -0
- data/app/views/spree/checkout/_coupon_code.html.erb +12 -0
- data/app/views/spree/checkout/_delivery.html.erb +108 -0
- data/app/views/spree/checkout/_payment.html.erb +67 -0
- data/app/views/spree/checkout/_summary.html.erb +76 -0
- data/app/views/spree/checkout/_terms_and_conditions.en.html.erb +1 -0
- data/app/views/spree/checkout/edit.html.erb +32 -0
- data/app/views/spree/checkout/existing_payment/_gateway.html.erb +9 -0
- data/app/views/spree/checkout/payment/_check.html.erb +0 -0
- data/app/views/spree/checkout/payment/_gateway.html.erb +36 -0
- data/app/views/spree/content/cvv.html.erb +13 -0
- data/app/views/spree/home/index.html.erb +12 -0
- data/app/views/spree/layouts/spree_application.html.erb +36 -0
- data/app/views/spree/orders/_adjustment_row.html.erb +8 -0
- data/app/views/spree/orders/_adjustments.html.erb +24 -0
- data/app/views/spree/orders/_form.html.erb +29 -0
- data/app/views/spree/orders/_line_item.html.erb +34 -0
- data/app/views/spree/orders/edit.html.erb +47 -0
- data/app/views/spree/orders/show.html.erb +22 -0
- data/app/views/spree/payments/_payment.html.erb +18 -0
- data/app/views/spree/products/_cart_form.html.erb +65 -0
- data/app/views/spree/products/_image.html.erb +8 -0
- data/app/views/spree/products/_promotions.html.erb +19 -0
- data/app/views/spree/products/_properties.html.erb +15 -0
- data/app/views/spree/products/_taxons.html.erb +14 -0
- data/app/views/spree/products/_thumbnails.html.erb +21 -0
- data/app/views/spree/products/index.html.erb +27 -0
- data/app/views/spree/products/show.html.erb +51 -0
- data/app/views/spree/shared/_address.html.erb +38 -0
- data/app/views/spree/shared/_filters.html.erb +27 -0
- data/app/views/spree/shared/_footer.html.erb +6 -0
- data/app/views/spree/shared/_head.html.erb +14 -0
- data/app/views/spree/shared/_header.html.erb +5 -0
- data/app/views/spree/shared/_image.html.erb +12 -0
- data/app/views/spree/shared/_link_to_cart.html.erb +1 -0
- data/app/views/spree/shared/_locale_selector.html.erb +25 -0
- data/app/views/spree/shared/_login_bar_items.html.erb +1 -0
- data/app/views/spree/shared/_main_nav_bar.html.erb +12 -0
- data/app/views/spree/shared/_nav_bar.html.erb +9 -0
- data/app/views/spree/shared/_order_details.html.erb +146 -0
- data/app/views/spree/shared/_products.html.erb +51 -0
- data/app/views/spree/shared/_search.html.erb +11 -0
- data/app/views/spree/shared/_shipment_tracking.html.erb +9 -0
- data/app/views/spree/shared/_sidebar.html.erb +3 -0
- data/app/views/spree/shared/_taxonomies.html.erb +9 -0
- data/app/views/spree/shared/unauthorized.html.erb +0 -0
- data/app/views/spree/store/cart_link.html.erb +1 -0
- data/app/views/spree/taxons/_taxon.html.erb +4 -0
- data/app/views/spree/taxons/show.html.erb +20 -0
- data/config/initializers/assets.rb +3 -0
- data/config/initializers/canonical_rails.rb +16 -0
- data/config/routes.rb +33 -0
- data/lib/generators/solidus/views/override_generator.rb +49 -0
- data/lib/solidus_frontend.rb +3 -0
- data/lib/spree/frontend/engine.rb +13 -0
- data/lib/spree/frontend/middleware/seo_assist.rb +52 -0
- data/lib/spree/frontend.rb +15 -0
- data/lib/spree_frontend.rb +3 -0
- data/lib/tasks/rake_util.rb +18 -0
- data/lib/tasks/taxon.rake +16 -0
- data/script/rails +10 -0
- data/solidus_frontend.gemspec +35 -0
- data/spec/controllers/controller_helpers_spec.rb +30 -0
- data/spec/controllers/locale_controller_spec.rb +57 -0
- data/spec/controllers/spree/checkout_controller_spec.rb +539 -0
- data/spec/controllers/spree/checkout_controller_with_views_spec.rb +37 -0
- data/spec/controllers/spree/content_controller_spec.rb +9 -0
- data/spec/controllers/spree/current_order_tracking_spec.rb +47 -0
- data/spec/controllers/spree/home_controller_spec.rb +29 -0
- data/spec/controllers/spree/orders_controller_ability_spec.rb +93 -0
- data/spec/controllers/spree/orders_controller_spec.rb +225 -0
- data/spec/controllers/spree/orders_controller_transitions_spec.rb +33 -0
- data/spec/controllers/spree/products_controller_spec.rb +38 -0
- data/spec/controllers/spree/taxons_controller_spec.rb +14 -0
- data/spec/features/address_spec.rb +78 -0
- data/spec/features/automatic_promotion_adjustments_spec.rb +49 -0
- data/spec/features/caching/products_spec.rb +48 -0
- data/spec/features/caching/taxons_spec.rb +21 -0
- data/spec/features/cart_spec.rb +85 -0
- data/spec/features/checkout_spec.rb +690 -0
- data/spec/features/checkout_unshippable_spec.rb +37 -0
- data/spec/features/coupon_code_spec.rb +266 -0
- data/spec/features/currency_spec.rb +20 -0
- data/spec/features/free_shipping_promotions_spec.rb +60 -0
- data/spec/features/locale_spec.rb +27 -0
- data/spec/features/order_spec.rb +73 -0
- data/spec/features/products_spec.rb +291 -0
- data/spec/features/promotion_code_invalidation_spec.rb +54 -0
- data/spec/features/quantity_promotions_spec.rb +130 -0
- data/spec/features/taxons_spec.rb +158 -0
- data/spec/features/template_rendering_spec.rb +20 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/generators/solidus/views/override_generator_spec.rb +50 -0
- data/spec/helpers/base_helper_spec.rb +13 -0
- data/spec/helpers/order_helper_spec.rb +14 -0
- data/spec/helpers/taxon_filters_helper_spec.rb +12 -0
- data/spec/spec_helper.rb +106 -0
- data/spec/support/features/fill_in_with_force.rb +12 -0
- data/spec/support/shared_contexts/checkout_setup.rb +12 -0
- data/spec/support/shared_contexts/custom_products.rb +28 -0
- data/spec/support/shared_contexts/locales.rb +16 -0
- data/spec/views/spree/checkout/_summary_spec.rb +11 -0
- 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
|