solidus_core 1.0.2 → 1.0.3
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 +4 -4
- data/CHANGELOG.md +1 -0
- data/Gemfile +3 -0
- data/Rakefile +16 -0
- data/script/rails +9 -0
- data/solidus_core.gemspec +48 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/helpers/base_helper_spec.rb +173 -0
- data/spec/helpers/order_helper_spec.rb +12 -0
- data/spec/helpers/products_helper_spec.rb +220 -0
- data/spec/helpers/taxons_helper_spec.rb +17 -0
- data/spec/lib/calculated_adjustments_spec.rb +7 -0
- data/spec/lib/i18n_spec.rb +123 -0
- data/spec/lib/search/base_spec.rb +86 -0
- data/spec/lib/search/variant_spec.rb +92 -0
- data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
- data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -0
- data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
- data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
- data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
- data/spec/lib/spree/core/current_store_spec.rb +36 -0
- data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
- data/spec/lib/spree/core/importer/order_spec.rb +431 -0
- data/spec/lib/spree/core/role_configuration_spec.rb +138 -0
- data/spec/lib/spree/core/validators/email_spec.rb +48 -0
- data/spec/lib/spree/localized_number_spec.rb +38 -0
- data/spec/lib/spree/migrations_spec.rb +36 -0
- data/spec/lib/spree/money_spec.rb +127 -0
- data/spec/lib/tasks/exchanges_spec.rb +231 -0
- data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
- data/spec/lib/tasks/order_capturing_spec.rb +56 -0
- data/spec/mailers/carton_mailer_spec.rb +43 -0
- data/spec/mailers/order_mailer_spec.rb +122 -0
- data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
- data/spec/mailers/test_mailer_spec.rb +15 -0
- data/spec/models/spree/ability_spec.rb +276 -0
- data/spec/models/spree/address_spec.rb +250 -0
- data/spec/models/spree/adjustment_reason_spec.rb +13 -0
- data/spec/models/spree/adjustment_spec.rb +177 -0
- data/spec/models/spree/app_configuration_spec.rb +20 -0
- data/spec/models/spree/asset_spec.rb +24 -0
- data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
- data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
- data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
- data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
- data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
- data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
- data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
- data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
- data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
- data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
- data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
- data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
- data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
- data/spec/models/spree/calculator_spec.rb +36 -0
- data/spec/models/spree/carton_spec.rb +133 -0
- data/spec/models/spree/classification_spec.rb +15 -0
- data/spec/models/spree/concerns/display_money_spec.rb +43 -0
- data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
- data/spec/models/spree/credit_card_spec.rb +334 -0
- data/spec/models/spree/customer_return_spec.rb +276 -0
- data/spec/models/spree/exchange_spec.rb +79 -0
- data/spec/models/spree/gateway/bogus_simple.rb +20 -0
- data/spec/models/spree/gateway/bogus_spec.rb +13 -0
- data/spec/models/spree/gateway_spec.rb +82 -0
- data/spec/models/spree/inventory_unit_spec.rb +307 -0
- data/spec/models/spree/item_adjustments_spec.rb +256 -0
- data/spec/models/spree/line_item_spec.rb +191 -0
- data/spec/models/spree/option_type_spec.rb +14 -0
- data/spec/models/spree/option_value_spec.rb +22 -0
- data/spec/models/spree/order/address_spec.rb +50 -0
- data/spec/models/spree/order/adjustments_spec.rb +39 -0
- data/spec/models/spree/order/callbacks_spec.rb +42 -0
- data/spec/models/spree/order/checkout_spec.rb +902 -0
- data/spec/models/spree/order/currency_updater_spec.rb +32 -0
- data/spec/models/spree/order/finalizing_spec.rb +111 -0
- data/spec/models/spree/order/payment_spec.rb +210 -0
- data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
- data/spec/models/spree/order/state_machine_spec.rb +221 -0
- data/spec/models/spree/order/tax_spec.rb +84 -0
- data/spec/models/spree/order/totals_spec.rb +24 -0
- data/spec/models/spree/order/updating_spec.rb +18 -0
- data/spec/models/spree/order/validations_spec.rb +15 -0
- data/spec/models/spree/order_cancellations_spec.rb +120 -0
- data/spec/models/spree/order_capturing_spec.rb +116 -0
- data/spec/models/spree/order_contents_spec.rb +265 -0
- data/spec/models/spree/order_inventory_spec.rb +228 -0
- data/spec/models/spree/order_mutex_spec.rb +85 -0
- data/spec/models/spree/order_promotion_spec.rb +31 -0
- data/spec/models/spree/order_shipping_spec.rb +247 -0
- data/spec/models/spree/order_spec.rb +1412 -0
- data/spec/models/spree/order_stock_location_spec.rb +18 -0
- data/spec/models/spree/order_updater_spec.rb +299 -0
- data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
- data/spec/models/spree/payment_method_spec.rb +96 -0
- data/spec/models/spree/payment_spec.rb +1044 -0
- data/spec/models/spree/permission_sets/base_spec.rb +12 -0
- data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
- data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
- data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
- data/spec/models/spree/permission_sets/order_display_spec.rb +49 -0
- data/spec/models/spree/permission_sets/order_management_spec.rb +36 -0
- data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
- data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
- data/spec/models/spree/permission_sets/promotion_display_spec.rb +34 -0
- data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
- data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
- data/spec/models/spree/permission_sets/restricted_transfer_management_spec.rb +132 -0
- data/spec/models/spree/permission_sets/stock_display_spec.rb +26 -0
- data/spec/models/spree/permission_sets/stock_management_spec.rb +24 -0
- data/spec/models/spree/permission_sets/user_display_spec.rb +36 -0
- data/spec/models/spree/permission_sets/user_management_spec.rb +28 -0
- data/spec/models/spree/preference_spec.rb +80 -0
- data/spec/models/spree/preferences/configuration_spec.rb +30 -0
- data/spec/models/spree/preferences/preferable_spec.rb +294 -0
- data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
- data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
- data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
- data/spec/models/spree/preferences/store_spec.rb +39 -0
- data/spec/models/spree/price_spec.rb +42 -0
- data/spec/models/spree/product/scopes_spec.rb +148 -0
- data/spec/models/spree/product_duplicator_spec.rb +103 -0
- data/spec/models/spree/product_filter_spec.rb +26 -0
- data/spec/models/spree/product_property_spec.rb +20 -0
- data/spec/models/spree/product_spec.rb +437 -0
- data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
- data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
- data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
- data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
- data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
- data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
- data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
- data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
- data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
- data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
- data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
- data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
- data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
- data/spec/models/spree/promotion_builder_spec.rb +118 -0
- data/spec/models/spree/promotion_category_spec.rb +17 -0
- data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
- data/spec/models/spree/promotion_code_spec.rb +187 -0
- data/spec/models/spree/promotion_handler/cart_spec.rb +114 -0
- data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
- data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
- data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
- data/spec/models/spree/promotion_rule_spec.rb +28 -0
- data/spec/models/spree/promotion_spec.rb +767 -0
- data/spec/models/spree/refund_spec.rb +204 -0
- data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
- data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
- data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
- data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
- data/spec/models/spree/reimbursement_spec.rb +231 -0
- data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
- data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
- data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
- data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
- data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
- data/spec/models/spree/return_authorization_spec.rb +290 -0
- data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
- data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
- data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
- data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
- data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
- data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
- data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
- data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
- data/spec/models/spree/return_item_spec.rb +775 -0
- data/spec/models/spree/returns_calculator_spec.rb +14 -0
- data/spec/models/spree/shipment_spec.rb +709 -0
- data/spec/models/spree/shipping_calculator_spec.rb +45 -0
- data/spec/models/spree/shipping_method_spec.rb +88 -0
- data/spec/models/spree/shipping_rate_spec.rb +142 -0
- data/spec/models/spree/state_spec.rb +14 -0
- data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
- data/spec/models/spree/stock/coordinator_spec.rb +116 -0
- data/spec/models/spree/stock/differentiator_spec.rb +39 -0
- data/spec/models/spree/stock/estimator_spec.rb +146 -0
- data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
- data/spec/models/spree/stock/package_spec.rb +163 -0
- data/spec/models/spree/stock/packer_spec.rb +91 -0
- data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
- data/spec/models/spree/stock/quantifier_spec.rb +115 -0
- data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
- data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
- data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
- data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
- data/spec/models/spree/stock_item_spec.rb +426 -0
- data/spec/models/spree/stock_location_spec.rb +279 -0
- data/spec/models/spree/stock_movement_spec.rb +56 -0
- data/spec/models/spree/stock_transfer_spec.rb +290 -0
- data/spec/models/spree/store_credit_category_spec.rb +17 -0
- data/spec/models/spree/store_credit_event_spec.rb +314 -0
- data/spec/models/spree/store_credit_spec.rb +876 -0
- data/spec/models/spree/store_spec.rb +55 -0
- data/spec/models/spree/tax_category_spec.rb +27 -0
- data/spec/models/spree/tax_rate_spec.rb +378 -0
- data/spec/models/spree/taxon_spec.rb +74 -0
- data/spec/models/spree/taxonomy_spec.rb +18 -0
- data/spec/models/spree/tracker_spec.rb +21 -0
- data/spec/models/spree/transfer_item_spec.rb +264 -0
- data/spec/models/spree/unit_cancel_spec.rb +148 -0
- data/spec/models/spree/user_spec.rb +223 -0
- data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
- data/spec/models/spree/variant/scopes_spec.rb +55 -0
- data/spec/models/spree/variant_spec.rb +546 -0
- data/spec/models/spree/zone_spec.rb +305 -0
- data/spec/spec_helper.rb +78 -0
- data/spec/support/big_decimal.rb +5 -0
- data/spec/support/concerns/default_price.rb +34 -0
- data/spec/support/dummy_ability.rb +4 -0
- data/spec/support/test_gateway.rb +2 -0
- metadata +229 -3
- data/lib/spree/testing_support/rspec-activemodel-mocks_patch.rb +0 -8
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Promotion::Actions::CreateAdjustment, :type => :model do
|
|
4
|
+
let(:order) { create(:order_with_line_items, :line_items_count => 1) }
|
|
5
|
+
let(:promotion) { create(:promotion) }
|
|
6
|
+
let(:action) { Spree::Promotion::Actions::CreateAdjustment.new }
|
|
7
|
+
let(:payload) { { order: order } }
|
|
8
|
+
|
|
9
|
+
# From promotion spec:
|
|
10
|
+
context "#perform" do
|
|
11
|
+
before do
|
|
12
|
+
action.calculator = Spree::Calculator::FlatRate.new(:preferred_amount => 10)
|
|
13
|
+
promotion.promotion_actions = [action]
|
|
14
|
+
allow(action).to receive_messages(:promotion => promotion)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Regression test for #3966
|
|
18
|
+
it "does not apply an adjustment if the amount is 0" do
|
|
19
|
+
action.calculator.preferred_amount = 0
|
|
20
|
+
action.perform(payload)
|
|
21
|
+
expect(promotion.usage_count).to eq(0)
|
|
22
|
+
expect(order.adjustments.count).to eq(0)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should create a discount with correct negative amount" do
|
|
26
|
+
order.shipments.create!(:cost => 10)
|
|
27
|
+
|
|
28
|
+
action.perform(payload)
|
|
29
|
+
expect(promotion.usage_count).to eq(0)
|
|
30
|
+
expect(order.adjustments.count).to eq(1)
|
|
31
|
+
expect(order.adjustments.first.amount.to_i).to eq(-10)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should create a discount accessible through both order_id and adjustable_id" do
|
|
35
|
+
action.perform(payload)
|
|
36
|
+
expect(order.adjustments.count).to eq(1)
|
|
37
|
+
expect(order.all_adjustments.count).to eq(1)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should not create a discount when order already has one from this promotion" do
|
|
41
|
+
order.shipments.create!(:cost => 10)
|
|
42
|
+
|
|
43
|
+
action.perform(payload)
|
|
44
|
+
action.perform(payload)
|
|
45
|
+
expect(promotion.usage_count).to eq(0)
|
|
46
|
+
expect(order.adjustments.count).to eq(1)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "when a promotion code is used" do
|
|
50
|
+
let(:promotion_code) { create(:promotion_code) }
|
|
51
|
+
let(:promotion) { promotion_code.promotion }
|
|
52
|
+
let(:payload) { { order: order, promotion_code: promotion_code } }
|
|
53
|
+
|
|
54
|
+
it "should connect the adjustment to the promotion_code" do
|
|
55
|
+
expect {
|
|
56
|
+
action.perform(payload)
|
|
57
|
+
}.to change { order.adjustments.count }.by(1)
|
|
58
|
+
expect(order.adjustments.last.promotion_code).to eq promotion_code
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context "#destroy" do
|
|
64
|
+
before(:each) do
|
|
65
|
+
action.calculator = Spree::Calculator::FlatRate.new(:preferred_amount => 10)
|
|
66
|
+
promotion.promotion_actions = [action]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context "when order is not complete" do
|
|
70
|
+
it "should not keep the adjustment" do
|
|
71
|
+
action.perform(payload)
|
|
72
|
+
action.destroy
|
|
73
|
+
expect(order.adjustments.count).to eq(0)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "when order is complete" do
|
|
78
|
+
let(:order) do
|
|
79
|
+
create(:completed_order_with_totals, :line_items_count => 1)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
before(:each) do
|
|
83
|
+
action.perform(payload)
|
|
84
|
+
action.destroy
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "should keep the adjustment" do
|
|
88
|
+
expect(order.adjustments.count).to eq(1)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should nullify the adjustment source" do
|
|
92
|
+
expect(order.adjustments.reload.first.source).to be_nil
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
class Promotion
|
|
5
|
+
module Actions
|
|
6
|
+
describe CreateItemAdjustments, :type => :model do
|
|
7
|
+
let(:order) { create(:order) }
|
|
8
|
+
let(:promotion) { create(:promotion) }
|
|
9
|
+
let(:action) { CreateItemAdjustments.new }
|
|
10
|
+
let!(:line_item) { create(:line_item, :order => order) }
|
|
11
|
+
let(:payload) { { order: order, promotion: promotion } }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
allow(action).to receive(:promotion).and_return(promotion)
|
|
15
|
+
promotion.promotion_actions = [action]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "#perform" do
|
|
19
|
+
# Regression test for #3966
|
|
20
|
+
context "when calculator computes 0" do
|
|
21
|
+
before do
|
|
22
|
+
allow(action).to receive_messages :compute_amount => 0
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "does not create an adjustment when calculator returns 0" do
|
|
26
|
+
action.perform(payload)
|
|
27
|
+
expect(action.adjustments).to be_empty
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "when calculator returns a non-zero value" do
|
|
32
|
+
before do
|
|
33
|
+
promotion.promotion_actions = [action]
|
|
34
|
+
allow(action).to receive_messages :compute_amount => 10
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "creates adjustment with item as adjustable" do
|
|
38
|
+
action.perform(payload)
|
|
39
|
+
expect(action.adjustments.count).to eq(1)
|
|
40
|
+
expect(line_item.reload.adjustments).to eq(action.adjustments)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "creates adjustment with self as source" do
|
|
44
|
+
action.perform(payload)
|
|
45
|
+
expect(line_item.reload.adjustments.first.source).to eq action
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "does not perform twice on the same item" do
|
|
49
|
+
2.times { action.perform(payload) }
|
|
50
|
+
expect(action.adjustments.count).to eq(1)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "with products rules" do
|
|
54
|
+
let(:rule) { double Spree::Promotion::Rules::Product }
|
|
55
|
+
|
|
56
|
+
before { allow(promotion).to receive(:eligible_rules) { [rule] } }
|
|
57
|
+
|
|
58
|
+
context "when the rule is actionable" do
|
|
59
|
+
before { allow(rule).to receive(:actionable?).and_return(true) }
|
|
60
|
+
|
|
61
|
+
it "creates an adjustment" do
|
|
62
|
+
expect {
|
|
63
|
+
expect {
|
|
64
|
+
action.perform(payload)
|
|
65
|
+
}.to change { action.adjustments.count }.by(1)
|
|
66
|
+
}.to change { line_item.adjustments.count }.by(1)
|
|
67
|
+
|
|
68
|
+
expect(action.adjustments.last).to eq line_item.adjustments.last
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "when the rule is not actionable" do
|
|
73
|
+
before { allow(rule).to receive(:actionable?).and_return(false) }
|
|
74
|
+
|
|
75
|
+
it "does not create an adjustment" do
|
|
76
|
+
expect {
|
|
77
|
+
expect {
|
|
78
|
+
action.perform(payload)
|
|
79
|
+
}.to_not change { action.adjustments.count }
|
|
80
|
+
}.to_not change { line_item.adjustments.count }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "when a promotion code is used" do
|
|
86
|
+
let(:promotion_code) { create(:promotion_code) }
|
|
87
|
+
let(:promotion) { promotion_code.promotion }
|
|
88
|
+
let(:payload) { { order: order, promotion: promotion, promotion_code: promotion_code } }
|
|
89
|
+
|
|
90
|
+
it "should connect the adjustment to the promotion_code" do
|
|
91
|
+
expect {
|
|
92
|
+
action.perform(payload)
|
|
93
|
+
}.to change { line_item.adjustments.count }.by(1)
|
|
94
|
+
expect(line_item.adjustments.last.promotion_code).to eq promotion_code
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "#compute_amount" do
|
|
101
|
+
before { promotion.promotion_actions = [action] }
|
|
102
|
+
|
|
103
|
+
context "when the adjustable is actionable" do
|
|
104
|
+
it "calls compute on the calculator" do
|
|
105
|
+
expect(action.calculator).to receive(:compute).with(line_item)
|
|
106
|
+
action.compute_amount(line_item)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context "calculator returns amount greater than item total" do
|
|
110
|
+
before do
|
|
111
|
+
expect(action.calculator).to receive(:compute).with(line_item).and_return(300)
|
|
112
|
+
allow(line_item).to receive_messages(amount: 100)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "does not exceed it" do
|
|
116
|
+
expect(action.compute_amount(line_item)).to eql(-100)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
context "when the adjustable is not actionable" do
|
|
122
|
+
before { allow(promotion).to receive(:line_item_actionable?) { false } }
|
|
123
|
+
|
|
124
|
+
it 'returns 0' do
|
|
125
|
+
expect(action.compute_amount(line_item)).to eql(0)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "#destroy" do
|
|
131
|
+
let!(:action) { promotion.actions.first }
|
|
132
|
+
let(:other_action) { other_promotion.actions.first }
|
|
133
|
+
let(:promotion) { create(:promotion, :with_line_item_adjustment) }
|
|
134
|
+
let(:other_promotion) { create(:promotion, :with_line_item_adjustment) }
|
|
135
|
+
|
|
136
|
+
it "destroys adjustments for incompleted orders" do
|
|
137
|
+
order = Order.create
|
|
138
|
+
action.adjustments.create!(label: "Check", amount: 0, order: order, adjustable: order)
|
|
139
|
+
|
|
140
|
+
expect {
|
|
141
|
+
action.destroy
|
|
142
|
+
}.to change { Adjustment.count }.by(-1)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "nullifies adjustments for completed orders" do
|
|
146
|
+
order = Order.create(completed_at: Time.now)
|
|
147
|
+
adjustment = action.adjustments.create!(label: "Check", amount: 0, order: order, adjustable: order)
|
|
148
|
+
|
|
149
|
+
expect {
|
|
150
|
+
action.destroy
|
|
151
|
+
}.to change { adjustment.reload.source_id }.from(action.id).to nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "doesnt mess with unrelated adjustments" do
|
|
155
|
+
other_action.adjustments.create!(label: "Check", amount: 0, order: order, adjustable: order)
|
|
156
|
+
|
|
157
|
+
expect {
|
|
158
|
+
action.destroy
|
|
159
|
+
}.not_to change { other_action.adjustments.count }
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module Spree::Promotion::Actions
|
|
4
|
+
RSpec.describe CreateQuantityAdjustments do
|
|
5
|
+
let(:action) { CreateQuantityAdjustments.create!(calculator: calculator, promotion: promotion) }
|
|
6
|
+
|
|
7
|
+
let(:order) { FactoryGirl.create :order }
|
|
8
|
+
let(:promotion) { FactoryGirl.create :promotion }
|
|
9
|
+
|
|
10
|
+
describe "#compute_amount" do
|
|
11
|
+
subject { action.compute_amount(line_item) }
|
|
12
|
+
|
|
13
|
+
let!(:item_a) { FactoryGirl.create :line_item, order: order, quantity: quantity, price: 10 }
|
|
14
|
+
|
|
15
|
+
context "with a flat rate adjustment" do
|
|
16
|
+
let(:calculator) { FactoryGirl.create :flat_rate_calculator, preferred_amount: 5 }
|
|
17
|
+
|
|
18
|
+
context "with a quantity group of 2" do
|
|
19
|
+
let(:line_item) { item_a }
|
|
20
|
+
before { action.preferred_group_size = 2 }
|
|
21
|
+
context "and an item with a quantity of 0" do
|
|
22
|
+
let(:quantity) { 0 }
|
|
23
|
+
it { is_expected.to eq 0 }
|
|
24
|
+
end
|
|
25
|
+
context "and an item with a quantity of 1" do
|
|
26
|
+
let(:quantity) { 1 }
|
|
27
|
+
it { is_expected.to eq 0 }
|
|
28
|
+
end
|
|
29
|
+
context "and an item with a quantity of 2" do
|
|
30
|
+
let(:quantity) { 2 }
|
|
31
|
+
it { is_expected.to eq -10 }
|
|
32
|
+
end
|
|
33
|
+
context "and an item with a quantity of 3" do
|
|
34
|
+
let(:quantity) { 3 }
|
|
35
|
+
it { is_expected.to eq -10 }
|
|
36
|
+
end
|
|
37
|
+
context "and an item with a quantity of 4" do
|
|
38
|
+
let(:quantity) { 4 }
|
|
39
|
+
it { is_expected.to eq -20 }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "with a quantity group of 3" do
|
|
44
|
+
let(:quantity) { 2 }
|
|
45
|
+
let!(:item_b) { FactoryGirl.create :line_item, order: order, quantity: 1 }
|
|
46
|
+
let!(:item_c) { FactoryGirl.create :line_item, order: order, quantity: 1 }
|
|
47
|
+
before { action.preferred_group_size = 3 }
|
|
48
|
+
context "and 2x item A, 1x item B and 1x item C" do
|
|
49
|
+
before { action.perform({ order: order, promotion: promotion }) }
|
|
50
|
+
describe "the adjustment for the first item" do
|
|
51
|
+
let(:line_item) { item_a }
|
|
52
|
+
it { is_expected.to eq -10 }
|
|
53
|
+
end
|
|
54
|
+
describe "the adjustment for the second item" do
|
|
55
|
+
let(:line_item) { item_b }
|
|
56
|
+
it { is_expected.to eq -5 }
|
|
57
|
+
end
|
|
58
|
+
describe "the adjustment for the third item" do
|
|
59
|
+
let(:line_item) { item_c }
|
|
60
|
+
it { is_expected.to eq 0 }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context "with multiple orders using the same action" do
|
|
66
|
+
let(:quantity) { 2 }
|
|
67
|
+
let(:line_item) { item_a }
|
|
68
|
+
before do
|
|
69
|
+
action.preferred_group_size = 2
|
|
70
|
+
other_order = FactoryGirl.create :order
|
|
71
|
+
FactoryGirl.create :line_item, order: other_order, quantity: 3
|
|
72
|
+
action.perform({ order: other_order, promotion: promotion })
|
|
73
|
+
end
|
|
74
|
+
it { is_expected.to eq -10 }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "with a percentage based adjustment" do
|
|
79
|
+
let(:calculator) { FactoryGirl.create :percent_on_item_calculator, preferred_percent: 10 }
|
|
80
|
+
|
|
81
|
+
context "with a quantity group of 3" do
|
|
82
|
+
before do
|
|
83
|
+
action.preferred_group_size = 3
|
|
84
|
+
action.perform({ order: order, promotion: promotion })
|
|
85
|
+
end
|
|
86
|
+
context "and 2x item A and 1x item B" do
|
|
87
|
+
let(:quantity) { 2 }
|
|
88
|
+
let!(:item_b) { FactoryGirl.create :line_item, order: order, quantity: 1, price: 10 }
|
|
89
|
+
describe "the adjustment for the first item" do
|
|
90
|
+
let(:line_item) { item_a }
|
|
91
|
+
it { is_expected.to eq -2 }
|
|
92
|
+
end
|
|
93
|
+
describe "the adjustment for the second item" do
|
|
94
|
+
let(:line_item) { item_b }
|
|
95
|
+
it { is_expected.to eq -1 }
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "and the items cost different amounts" do
|
|
100
|
+
let(:quantity) { 3 }
|
|
101
|
+
let!(:item_b) { FactoryGirl.create :line_item, order: order, quantity: 1, price: 20 }
|
|
102
|
+
describe "the adjustment for the first item" do
|
|
103
|
+
let(:line_item) { item_a }
|
|
104
|
+
it { is_expected.to eq -3 }
|
|
105
|
+
end
|
|
106
|
+
describe "the adjustment for the second item" do
|
|
107
|
+
let(:line_item) { item_b }
|
|
108
|
+
it { is_expected.to eq 0 }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Promotion::Actions::FreeShipping, :type => :model do
|
|
4
|
+
let(:order) { create(:completed_order_with_totals) }
|
|
5
|
+
let(:promotion_code) { create(:promotion_code, value: 'somecode') }
|
|
6
|
+
let(:promotion) { promotion_code.promotion }
|
|
7
|
+
let(:action) { Spree::Promotion::Actions::FreeShipping.create }
|
|
8
|
+
let(:payload) { { order: order, promotion_code: promotion_code } }
|
|
9
|
+
|
|
10
|
+
# From promotion spec:
|
|
11
|
+
context "#perform" do
|
|
12
|
+
before do
|
|
13
|
+
order.shipments << create(:shipment)
|
|
14
|
+
promotion.promotion_actions << action
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "when valid" do
|
|
18
|
+
it "should create a discount with correct negative amount" do
|
|
19
|
+
expect(order.shipments.count).to eq(2)
|
|
20
|
+
expect(order.shipments.first.cost).to eq(100)
|
|
21
|
+
expect(order.shipments.last.cost).to eq(100)
|
|
22
|
+
expect(action.perform(payload)).to be true
|
|
23
|
+
expect(promotion.usage_count).to eq(1)
|
|
24
|
+
expect(order.shipment_adjustments.count).to eq(2)
|
|
25
|
+
expect(order.shipment_adjustments.first.amount.to_i).to eq(-100)
|
|
26
|
+
expect(order.shipment_adjustments.last.amount.to_i).to eq(-100)
|
|
27
|
+
expect(order.shipment_adjustments.map(&:promotion_code)).to eq [promotion_code, promotion_code]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "when order already has one from this promotion" do
|
|
32
|
+
it "should not create a discount" do
|
|
33
|
+
expect(action.perform(payload)).to be true
|
|
34
|
+
expect(action.perform(payload)).to be false
|
|
35
|
+
expect(promotion.usage_count).to eq(1)
|
|
36
|
+
expect(order.shipment_adjustments.count).to eq(2)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Promotion::Rules::FirstOrder, :type => :model do
|
|
4
|
+
let(:rule) { Spree::Promotion::Rules::FirstOrder.new }
|
|
5
|
+
let(:order) { mock_model(Spree::Order, :user => nil, :email => nil) }
|
|
6
|
+
let(:user) { mock_model(Spree::LegacyUser) }
|
|
7
|
+
|
|
8
|
+
context "without a user or email" do
|
|
9
|
+
it { expect(rule).not_to be_eligible(order) }
|
|
10
|
+
it "sets an error message" do
|
|
11
|
+
rule.eligible?(order)
|
|
12
|
+
expect(rule.eligibility_errors.full_messages.first).
|
|
13
|
+
to eq "You need to login or provide your email before applying this coupon code."
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "first order" do
|
|
18
|
+
context "for a signed user" do
|
|
19
|
+
context "with no completed orders" do
|
|
20
|
+
before(:each) do
|
|
21
|
+
allow(user).to receive_message_chain(:orders, :complete => [])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
specify do
|
|
25
|
+
allow(order).to receive_messages(:user => user)
|
|
26
|
+
expect(rule).to be_eligible(order)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should be eligible when user passed in payload data" do
|
|
30
|
+
expect(rule).to be_eligible(order, :user => user)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "with completed orders" do
|
|
35
|
+
before(:each) do
|
|
36
|
+
allow(order).to receive_messages(:user => user)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should be eligible when checked against first completed order" do
|
|
40
|
+
allow(user).to receive_message_chain(:orders, :complete => [order])
|
|
41
|
+
expect(rule).to be_eligible(order)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "with another order" do
|
|
45
|
+
before { allow(user).to receive_message_chain(:orders, :complete => [mock_model(Spree::Order)]) }
|
|
46
|
+
it { expect(rule).not_to be_eligible(order) }
|
|
47
|
+
it "sets an error message" do
|
|
48
|
+
rule.eligible?(order)
|
|
49
|
+
expect(rule.eligibility_errors.full_messages.first).
|
|
50
|
+
to eq "This coupon code can only be applied to your first order."
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "for a guest user" do
|
|
57
|
+
let(:email) { 'user@spreecommerce.com' }
|
|
58
|
+
before { allow(order).to receive_messages :email => 'user@spreecommerce.com' }
|
|
59
|
+
|
|
60
|
+
context "with no other orders" do
|
|
61
|
+
it { expect(rule).to be_eligible(order) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "with another order" do
|
|
65
|
+
before { allow(rule).to receive_messages(:orders_by_email => [mock_model(Spree::Order)]) }
|
|
66
|
+
it { expect(rule).not_to be_eligible(order) }
|
|
67
|
+
it "sets an error message" do
|
|
68
|
+
rule.eligible?(order)
|
|
69
|
+
expect(rule.eligibility_errors.full_messages.first).
|
|
70
|
+
to eq "This coupon code can only be applied to your first order."
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|