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,1412 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class FakeCalculator < Spree::Calculator
|
|
4
|
+
def compute(computable)
|
|
5
|
+
5
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe Spree::Order, :type => :model do
|
|
10
|
+
let(:user) { stub_model(Spree::LegacyUser, :email => "spree@example.com") }
|
|
11
|
+
let(:order) { stub_model(Spree::Order, :user => user) }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
allow(Spree::LegacyUser).to receive_messages(:current => mock_model(Spree::LegacyUser, :id => 123))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "#canceled_by" do
|
|
18
|
+
let(:admin_user) { create :admin_user }
|
|
19
|
+
let(:order) { create :order }
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
allow(order).to receive(:cancel!)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
subject { order.canceled_by(admin_user) }
|
|
26
|
+
|
|
27
|
+
it 'should cancel the order' do
|
|
28
|
+
expect(order).to receive(:cancel!)
|
|
29
|
+
subject
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should save canceler_id' do
|
|
33
|
+
subject
|
|
34
|
+
expect(order.reload.canceler_id).to eq(admin_user.id)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should save canceled_at' do
|
|
38
|
+
subject
|
|
39
|
+
expect(order.reload.canceled_at).to_not be_nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'should have canceler' do
|
|
43
|
+
subject
|
|
44
|
+
expect(order.reload.canceler).to eq(admin_user)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "#create" do
|
|
49
|
+
let(:order) { Spree::Order.create }
|
|
50
|
+
|
|
51
|
+
it "should assign an order number" do
|
|
52
|
+
expect(order.number).not_to be_nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'should create a randomized 22 character token' do
|
|
56
|
+
expect(order.guest_token.size).to eq(22)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "creates shipments cost" do
|
|
61
|
+
let(:shipment) { double }
|
|
62
|
+
|
|
63
|
+
before { allow(order).to receive_messages shipments: [shipment] }
|
|
64
|
+
|
|
65
|
+
it "update and persist totals" do
|
|
66
|
+
expect(shipment).to receive :update_amounts
|
|
67
|
+
expect(order.updater).to receive :update_shipment_total
|
|
68
|
+
expect(order.updater).to receive :persist_totals
|
|
69
|
+
|
|
70
|
+
order.set_shipments_cost
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "insufficient_stock_lines" do
|
|
75
|
+
let(:line_item) { mock_model Spree::LineItem, :insufficient_stock? => true }
|
|
76
|
+
|
|
77
|
+
before { allow(order).to receive_messages(:line_items => [line_item]) }
|
|
78
|
+
|
|
79
|
+
it "should return line_item that has insufficient stock on hand" do
|
|
80
|
+
expect(order.insufficient_stock_lines.size).to eq(1)
|
|
81
|
+
expect(order.insufficient_stock_lines.include?(line_item)).to be true
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe '#ensure_line_item_variants_are_not_deleted' do
|
|
86
|
+
subject { order.ensure_line_item_variants_are_not_deleted }
|
|
87
|
+
|
|
88
|
+
let(:order) { create :order_with_line_items }
|
|
89
|
+
|
|
90
|
+
context 'when variant is destroyed' do
|
|
91
|
+
before do
|
|
92
|
+
allow(order).to receive(:restart_checkout_flow)
|
|
93
|
+
order.line_items.first.variant.destroy
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should restart checkout flow' do
|
|
97
|
+
expect(order).to receive(:restart_checkout_flow).once
|
|
98
|
+
subject
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'should have error message' do
|
|
102
|
+
subject
|
|
103
|
+
expect(order.errors[:base]).to include(Spree.t(:deleted_variants_present))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'should be false' do
|
|
107
|
+
expect(subject).to be_falsey
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context 'when no variants are destroyed' do
|
|
112
|
+
it 'should not restart checkout' do
|
|
113
|
+
expect(order).to receive(:restart_checkout_flow).never
|
|
114
|
+
subject
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'should be true' do
|
|
118
|
+
expect(subject).to be_truthy
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context "empty!" do
|
|
124
|
+
let(:order) { stub_model(Spree::Order, item_count: 2) }
|
|
125
|
+
|
|
126
|
+
before do
|
|
127
|
+
allow(order).to receive_messages(:line_items => line_items = [1, 2])
|
|
128
|
+
allow(order).to receive_messages(:adjustments => adjustments = [])
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "clears out line items, adjustments and update totals" do
|
|
132
|
+
expect(order.line_items).to receive(:destroy_all)
|
|
133
|
+
expect(order.adjustments).to receive(:destroy_all)
|
|
134
|
+
expect(order.shipments).to receive(:destroy_all)
|
|
135
|
+
expect(order.updater).to receive(:update_totals)
|
|
136
|
+
expect(order.updater).to receive(:persist_totals)
|
|
137
|
+
|
|
138
|
+
order.empty!
|
|
139
|
+
expect(order.item_total).to eq 0
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context "#display_outstanding_balance" do
|
|
144
|
+
it "returns the value as a spree money" do
|
|
145
|
+
allow(order).to receive(:outstanding_balance) { 10.55 }
|
|
146
|
+
expect(order.display_outstanding_balance).to eq(Spree::Money.new(10.55))
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
context "#display_item_total" do
|
|
151
|
+
it "returns the value as a spree money" do
|
|
152
|
+
allow(order).to receive(:item_total) { 10.55 }
|
|
153
|
+
expect(order.display_item_total).to eq(Spree::Money.new(10.55))
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context "#display_adjustment_total" do
|
|
158
|
+
it "returns the value as a spree money" do
|
|
159
|
+
order.adjustment_total = 10.55
|
|
160
|
+
expect(order.display_adjustment_total).to eq(Spree::Money.new(10.55))
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "#display_total" do
|
|
165
|
+
it "returns the value as a spree money" do
|
|
166
|
+
order.total = 10.55
|
|
167
|
+
expect(order.display_total).to eq(Spree::Money.new(10.55))
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context "#currency" do
|
|
172
|
+
context "when object currency is ABC" do
|
|
173
|
+
before { order.currency = "ABC" }
|
|
174
|
+
|
|
175
|
+
it "returns the currency from the object" do
|
|
176
|
+
expect(order.currency).to eq("ABC")
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context "when object currency is nil" do
|
|
181
|
+
before { order.currency = nil }
|
|
182
|
+
|
|
183
|
+
it "returns the globally configured currency" do
|
|
184
|
+
expect(order.currency).to eq("USD")
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Regression tests for #2179
|
|
190
|
+
context "#merge!" do
|
|
191
|
+
let(:variant) { create(:variant) }
|
|
192
|
+
let(:order_1) { Spree::Order.create }
|
|
193
|
+
let(:order_2) { Spree::Order.create }
|
|
194
|
+
|
|
195
|
+
it "destroys the other order" do
|
|
196
|
+
order_1.merge!(order_2)
|
|
197
|
+
expect { order_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
context "user is provided" do
|
|
201
|
+
it "assigns user to new order" do
|
|
202
|
+
order_1.merge!(order_2, user)
|
|
203
|
+
expect(order_1.user).to eq user
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
context "merging together two orders with line items for the same variant" do
|
|
208
|
+
before do
|
|
209
|
+
order_1.contents.add(variant, 1)
|
|
210
|
+
order_2.contents.add(variant, 1)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
specify do
|
|
214
|
+
order_1.merge!(order_2)
|
|
215
|
+
expect(order_1.line_items.count).to eq(1)
|
|
216
|
+
|
|
217
|
+
line_item = order_1.line_items.first
|
|
218
|
+
expect(line_item.quantity).to eq(2)
|
|
219
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context "merging using extension-specific line_item_comparison_hooks" do
|
|
225
|
+
before do
|
|
226
|
+
Spree::Order.register_line_item_comparison_hook(:foos_match)
|
|
227
|
+
allow(Spree::Variant).to receive(:price_modifier_amount).and_return(0.00)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
after do
|
|
231
|
+
# reset to avoid test pollution
|
|
232
|
+
Spree::Order.line_item_comparison_hooks = Set.new
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
context "2 equal line items" do
|
|
236
|
+
before do
|
|
237
|
+
@line_item_1 = order_1.contents.add(variant, 1, {foos: {}})
|
|
238
|
+
@line_item_2 = order_2.contents.add(variant, 1, {foos: {}})
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
specify do
|
|
242
|
+
expect(order_1).to receive(:foos_match).with(@line_item_1, kind_of(Hash)).and_return(true)
|
|
243
|
+
order_1.merge!(order_2)
|
|
244
|
+
expect(order_1.line_items.count).to eq(1)
|
|
245
|
+
|
|
246
|
+
line_item = order_1.line_items.first
|
|
247
|
+
expect(line_item.quantity).to eq(2)
|
|
248
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
context "2 different line items" do
|
|
253
|
+
before do
|
|
254
|
+
allow(order_1).to receive(:foos_match).and_return(false)
|
|
255
|
+
|
|
256
|
+
order_1.contents.add(variant, 1, {foos: {}})
|
|
257
|
+
order_2.contents.add(variant, 1, {foos: {bar: :zoo}})
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
specify do
|
|
261
|
+
order_1.merge!(order_2)
|
|
262
|
+
expect(order_1.line_items.count).to eq(2)
|
|
263
|
+
|
|
264
|
+
line_item = order_1.line_items.first
|
|
265
|
+
expect(line_item.quantity).to eq(1)
|
|
266
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
267
|
+
|
|
268
|
+
line_item = order_1.line_items.last
|
|
269
|
+
expect(line_item.quantity).to eq(1)
|
|
270
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
context "merging together two orders with different line items" do
|
|
276
|
+
let(:variant_2) { create(:variant) }
|
|
277
|
+
|
|
278
|
+
before do
|
|
279
|
+
order_1.contents.add(variant, 1)
|
|
280
|
+
order_2.contents.add(variant_2, 1)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
specify do
|
|
284
|
+
order_1.merge!(order_2)
|
|
285
|
+
line_items = order_1.line_items.reload
|
|
286
|
+
expect(line_items.count).to eq(2)
|
|
287
|
+
|
|
288
|
+
expect(order_1.item_count).to eq 2
|
|
289
|
+
expect(order_1.item_total).to eq line_items.map(&:amount).sum
|
|
290
|
+
|
|
291
|
+
# No guarantee on ordering of line items, so we do this:
|
|
292
|
+
expect(line_items.pluck(:quantity)).to match_array([1, 1])
|
|
293
|
+
expect(line_items.pluck(:variant_id)).to match_array([variant.id, variant_2.id])
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
context "add_update_hook" do
|
|
299
|
+
before do
|
|
300
|
+
Spree::Order.class_eval do
|
|
301
|
+
register_update_hook :add_awesome_sauce
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
after do
|
|
306
|
+
Spree::Order.update_hooks = Set.new
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "calls hook during update" do
|
|
310
|
+
order = create(:order)
|
|
311
|
+
expect(order).to receive(:add_awesome_sauce)
|
|
312
|
+
order.update!
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "calls hook during finalize" do
|
|
316
|
+
order = create(:order)
|
|
317
|
+
expect(order).to receive(:add_awesome_sauce)
|
|
318
|
+
order.finalize!
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context "ensure shipments will be updated" do
|
|
323
|
+
before do
|
|
324
|
+
Spree::Shipment.create!(order: order)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
['payment', 'confirm'].each do |order_state|
|
|
328
|
+
context "when ther order is in the #{order_state} state" do
|
|
329
|
+
before do
|
|
330
|
+
order.state = order_state
|
|
331
|
+
order.shipments.create!
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it "destroys current shipments" do
|
|
335
|
+
order.ensure_updated_shipments
|
|
336
|
+
expect(order.shipments).to be_empty
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "puts order back in address state" do
|
|
340
|
+
order.ensure_updated_shipments
|
|
341
|
+
expect(order.state).to eql "cart"
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it "resets shipment_total" do
|
|
345
|
+
order.update_column(:shipment_total, 5)
|
|
346
|
+
order.ensure_updated_shipments
|
|
347
|
+
expect(order.shipment_total).to eq(0)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it "does nothing if any shipments are ready" do
|
|
351
|
+
shipment = create(:shipment, order: subject, state: "ready")
|
|
352
|
+
expect { subject.ensure_updated_shipments }.not_to change { subject.reload.shipments }
|
|
353
|
+
expect { shipment.reload }.not_to raise_error
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it "does nothing if any shipments are shipped" do
|
|
357
|
+
shipment = create(:shipment, order: subject, state: "shipped")
|
|
358
|
+
expect { subject.ensure_updated_shipments }.not_to change { subject.reload.shipments }
|
|
359
|
+
expect { shipment.reload }.not_to raise_error
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'when the order is in address state' do
|
|
366
|
+
before do
|
|
367
|
+
order.state = 'address'
|
|
368
|
+
order.shipments.create!
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
it "destroys current shipments" do
|
|
372
|
+
order.ensure_updated_shipments
|
|
373
|
+
expect(order.shipments).to be_empty
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
it "resets shipment_total" do
|
|
377
|
+
order.update_column(:shipment_total, 5)
|
|
378
|
+
order.ensure_updated_shipments
|
|
379
|
+
expect(order.shipment_total).to eq(0)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
it "puts the order in the cart state" do
|
|
383
|
+
order.ensure_updated_shipments
|
|
384
|
+
expect(order.state).to eq "cart"
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
context 'when the order is completed' do
|
|
389
|
+
before do
|
|
390
|
+
order.state = 'complete'
|
|
391
|
+
order.completed_at = Time.now
|
|
392
|
+
order.update_column(:shipment_total, 5)
|
|
393
|
+
order.shipments.create!
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
it "does not destroy the current shipments" do
|
|
397
|
+
expect {
|
|
398
|
+
order.ensure_updated_shipments
|
|
399
|
+
}.not_to change { order.shipments }
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it "does not reset the shipment total" do
|
|
403
|
+
expect {
|
|
404
|
+
order.ensure_updated_shipments
|
|
405
|
+
}.not_to change { order.shipment_total }
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
it "does not put the order back in the address state" do
|
|
409
|
+
expect {
|
|
410
|
+
order.ensure_updated_shipments
|
|
411
|
+
}.not_to change { order.state }
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
context "except when order is completed, that's OrderInventory job" do
|
|
416
|
+
it "doesn't touch anything" do
|
|
417
|
+
allow(order).to receive_messages completed?: true
|
|
418
|
+
order.update_column(:shipment_total, 5)
|
|
419
|
+
order.shipments.create!
|
|
420
|
+
|
|
421
|
+
expect {
|
|
422
|
+
order.ensure_updated_shipments
|
|
423
|
+
}.not_to change { order.shipment_total }
|
|
424
|
+
|
|
425
|
+
expect {
|
|
426
|
+
order.ensure_updated_shipments
|
|
427
|
+
}.not_to change { order.shipments }
|
|
428
|
+
|
|
429
|
+
expect {
|
|
430
|
+
order.ensure_updated_shipments
|
|
431
|
+
}.not_to change { order.state }
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
describe "#tax_address" do
|
|
438
|
+
before { Spree::Config[:tax_using_ship_address] = tax_using_ship_address }
|
|
439
|
+
subject { order.tax_address }
|
|
440
|
+
|
|
441
|
+
context "when tax_using_ship_address is true" do
|
|
442
|
+
let(:tax_using_ship_address) { true }
|
|
443
|
+
|
|
444
|
+
it 'returns ship_address' do
|
|
445
|
+
expect(subject).to eq(order.ship_address)
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
context "when tax_using_ship_address is not true" do
|
|
450
|
+
let(:tax_using_ship_address) { false }
|
|
451
|
+
|
|
452
|
+
it "returns bill_address" do
|
|
453
|
+
expect(subject).to eq(order.bill_address)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
describe "#restart_checkout_flow" do
|
|
459
|
+
context "when in cart state" do
|
|
460
|
+
let(:order) { create(:order_with_totals, state: "cart") }
|
|
461
|
+
|
|
462
|
+
it "remains in cart state" do
|
|
463
|
+
expect { order.restart_checkout_flow }.not_to change { order.state }
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
it "updates the state column to the first checkout_steps value" do
|
|
467
|
+
order = create(:order_with_totals, state: "delivery")
|
|
468
|
+
expect(order.checkout_steps).to eql ["address", "delivery", "confirm", "complete"]
|
|
469
|
+
expect{ order.restart_checkout_flow }.to change{order.state}.from("delivery").to("address")
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
context "without line items" do
|
|
473
|
+
it "updates the state column to cart" do
|
|
474
|
+
order = create(:order, state: "delivery")
|
|
475
|
+
expect{ order.restart_checkout_flow }.to change{order.state}.from("delivery").to("cart")
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# Regression tests for #4072
|
|
481
|
+
context "#state_changed" do
|
|
482
|
+
let(:order) { FactoryGirl.create(:order) }
|
|
483
|
+
|
|
484
|
+
it "logs state changes" do
|
|
485
|
+
order.update_column(:payment_state, 'balance_due')
|
|
486
|
+
order.payment_state = 'paid'
|
|
487
|
+
expect(order.state_changes).to be_empty
|
|
488
|
+
order.state_changed('payment')
|
|
489
|
+
state_change = order.state_changes.find_by(:name => 'payment')
|
|
490
|
+
expect(state_change.previous_state).to eq('balance_due')
|
|
491
|
+
expect(state_change.next_state).to eq('paid')
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it "does not do anything if state does not change" do
|
|
495
|
+
order.update_column(:payment_state, 'balance_due')
|
|
496
|
+
expect(order.state_changes).to be_empty
|
|
497
|
+
order.state_changed('payment')
|
|
498
|
+
expect(order.state_changes).to be_empty
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
# Regression test for #4199
|
|
503
|
+
context "#available_payment_methods" do
|
|
504
|
+
it "includes frontend payment methods" do
|
|
505
|
+
payment_method = Spree::PaymentMethod.create!({
|
|
506
|
+
:name => "Fake",
|
|
507
|
+
:active => true,
|
|
508
|
+
:display_on => "front_end",
|
|
509
|
+
:environment => Rails.env
|
|
510
|
+
})
|
|
511
|
+
expect(order.available_payment_methods).to include(payment_method)
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
it "includes 'both' payment methods" do
|
|
515
|
+
payment_method = Spree::PaymentMethod.create!({
|
|
516
|
+
:name => "Fake",
|
|
517
|
+
:active => true,
|
|
518
|
+
:display_on => "both",
|
|
519
|
+
:environment => Rails.env
|
|
520
|
+
})
|
|
521
|
+
expect(order.available_payment_methods).to include(payment_method)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
it "does not include a payment method twice if display_on is blank" do
|
|
525
|
+
payment_method = Spree::PaymentMethod.create!({
|
|
526
|
+
:name => "Fake",
|
|
527
|
+
:active => true,
|
|
528
|
+
:display_on => "both",
|
|
529
|
+
:environment => Rails.env
|
|
530
|
+
})
|
|
531
|
+
expect(order.available_payment_methods.count).to eq(1)
|
|
532
|
+
expect(order.available_payment_methods).to include(payment_method)
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
context "#apply_free_shipping_promotions" do
|
|
537
|
+
it "calls out to the FreeShipping promotion handler" do
|
|
538
|
+
shipment = double('Shipment')
|
|
539
|
+
allow(order).to receive_messages :shipments => [shipment]
|
|
540
|
+
expect(Spree::PromotionHandler::FreeShipping).to receive(:new).and_return(handler = double)
|
|
541
|
+
expect(handler).to receive(:activate)
|
|
542
|
+
|
|
543
|
+
expect(Spree::ItemAdjustments).to receive(:new).with(shipment).and_return(adjuster = double)
|
|
544
|
+
expect(adjuster).to receive(:update)
|
|
545
|
+
|
|
546
|
+
expect(order.updater).to receive(:update_shipment_total)
|
|
547
|
+
expect(order.updater).to receive(:persist_totals)
|
|
548
|
+
order.apply_free_shipping_promotions
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
context "#products" do
|
|
554
|
+
before :each do
|
|
555
|
+
@variant1 = mock_model(Spree::Variant, :product => "product1")
|
|
556
|
+
@variant2 = mock_model(Spree::Variant, :product => "product2")
|
|
557
|
+
@line_items = [mock_model(Spree::LineItem, :product => "product1", :variant => @variant1, :variant_id => @variant1.id, :quantity => 1),
|
|
558
|
+
mock_model(Spree::LineItem, :product => "product2", :variant => @variant2, :variant_id => @variant2.id, :quantity => 2)]
|
|
559
|
+
allow(order).to receive_messages(:line_items => @line_items)
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
it "contains?" do
|
|
563
|
+
expect(order.contains?(@variant1)).to be true
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
it "gets the quantity of a given variant" do
|
|
567
|
+
expect(order.quantity_of(@variant1)).to eq(1)
|
|
568
|
+
|
|
569
|
+
@variant3 = mock_model(Spree::Variant, :product => "product3")
|
|
570
|
+
expect(order.quantity_of(@variant3)).to eq(0)
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
it "can find a line item matching a given variant" do
|
|
574
|
+
expect(order.find_line_item_by_variant(@variant1)).not_to be_nil
|
|
575
|
+
expect(order.find_line_item_by_variant(mock_model(Spree::Variant))).to be_nil
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
context "match line item with options" do
|
|
579
|
+
before do
|
|
580
|
+
Spree::Order.register_line_item_comparison_hook(:foos_match)
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
after do
|
|
584
|
+
# reset to avoid test pollution
|
|
585
|
+
Spree::Order.line_item_comparison_hooks = Set.new
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
it "matches line item when options match" do
|
|
589
|
+
allow(order).to receive(:foos_match).and_return(true)
|
|
590
|
+
expect(order.line_item_options_match(@line_items.first, {foos: {bar: :zoo}})).to be true
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
it "does not match line item without options" do
|
|
594
|
+
allow(order).to receive(:foos_match).and_return(false)
|
|
595
|
+
expect(order.line_item_options_match(@line_items.first, {})).to be false
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
context "#generate_order_number" do
|
|
601
|
+
context "when no configure" do
|
|
602
|
+
let(:default_length) { Spree::Order::ORDER_NUMBER_LENGTH + Spree::Order::ORDER_NUMBER_PREFIX.length }
|
|
603
|
+
subject(:order_number) { order.generate_order_number }
|
|
604
|
+
|
|
605
|
+
describe '#class' do
|
|
606
|
+
subject { super().class }
|
|
607
|
+
it { is_expected.to eq String }
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
describe '#length' do
|
|
611
|
+
subject { super().length }
|
|
612
|
+
it { is_expected.to eq default_length }
|
|
613
|
+
end
|
|
614
|
+
it { is_expected.to match /^#{Spree::Order::ORDER_NUMBER_PREFIX}/ }
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
context "when length option is 5" do
|
|
618
|
+
let(:option_length) { 5 + Spree::Order::ORDER_NUMBER_PREFIX.length }
|
|
619
|
+
it "should be option length for order number" do
|
|
620
|
+
expect(order.generate_order_number(length: 5).length).to eq option_length
|
|
621
|
+
end
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
context "when letters option is true" do
|
|
625
|
+
it "generates order number include letter" do
|
|
626
|
+
expect(order.generate_order_number(length: 100, letters: true)).to match /[A-Z]/
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
context "when prefix option is 'P'" do
|
|
631
|
+
it "generates order number and it prefix is 'P'" do
|
|
632
|
+
expect(order.generate_order_number(prefix: 'P')).to match /^P/
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
context "#associate_user!" do
|
|
638
|
+
let!(:user) { FactoryGirl.create(:user) }
|
|
639
|
+
|
|
640
|
+
it "should associate a user with a persisted order" do
|
|
641
|
+
order = FactoryGirl.create(:order_with_line_items, created_by: nil)
|
|
642
|
+
order.user = nil
|
|
643
|
+
order.email = nil
|
|
644
|
+
order.associate_user!(user)
|
|
645
|
+
expect(order.user).to eq(user)
|
|
646
|
+
expect(order.email).to eq(user.email)
|
|
647
|
+
expect(order.created_by).to eq(user)
|
|
648
|
+
|
|
649
|
+
# verify that the changes we made were persisted
|
|
650
|
+
order.reload
|
|
651
|
+
expect(order.user).to eq(user)
|
|
652
|
+
expect(order.email).to eq(user.email)
|
|
653
|
+
expect(order.created_by).to eq(user)
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
it "should not overwrite the created_by if it already is set" do
|
|
657
|
+
creator = create(:user)
|
|
658
|
+
order = FactoryGirl.create(:order_with_line_items, created_by: creator)
|
|
659
|
+
|
|
660
|
+
order.user = nil
|
|
661
|
+
order.email = nil
|
|
662
|
+
order.associate_user!(user)
|
|
663
|
+
expect(order.user).to eq(user)
|
|
664
|
+
expect(order.email).to eq(user.email)
|
|
665
|
+
expect(order.created_by).to eq(creator)
|
|
666
|
+
|
|
667
|
+
# verify that the changes we made were persisted
|
|
668
|
+
order.reload
|
|
669
|
+
expect(order.user).to eq(user)
|
|
670
|
+
expect(order.email).to eq(user.email)
|
|
671
|
+
expect(order.created_by).to eq(creator)
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
it "should associate a user with a non-persisted order" do
|
|
675
|
+
order = Spree::Order.new
|
|
676
|
+
|
|
677
|
+
expect do
|
|
678
|
+
order.associate_user!(user)
|
|
679
|
+
end.to change { [order.user, order.email] }.from([nil, nil]).to([user, user.email])
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
it "should not persist an invalid address" do
|
|
683
|
+
address = Spree::Address.new
|
|
684
|
+
order.user = nil
|
|
685
|
+
order.email = nil
|
|
686
|
+
order.ship_address = address
|
|
687
|
+
expect do
|
|
688
|
+
order.associate_user!(user)
|
|
689
|
+
end.not_to change { address.persisted? }.from(false)
|
|
690
|
+
end
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
context "#can_ship?" do
|
|
694
|
+
let(:order) { Spree::Order.create }
|
|
695
|
+
|
|
696
|
+
it "should be true for order in the 'complete' state" do
|
|
697
|
+
allow(order).to receive_messages(:complete? => true)
|
|
698
|
+
expect(order.can_ship?).to be true
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
it "should be true for order in the 'resumed' state" do
|
|
702
|
+
allow(order).to receive_messages(:resumed? => true)
|
|
703
|
+
expect(order.can_ship?).to be true
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
it "should be true for an order in the 'awaiting return' state" do
|
|
707
|
+
allow(order).to receive_messages(:awaiting_return? => true)
|
|
708
|
+
expect(order.can_ship?).to be true
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
it "should be true for an order in the 'returned' state" do
|
|
712
|
+
allow(order).to receive_messages(:returned? => true)
|
|
713
|
+
expect(order.can_ship?).to be true
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
it "should be false if the order is neither in the 'complete' nor 'resumed' state" do
|
|
717
|
+
allow(order).to receive_messages(:resumed? => false, :complete? => false)
|
|
718
|
+
expect(order.can_ship?).to be false
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
context "#completed?" do
|
|
723
|
+
it "should indicate if order is completed" do
|
|
724
|
+
order.completed_at = nil
|
|
725
|
+
expect(order.completed?).to be false
|
|
726
|
+
|
|
727
|
+
order.completed_at = Time.now
|
|
728
|
+
expect(order.completed?).to be true
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
context "#allow_checkout?" do
|
|
733
|
+
it "should be true if there are line_items in the order" do
|
|
734
|
+
allow(order).to receive_message_chain(:line_items, :count => 1)
|
|
735
|
+
expect(order.checkout_allowed?).to be true
|
|
736
|
+
end
|
|
737
|
+
it "should be false if there are no line_items in the order" do
|
|
738
|
+
allow(order).to receive_message_chain(:line_items, :count => 0)
|
|
739
|
+
expect(order.checkout_allowed?).to be false
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
context "#amount" do
|
|
744
|
+
before do
|
|
745
|
+
@order = create(:order, :user => user)
|
|
746
|
+
@order.line_items = [create(:line_item, :price => 1.0, :quantity => 2),
|
|
747
|
+
create(:line_item, :price => 1.0, :quantity => 1)]
|
|
748
|
+
end
|
|
749
|
+
it "should return the correct lum sum of items" do
|
|
750
|
+
expect(@order.amount).to eq(3.0)
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
context "#backordered?" do
|
|
755
|
+
it 'is backordered if one of the shipments is backordered' do
|
|
756
|
+
allow(order).to receive_messages(:shipments => [mock_model(Spree::Shipment, :backordered? => false),
|
|
757
|
+
mock_model(Spree::Shipment, :backordered? => true)])
|
|
758
|
+
expect(order).to be_backordered
|
|
759
|
+
end
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
context "#can_cancel?" do
|
|
763
|
+
it "should be false for completed order in the canceled state" do
|
|
764
|
+
order.state = 'canceled'
|
|
765
|
+
order.shipment_state = 'ready'
|
|
766
|
+
order.completed_at = Time.now
|
|
767
|
+
expect(order.can_cancel?).to be false
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
it "should be true for completed order with no shipment" do
|
|
771
|
+
order.state = 'complete'
|
|
772
|
+
order.shipment_state = nil
|
|
773
|
+
order.completed_at = Time.now
|
|
774
|
+
expect(order.can_cancel?).to be true
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
context "#tax_total" do
|
|
779
|
+
it "adds included tax and additional tax" do
|
|
780
|
+
allow(order).to receive_messages(:additional_tax_total => 10, :included_tax_total => 20)
|
|
781
|
+
|
|
782
|
+
expect(order.tax_total).to eq 30
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
# Regression test for #4923
|
|
787
|
+
context "locking" do
|
|
788
|
+
let(:order) { Spree::Order.create } # need a persisted in order to test locking
|
|
789
|
+
|
|
790
|
+
it 'can lock' do
|
|
791
|
+
expect { order.with_lock {} }.to_not raise_error
|
|
792
|
+
end
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
describe "#pre_tax_item_amount" do
|
|
796
|
+
it "sums all of the line items' pre tax amounts" do
|
|
797
|
+
subject.line_items = [
|
|
798
|
+
Spree::LineItem.new(price: 10, quantity: 2, pre_tax_amount: 5.0),
|
|
799
|
+
Spree::LineItem.new(price: 30, quantity: 1, pre_tax_amount: 14.0),
|
|
800
|
+
]
|
|
801
|
+
|
|
802
|
+
expect(subject.pre_tax_item_amount).to eq 19.0
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
describe '#quantity' do
|
|
807
|
+
# Uses a persisted record, as the quantity is retrieved via a DB count
|
|
808
|
+
let(:order) { create :order_with_line_items, line_items_count: 3 }
|
|
809
|
+
|
|
810
|
+
it 'sums the quantity of all line items' do
|
|
811
|
+
expect(order.quantity).to eq 3
|
|
812
|
+
end
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
describe '#has_non_reimbursement_related_refunds?' do
|
|
816
|
+
subject do
|
|
817
|
+
order.has_non_reimbursement_related_refunds?
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
context 'no refunds exist' do
|
|
821
|
+
it { is_expected.to eq false }
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
context 'a non-reimbursement related refund exists' do
|
|
825
|
+
let(:order) { refund.payment.order }
|
|
826
|
+
let(:refund) { create(:refund, reimbursement_id: nil, amount: 5) }
|
|
827
|
+
|
|
828
|
+
it { is_expected.to eq true }
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
context 'an old-style refund exists' do
|
|
832
|
+
let(:order) { create(:order_ready_to_ship) }
|
|
833
|
+
let(:payment) { order.payments.first.tap { |p| allow(p).to receive_messages(profiles_supported: false) } }
|
|
834
|
+
let!(:refund_payment) {
|
|
835
|
+
build(:payment, amount: -1, order: order, state: 'completed', source: payment).tap do |p|
|
|
836
|
+
allow(p).to receive_messages(profiles_supported?: false)
|
|
837
|
+
p.save!
|
|
838
|
+
end
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
it { is_expected.to eq true }
|
|
842
|
+
end
|
|
843
|
+
|
|
844
|
+
context 'a reimbursement related refund exists' do
|
|
845
|
+
let(:order) { refund.payment.order }
|
|
846
|
+
let(:refund) { create(:refund, reimbursement_id: 123, amount: 5)}
|
|
847
|
+
|
|
848
|
+
it { is_expected.to eq false }
|
|
849
|
+
end
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
describe "#create_proposed_shipments" do
|
|
853
|
+
it "assigns the coordinator returned shipments to its shipments" do
|
|
854
|
+
shipment = build(:shipment)
|
|
855
|
+
allow_any_instance_of(Spree::Stock::Coordinator).to receive(:shipments).and_return([shipment])
|
|
856
|
+
subject.create_proposed_shipments
|
|
857
|
+
expect(subject.shipments).to eq [shipment]
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
it "raises an error if any shipments are ready" do
|
|
861
|
+
shipment = create(:shipment, order: subject, state: "ready")
|
|
862
|
+
expect {
|
|
863
|
+
expect {
|
|
864
|
+
subject.create_proposed_shipments
|
|
865
|
+
}.to raise_error(Spree::Order::CannotRebuildShipments)
|
|
866
|
+
}.not_to change { subject.reload.shipments }
|
|
867
|
+
|
|
868
|
+
expect { shipment.reload }.not_to raise_error
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
it "raises an error if any shipments are shipped" do
|
|
872
|
+
shipment = create(:shipment, order: subject, state: "shipped")
|
|
873
|
+
expect {
|
|
874
|
+
expect {
|
|
875
|
+
subject.create_proposed_shipments
|
|
876
|
+
}.to raise_error(Spree::Order::CannotRebuildShipments)
|
|
877
|
+
}.not_to change { subject.reload.shipments }
|
|
878
|
+
|
|
879
|
+
expect { shipment.reload }.not_to raise_error
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
describe "#all_inventory_units_returned?" do
|
|
884
|
+
let(:order) { create(:order_with_line_items, line_items_count: 3) }
|
|
885
|
+
|
|
886
|
+
subject { order.all_inventory_units_returned? }
|
|
887
|
+
|
|
888
|
+
context "all inventory units are returned" do
|
|
889
|
+
before { order.inventory_units.update_all(state: 'returned') }
|
|
890
|
+
|
|
891
|
+
it "is true" do
|
|
892
|
+
expect(subject).to eq true
|
|
893
|
+
end
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
context "some inventory units are returned" do
|
|
897
|
+
before do
|
|
898
|
+
order.inventory_units.first.update_attribute(:state, 'returned')
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
it "is false" do
|
|
902
|
+
expect(subject).to eq false
|
|
903
|
+
end
|
|
904
|
+
end
|
|
905
|
+
|
|
906
|
+
context "no inventory units are returned" do
|
|
907
|
+
it "is false" do
|
|
908
|
+
expect(subject).to eq false
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
describe "#unreturned_exchange?" do
|
|
914
|
+
let(:order) { create(:order_with_line_items) }
|
|
915
|
+
subject { order.reload.unreturned_exchange? }
|
|
916
|
+
|
|
917
|
+
context "the order does not have a shipment" do
|
|
918
|
+
before { order.shipments.destroy_all }
|
|
919
|
+
|
|
920
|
+
it { is_expected.to be false }
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
context "shipment created after order" do
|
|
924
|
+
it { is_expected.to be false }
|
|
925
|
+
end
|
|
926
|
+
|
|
927
|
+
context "shipment created before order" do
|
|
928
|
+
before do
|
|
929
|
+
order.shipments.first.update_attributes!(created_at: order.created_at - 1.day)
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
it { is_expected.to be true }
|
|
933
|
+
end
|
|
934
|
+
end
|
|
935
|
+
|
|
936
|
+
describe '.unreturned_exchange' do
|
|
937
|
+
let(:order) { create(:order_with_line_items) }
|
|
938
|
+
subject { described_class.unreturned_exchange }
|
|
939
|
+
|
|
940
|
+
it 'includes orders that have a shipment created prior to the order' do
|
|
941
|
+
order.shipments.first.update_attributes!(created_at: order.created_at - 1.day)
|
|
942
|
+
expect(subject).to include order
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
it 'excludes orders that were created prior to their shipment' do
|
|
946
|
+
expect(subject).not_to include order
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
it 'excludes orders with no shipment' do
|
|
950
|
+
order.shipments.destroy_all
|
|
951
|
+
expect(subject).not_to include order
|
|
952
|
+
end
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
describe "#fully_discounted?" do
|
|
956
|
+
let(:line_item) { Spree::LineItem.new(price: 10, quantity: 1) }
|
|
957
|
+
let(:shipment) { Spree::Shipment.new(cost: 10) }
|
|
958
|
+
let(:payment) { Spree::Payment.new(amount: 10) }
|
|
959
|
+
|
|
960
|
+
before do
|
|
961
|
+
allow(order).to receive(:line_items) { [line_item] }
|
|
962
|
+
allow(order).to receive(:shipments) { [shipment] }
|
|
963
|
+
allow(order).to receive(:payments) { [payment] }
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
context "the order had no inventory-related cost" do
|
|
967
|
+
before do
|
|
968
|
+
# discount the cost of the line items
|
|
969
|
+
allow(order).to receive(:adjustment_total) { -5 }
|
|
970
|
+
allow(line_item).to receive(:adjustment_total) { -5 }
|
|
971
|
+
|
|
972
|
+
# but leave some shipment payment amount
|
|
973
|
+
allow(shipment).to receive(:adjustment_total) { 0 }
|
|
974
|
+
end
|
|
975
|
+
|
|
976
|
+
it { expect(order.fully_discounted?).to eq true }
|
|
977
|
+
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
context "the order had inventory-related cost" do
|
|
981
|
+
before do
|
|
982
|
+
# partially discount the cost of the line item
|
|
983
|
+
allow(order).to receive(:adjustment_total) { 0 }
|
|
984
|
+
allow(line_item).to receive(:adjustment_total) { -5 }
|
|
985
|
+
|
|
986
|
+
# and partially discount the cost of the shipment so the total
|
|
987
|
+
# discount matches the item total for test completeness
|
|
988
|
+
allow(shipment).to receive(:adjustment_total) { -5 }
|
|
989
|
+
end
|
|
990
|
+
|
|
991
|
+
it { expect(order.fully_discounted?).to eq false }
|
|
992
|
+
|
|
993
|
+
end
|
|
994
|
+
end
|
|
995
|
+
|
|
996
|
+
context "store credit" do
|
|
997
|
+
shared_examples "check total store credit from payments" do
|
|
998
|
+
context "with valid payments" do
|
|
999
|
+
let(:order) { payment.order }
|
|
1000
|
+
let!(:payment) { create(:store_credit_payment) }
|
|
1001
|
+
let!(:second_payment) { create(:store_credit_payment, order: order) }
|
|
1002
|
+
|
|
1003
|
+
subject { order }
|
|
1004
|
+
|
|
1005
|
+
it "returns the sum of the payment amounts" do
|
|
1006
|
+
expect(subject.total_applicable_store_credit).to eq (payment.amount + second_payment.amount)
|
|
1007
|
+
end
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
context "without valid payments" do
|
|
1011
|
+
let(:order) { create(:order) }
|
|
1012
|
+
|
|
1013
|
+
subject { order }
|
|
1014
|
+
|
|
1015
|
+
it "returns 0" do
|
|
1016
|
+
expect(subject.total_applicable_store_credit).to be_zero
|
|
1017
|
+
end
|
|
1018
|
+
end
|
|
1019
|
+
end
|
|
1020
|
+
|
|
1021
|
+
describe "#add_store_credit_payments" do
|
|
1022
|
+
let(:order_total) { 500.00 }
|
|
1023
|
+
|
|
1024
|
+
before { create(:store_credit_payment_method) }
|
|
1025
|
+
|
|
1026
|
+
subject { order.add_store_credit_payments }
|
|
1027
|
+
|
|
1028
|
+
context "there is no store credit" do
|
|
1029
|
+
let(:order) { create(:order, total: order_total) }
|
|
1030
|
+
|
|
1031
|
+
context "there is a credit card payment" do
|
|
1032
|
+
let!(:cc_payment) { create(:payment, order: order, amount: order_total) }
|
|
1033
|
+
|
|
1034
|
+
before do
|
|
1035
|
+
# callbacks recalculate total based on line items
|
|
1036
|
+
# this ensures the total is what we expect
|
|
1037
|
+
order.update_column(:total, order_total)
|
|
1038
|
+
subject
|
|
1039
|
+
order.reload
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
it "charges the outstanding balance to the credit card" do
|
|
1043
|
+
expect(order.errors.messages).to be_empty
|
|
1044
|
+
expect(order.payments.count).to eq 1
|
|
1045
|
+
expect(order.payments.first.source).to be_a(Spree::CreditCard)
|
|
1046
|
+
expect(order.payments.first.amount).to eq order_total
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
context "there are no other payments" do
|
|
1051
|
+
it "adds an error to the model" do
|
|
1052
|
+
expect(subject).to be false
|
|
1053
|
+
expect(order.errors.full_messages).to include(Spree.t("store_credit.errors.unable_to_fund"))
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
context "there is enough store credit to pay for the entire order" do
|
|
1059
|
+
let(:store_credit) { create(:store_credit, amount: order_total) }
|
|
1060
|
+
let(:order) { create(:order_with_totals, user: store_credit.user, line_items_price: order_total).tap(&:update!) }
|
|
1061
|
+
|
|
1062
|
+
context "there are no other payments" do
|
|
1063
|
+
before do
|
|
1064
|
+
subject
|
|
1065
|
+
order.reload
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
it "creates a store credit payment for the full amount" do
|
|
1069
|
+
expect(order.errors.messages).to be_empty
|
|
1070
|
+
expect(order.payments.count).to eq 1
|
|
1071
|
+
expect(order.payments.first).to be_store_credit
|
|
1072
|
+
expect(order.payments.first.amount).to eq order_total
|
|
1073
|
+
end
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
context "there is a credit card payment" do
|
|
1077
|
+
it "invalidates the credit card payment" do
|
|
1078
|
+
cc_payment = create(:payment, order: order)
|
|
1079
|
+
expect { subject }.to change { cc_payment.reload.state }.to 'invalid'
|
|
1080
|
+
end
|
|
1081
|
+
end
|
|
1082
|
+
end
|
|
1083
|
+
|
|
1084
|
+
context "the available store credit is not enough to pay for the entire order" do
|
|
1085
|
+
let(:order_total) { 500 }
|
|
1086
|
+
let(:store_credit_total) { order_total - 100 }
|
|
1087
|
+
let(:store_credit) { create(:store_credit, amount: store_credit_total) }
|
|
1088
|
+
let(:order) { create(:order_with_totals, user: store_credit.user, line_items_price: order_total).tap(&:update!) }
|
|
1089
|
+
|
|
1090
|
+
context "there are no other payments" do
|
|
1091
|
+
it "adds an error to the model" do
|
|
1092
|
+
expect(subject).to be false
|
|
1093
|
+
expect(order.errors.full_messages).to include(Spree.t("store_credit.errors.unable_to_fund"))
|
|
1094
|
+
end
|
|
1095
|
+
end
|
|
1096
|
+
|
|
1097
|
+
context "there is a credit card payment" do
|
|
1098
|
+
let!(:cc_payment) { create(:payment, order: order, state: "checkout") }
|
|
1099
|
+
|
|
1100
|
+
before do
|
|
1101
|
+
subject
|
|
1102
|
+
end
|
|
1103
|
+
|
|
1104
|
+
it "charges the outstanding balance to the credit card" do
|
|
1105
|
+
expect(order.errors.messages).to be_empty
|
|
1106
|
+
expect(order.payments.count).to eq 2
|
|
1107
|
+
expect(order.payments.first.source).to be_a(Spree::CreditCard)
|
|
1108
|
+
expect(order.payments.first.amount).to eq 100
|
|
1109
|
+
end
|
|
1110
|
+
|
|
1111
|
+
# see associated comment in order_decorator#add_store_credit_payments
|
|
1112
|
+
context "the store credit is already in the pending state" do
|
|
1113
|
+
before do
|
|
1114
|
+
order.payments.store_credits.last.authorize!
|
|
1115
|
+
order.add_store_credit_payments
|
|
1116
|
+
end
|
|
1117
|
+
|
|
1118
|
+
it "charges the outstanding balance to the credit card" do
|
|
1119
|
+
expect(order.errors.messages).to be_empty
|
|
1120
|
+
expect(order.payments.count).to eq 2
|
|
1121
|
+
expect(order.payments.first.source).to be_a(Spree::CreditCard)
|
|
1122
|
+
expect(order.payments.first.amount).to eq 100
|
|
1123
|
+
end
|
|
1124
|
+
end
|
|
1125
|
+
end
|
|
1126
|
+
end
|
|
1127
|
+
|
|
1128
|
+
context "there are multiple store credits" do
|
|
1129
|
+
context "they have different credit type priorities" do
|
|
1130
|
+
let(:amount_difference) { 100 }
|
|
1131
|
+
let!(:primary_store_credit) { create(:store_credit, amount: (order_total - amount_difference)) }
|
|
1132
|
+
let!(:secondary_store_credit) { create(:store_credit, amount: order_total, user: primary_store_credit.user, credit_type: create(:secondary_credit_type)) }
|
|
1133
|
+
let(:order) { create(:order_with_totals, user: primary_store_credit.user, line_items_price: order_total).tap(&:update!) }
|
|
1134
|
+
|
|
1135
|
+
before do
|
|
1136
|
+
subject
|
|
1137
|
+
order.reload
|
|
1138
|
+
end
|
|
1139
|
+
|
|
1140
|
+
it "uses the primary store credit type over the secondary" do
|
|
1141
|
+
primary_payment = order.payments.detect{|x| x.source == primary_store_credit }
|
|
1142
|
+
secondary_payment = order.payments.detect{|x| x.source == secondary_store_credit }
|
|
1143
|
+
|
|
1144
|
+
expect(order.payments.size).to eq 2
|
|
1145
|
+
expect(primary_payment.source).to eq primary_store_credit
|
|
1146
|
+
expect(secondary_payment.source).to eq secondary_store_credit
|
|
1147
|
+
expect(primary_payment.amount).to eq(order_total - amount_difference)
|
|
1148
|
+
expect(secondary_payment.amount).to eq(amount_difference)
|
|
1149
|
+
end
|
|
1150
|
+
end
|
|
1151
|
+
end
|
|
1152
|
+
end
|
|
1153
|
+
|
|
1154
|
+
describe "#covered_by_store_credit" do
|
|
1155
|
+
context "order doesn't have an associated user" do
|
|
1156
|
+
subject { create(:order, user: nil) }
|
|
1157
|
+
|
|
1158
|
+
it "returns false" do
|
|
1159
|
+
expect(subject.covered_by_store_credit).to be false
|
|
1160
|
+
end
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
context "order has an associated user" do
|
|
1164
|
+
let(:user) { create(:user) }
|
|
1165
|
+
|
|
1166
|
+
subject { create(:order, user: user) }
|
|
1167
|
+
|
|
1168
|
+
context "user has enough store credit to pay for the order" do
|
|
1169
|
+
before do
|
|
1170
|
+
allow(user).to receive_messages(total_available_store_credit: 10.0)
|
|
1171
|
+
allow(subject).to receive_messages(total: 5.0)
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
it "returns true" do
|
|
1175
|
+
expect(subject.covered_by_store_credit).to be true
|
|
1176
|
+
end
|
|
1177
|
+
end
|
|
1178
|
+
|
|
1179
|
+
context "user does not have enough store credit to pay for the order" do
|
|
1180
|
+
before do
|
|
1181
|
+
allow(user).to receive_messages(total_available_store_credit: 0.0)
|
|
1182
|
+
allow(subject).to receive_messages(total: 5.0)
|
|
1183
|
+
end
|
|
1184
|
+
|
|
1185
|
+
it "returns false" do
|
|
1186
|
+
expect(subject.covered_by_store_credit).to be false
|
|
1187
|
+
end
|
|
1188
|
+
end
|
|
1189
|
+
end
|
|
1190
|
+
end
|
|
1191
|
+
|
|
1192
|
+
describe "#total_available_store_credit" do
|
|
1193
|
+
context "order does not have an associated user" do
|
|
1194
|
+
subject { create(:order, user: nil) }
|
|
1195
|
+
|
|
1196
|
+
it "returns 0" do
|
|
1197
|
+
expect(subject.total_available_store_credit).to be_zero
|
|
1198
|
+
end
|
|
1199
|
+
end
|
|
1200
|
+
|
|
1201
|
+
context "order has an associated user" do
|
|
1202
|
+
let(:user) { create(:user) }
|
|
1203
|
+
let(:available_store_credit) { 25.0 }
|
|
1204
|
+
|
|
1205
|
+
subject { create(:order, user: user) }
|
|
1206
|
+
|
|
1207
|
+
before do
|
|
1208
|
+
allow(user).to receive_messages(total_available_store_credit: available_store_credit)
|
|
1209
|
+
end
|
|
1210
|
+
|
|
1211
|
+
it "returns the user's available store credit" do
|
|
1212
|
+
expect(subject.total_available_store_credit).to eq available_store_credit
|
|
1213
|
+
end
|
|
1214
|
+
end
|
|
1215
|
+
end
|
|
1216
|
+
|
|
1217
|
+
describe "#order_total_after_store_credit" do
|
|
1218
|
+
let(:order_total) { 100.0 }
|
|
1219
|
+
|
|
1220
|
+
subject { create(:order, total: order_total) }
|
|
1221
|
+
|
|
1222
|
+
before do
|
|
1223
|
+
allow(subject).to receive_messages(total_applicable_store_credit: applicable_store_credit)
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
context "order's user has store credits" do
|
|
1227
|
+
let(:applicable_store_credit) { 10.0 }
|
|
1228
|
+
|
|
1229
|
+
it "deducts the applicable store credit" do
|
|
1230
|
+
expect(subject.order_total_after_store_credit).to eq (order_total - applicable_store_credit)
|
|
1231
|
+
end
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
context "order's user does not have any store credits" do
|
|
1235
|
+
let(:applicable_store_credit) { 0.0 }
|
|
1236
|
+
|
|
1237
|
+
it "returns the order total" do
|
|
1238
|
+
expect(subject.order_total_after_store_credit).to eq order_total
|
|
1239
|
+
end
|
|
1240
|
+
end
|
|
1241
|
+
end
|
|
1242
|
+
|
|
1243
|
+
describe "#total_applicable_store_credit" do
|
|
1244
|
+
context "order is in the confirm state" do
|
|
1245
|
+
before { order.update_attributes(state: 'confirm') }
|
|
1246
|
+
include_examples "check total store credit from payments"
|
|
1247
|
+
end
|
|
1248
|
+
|
|
1249
|
+
context "order is completed" do
|
|
1250
|
+
before { order.update_attributes(state: 'complete') }
|
|
1251
|
+
include_examples "check total store credit from payments"
|
|
1252
|
+
end
|
|
1253
|
+
|
|
1254
|
+
context "order is in any state other than confirm or complete" do
|
|
1255
|
+
context "the associated user has store credits" do
|
|
1256
|
+
let(:store_credit) { create(:store_credit) }
|
|
1257
|
+
let(:order) { create(:order, user: store_credit.user) }
|
|
1258
|
+
|
|
1259
|
+
subject { order }
|
|
1260
|
+
|
|
1261
|
+
context "the store credit is more than the order total" do
|
|
1262
|
+
let(:order_total) { store_credit.amount - 1 }
|
|
1263
|
+
|
|
1264
|
+
before { order.update_attributes(total: order_total) }
|
|
1265
|
+
|
|
1266
|
+
it "returns the order total" do
|
|
1267
|
+
expect(subject.total_applicable_store_credit).to eq order_total
|
|
1268
|
+
end
|
|
1269
|
+
end
|
|
1270
|
+
|
|
1271
|
+
context "the store credit is less than the order total" do
|
|
1272
|
+
let(:order_total) { store_credit.amount * 10 }
|
|
1273
|
+
|
|
1274
|
+
before { order.update_attributes(total: order_total) }
|
|
1275
|
+
|
|
1276
|
+
it "returns the store credit amount" do
|
|
1277
|
+
expect(subject.total_applicable_store_credit).to eq store_credit.amount
|
|
1278
|
+
end
|
|
1279
|
+
end
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1282
|
+
context "the associated user does not have store credits" do
|
|
1283
|
+
let(:order) { create(:order) }
|
|
1284
|
+
|
|
1285
|
+
subject { order }
|
|
1286
|
+
|
|
1287
|
+
it "returns 0" do
|
|
1288
|
+
expect(subject.total_applicable_store_credit).to be_zero
|
|
1289
|
+
end
|
|
1290
|
+
end
|
|
1291
|
+
|
|
1292
|
+
context "the order does not have an associated user" do
|
|
1293
|
+
subject { create(:order, user: nil) }
|
|
1294
|
+
|
|
1295
|
+
it "returns 0" do
|
|
1296
|
+
expect(subject.total_applicable_store_credit).to be_zero
|
|
1297
|
+
end
|
|
1298
|
+
end
|
|
1299
|
+
end
|
|
1300
|
+
end
|
|
1301
|
+
|
|
1302
|
+
describe "#display_total_applicable_store_credit" do
|
|
1303
|
+
let(:total_applicable_store_credit) { 10.00 }
|
|
1304
|
+
|
|
1305
|
+
subject { create(:order) }
|
|
1306
|
+
|
|
1307
|
+
before { allow(subject).to receive_messages(total_applicable_store_credit: total_applicable_store_credit) }
|
|
1308
|
+
|
|
1309
|
+
it "returns a money instance" do
|
|
1310
|
+
expect(subject.display_total_applicable_store_credit).to be_a(Spree::Money)
|
|
1311
|
+
end
|
|
1312
|
+
|
|
1313
|
+
it "returns a negative amount" do
|
|
1314
|
+
expect(subject.display_total_applicable_store_credit.money.cents).to eq (total_applicable_store_credit * -100.0)
|
|
1315
|
+
end
|
|
1316
|
+
end
|
|
1317
|
+
|
|
1318
|
+
describe "#display_order_total_after_store_credit" do
|
|
1319
|
+
let(:order_total_after_store_credit) { 10.00 }
|
|
1320
|
+
|
|
1321
|
+
subject { create(:order) }
|
|
1322
|
+
|
|
1323
|
+
before { allow(subject).to receive_messages(order_total_after_store_credit: order_total_after_store_credit) }
|
|
1324
|
+
|
|
1325
|
+
it "returns a money instance" do
|
|
1326
|
+
expect(subject.display_order_total_after_store_credit).to be_a(Spree::Money)
|
|
1327
|
+
end
|
|
1328
|
+
|
|
1329
|
+
it "returns the order_total_after_store_credit amount" do
|
|
1330
|
+
expect(subject.display_order_total_after_store_credit.money.cents).to eq (order_total_after_store_credit * 100.0)
|
|
1331
|
+
end
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
describe "#display_total_available_store_credit" do
|
|
1335
|
+
let(:total_available_store_credit) { 10.00 }
|
|
1336
|
+
|
|
1337
|
+
subject { create(:order) }
|
|
1338
|
+
|
|
1339
|
+
before { allow(subject).to receive_messages(total_available_store_credit: total_available_store_credit) }
|
|
1340
|
+
|
|
1341
|
+
it "returns a money instance" do
|
|
1342
|
+
expect(subject.display_total_available_store_credit).to be_a(Spree::Money)
|
|
1343
|
+
end
|
|
1344
|
+
|
|
1345
|
+
it "returns the total_available_store_credit amount" do
|
|
1346
|
+
expect(subject.display_total_available_store_credit.money.cents).to eq (total_available_store_credit * 100.0)
|
|
1347
|
+
end
|
|
1348
|
+
end
|
|
1349
|
+
|
|
1350
|
+
describe "#display_store_credit_remaining_after_capture" do
|
|
1351
|
+
let(:total_available_store_credit) { 10.00 }
|
|
1352
|
+
let(:total_applicable_store_credit) { 5.00 }
|
|
1353
|
+
|
|
1354
|
+
subject { create(:order) }
|
|
1355
|
+
|
|
1356
|
+
before do
|
|
1357
|
+
allow(subject).to receive_messages(total_available_store_credit: total_available_store_credit,
|
|
1358
|
+
total_applicable_store_credit: total_applicable_store_credit)
|
|
1359
|
+
end
|
|
1360
|
+
|
|
1361
|
+
it "returns a money instance" do
|
|
1362
|
+
expect(subject.display_store_credit_remaining_after_capture).to be_a(Spree::Money)
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
it "returns all of the user's available store credit minus what's applied to the order amount" do
|
|
1366
|
+
amount_remaining = total_available_store_credit - total_applicable_store_credit
|
|
1367
|
+
expect(subject.display_store_credit_remaining_after_capture.money.cents).to eq (amount_remaining * 100.0)
|
|
1368
|
+
end
|
|
1369
|
+
end
|
|
1370
|
+
|
|
1371
|
+
context 'when not capturing at order completion' do
|
|
1372
|
+
let!(:store_credit_payment_method) do
|
|
1373
|
+
create(
|
|
1374
|
+
:store_credit_payment_method,
|
|
1375
|
+
auto_capture: false, # not capturing at completion time
|
|
1376
|
+
)
|
|
1377
|
+
end
|
|
1378
|
+
|
|
1379
|
+
describe '#after_cancel' do
|
|
1380
|
+
let(:user) { create(:user) }
|
|
1381
|
+
let!(:store_credit) do
|
|
1382
|
+
create(:store_credit, amount: 100, user: user)
|
|
1383
|
+
end
|
|
1384
|
+
let(:order) do
|
|
1385
|
+
create(
|
|
1386
|
+
:order_with_line_items,
|
|
1387
|
+
user: user,
|
|
1388
|
+
line_items_count: 1,
|
|
1389
|
+
# order will be $20 total:
|
|
1390
|
+
line_items_price: 10,
|
|
1391
|
+
shipment_cost: 10,
|
|
1392
|
+
)
|
|
1393
|
+
end
|
|
1394
|
+
|
|
1395
|
+
before do
|
|
1396
|
+
order.contents.advance
|
|
1397
|
+
order.complete!
|
|
1398
|
+
end
|
|
1399
|
+
|
|
1400
|
+
it 'releases the pending store credit authorization' do
|
|
1401
|
+
expect {
|
|
1402
|
+
order.cancel!
|
|
1403
|
+
}.to change {
|
|
1404
|
+
store_credit.reload.amount_authorized
|
|
1405
|
+
}.from(20).to(0)
|
|
1406
|
+
|
|
1407
|
+
expect(store_credit.amount_remaining).to eq 100
|
|
1408
|
+
end
|
|
1409
|
+
end
|
|
1410
|
+
end
|
|
1411
|
+
end
|
|
1412
|
+
end
|