solidus_core 1.1.0 → 1.1.1
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/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 +208 -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 +106 -0
- data/spec/lib/search/base_spec.rb +86 -0
- data/spec/lib/search/variant_spec.rb +112 -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/payment_parameters_spec.rb +80 -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 +24 -0
- data/spec/lib/spree/core/importer/order_spec.rb +431 -0
- data/spec/lib/spree/core/role_configuration_spec.rb +156 -0
- data/spec/lib/spree/core/unreturned_item_charger_spec.rb +130 -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 +55 -0
- data/spec/mailers/order_mailer_spec.rb +135 -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 +376 -0
- data/spec/models/spree/adjustment_reason_spec.rb +13 -0
- data/spec/models/spree/adjustment_spec.rb +169 -0
- data/spec/models/spree/app_configuration_spec.rb +24 -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 +60 -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 +93 -0
- data/spec/models/spree/concerns/display_money_spec.rb +43 -0
- data/spec/models/spree/concerns/ordered_property_value_list_spec.rb +25 -0
- data/spec/models/spree/concerns/user_address_book_spec.rb +332 -0
- data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
- data/spec/models/spree/credit_card_spec.rb +341 -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 +104 -0
- data/spec/models/spree/inventory_unit_spec.rb +307 -0
- data/spec/models/spree/item_adjustments_spec.rb +275 -0
- data/spec/models/spree/line_item_spec.rb +199 -0
- data/spec/models/spree/option_type_spec.rb +14 -0
- data/spec/models/spree/option_value_spec.rb +45 -0
- data/spec/models/spree/order/address_spec.rb +50 -0
- data/spec/models/spree/order/adjustments_spec.rb +27 -0
- data/spec/models/spree/order/callbacks_spec.rb +42 -0
- data/spec/models/spree/order/checkout_spec.rb +884 -0
- data/spec/models/spree/order/currency_updater_spec.rb +32 -0
- data/spec/models/spree/order/finalizing_spec.rb +110 -0
- data/spec/models/spree/order/payment_spec.rb +243 -0
- data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
- data/spec/models/spree/order/state_machine_spec.rb +209 -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 +150 -0
- data/spec/models/spree/order_contents_spec.rb +307 -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 +241 -0
- data/spec/models/spree/order_spec.rb +1482 -0
- data/spec/models/spree/order_stock_location_spec.rb +18 -0
- data/spec/models/spree/order_updater_spec.rb +283 -0
- data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
- data/spec/models/spree/payment_method_spec.rb +147 -0
- data/spec/models/spree/payment_spec.rb +1087 -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 +55 -0
- data/spec/models/spree/permission_sets/order_management_spec.rb +42 -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 +40 -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_stock_display_spec.rb +41 -0
- data/spec/models/spree/permission_sets/restricted_stock_management_spec.rb +41 -0
- data/spec/models/spree/permission_sets/restricted_stock_transfer_display_spec.rb +50 -0
- data/spec/models/spree/permission_sets/restricted_stock_transfer_management_spec.rb +160 -0
- data/spec/models/spree/permission_sets/stock_display_spec.rb +24 -0
- data/spec/models/spree/permission_sets/stock_management_spec.rb +22 -0
- data/spec/models/spree/permission_sets/stock_transfer_display_spec.rb +24 -0
- data/spec/models/spree/permission_sets/stock_transfer_management_spec.rb +25 -0
- data/spec/models/spree/permission_sets/user_display_spec.rb +38 -0
- data/spec/models/spree/permission_sets/user_management_spec.rb +48 -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 +60 -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 +116 -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 +18 -0
- data/spec/models/spree/product_spec.rb +504 -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/first_repeat_purchase_since_spec.rb +69 -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 +130 -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 +776 -0
- data/spec/models/spree/refund_spec.rb +192 -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 +776 -0
- data/spec/models/spree/returns_calculator_spec.rb +14 -0
- data/spec/models/spree/shipment_spec.rb +753 -0
- data/spec/models/spree/shipping_calculator_spec.rb +45 -0
- data/spec/models/spree/shipping_manifest_spec.rb +94 -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 +444 -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 +149 -0
- data/spec/models/spree/user_spec.rb +246 -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_property_rule_condition_spec.rb +15 -0
- data/spec/models/spree/variant_property_rule_spec.rb +83 -0
- data/spec/models/spree/variant_property_rule_value_spec.rb +18 -0
- data/spec/models/spree/variant_spec.rb +601 -0
- data/spec/models/spree/zone_spec.rb +305 -0
- data/spec/spec_helper.rb +80 -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 +242 -2
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Promotion::Rules::Taxon, :type => :model do
|
|
4
|
+
let(:rule) { Spree::Promotion::Rules::Taxon.create!(promotion: create(:promotion)) }
|
|
5
|
+
|
|
6
|
+
context '#elegible?(order)' do
|
|
7
|
+
let(:taxon){ create :taxon, name: 'first' }
|
|
8
|
+
let(:taxon2){ create :taxon, name: 'second'}
|
|
9
|
+
let(:order){ create :order_with_line_items }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
rule.save
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'with any match policy' do
|
|
16
|
+
before do
|
|
17
|
+
rule.preferred_match_policy = 'any'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'is eligible if order does have any prefered taxon' do
|
|
21
|
+
order.products.first.taxons << taxon
|
|
22
|
+
rule.taxons << taxon
|
|
23
|
+
expect(rule).to be_eligible(order)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when order contains items from different taxons' do
|
|
27
|
+
before do
|
|
28
|
+
order.products.first.taxons << taxon
|
|
29
|
+
rule.taxons << taxon
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should act on a product within the eligible taxon' do
|
|
33
|
+
expect(rule).to be_actionable(order.line_items.last)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'should not act on a product in another taxon' do
|
|
37
|
+
order.line_items << create(:line_item, product: create(:product, taxons: [taxon2]))
|
|
38
|
+
expect(rule).not_to be_actionable(order.line_items.last)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "when order does not have any prefered taxon" do
|
|
43
|
+
before { rule.taxons << taxon2 }
|
|
44
|
+
it { expect(rule).not_to be_eligible(order) }
|
|
45
|
+
it "sets an error message" do
|
|
46
|
+
rule.eligible?(order)
|
|
47
|
+
expect(rule.eligibility_errors.full_messages.first).
|
|
48
|
+
to eq "You need to add a product from an applicable category before applying this coupon code."
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'when a product has a taxon child of a taxon rule' do
|
|
53
|
+
before do
|
|
54
|
+
taxon.children << taxon2
|
|
55
|
+
order.products.first.taxons << taxon2
|
|
56
|
+
rule.taxons << taxon2
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it{ expect(rule).to be_eligible(order) }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'with all match policy' do
|
|
64
|
+
before do
|
|
65
|
+
rule.preferred_match_policy = 'all'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'is eligible order has all prefered taxons' do
|
|
69
|
+
order.products.first.taxons << taxon2
|
|
70
|
+
order.products.last.taxons << taxon
|
|
71
|
+
|
|
72
|
+
rule.taxons = [taxon, taxon2]
|
|
73
|
+
|
|
74
|
+
expect(rule).to be_eligible(order)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "when order does not have all prefered taxons" do
|
|
78
|
+
before { rule.taxons << taxon }
|
|
79
|
+
it { expect(rule).not_to be_eligible(order) }
|
|
80
|
+
it "sets an error message" do
|
|
81
|
+
rule.eligible?(order)
|
|
82
|
+
expect(rule.eligibility_errors.full_messages.first).
|
|
83
|
+
to eq "You need to add a product from all applicable categories before applying this coupon code."
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'when a product has a taxon child of a taxon rule' do
|
|
88
|
+
let(:taxon3){ create :taxon }
|
|
89
|
+
|
|
90
|
+
before do
|
|
91
|
+
taxon.children << taxon2
|
|
92
|
+
order.products.first.taxons << taxon2
|
|
93
|
+
order.products.last.taxons << taxon3
|
|
94
|
+
rule.taxons << taxon2
|
|
95
|
+
rule.taxons << taxon3
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it{ expect(rule).to be_eligible(order) }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Promotion::Rules::UserLoggedIn, :type => :model do
|
|
4
|
+
let(:rule) { Spree::Promotion::Rules::UserLoggedIn.new }
|
|
5
|
+
|
|
6
|
+
context "#eligible?(order)" do
|
|
7
|
+
let(:order) { Spree::Order.new }
|
|
8
|
+
|
|
9
|
+
it "should be eligible if order has an associated user" do
|
|
10
|
+
user = double('User')
|
|
11
|
+
allow(order).to receive_messages(:user => user)
|
|
12
|
+
|
|
13
|
+
expect(rule).to be_eligible(order)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "when user is not logged in" do
|
|
17
|
+
before { allow(order).to receive_messages(:user => nil) } # better to be explicit here
|
|
18
|
+
it { expect(rule).not_to be_eligible(order) }
|
|
19
|
+
it "sets an error message" do
|
|
20
|
+
rule.eligible?(order)
|
|
21
|
+
expect(rule.eligibility_errors.full_messages.first).
|
|
22
|
+
to eq "You need to login before applying this coupon code."
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Promotion::Rules::User, :type => :model do
|
|
4
|
+
let(:rule) { Spree::Promotion::Rules::User.new }
|
|
5
|
+
|
|
6
|
+
context "#eligible?(order)" do
|
|
7
|
+
let(:order) { Spree::Order.new }
|
|
8
|
+
|
|
9
|
+
it "should not be eligible if users are not provided" do
|
|
10
|
+
expect(rule).not_to be_eligible(order)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should be eligible if users include user placing the order" do
|
|
14
|
+
user = mock_model(Spree::LegacyUser)
|
|
15
|
+
users = [user, mock_model(Spree::LegacyUser)]
|
|
16
|
+
allow(rule).to receive_messages(:users => users)
|
|
17
|
+
allow(order).to receive_messages(:user => user)
|
|
18
|
+
|
|
19
|
+
expect(rule).to be_eligible(order)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should not be eligible if user placing the order is not listed" do
|
|
23
|
+
allow(order).to receive_messages(:user => mock_model(Spree::LegacyUser))
|
|
24
|
+
users = [mock_model(Spree::LegacyUser), mock_model(Spree::LegacyUser)]
|
|
25
|
+
allow(rule).to receive_messages(:users => users)
|
|
26
|
+
|
|
27
|
+
expect(rule).not_to be_eligible(order)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Regression test for #3885
|
|
31
|
+
it "can assign to user_ids" do
|
|
32
|
+
user1 = Spree::LegacyUser.create!(:email => "test1@example.com")
|
|
33
|
+
user2 = Spree::LegacyUser.create!(:email => "test2@example.com")
|
|
34
|
+
expect { rule.user_ids = "#{user1.id}, #{user2.id}" }.not_to raise_error
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::PromotionBuilder do
|
|
4
|
+
let(:promotion) { build(:promotion) }
|
|
5
|
+
let(:base_code) { 'abc' }
|
|
6
|
+
let(:number_of_codes) { 1 }
|
|
7
|
+
let(:promotion_attrs) { { name: 'some promo' } }
|
|
8
|
+
let(:builder) { Spree::PromotionBuilder.new(
|
|
9
|
+
{
|
|
10
|
+
base_code: base_code,
|
|
11
|
+
number_of_codes: number_of_codes
|
|
12
|
+
},
|
|
13
|
+
promotion_attrs,
|
|
14
|
+
) }
|
|
15
|
+
|
|
16
|
+
describe '#initialize' do
|
|
17
|
+
subject { builder }
|
|
18
|
+
it 'has the right base code' do
|
|
19
|
+
expect(subject.base_code).to eq 'abc'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'has the right base code' do
|
|
23
|
+
expect(subject.number_of_codes).to eq 1
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#valid?' do
|
|
28
|
+
subject { builder.valid? }
|
|
29
|
+
|
|
30
|
+
it 'is true' do
|
|
31
|
+
expect(subject).to be
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'promotion is not valid' do
|
|
35
|
+
let(:promotion_attrs) { { name: nil } }
|
|
36
|
+
|
|
37
|
+
it 'is true' do
|
|
38
|
+
expect(subject).to_not be
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'has errors on the promotion' do
|
|
42
|
+
subject
|
|
43
|
+
expect(builder.errors).to_not be_empty
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context 'number of codes is invalid' do
|
|
48
|
+
let(:number_of_codes) { -1 }
|
|
49
|
+
|
|
50
|
+
it 'is false ' do
|
|
51
|
+
expect(subject).to_not be
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'validates numericality' do
|
|
55
|
+
subject
|
|
56
|
+
expect(builder.errors.full_messages).to eq ["Number of codes must be greater than 0"]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe '#number_of_codes=' do
|
|
62
|
+
it 'coerces a string' do
|
|
63
|
+
builder.number_of_codes = '3'
|
|
64
|
+
expect(builder.number_of_codes).to eq 3
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'is nil for empty string' do
|
|
68
|
+
builder.number_of_codes = ''
|
|
69
|
+
expect(builder.number_of_codes).to be_nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe "#perform" do
|
|
74
|
+
subject { builder.perform }
|
|
75
|
+
|
|
76
|
+
context 'when the builder is invalid' do
|
|
77
|
+
let(:number_of_codes) { 'sups' }
|
|
78
|
+
|
|
79
|
+
it 'returns false' do
|
|
80
|
+
expect(subject).to_not be
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context "when the builder is valid" do
|
|
85
|
+
context "when the builder cant build promotion codes" do
|
|
86
|
+
let(:number_of_codes) { nil }
|
|
87
|
+
|
|
88
|
+
it "doesn't create any new codes" do
|
|
89
|
+
subject
|
|
90
|
+
expect(builder.promotion.codes).to be_empty
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context "when the builder can build promotion codes" do
|
|
95
|
+
let(:number_of_codes) { 1 }
|
|
96
|
+
|
|
97
|
+
it "creates the correct number of codes" do
|
|
98
|
+
subject
|
|
99
|
+
expect(builder.promotion.codes.length).to eq number_of_codes
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "creates the promotion with the correct code" do
|
|
103
|
+
subject
|
|
104
|
+
expect(builder.promotion.codes.first.value).to eq base_code
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "saves the promotion" do
|
|
109
|
+
subject
|
|
110
|
+
expect(builder.promotion).to be_persisted
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "returns true on success" do
|
|
114
|
+
expect(subject).to be true
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::PromotionCategory, :type => :model do
|
|
4
|
+
describe 'validation' do
|
|
5
|
+
let(:name) { 'Nom' }
|
|
6
|
+
subject { Spree::PromotionCategory.new name: name }
|
|
7
|
+
|
|
8
|
+
context 'when all required attributes are specified' do
|
|
9
|
+
it { is_expected.to be_valid }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context 'when name is missing' do
|
|
13
|
+
let(:name) { nil }
|
|
14
|
+
it { is_expected.not_to be_valid }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::PromotionCode::CodeBuilder do
|
|
4
|
+
let(:promotion) { build_stubbed :promotion }
|
|
5
|
+
let(:base_code) { "abc" }
|
|
6
|
+
let(:builder) do
|
|
7
|
+
described_class.new promotion, base_code, num_codes
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "#build_promotion_codes" do
|
|
11
|
+
subject { builder.build_promotion_codes }
|
|
12
|
+
|
|
13
|
+
context "with one code" do
|
|
14
|
+
let(:num_codes) { 1 }
|
|
15
|
+
|
|
16
|
+
it "builds a single promotion code" do
|
|
17
|
+
subject
|
|
18
|
+
expect(builder.promotion.codes.size).to eq(num_codes)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "creates the promotion code with the correct value" do
|
|
22
|
+
subject
|
|
23
|
+
expect(builder.promotion.codes.first.value).to eq base_code
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with more than one code" do
|
|
28
|
+
let(:num_codes) { 2 }
|
|
29
|
+
|
|
30
|
+
it "builds the correct number of codes" do
|
|
31
|
+
subject
|
|
32
|
+
expect(builder.promotion.codes.size).to eq(num_codes)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "builds codes with distinct values" do
|
|
36
|
+
subject
|
|
37
|
+
expect(builder.promotion.codes.map(&:value).uniq.size).to eq(num_codes)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "builds codes with the same base prefix" do
|
|
41
|
+
subject
|
|
42
|
+
values = builder.promotion.codes.map &:value
|
|
43
|
+
expect(values.all? { |val| val.starts_with?("#{base_code}_") }).to be true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'when every possible code must be used' do
|
|
47
|
+
before do
|
|
48
|
+
@old_length = described_class.random_code_length
|
|
49
|
+
described_class.random_code_length = 1
|
|
50
|
+
end
|
|
51
|
+
after { described_class.random_code_length = @old_length }
|
|
52
|
+
|
|
53
|
+
let(:num_codes) { 26 }
|
|
54
|
+
|
|
55
|
+
it "resolves the collision" do
|
|
56
|
+
subject
|
|
57
|
+
expect(builder.promotion.codes.map(&:value).uniq.size).to eq(num_codes)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "when collisions occur" do
|
|
62
|
+
before do
|
|
63
|
+
@old_length = described_class.random_code_length
|
|
64
|
+
described_class.random_code_length = 1
|
|
65
|
+
end
|
|
66
|
+
after { described_class.random_code_length = @old_length }
|
|
67
|
+
|
|
68
|
+
let(:num_codes) { 25 } # every possible code except 1
|
|
69
|
+
|
|
70
|
+
it "resolves the collisions and returns the correct number of codes" do
|
|
71
|
+
subject
|
|
72
|
+
expect(builder.promotion.codes.map(&:value).uniq.size).to eq(num_codes)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Spree::PromotionCode do
|
|
4
|
+
context 'callbacks' do
|
|
5
|
+
subject { promotion_code.save }
|
|
6
|
+
|
|
7
|
+
describe '#downcase_value' do
|
|
8
|
+
let(:promotion) { create(:promotion, code: 'NewCoDe') }
|
|
9
|
+
let(:promotion_code) { promotion.codes.first }
|
|
10
|
+
|
|
11
|
+
it 'downcases the value before saving' do
|
|
12
|
+
subject
|
|
13
|
+
expect(promotion_code.value).to eq('newcode')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "#usage_limit_exceeded?" do
|
|
19
|
+
subject { code.usage_limit_exceeded? }
|
|
20
|
+
|
|
21
|
+
shared_examples "it should" do
|
|
22
|
+
context "when there is a usage limit" do
|
|
23
|
+
context "and the limit is not exceeded" do
|
|
24
|
+
let(:usage_limit) { 10 }
|
|
25
|
+
it { is_expected.to be_falsy }
|
|
26
|
+
end
|
|
27
|
+
context "and the limit is exceeded" do
|
|
28
|
+
let(:usage_limit) { 1 }
|
|
29
|
+
context "on a different order" do
|
|
30
|
+
before do
|
|
31
|
+
FactoryGirl.create(
|
|
32
|
+
:completed_order_with_promotion,
|
|
33
|
+
promotion: promotion
|
|
34
|
+
)
|
|
35
|
+
code.adjustments.update_all(eligible: true)
|
|
36
|
+
end
|
|
37
|
+
it { is_expected.to be_truthy }
|
|
38
|
+
end
|
|
39
|
+
context "on the same order" do
|
|
40
|
+
it { is_expected.to be_falsy }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
context "when there is no usage limit" do
|
|
45
|
+
let(:usage_limit) { nil }
|
|
46
|
+
it { is_expected.to be_falsy }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
let(:code) { promotion.codes.first }
|
|
51
|
+
|
|
52
|
+
context "with an order-level adjustment" do
|
|
53
|
+
let(:promotion) do
|
|
54
|
+
FactoryGirl.create(
|
|
55
|
+
:promotion,
|
|
56
|
+
:with_order_adjustment,
|
|
57
|
+
code: "discount",
|
|
58
|
+
per_code_usage_limit: usage_limit
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
let(:promotable) do
|
|
62
|
+
FactoryGirl.create(
|
|
63
|
+
:completed_order_with_promotion,
|
|
64
|
+
promotion: promotion
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
it_behaves_like "it should"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "with an item-level adjustment" do
|
|
71
|
+
let(:promotion) do
|
|
72
|
+
FactoryGirl.create(
|
|
73
|
+
:promotion,
|
|
74
|
+
:with_line_item_adjustment,
|
|
75
|
+
code: "discount",
|
|
76
|
+
per_code_usage_limit: usage_limit
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
before do
|
|
80
|
+
promotion.actions.first.perform({
|
|
81
|
+
order: order,
|
|
82
|
+
promotion: promotion,
|
|
83
|
+
promotion_code: code
|
|
84
|
+
})
|
|
85
|
+
end
|
|
86
|
+
context "when there are multiple line items" do
|
|
87
|
+
let(:order) { FactoryGirl.create(:order_with_line_items, line_items_count: 2) }
|
|
88
|
+
describe "the first item" do
|
|
89
|
+
let(:promotable) { order.line_items.first }
|
|
90
|
+
it_behaves_like "it should"
|
|
91
|
+
end
|
|
92
|
+
describe "the second item" do
|
|
93
|
+
let(:promotable) { order.line_items.last }
|
|
94
|
+
it_behaves_like "it should"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
context "when there is a single line item" do
|
|
98
|
+
let(:order) { FactoryGirl.create(:order_with_line_items) }
|
|
99
|
+
let(:promotable) { order.line_items.first }
|
|
100
|
+
it_behaves_like "it should"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe "#usage_count" do
|
|
106
|
+
let(:promotion) do
|
|
107
|
+
FactoryGirl.create(
|
|
108
|
+
:promotion,
|
|
109
|
+
:with_order_adjustment,
|
|
110
|
+
code: "discount"
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
let(:code) { promotion.codes.first }
|
|
114
|
+
|
|
115
|
+
subject { code.usage_count }
|
|
116
|
+
|
|
117
|
+
context "when the code is applied to a non-complete order" do
|
|
118
|
+
let(:order) { FactoryGirl.create(:order_with_line_items) }
|
|
119
|
+
before { promotion.activate(order: order, promotion_code: code) }
|
|
120
|
+
it { is_expected.to eq 0 }
|
|
121
|
+
end
|
|
122
|
+
context "when the code is applied to a complete order" do
|
|
123
|
+
let!(:order) do
|
|
124
|
+
FactoryGirl.create(
|
|
125
|
+
:completed_order_with_promotion,
|
|
126
|
+
promotion: promotion
|
|
127
|
+
)
|
|
128
|
+
end
|
|
129
|
+
context "and the promo is eligible" do
|
|
130
|
+
it { is_expected.to eq 1 }
|
|
131
|
+
end
|
|
132
|
+
context "and the promo is ineligible" do
|
|
133
|
+
before { order.adjustments.promotion.update_all(eligible: false) }
|
|
134
|
+
it { is_expected.to eq 0 }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "completing multiple orders with the same code", slow: true do
|
|
140
|
+
let(:promotion) do
|
|
141
|
+
FactoryGirl.create(
|
|
142
|
+
:promotion,
|
|
143
|
+
:with_order_adjustment,
|
|
144
|
+
code: "discount",
|
|
145
|
+
per_code_usage_limit: 1
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
let(:code) { promotion.codes.first }
|
|
149
|
+
let(:order) do
|
|
150
|
+
FactoryGirl.create(:order_with_line_items).tap do |order|
|
|
151
|
+
FactoryGirl.create(:payment, amount: order.total, order: order)
|
|
152
|
+
promotion.activate(order: order, promotion_code: code)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
let(:promo_adjustment) { order.adjustments.promotion.first }
|
|
156
|
+
before do
|
|
157
|
+
order.next! until order.confirm?
|
|
158
|
+
|
|
159
|
+
FactoryGirl.create(:order_with_line_items).tap do |order|
|
|
160
|
+
FactoryGirl.create(:payment, amount: order.total, order: order)
|
|
161
|
+
promotion.activate(order: order, promotion_code: code)
|
|
162
|
+
order.next! until order.confirm?
|
|
163
|
+
order.complete!
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
it "makes the promotion ineligible" do
|
|
167
|
+
expect{
|
|
168
|
+
order.complete
|
|
169
|
+
}.to change{ promo_adjustment.reload.eligible }.to(false)
|
|
170
|
+
end
|
|
171
|
+
it "adjusts the promo_total" do
|
|
172
|
+
expect{
|
|
173
|
+
order.complete
|
|
174
|
+
}.to change(order, :promo_total).by(10)
|
|
175
|
+
end
|
|
176
|
+
it "adjusts the total" do
|
|
177
|
+
expect{
|
|
178
|
+
order.complete
|
|
179
|
+
}.to change(order, :total).by(10)
|
|
180
|
+
end
|
|
181
|
+
it "resets the state of the order" do
|
|
182
|
+
expect{
|
|
183
|
+
order.complete
|
|
184
|
+
}.to change{ order.reload.state }.from("confirm").to("address")
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|