spree_core 3.0.5 → 3.0.6
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 +4 -0
- data/Gemfile +3 -0
- data/Rakefile +30 -0
- data/app/assets/javascripts/spree.js.coffee.erb +1 -1
- data/app/models/spree/ability.rb +1 -1
- data/app/models/spree/base.rb +3 -1
- data/app/models/spree/order_updater.rb +2 -1
- data/app/models/spree/price.rb +7 -12
- data/app/models/spree/product.rb +3 -2
- data/app/models/spree/reimbursement.rb +1 -1
- data/app/models/spree/state.rb +2 -0
- data/app/models/spree/zone.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/testing_support/shoulda_matcher_configuration.rb +6 -0
- data/script/rails +9 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/helpers/base_helper_spec.rb +137 -0
- data/spec/helpers/products_helper_spec.rb +224 -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/spree/core/controller_helpers/auth_spec.rb +101 -0
- data/spec/lib/spree/core/controller_helpers/order_spec.rb +95 -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/delegate_belongs_to_spec.rb +22 -0
- data/spec/lib/spree/core/importer/order_spec.rb +502 -0
- data/spec/lib/spree/core/validators/email_spec.rb +53 -0
- data/spec/lib/spree/localized_number_spec.rb +38 -0
- data/spec/lib/spree/migrations_spec.rb +34 -0
- data/spec/lib/spree/money_spec.rb +122 -0
- data/spec/lib/tasks/exchanges_spec.rb +136 -0
- data/spec/mailers/order_mailer_spec.rb +124 -0
- data/spec/mailers/reimbursement_mailer_spec.rb +47 -0
- data/spec/mailers/shipment_mailer_spec.rb +63 -0
- data/spec/mailers/test_mailer_spec.rb +24 -0
- data/spec/models/spree/ability_spec.rb +246 -0
- data/spec/models/spree/address_spec.rb +291 -0
- data/spec/models/spree/adjustable/adjustments_updater_spec.rb +286 -0
- data/spec/models/spree/adjustment_spec.rb +163 -0
- data/spec/models/spree/app_configuration_spec.rb +23 -0
- data/spec/models/spree/asset_spec.rb +25 -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.rb +8 -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 +29 -0
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +40 -0
- data/spec/models/spree/calculator/tiered_percent_spec.rb +51 -0
- data/spec/models/spree/calculator_spec.rb +69 -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/country_spec.rb +18 -0
- data/spec/models/spree/credit_card_spec.rb +324 -0
- data/spec/models/spree/customer_return_spec.rb +262 -0
- data/spec/models/spree/exchange_spec.rb +75 -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 +54 -0
- data/spec/models/spree/image_spec.rb +5 -0
- data/spec/models/spree/inventory_unit_spec.rb +242 -0
- data/spec/models/spree/line_item_spec.rb +267 -0
- data/spec/models/spree/option_type_spec.rb +14 -0
- data/spec/models/spree/option_value_spec.rb +13 -0
- data/spec/models/spree/order/address_spec.rb +50 -0
- data/spec/models/spree/order/adjustments_spec.rb +29 -0
- data/spec/models/spree/order/callbacks_spec.rb +42 -0
- data/spec/models/spree/order/checkout_spec.rb +764 -0
- data/spec/models/spree/order/currency_updater_spec.rb +32 -0
- data/spec/models/spree/order/finalizing_spec.rb +117 -0
- data/spec/models/spree/order/helpers_spec.rb +5 -0
- data/spec/models/spree/order/payment_spec.rb +214 -0
- data/spec/models/spree/order/risk_assessment_spec.rb +84 -0
- data/spec/models/spree/order/shipments_spec.rb +43 -0
- data/spec/models/spree/order/state_machine_spec.rb +216 -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_contents_spec.rb +256 -0
- data/spec/models/spree/order_inventory_spec.rb +228 -0
- data/spec/models/spree/order_merger_spec.rb +133 -0
- data/spec/models/spree/order_spec.rb +954 -0
- data/spec/models/spree/order_updater_spec.rb +283 -0
- data/spec/models/spree/payment/gateway_options_spec.rb +119 -0
- data/spec/models/spree/payment_method_spec.rb +95 -0
- data/spec/models/spree/payment_spec.rb +926 -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 +348 -0
- data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
- data/spec/models/spree/preferences/store_spec.rb +46 -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_option_type_spec.rb +5 -0
- data/spec/models/spree/product_property_spec.rb +11 -0
- data/spec/models/spree/product_spec.rb +474 -0
- data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +50 -0
- data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +148 -0
- data/spec/models/spree/promotion/actions/create_line_items_spec.rb +86 -0
- data/spec/models/spree/promotion/actions/free_shipping_spec.rb +36 -0
- data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
- data/spec/models/spree/promotion/rules/item_total_spec.rb +282 -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 +90 -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_action_spec.rb +10 -0
- data/spec/models/spree/promotion_category_spec.rb +17 -0
- data/spec/models/spree/promotion_handler/cart_spec.rb +102 -0
- data/spec/models/spree/promotion_handler/coupon_spec.rb +323 -0
- data/spec/models/spree/promotion_handler/free_shipping_spec.rb +48 -0
- data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
- data/spec/models/spree/promotion_rule_spec.rb +29 -0
- data/spec/models/spree/promotion_spec.rb +603 -0
- data/spec/models/spree/property_spec.rb +5 -0
- data/spec/models/spree/prototype_spec.rb +5 -0
- data/spec/models/spree/refund_spec.rb +195 -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 +215 -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 +55 -0
- data/spec/models/spree/return_authorization_spec.rb +250 -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 +61 -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 +682 -0
- data/spec/models/spree/returns_calculator_spec.rb +14 -0
- data/spec/models/spree/shipment_spec.rb +740 -0
- data/spec/models/spree/shipping_calculator_spec.rb +45 -0
- data/spec/models/spree/shipping_category_spec.rb +5 -0
- data/spec/models/spree/shipping_method_spec.rb +88 -0
- data/spec/models/spree/shipping_rate_spec.rb +141 -0
- data/spec/models/spree/state_spec.rb +18 -0
- data/spec/models/spree/stock/availability_validator_spec.rb +36 -0
- data/spec/models/spree/stock/content_item_spec.rb +22 -0
- data/spec/models/spree/stock/coordinator_spec.rb +51 -0
- data/spec/models/spree/stock/differentiator_spec.rb +39 -0
- data/spec/models/spree/stock/estimator_spec.rb +154 -0
- data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
- data/spec/models/spree/stock/package_spec.rb +194 -0
- data/spec/models/spree/stock/packer_spec.rb +70 -0
- data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
- data/spec/models/spree/stock/quantifier_spec.rb +97 -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 +47 -0
- data/spec/models/spree/stock/splitter/weight_spec.rb +32 -0
- data/spec/models/spree/stock_item_spec.rb +410 -0
- data/spec/models/spree/stock_location_spec.rb +243 -0
- data/spec/models/spree/stock_movement_spec.rb +56 -0
- data/spec/models/spree/stock_transfer_spec.rb +50 -0
- data/spec/models/spree/store_spec.rb +50 -0
- data/spec/models/spree/tax_category_spec.rb +27 -0
- data/spec/models/spree/tax_rate_spec.rb +382 -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/user_spec.rb +130 -0
- data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +24 -0
- data/spec/models/spree/variant_spec.rb +523 -0
- data/spec/models/spree/zone_spec.rb +444 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/support/big_decimal.rb +5 -0
- data/spec/support/concerns/adjustment_source_spec.rb +23 -0
- data/spec/support/concerns/default_price_spec.rb +28 -0
- data/spec/support/rake.rb +13 -0
- data/spec/support/test_gateway.rb +2 -0
- data/spree_core.gemspec +48 -0
- metadata +185 -4
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
describe Estimator, :type => :model do
|
|
6
|
+
let!(:shipping_method) { create(:shipping_method) }
|
|
7
|
+
let(:package) { build(:stock_package, contents: inventory_units.map { |i| ContentItem.new(inventory_unit) }) }
|
|
8
|
+
let(:order) { build(:order_with_line_items) }
|
|
9
|
+
let(:inventory_units) { order.inventory_units }
|
|
10
|
+
|
|
11
|
+
subject { Estimator.new(order) }
|
|
12
|
+
|
|
13
|
+
context "#shipping rates" do
|
|
14
|
+
before(:each) do
|
|
15
|
+
shipping_method.zones.first.members.create(:zoneable => order.ship_address.country)
|
|
16
|
+
allow_any_instance_of(ShippingMethod).to receive_message_chain(:calculator, :available?).and_return(true)
|
|
17
|
+
allow_any_instance_of(ShippingMethod).to receive_message_chain(:calculator, :compute).and_return(4.00)
|
|
18
|
+
allow_any_instance_of(ShippingMethod).to receive_message_chain(:calculator, :preferences).and_return({:currency => currency})
|
|
19
|
+
allow_any_instance_of(ShippingMethod).to receive_message_chain(:calculator, :marked_for_destruction?)
|
|
20
|
+
|
|
21
|
+
allow(package).to receive_messages(:shipping_methods => [shipping_method])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:currency) { "USD" }
|
|
25
|
+
|
|
26
|
+
shared_examples_for "shipping rate matches" do
|
|
27
|
+
it "returns shipping rates" do
|
|
28
|
+
shipping_rates = subject.shipping_rates(package)
|
|
29
|
+
expect(shipping_rates.first.cost).to eq 4.00
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
shared_examples_for "shipping rate doesn't match" do
|
|
34
|
+
it "does not return shipping rates" do
|
|
35
|
+
shipping_rates = subject.shipping_rates(package)
|
|
36
|
+
expect(shipping_rates).to eq([])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "when the order's ship address is in the same zone" do
|
|
41
|
+
it_should_behave_like "shipping rate matches"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "when the order's ship address is in a different zone" do
|
|
45
|
+
before { shipping_method.zones.each{|z| z.members.delete_all} }
|
|
46
|
+
it_should_behave_like "shipping rate doesn't match"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "when the calculator is not available for that order" do
|
|
50
|
+
before { allow_any_instance_of(ShippingMethod).to receive_message_chain(:calculator, :available?).and_return(false) }
|
|
51
|
+
it_should_behave_like "shipping rate doesn't match"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "when the currency is nil" do
|
|
55
|
+
let(:currency) { nil }
|
|
56
|
+
it_should_behave_like "shipping rate matches"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "when the currency is an empty string" do
|
|
60
|
+
let(:currency) { "" }
|
|
61
|
+
it_should_behave_like "shipping rate matches"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "when the current matches the order's currency" do
|
|
65
|
+
it_should_behave_like "shipping rate matches"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "if the currency is different than the order's currency" do
|
|
69
|
+
let(:currency) { "GBP" }
|
|
70
|
+
it_should_behave_like "shipping rate doesn't match"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "when the shipping method's calculator raises an exception" do
|
|
74
|
+
before do
|
|
75
|
+
allow_any_instance_of(ShippingMethod).to receive_message_chain(:calculator, :available?).and_raise(Exception, "Something went wrong!")
|
|
76
|
+
expect(subject).to receive(:log_calculator_exception)
|
|
77
|
+
end
|
|
78
|
+
it_should_behave_like "shipping rate doesn't match"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "sorts shipping rates by cost" do
|
|
82
|
+
shipping_methods = 3.times.map { create(:shipping_method) }
|
|
83
|
+
allow(shipping_methods[0]).to receive_message_chain(:calculator, :compute).and_return(5.00)
|
|
84
|
+
allow(shipping_methods[1]).to receive_message_chain(:calculator, :compute).and_return(3.00)
|
|
85
|
+
allow(shipping_methods[2]).to receive_message_chain(:calculator, :compute).and_return(4.00)
|
|
86
|
+
|
|
87
|
+
allow(subject).to receive(:shipping_methods).and_return(shipping_methods)
|
|
88
|
+
|
|
89
|
+
expect(subject.shipping_rates(package).map(&:cost)).to eq %w[3.00 4.00 5.00].map(&BigDecimal.method(:new))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "general shipping methods" do
|
|
93
|
+
let(:shipping_methods) { 2.times.map { create(:shipping_method) } }
|
|
94
|
+
|
|
95
|
+
it "selects the most affordable shipping rate" do
|
|
96
|
+
allow(shipping_methods[0]).to receive_message_chain(:calculator, :compute).and_return(5.00)
|
|
97
|
+
allow(shipping_methods[1]).to receive_message_chain(:calculator, :compute).and_return(3.00)
|
|
98
|
+
|
|
99
|
+
allow(subject).to receive(:shipping_methods).and_return(shipping_methods)
|
|
100
|
+
|
|
101
|
+
expect(subject.shipping_rates(package).sort_by(&:cost).map(&:selected)).to eq [true, false]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "selects the most affordable shipping rate and doesn't raise exception over nil cost" do
|
|
105
|
+
allow(shipping_methods[0]).to receive_message_chain(:calculator, :compute).and_return(1.00)
|
|
106
|
+
allow(shipping_methods[1]).to receive_message_chain(:calculator, :compute).and_return(nil)
|
|
107
|
+
|
|
108
|
+
allow(subject).to receive(:shipping_methods).and_return(shipping_methods)
|
|
109
|
+
|
|
110
|
+
subject.shipping_rates(package)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context "involves backend only shipping methods" do
|
|
115
|
+
let(:backend_method) { create(:shipping_method, display_on: "back_end") }
|
|
116
|
+
let(:generic_method) { create(:shipping_method) }
|
|
117
|
+
|
|
118
|
+
before do
|
|
119
|
+
allow(backend_method).to receive_message_chain(:calculator, :compute).and_return(0.00)
|
|
120
|
+
allow(generic_method).to receive_message_chain(:calculator, :compute).and_return(5.00)
|
|
121
|
+
allow(package).to receive(:shipping_methods).and_return([backend_method, generic_method])
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "does not return backend rates at all" do
|
|
125
|
+
expect(subject.shipping_rates(package).map(&:shipping_method_id)).to eq([generic_method.id])
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# regression for #3287
|
|
129
|
+
it "doesn't select backend rates even if they're more affordable" do
|
|
130
|
+
expect(subject.shipping_rates(package).map(&:selected)).to eq [true]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "includes tax adjustments if applicable" do
|
|
135
|
+
let!(:tax_rate) { create(:tax_rate, zone: order.tax_zone) }
|
|
136
|
+
|
|
137
|
+
before do
|
|
138
|
+
Spree::ShippingMethod.all.each do |sm|
|
|
139
|
+
sm.tax_category_id = tax_rate.tax_category_id
|
|
140
|
+
sm.save
|
|
141
|
+
end
|
|
142
|
+
package.shipping_methods.map(&:reload)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
it "links the shipping rate and the tax rate" do
|
|
147
|
+
shipping_rates = subject.shipping_rates(package)
|
|
148
|
+
expect(shipping_rates.first.tax_rate).to eq(tax_rate)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
describe InventoryUnitBuilder, :type => :model do
|
|
6
|
+
let(:line_item_1) { build(:line_item) }
|
|
7
|
+
let(:line_item_2) { build(:line_item, quantity: 2) }
|
|
8
|
+
let(:order) { build(:order, line_items: [line_item_1, line_item_2]) }
|
|
9
|
+
|
|
10
|
+
subject { InventoryUnitBuilder.new(order) }
|
|
11
|
+
|
|
12
|
+
describe "#units" do
|
|
13
|
+
it "returns an inventory unit for each quantity for the order's line items" do
|
|
14
|
+
units = subject.units
|
|
15
|
+
expect(units.count).to eq 3
|
|
16
|
+
expect(units.first.line_item).to eq line_item_1
|
|
17
|
+
expect(units.first.variant).to eq line_item_1.variant
|
|
18
|
+
|
|
19
|
+
expect(units[1].line_item).to eq line_item_2
|
|
20
|
+
expect(units[1].variant).to eq line_item_2.variant
|
|
21
|
+
|
|
22
|
+
expect(units[2].line_item).to eq line_item_2
|
|
23
|
+
expect(units[2].variant).to eq line_item_2.variant
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "builds the inventory units as pending" do
|
|
27
|
+
expect(subject.units.map(&:pending).uniq).to eq [true]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "associates the inventory units to the order" do
|
|
31
|
+
expect(subject.units.map(&:order).uniq).to eq [order]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
describe Package, :type => :model do
|
|
6
|
+
let(:variant) { build(:variant, weight: 25.0) }
|
|
7
|
+
let(:stock_location) { build(:stock_location) }
|
|
8
|
+
let(:order) { build(:order) }
|
|
9
|
+
|
|
10
|
+
subject { Package.new(stock_location) }
|
|
11
|
+
|
|
12
|
+
def build_inventory_unit
|
|
13
|
+
build(:inventory_unit, variant: variant)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'calculates the weight of all the contents' do
|
|
17
|
+
4.times { subject.add build_inventory_unit }
|
|
18
|
+
expect(subject.weight).to eq(100.0)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "currency" do
|
|
22
|
+
let(:unit) { build_inventory_unit }
|
|
23
|
+
before { subject.add unit }
|
|
24
|
+
|
|
25
|
+
it "returns the currency based on the currency from the order" do
|
|
26
|
+
expect(subject.currency).to eql "USD"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'filters by on_hand and backordered' do
|
|
31
|
+
4.times { subject.add build_inventory_unit }
|
|
32
|
+
3.times { subject.add build_inventory_unit, :backordered }
|
|
33
|
+
expect(subject.on_hand.count).to eq 4
|
|
34
|
+
expect(subject.backordered.count).to eq 3
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'calculates the quantity by state' do
|
|
38
|
+
4.times { subject.add build_inventory_unit }
|
|
39
|
+
3.times { subject.add build_inventory_unit, :backordered }
|
|
40
|
+
|
|
41
|
+
expect(subject.quantity).to eq 7
|
|
42
|
+
expect(subject.quantity(:on_hand)).to eq 4
|
|
43
|
+
expect(subject.quantity(:backordered)).to eq 3
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'returns nil for content item not found' do
|
|
47
|
+
unit = build_inventory_unit
|
|
48
|
+
item = subject.find_item(unit, :on_hand)
|
|
49
|
+
expect(item).to be_nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'finds content item for an inventory unit' do
|
|
53
|
+
unit = build_inventory_unit
|
|
54
|
+
subject.add unit
|
|
55
|
+
item = subject.find_item(unit, :on_hand)
|
|
56
|
+
expect(item.quantity).to eq 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Contains regression test for #2804
|
|
60
|
+
it 'builds a list of shipping methods common to all categories' do
|
|
61
|
+
category1 = create(:shipping_category)
|
|
62
|
+
category2 = create(:shipping_category)
|
|
63
|
+
method1 = create(:shipping_method)
|
|
64
|
+
method2 = create(:shipping_method)
|
|
65
|
+
method1.shipping_categories = [category1, category2]
|
|
66
|
+
method2.shipping_categories = [category1]
|
|
67
|
+
variant1 = mock_model(Variant, shipping_category: category1)
|
|
68
|
+
variant2 = mock_model(Variant, shipping_category: category2)
|
|
69
|
+
variant3 = mock_model(Variant, shipping_category: nil)
|
|
70
|
+
contents = [ContentItem.new(build(:inventory_unit, variant: variant1)),
|
|
71
|
+
ContentItem.new(build(:inventory_unit, variant: variant1)),
|
|
72
|
+
ContentItem.new(build(:inventory_unit, variant: variant2)),
|
|
73
|
+
ContentItem.new(build(:inventory_unit, variant: variant3))]
|
|
74
|
+
|
|
75
|
+
package = Package.new(stock_location, contents)
|
|
76
|
+
expect(package.shipping_methods).to eq([method1])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'builds an empty list of shipping methods when no categories' do
|
|
80
|
+
variant = mock_model(Variant, shipping_category: nil)
|
|
81
|
+
contents = [ContentItem.new(build(:inventory_unit, variant: variant))]
|
|
82
|
+
package = Package.new(stock_location, contents)
|
|
83
|
+
expect(package.shipping_methods).to be_empty
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "can convert to a shipment" do
|
|
87
|
+
2.times { subject.add build_inventory_unit }
|
|
88
|
+
subject.add build_inventory_unit, :backordered
|
|
89
|
+
|
|
90
|
+
shipping_method = build(:shipping_method)
|
|
91
|
+
subject.shipping_rates = [ Spree::ShippingRate.new(shipping_method: shipping_method, cost: 10.00, selected: true) ]
|
|
92
|
+
|
|
93
|
+
shipment = subject.to_shipment
|
|
94
|
+
expect(shipment.stock_location).to eq subject.stock_location
|
|
95
|
+
expect(shipment.inventory_units.size).to eq 3
|
|
96
|
+
|
|
97
|
+
first_unit = shipment.inventory_units.first
|
|
98
|
+
expect(first_unit.variant).to eq variant
|
|
99
|
+
expect(first_unit.state).to eq 'on_hand'
|
|
100
|
+
expect(first_unit).to be_pending
|
|
101
|
+
|
|
102
|
+
last_unit = shipment.inventory_units.last
|
|
103
|
+
expect(last_unit.variant).to eq variant
|
|
104
|
+
expect(last_unit.state).to eq 'backordered'
|
|
105
|
+
|
|
106
|
+
expect(shipment.shipping_method).to eq shipping_method
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'does not add an inventory unit to a package twice' do
|
|
110
|
+
# since inventory units currently don't have a quantity
|
|
111
|
+
unit = build_inventory_unit
|
|
112
|
+
subject.add unit
|
|
113
|
+
subject.add unit
|
|
114
|
+
expect(subject.quantity).to eq 1
|
|
115
|
+
expect(subject.contents.first.inventory_unit).to eq unit
|
|
116
|
+
expect(subject.contents.first.quantity).to eq 1
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe "#add_multiple" do
|
|
120
|
+
it "adds multiple inventory units" do
|
|
121
|
+
expect { subject.add_multiple [build_inventory_unit, build_inventory_unit] }.to change { subject.quantity }.by(2)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "allows adding with a state" do
|
|
125
|
+
expect { subject.add_multiple [build_inventory_unit, build_inventory_unit], :backordered }.to change { subject.backordered.count }.by(2)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "defaults to adding with the on hand state" do
|
|
129
|
+
expect { subject.add_multiple [build_inventory_unit, build_inventory_unit] }.to change { subject.on_hand.count }.by(2)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe "#remove" do
|
|
134
|
+
let(:unit) { build_inventory_unit }
|
|
135
|
+
context "there is a content item for the inventory unit" do
|
|
136
|
+
|
|
137
|
+
before { subject.add unit }
|
|
138
|
+
|
|
139
|
+
it "removes that content item" do
|
|
140
|
+
expect { subject.remove(unit) }.to change { subject.quantity }.by(-1)
|
|
141
|
+
expect(subject.contents.map(&:inventory_unit)).not_to include unit
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context "there is no content item for the inventory unit" do
|
|
146
|
+
it "doesn't change the set of content items" do
|
|
147
|
+
expect { subject.remove(unit) }.not_to change { subject.quantity }
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe "#order" do
|
|
153
|
+
let(:unit) { build_inventory_unit }
|
|
154
|
+
context "there is an inventory unit" do
|
|
155
|
+
|
|
156
|
+
before { subject.add unit }
|
|
157
|
+
|
|
158
|
+
it "returns an order" do
|
|
159
|
+
expect(subject.order).to be_a_kind_of Spree::Order
|
|
160
|
+
expect(subject.order).to eq unit.order
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "there is no inventory unit" do
|
|
165
|
+
it "returns nil" do
|
|
166
|
+
expect(subject.order).to eq nil
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context "#volume" do
|
|
172
|
+
it "calculates the sum of the volume of all the items" do
|
|
173
|
+
contents = [ContentItem.new(build(:inventory_unit, variant: build(:variant))),
|
|
174
|
+
ContentItem.new(build(:inventory_unit, variant: build(:variant))),
|
|
175
|
+
ContentItem.new(build(:inventory_unit, variant: build(:variant))),
|
|
176
|
+
ContentItem.new(build(:inventory_unit, variant: build(:variant)))]
|
|
177
|
+
package = Package.new(stock_location, contents)
|
|
178
|
+
expect(package.volume).to eq contents.sum(&:volume)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
context "#dimension" do
|
|
183
|
+
it "calculates the sum of the dimension of all the items" do
|
|
184
|
+
contents = [ContentItem.new(build(:inventory_unit, variant: build(:variant))),
|
|
185
|
+
ContentItem.new(build(:inventory_unit, variant: build(:variant))),
|
|
186
|
+
ContentItem.new(build(:inventory_unit, variant: build(:variant))),
|
|
187
|
+
ContentItem.new(build(:inventory_unit, variant: build(:variant)))]
|
|
188
|
+
package = Package.new(stock_location, contents)
|
|
189
|
+
expect(package.dimension).to eq contents.sum(&:dimension)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
describe Packer, :type => :model do
|
|
6
|
+
let(:inventory_units) { [InventoryUnit.new(variant: create(:variant))] }
|
|
7
|
+
let(:stock_location) { create(:stock_location) }
|
|
8
|
+
|
|
9
|
+
subject { Packer.new(stock_location, inventory_units) }
|
|
10
|
+
|
|
11
|
+
context 'packages' do
|
|
12
|
+
it 'builds an array of packages' do
|
|
13
|
+
packages = subject.packages
|
|
14
|
+
expect(packages).to be_a Array
|
|
15
|
+
expect(packages.first).to be_a Package
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'allows users to set splitters to an empty array' do
|
|
19
|
+
packer = Packer.new(StockLocation.new, [], [])
|
|
20
|
+
expect(packer).not_to receive(:build_splitter)
|
|
21
|
+
packages = packer.packages
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'default_package' do
|
|
26
|
+
let!(:inventory_units) { 2.times.map { InventoryUnit.new variant: create(:variant) } }
|
|
27
|
+
|
|
28
|
+
it 'contains all the items' do
|
|
29
|
+
package = subject.default_package
|
|
30
|
+
expect(package.contents.size).to eq 2
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'variants are added as backordered without enough on_hand' do
|
|
34
|
+
expect(stock_location).to receive(:fill_status).exactly(2).times.and_return(
|
|
35
|
+
*(Array.new(1, [1,0]) + Array.new(1, [0,1]))
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
package = subject.default_package
|
|
39
|
+
expect(package.on_hand.size).to eq 1
|
|
40
|
+
expect(package.backordered.size).to eq 1
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "location doesn't have order items in stock" do
|
|
44
|
+
let(:stock_location) { create(:stock_location, propagate_all_variants: false) }
|
|
45
|
+
let(:inventory_units) { [InventoryUnit.new(variant: create(:variant))] }
|
|
46
|
+
let(:packer) { Packer.new(stock_location, inventory_units) }
|
|
47
|
+
|
|
48
|
+
it "builds an empty package" do
|
|
49
|
+
expect(packer.default_package.contents).to be_empty
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "doesn't track inventory levels" do
|
|
54
|
+
let(:inventory_units) { 2.times.map { InventoryUnit.new(variant: create(:variant)) } }
|
|
55
|
+
|
|
56
|
+
before { Config.track_inventory_levels = false }
|
|
57
|
+
|
|
58
|
+
it "doesn't bother stock items status in stock location" do
|
|
59
|
+
expect(subject.stock_location).not_to receive(:fill_status)
|
|
60
|
+
subject.default_package
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "still creates package with proper quantity" do
|
|
64
|
+
expect(subject.default_package.quantity).to eql 2
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|