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,191 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::LineItem, :type => :model do
|
|
4
|
+
let(:order) { create :order_with_line_items, line_items_count: 1 }
|
|
5
|
+
let(:line_item) { order.line_items.first }
|
|
6
|
+
|
|
7
|
+
context '#destroy' do
|
|
8
|
+
it "fetches deleted products" do
|
|
9
|
+
line_item.product.destroy
|
|
10
|
+
expect(line_item.reload.product).to be_a Spree::Product
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "fetches deleted variants" do
|
|
14
|
+
line_item.variant.destroy
|
|
15
|
+
expect(line_item.reload.variant).to be_a Spree::Variant
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "returns inventory when a line item is destroyed" do
|
|
19
|
+
expect_any_instance_of(Spree::OrderInventory).to receive(:verify)
|
|
20
|
+
line_item.destroy
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "deletes inventory units" do
|
|
24
|
+
expect { line_item.destroy }.to change { line_item.inventory_units.count }.from(1).to(0)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "#save" do
|
|
29
|
+
context "line item changes" do
|
|
30
|
+
before do
|
|
31
|
+
line_item.quantity = line_item.quantity + 1
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "triggers adjustment total recalculation" do
|
|
35
|
+
expect(line_item).to receive(:update_tax_charge) # Regression test for https://github.com/spree/spree/issues/4671
|
|
36
|
+
expect(line_item).to receive(:recalculate_adjustments)
|
|
37
|
+
line_item.save
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "line item does not change" do
|
|
42
|
+
it "does not trigger adjustment total recalculation" do
|
|
43
|
+
expect(line_item).not_to receive(:recalculate_adjustments)
|
|
44
|
+
line_item.save
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "target_shipment is provided" do
|
|
49
|
+
it "verifies inventory" do
|
|
50
|
+
line_item.target_shipment = Spree::Shipment.new
|
|
51
|
+
expect_any_instance_of(Spree::OrderInventory).to receive(:verify)
|
|
52
|
+
line_item.save
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "#create" do
|
|
58
|
+
let(:variant) { create(:variant) }
|
|
59
|
+
|
|
60
|
+
before do
|
|
61
|
+
create(:tax_rate, :zone => order.tax_zone, :tax_category => variant.tax_category)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "when order has a tax zone" do
|
|
65
|
+
before do
|
|
66
|
+
expect(order.tax_zone).to be_present
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "creates a tax adjustment" do
|
|
70
|
+
order.contents.add(variant)
|
|
71
|
+
line_item = order.find_line_item_by_variant(variant)
|
|
72
|
+
expect(line_item.adjustments.tax.count).to eq(1)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "when order does not have a tax zone" do
|
|
77
|
+
before do
|
|
78
|
+
order.bill_address = nil
|
|
79
|
+
order.ship_address = nil
|
|
80
|
+
order.save
|
|
81
|
+
expect(order.reload.tax_zone).to be_nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "does not create a tax adjustment" do
|
|
85
|
+
order.contents.add(variant)
|
|
86
|
+
line_item = order.find_line_item_by_variant(variant)
|
|
87
|
+
expect(line_item.adjustments.tax.count).to eq(0)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Test for #3391
|
|
93
|
+
context '#copy_price' do
|
|
94
|
+
it "copies over a variant's prices" do
|
|
95
|
+
line_item.price = nil
|
|
96
|
+
line_item.cost_price = nil
|
|
97
|
+
line_item.currency = nil
|
|
98
|
+
line_item.copy_price
|
|
99
|
+
variant = line_item.variant
|
|
100
|
+
expect(line_item.price).to eq(variant.price)
|
|
101
|
+
expect(line_item.cost_price).to eq(variant.cost_price)
|
|
102
|
+
expect(line_item.currency).to eq(variant.currency)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Test for #3481
|
|
107
|
+
context '#copy_tax_category' do
|
|
108
|
+
it "copies over a variant's tax category" do
|
|
109
|
+
line_item.tax_category = nil
|
|
110
|
+
line_item.copy_tax_category
|
|
111
|
+
expect(line_item.tax_category).to eq(line_item.variant.tax_category)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe '.discounted_amount' do
|
|
116
|
+
it "returns the amount minus any discounts" do
|
|
117
|
+
line_item.price = 10
|
|
118
|
+
line_item.quantity = 2
|
|
119
|
+
line_item.promo_total = -5
|
|
120
|
+
expect(line_item.discounted_amount).to eq(15)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe "#discounted_money" do
|
|
125
|
+
it "should return a money object with the discounted amount" do
|
|
126
|
+
expect(line_item.discounted_money.to_s).to eq "$10.00"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe '.currency' do
|
|
131
|
+
it 'returns the globally configured currency' do
|
|
132
|
+
line_item.currency == 'USD'
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe ".money" do
|
|
137
|
+
before do
|
|
138
|
+
line_item.price = 3.50
|
|
139
|
+
line_item.quantity = 2
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "returns a Spree::Money representing the total for this line item" do
|
|
143
|
+
expect(line_item.money.to_s).to eq("$7.00")
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
describe '.single_money' do
|
|
148
|
+
before { line_item.price = 3.50 }
|
|
149
|
+
it "returns a Spree::Money representing the price for one variant" do
|
|
150
|
+
expect(line_item.single_money.to_s).to eq("$3.50")
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context "currency same as order.currency" do
|
|
155
|
+
it "is a valid line item" do
|
|
156
|
+
line_item = order.line_items.first
|
|
157
|
+
line_item.currency = order.currency
|
|
158
|
+
line_item.valid?
|
|
159
|
+
|
|
160
|
+
expect(line_item.error_on(:currency).size).to eq(0)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "currency different than order.currency" do
|
|
165
|
+
it "is not a valid line item" do
|
|
166
|
+
line_item = order.line_items.first
|
|
167
|
+
line_item.currency = "no currency"
|
|
168
|
+
line_item.valid?
|
|
169
|
+
|
|
170
|
+
expect(line_item.error_on(:currency).size).to eq(1)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe "#options=" do
|
|
175
|
+
it "can handle updating a blank line item with no order" do
|
|
176
|
+
line_item.options = { price: 123 }
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "updates the data provided in the options" do
|
|
180
|
+
line_item.options = { price: 123 }
|
|
181
|
+
expect(line_item.price).to eq 123
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "updates the price based on the options provided" do
|
|
185
|
+
expect(line_item).to receive(:gift_wrap=).with(true)
|
|
186
|
+
expect(line_item.variant).to receive(:gift_wrap_price_modifier_amount_in).with("USD", true).and_return 1.99
|
|
187
|
+
line_item.options = { gift_wrap: true }
|
|
188
|
+
expect(line_item.price).to eq 21.98
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::OptionType, :type => :model do
|
|
4
|
+
context "touching" do
|
|
5
|
+
it "should touch a product" do
|
|
6
|
+
product_option_type = create(:product_option_type)
|
|
7
|
+
option_type = product_option_type.option_type
|
|
8
|
+
product = product_option_type.product
|
|
9
|
+
product.update_column(:updated_at, 1.day.ago)
|
|
10
|
+
option_type.touch
|
|
11
|
+
expect(product.reload.updated_at).to be_within(3.seconds).of(Time.now)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::OptionValue, :type => :model do
|
|
4
|
+
context "touching" do
|
|
5
|
+
it "should touch a variant" do
|
|
6
|
+
variant = create(:variant)
|
|
7
|
+
option_value = variant.option_values.first
|
|
8
|
+
variant.update_column(:updated_at, 1.day.ago)
|
|
9
|
+
option_value.touch
|
|
10
|
+
expect(variant.reload.updated_at).to be_within(3.seconds).of(Time.now)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "#presentation_with_option_type" do
|
|
15
|
+
let(:option_value) { build(:option_value) }
|
|
16
|
+
subject { option_value.presentation_with_option_type }
|
|
17
|
+
|
|
18
|
+
it "returns a string in the correct form" do
|
|
19
|
+
expect(subject).to eq "Size - S"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Order, :type => :model do
|
|
4
|
+
let(:order) { Spree::Order.new }
|
|
5
|
+
|
|
6
|
+
context 'validation' do
|
|
7
|
+
context "when @use_billing is populated" do
|
|
8
|
+
before do
|
|
9
|
+
order.bill_address = stub_model(Spree::Address)
|
|
10
|
+
order.ship_address = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "with true" do
|
|
14
|
+
before { order.use_billing = true }
|
|
15
|
+
|
|
16
|
+
it "clones the bill address to the ship address" do
|
|
17
|
+
order.valid?
|
|
18
|
+
expect(order.ship_address).to eq(order.bill_address)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "with 'true'" do
|
|
23
|
+
before { order.use_billing = 'true' }
|
|
24
|
+
|
|
25
|
+
it "clones the bill address to the shipping" do
|
|
26
|
+
order.valid?
|
|
27
|
+
expect(order.ship_address).to eq(order.bill_address)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "with '1'" do
|
|
32
|
+
before { order.use_billing = '1' }
|
|
33
|
+
|
|
34
|
+
it "clones the bill address to the shipping" do
|
|
35
|
+
order.valid?
|
|
36
|
+
expect(order.ship_address).to eq(order.bill_address)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "with something other than a 'truthful' value" do
|
|
41
|
+
before { order.use_billing = '0' }
|
|
42
|
+
|
|
43
|
+
it "does not clone the bill address to the shipping" do
|
|
44
|
+
order.valid?
|
|
45
|
+
expect(order.ship_address).to be_nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Order, :type => :model do
|
|
4
|
+
context "#all_adjustments" do
|
|
5
|
+
# Regression test for #4537
|
|
6
|
+
it "does not show adjustments from other, non-order adjustables" do
|
|
7
|
+
order = Spree::Order.new(:id => 1)
|
|
8
|
+
where_sql = order.all_adjustments.where_values.to_s
|
|
9
|
+
expect(where_sql).to include("(adjustable_id = 1 AND adjustable_type = 'Spree::Order')")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Regression test for #2191
|
|
14
|
+
context "when an order has an adjustment that zeroes the total, but another adjustment for shipping that raises it above zero" do
|
|
15
|
+
let!(:persisted_order) { create(:order) }
|
|
16
|
+
let!(:line_item) { create(:line_item) }
|
|
17
|
+
let!(:shipping_method) do
|
|
18
|
+
sm = create(:shipping_method)
|
|
19
|
+
sm.calculator.preferred_amount = 10
|
|
20
|
+
sm.save
|
|
21
|
+
sm
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
# Don't care about available payment methods in this test
|
|
26
|
+
allow(persisted_order).to receive_messages(:has_available_payment => false)
|
|
27
|
+
persisted_order.line_items << line_item
|
|
28
|
+
create(:adjustment, amount: -line_item.amount, label: "Promotion", adjustable: line_item, order: persisted_order)
|
|
29
|
+
persisted_order.state = 'delivery'
|
|
30
|
+
persisted_order.save # To ensure new state_change event
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "transitions from delivery to payment" do
|
|
34
|
+
allow(persisted_order).to receive_messages(payment_required?: true)
|
|
35
|
+
persisted_order.next!
|
|
36
|
+
expect(persisted_order.state).to eq("payment")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Order, :type => :model do
|
|
4
|
+
let(:order) { stub_model(Spree::Order) }
|
|
5
|
+
before do
|
|
6
|
+
Spree::Order.define_state_machine!
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context "validations" do
|
|
10
|
+
context "email validation" do
|
|
11
|
+
# Regression test for #1238
|
|
12
|
+
it "o'brien@gmail.com is a valid email address" do
|
|
13
|
+
order.state = 'address'
|
|
14
|
+
order.email = "o'brien@gmail.com"
|
|
15
|
+
expect(order.error_on(:email).size).to eq(0)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "#save" do
|
|
21
|
+
context "when associated with a registered user" do
|
|
22
|
+
let(:user) { double(:user, :email => "test@example.com") }
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
allow(order).to receive_messages :user => user
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should assign the email address of the user" do
|
|
29
|
+
order.run_callbacks(:create)
|
|
30
|
+
expect(order.email).to eq(user.email)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "in the cart state" do
|
|
36
|
+
it "should not validate email address" do
|
|
37
|
+
order.state = "cart"
|
|
38
|
+
order.email = nil
|
|
39
|
+
expect(order.error_on(:email).size).to eq(0)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,902 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'spree/testing_support/order_walkthrough'
|
|
3
|
+
|
|
4
|
+
describe Spree::Order, :type => :model do
|
|
5
|
+
let(:order) { Spree::Order.new }
|
|
6
|
+
|
|
7
|
+
def assert_state_changed(order, from, to)
|
|
8
|
+
state_change_exists = order.state_changes.where(:previous_state => from, :next_state => to).exists?
|
|
9
|
+
assert state_change_exists, "Expected order to transition from #{from} to #{to}, but didn't."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context "with default state machine" do
|
|
13
|
+
transitions = [
|
|
14
|
+
{ :address => :delivery },
|
|
15
|
+
{ :delivery => :payment },
|
|
16
|
+
{ :payment => :confirm },
|
|
17
|
+
{ :delivery => :confirm },
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
transitions.each do |transition|
|
|
21
|
+
it "transitions from #{transition.keys.first} to #{transition.values.first}" do
|
|
22
|
+
transition = Spree::Order.find_transition(:from => transition.keys.first, :to => transition.values.first)
|
|
23
|
+
expect(transition).not_to be_nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it '.find_transition when contract was broken' do
|
|
28
|
+
expect(Spree::Order.find_transition({foo: :bar, baz: :dog})).to be_falsey
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "remove_transition" do
|
|
32
|
+
after do
|
|
33
|
+
Spree::Order.checkout_flow(&@old_checkout_flow)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it '.remove_transition' do
|
|
37
|
+
options = {:from => transitions.first.keys.first, :to => transitions.first.values.first}
|
|
38
|
+
allow(Spree::Order).to receive(:next_event_transition).and_return([options])
|
|
39
|
+
expect(Spree::Order.remove_transition(options)).to be_truthy
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it '.remove_transition when contract was broken' do
|
|
43
|
+
expect(Spree::Order.remove_transition(nil)).to be_falsey
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "always return integer on checkout_step_index" do
|
|
48
|
+
expect(order.checkout_step_index("imnotthere")).to be_a Integer
|
|
49
|
+
expect(order.checkout_step_index("delivery")).to be > 0
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "passes delivery state when transitioning from address over delivery to payment" do
|
|
53
|
+
allow(order).to receive_messages :payment_required? => true
|
|
54
|
+
order.state = "address"
|
|
55
|
+
expect(order.passed_checkout_step?("delivery")).to be false
|
|
56
|
+
order.state = "delivery"
|
|
57
|
+
expect(order.passed_checkout_step?("delivery")).to be false
|
|
58
|
+
order.state = "payment"
|
|
59
|
+
expect(order.passed_checkout_step?("delivery")).to be true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context "#checkout_steps" do
|
|
63
|
+
context "when confirmation not required" do
|
|
64
|
+
before do
|
|
65
|
+
allow(order).to receive_messages :payment_required? => true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
specify do
|
|
69
|
+
expect(order.checkout_steps).to eq(%w(address delivery payment confirm complete))
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "when confirmation required" do
|
|
74
|
+
before do
|
|
75
|
+
allow(order).to receive_messages :payment_required? => true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
specify do
|
|
79
|
+
expect(order.checkout_steps).to eq(%w(address delivery payment confirm complete))
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context "when payment not required" do
|
|
84
|
+
before { allow(order).to receive_messages :payment_required? => false }
|
|
85
|
+
specify do
|
|
86
|
+
expect(order.checkout_steps).to eq(%w(address delivery confirm complete))
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "when payment required" do
|
|
91
|
+
before { allow(order).to receive_messages :payment_required? => true }
|
|
92
|
+
specify do
|
|
93
|
+
expect(order.checkout_steps).to eq(%w(address delivery payment confirm complete))
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "starts out at cart" do
|
|
99
|
+
expect(order.state).to eq("cart")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "to address" do
|
|
103
|
+
before do
|
|
104
|
+
order.email = "user@example.com"
|
|
105
|
+
order.save!
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "with a line item" do
|
|
109
|
+
before do
|
|
110
|
+
order.line_items << FactoryGirl.create(:line_item)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "transitions to address" do
|
|
114
|
+
order.next!
|
|
115
|
+
assert_state_changed(order, 'cart', 'address')
|
|
116
|
+
expect(order.state).to eq("address")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "doesn't raise an error if the default address is invalid" do
|
|
120
|
+
order.user = mock_model(Spree::LegacyUser, ship_address: Spree::Address.new, bill_address: Spree::Address.new)
|
|
121
|
+
expect { order.next! }.to_not raise_error
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "with default addresses" do
|
|
125
|
+
let(:default_address) { FactoryGirl.create(:address) }
|
|
126
|
+
|
|
127
|
+
before do
|
|
128
|
+
order.user = FactoryGirl.create(:user, "#{address_kind}_address" => default_address)
|
|
129
|
+
order.next!
|
|
130
|
+
order.reload
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
shared_examples "it cloned the default address" do
|
|
134
|
+
it do
|
|
135
|
+
default_attributes = default_address.attributes
|
|
136
|
+
order_attributes = order.send("#{address_kind}_address".to_sym).try(:attributes) || {}
|
|
137
|
+
|
|
138
|
+
expect(order_attributes.except('id', 'created_at', 'updated_at')).to eql(default_attributes.except('id', 'created_at', 'updated_at'))
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it_behaves_like "it cloned the default address" do
|
|
143
|
+
let(:address_kind) { 'ship' }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it_behaves_like "it cloned the default address" do
|
|
147
|
+
let(:address_kind) { 'bill' }
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "cannot transition to address without any line items" do
|
|
153
|
+
expect(order.line_items).to be_blank
|
|
154
|
+
expect { order.next! }.to raise_error(StateMachines::InvalidTransition, /#{Spree.t(:there_are_no_items_for_this_order)}/)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context "from address" do
|
|
159
|
+
let(:ship_address) { FactoryGirl.create(:ship_address) }
|
|
160
|
+
|
|
161
|
+
before do
|
|
162
|
+
order.state = 'address'
|
|
163
|
+
order.ship_address = ship_address
|
|
164
|
+
allow(order).to receive(:has_available_payment)
|
|
165
|
+
shipment = FactoryGirl.create(:shipment, :order => order, :cost => 10)
|
|
166
|
+
order.email = "user@example.com"
|
|
167
|
+
order.save!
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "no shipping address" do
|
|
171
|
+
let(:ship_address) { nil }
|
|
172
|
+
|
|
173
|
+
it "does not transition without a ship address" do
|
|
174
|
+
expect { order.next! }.to raise_error StateMachines::InvalidTransition
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "updates totals" do
|
|
179
|
+
line_item = FactoryGirl.create(:line_item, :price => 10, :adjustment_total => 10)
|
|
180
|
+
order.line_items << line_item
|
|
181
|
+
tax_rate = create(:tax_rate, :tax_category => line_item.tax_category, :amount => 0.05)
|
|
182
|
+
allow(Spree::TaxRate).to receive_messages :match => [tax_rate]
|
|
183
|
+
FactoryGirl.create(:tax_adjustment, :adjustable => line_item, :source => tax_rate, order: order)
|
|
184
|
+
order.email = "user@example.com"
|
|
185
|
+
order.next!
|
|
186
|
+
expect(order.adjustment_total).to eq(0.5)
|
|
187
|
+
expect(order.additional_tax_total).to eq(0.5)
|
|
188
|
+
expect(order.included_tax_total).to eq(0)
|
|
189
|
+
expect(order.total).to eq(20.5)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "transitions to delivery" do
|
|
193
|
+
allow(order).to receive_messages(:ensure_available_shipping_rates => true)
|
|
194
|
+
order.next!
|
|
195
|
+
assert_state_changed(order, 'address', 'delivery')
|
|
196
|
+
expect(order.state).to eq("delivery")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "does not call persist_order_address if there is no address on the order" do
|
|
200
|
+
# otherwise, it will crash
|
|
201
|
+
allow(order).to receive_messages(:ensure_available_shipping_rates => true)
|
|
202
|
+
|
|
203
|
+
order.user = FactoryGirl.create(:user)
|
|
204
|
+
order.save!
|
|
205
|
+
|
|
206
|
+
expect(order.user).to_not receive(:persist_order_address).with(order)
|
|
207
|
+
order.next!
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it "calls persist_order_address on the order's user" do
|
|
211
|
+
allow(order).to receive_messages(:ensure_available_shipping_rates => true)
|
|
212
|
+
|
|
213
|
+
order.user = FactoryGirl.create(:user)
|
|
214
|
+
order.ship_address = FactoryGirl.create(:address)
|
|
215
|
+
order.bill_address = FactoryGirl.create(:address)
|
|
216
|
+
order.save!
|
|
217
|
+
|
|
218
|
+
expect(order.user).to receive(:persist_order_address).with(order)
|
|
219
|
+
order.next!
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "does not call persist_order_address on the order's user for a temporary address" do
|
|
223
|
+
allow(order).to receive_messages(:ensure_available_shipping_rates => true)
|
|
224
|
+
|
|
225
|
+
order.user = FactoryGirl.create(:user)
|
|
226
|
+
order.temporary_address = true
|
|
227
|
+
order.save!
|
|
228
|
+
|
|
229
|
+
expect(order.user).to_not receive(:persist_order_address)
|
|
230
|
+
order.next!
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
context "to delivery" do
|
|
235
|
+
let(:ship_address) { FactoryGirl.create(:ship_address) }
|
|
236
|
+
|
|
237
|
+
before do
|
|
238
|
+
order.ship_address = ship_address
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
context 'when order has default selected_shipping_rate_id' do
|
|
242
|
+
let(:shipment) { create(:shipment, order: order) }
|
|
243
|
+
let(:shipping_method) { create(:shipping_method) }
|
|
244
|
+
let(:shipping_rate) { [
|
|
245
|
+
Spree::ShippingRate.create!(shipping_method: shipping_method, cost: 10.00, shipment: shipment)
|
|
246
|
+
] }
|
|
247
|
+
|
|
248
|
+
before do
|
|
249
|
+
order.state = 'address'
|
|
250
|
+
shipment.selected_shipping_rate_id = shipping_rate.first.id
|
|
251
|
+
order.email = "user@example.com"
|
|
252
|
+
order.save!
|
|
253
|
+
|
|
254
|
+
allow(order).to receive(:has_available_payment)
|
|
255
|
+
allow(order).to receive(:create_proposed_shipments)
|
|
256
|
+
allow(order).to receive(:ensure_available_shipping_rates) { true }
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it 'should invoke set_shipment_cost' do
|
|
260
|
+
expect(order).to receive(:set_shipments_cost)
|
|
261
|
+
order.next!
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'should update shipment_total' do
|
|
265
|
+
expect { order.next! }.to change{ order.shipment_total }.by(10.00)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
context "cannot transition to delivery" do
|
|
270
|
+
context "if there are no shipping rates for any shipment" do
|
|
271
|
+
let!(:line_item){ create :line_item, order: order }
|
|
272
|
+
before do
|
|
273
|
+
order.state = 'address'
|
|
274
|
+
order.email = 'user@example.com'
|
|
275
|
+
end
|
|
276
|
+
specify do
|
|
277
|
+
transition = lambda { order.next! }
|
|
278
|
+
expect(transition).to raise_error(StateMachines::InvalidTransition, /#{Spree.t(:items_cannot_be_shipped)}/)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
context "from delivery" do
|
|
285
|
+
let(:ship_address) { FactoryGirl.create(:ship_address) }
|
|
286
|
+
|
|
287
|
+
before do
|
|
288
|
+
order.ship_address = ship_address
|
|
289
|
+
order.state = 'delivery'
|
|
290
|
+
allow(order).to receive(:apply_free_shipping_promotions)
|
|
291
|
+
allow(order).to receive(:ensure_available_shipping_rates) { true }
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it "attempts to apply free shipping promotions" do
|
|
295
|
+
expect(order).to receive(:apply_free_shipping_promotions)
|
|
296
|
+
order.next!
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
context "with payment required" do
|
|
300
|
+
before do
|
|
301
|
+
allow(order).to receive_messages :payment_required? => true
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it "transitions to payment" do
|
|
305
|
+
expect(order).to receive(:set_shipments_cost)
|
|
306
|
+
order.next!
|
|
307
|
+
assert_state_changed(order, 'delivery', 'payment')
|
|
308
|
+
expect(order.state).to eq('payment')
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
context "without payment required" do
|
|
313
|
+
before do
|
|
314
|
+
allow(order).to receive_messages :payment_required? => false
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "transitions to complete" do
|
|
318
|
+
order.next!
|
|
319
|
+
expect(order.state).to eq("confirm")
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
context "correctly determining payment required based on shipping information" do
|
|
324
|
+
let(:shipment) do
|
|
325
|
+
FactoryGirl.create(:shipment)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
before do
|
|
329
|
+
# Needs to be set here because we're working with a persisted order object
|
|
330
|
+
order.email = "test@example.com"
|
|
331
|
+
order.save!
|
|
332
|
+
order.shipments << shipment
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
context "with a shipment that has a price" do
|
|
336
|
+
before do
|
|
337
|
+
shipment.shipping_rates.first.update_column(:cost, 10)
|
|
338
|
+
order.set_shipments_cost
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it "transitions to payment" do
|
|
342
|
+
order.next!
|
|
343
|
+
expect(order.state).to eq("payment")
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
context "with a shipment that is free" do
|
|
348
|
+
before do
|
|
349
|
+
shipment.shipping_rates.first.update_column(:cost, 0)
|
|
350
|
+
order.set_shipments_cost
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it "skips payment, transitions to confirm" do
|
|
354
|
+
order.next!
|
|
355
|
+
expect(order.state).to eq("confirm")
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
context "to payment" do
|
|
362
|
+
let(:user_bill_address) { nil }
|
|
363
|
+
let(:order_bill_address) { nil }
|
|
364
|
+
let(:default_credit_card) { create(:credit_card) }
|
|
365
|
+
|
|
366
|
+
before do
|
|
367
|
+
@default_credit_card = FactoryGirl.create(:credit_card)
|
|
368
|
+
user = Spree::LegacyUser.new(email: 'spree@example.org', bill_address: user_bill_address)
|
|
369
|
+
allow(user).to receive(:default_credit_card) { @default_credit_card }
|
|
370
|
+
order.user = user
|
|
371
|
+
|
|
372
|
+
allow(order).to receive_messages(payment_required?: true)
|
|
373
|
+
order.state = 'delivery'
|
|
374
|
+
order.bill_address = order_bill_address
|
|
375
|
+
order.save!
|
|
376
|
+
order.next!
|
|
377
|
+
order.reload
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
it "assigns the user's default credit card" do
|
|
381
|
+
expect(order.state).to eq 'payment'
|
|
382
|
+
expect(order.payments.count).to eq 1
|
|
383
|
+
expect(order.payments.first.source).to eq @default_credit_card
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
context "order already has a billing address" do
|
|
387
|
+
let(:order_bill_address) { create(:address) }
|
|
388
|
+
|
|
389
|
+
it "keeps the order's billing address" do
|
|
390
|
+
expect(order.bill_address).to eq order_bill_address
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
context "order doesn't have a billing address" do
|
|
395
|
+
let(:user_bill_address) { create(:address) }
|
|
396
|
+
|
|
397
|
+
it "assigns the user's billing address to the order" do
|
|
398
|
+
expect(order.bill_address).to eq user_bill_address
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
context "from payment" do
|
|
404
|
+
before do
|
|
405
|
+
order.state = 'payment'
|
|
406
|
+
allow(order).to receive(:ensure_available_shipping_rates) { true }
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
context "with confirmation required" do
|
|
410
|
+
before do
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
it "transitions to confirm" do
|
|
414
|
+
order.next!
|
|
415
|
+
assert_state_changed(order, 'payment', 'confirm')
|
|
416
|
+
expect(order.state).to eq("confirm")
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
context "without confirmation required" do
|
|
421
|
+
before do
|
|
422
|
+
order.email = "spree@example.com"
|
|
423
|
+
order.store = FactoryGirl.build(:store)
|
|
424
|
+
allow(order).to receive_messages :payment_required? => true
|
|
425
|
+
order.payments << FactoryGirl.create(:payment, state: payment_state, order: order)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
context 'when there is at least one valid payment' do
|
|
429
|
+
let(:payment_state) { 'checkout' }
|
|
430
|
+
|
|
431
|
+
before do
|
|
432
|
+
expect(order).to receive(:process_payments!).once { true }
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
it "transitions to complete" do
|
|
436
|
+
order.complete!
|
|
437
|
+
assert_state_changed(order, 'payment', 'complete')
|
|
438
|
+
expect(order.state).to eq('complete')
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
context 'when there is only an invalid payment' do
|
|
443
|
+
let(:payment_state) { 'failed' }
|
|
444
|
+
|
|
445
|
+
it "raises a StateMachines::InvalidTransition" do
|
|
446
|
+
expect {
|
|
447
|
+
order.complete!
|
|
448
|
+
}.to raise_error(StateMachines::InvalidTransition, /#{Spree.t(:no_payment_found)}/)
|
|
449
|
+
|
|
450
|
+
expect(order.errors[:base]).to include(Spree.t(:no_payment_found))
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# Regression test for #2028
|
|
456
|
+
context "when payment is not required" do
|
|
457
|
+
before do
|
|
458
|
+
allow(order).to receive_messages :payment_required? => false
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
it "does not call process payments" do
|
|
462
|
+
expect(order).not_to receive(:process_payments!)
|
|
463
|
+
order.next!
|
|
464
|
+
assert_state_changed(order, 'payment', 'confirm')
|
|
465
|
+
expect(order.state).to eq("confirm")
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
context "from confirm" do
|
|
472
|
+
before do
|
|
473
|
+
order.state = 'confirm'
|
|
474
|
+
order.save!
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
it "returns false on next" do
|
|
478
|
+
expect(order.next).to be_falsy
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
it "is unable to next" do
|
|
482
|
+
expect(order).not_to be_can_next
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
context "to complete" do
|
|
487
|
+
before do
|
|
488
|
+
order.state = 'confirm'
|
|
489
|
+
order.save!
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
context "out of stock" do
|
|
493
|
+
before do
|
|
494
|
+
order.user = FactoryGirl.create(:user)
|
|
495
|
+
order.email = 'spree@example.org'
|
|
496
|
+
order.payments << FactoryGirl.create(:payment)
|
|
497
|
+
allow(order).to receive_messages(payment_required?: true)
|
|
498
|
+
order.line_items << FactoryGirl.create(:line_item)
|
|
499
|
+
order.line_items.first.variant.stock_items.each do |si|
|
|
500
|
+
si.set_count_on_hand(0)
|
|
501
|
+
si.update_attributes(:backorderable => false)
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
Spree::OrderUpdater.new(order).update
|
|
505
|
+
order.save!
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
it "does not allow the order to complete" do
|
|
509
|
+
expect {
|
|
510
|
+
order.complete!
|
|
511
|
+
}.to raise_error Spree::Order::InsufficientStock
|
|
512
|
+
|
|
513
|
+
expect(order.state).to eq 'confirm'
|
|
514
|
+
expect(order.line_items.first.errors[:quantity]).to be_present
|
|
515
|
+
expect(order.payments.first.state).to eq('checkout')
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
context "no inventory units" do
|
|
520
|
+
before do
|
|
521
|
+
order.user = FactoryGirl.create(:user)
|
|
522
|
+
order.email = 'spree@example.com'
|
|
523
|
+
order.payments << FactoryGirl.create(:payment)
|
|
524
|
+
allow(order).to receive_messages(payment_required?: true)
|
|
525
|
+
allow(order).to receive(:ensure_available_shipping_rates) { true }
|
|
526
|
+
order.line_items << FactoryGirl.create(:line_item)
|
|
527
|
+
|
|
528
|
+
Spree::OrderUpdater.new(order).update
|
|
529
|
+
order.save!
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it "does not allow order to complete" do
|
|
533
|
+
expect { order.complete! }.to raise_error Spree::Order::InsufficientStock
|
|
534
|
+
|
|
535
|
+
expect(order.state).to eq 'confirm'
|
|
536
|
+
expect(order.line_items.first.errors[:inventory]).to be_present
|
|
537
|
+
expect(order.payments.first.state).to eq('checkout')
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
context "exchange order completion" do
|
|
542
|
+
before do
|
|
543
|
+
order.email = 'spree@example.org'
|
|
544
|
+
order.payments << FactoryGirl.create(:payment)
|
|
545
|
+
order.shipments.create!
|
|
546
|
+
allow(order).to receive_messages(payment_required?: true)
|
|
547
|
+
allow(order).to receive(:ensure_available_shipping_rates).and_return(true)
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
context 'when the line items are not available' do
|
|
551
|
+
before do
|
|
552
|
+
order.line_items << FactoryGirl.create(:line_item)
|
|
553
|
+
order.store = FactoryGirl.build(:store)
|
|
554
|
+
Spree::OrderUpdater.new(order).update
|
|
555
|
+
|
|
556
|
+
order.save!
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
context 'when the exchange is for an unreturned item' do
|
|
560
|
+
before do
|
|
561
|
+
order.shipments.first.update_attributes!(created_at: order.created_at - 1.day)
|
|
562
|
+
expect(order.unreturned_exchange?).to eq true
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
it 'allows the order to complete' do
|
|
566
|
+
order.complete!
|
|
567
|
+
|
|
568
|
+
expect(order).to be_complete
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
context 'when the exchange is not for an unreturned item' do
|
|
573
|
+
it 'does not allow the order to completed' do
|
|
574
|
+
expect { order.complete! }.to raise_error Spree::Order::InsufficientStock
|
|
575
|
+
expect(order.payments.first.state).to eq('checkout')
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
context "default credit card" do
|
|
582
|
+
before do
|
|
583
|
+
order.user = FactoryGirl.create(:user)
|
|
584
|
+
order.store = FactoryGirl.create(:store)
|
|
585
|
+
order.email = 'spree@example.org'
|
|
586
|
+
order.payments << FactoryGirl.create(:payment)
|
|
587
|
+
|
|
588
|
+
# make sure we will actually capture a payment
|
|
589
|
+
allow(order).to receive_messages(payment_required?: true)
|
|
590
|
+
allow(order).to receive_messages(ensure_available_shipping_rates: true)
|
|
591
|
+
allow(order).to receive_messages(validate_line_item_availability: true)
|
|
592
|
+
order.line_items << FactoryGirl.create(:line_item)
|
|
593
|
+
order.create_proposed_shipments
|
|
594
|
+
Spree::OrderUpdater.new(order).update
|
|
595
|
+
|
|
596
|
+
order.save!
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
it "makes the current credit card a user's default credit card" do
|
|
600
|
+
order.complete!
|
|
601
|
+
expect(order.state).to eq 'complete'
|
|
602
|
+
expect(order.user.reload.default_credit_card.try(:id)).to eq(order.credit_cards.first.id)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
it "does not assign a default credit card if temporary_credit_card is set" do
|
|
606
|
+
order.temporary_credit_card = true
|
|
607
|
+
order.complete!
|
|
608
|
+
expect(order.user.reload.default_credit_card).to be_nil
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
context "a payment fails during processing" do
|
|
613
|
+
before do
|
|
614
|
+
order.user = FactoryGirl.create(:user)
|
|
615
|
+
order.email = 'spree@example.org'
|
|
616
|
+
payment = FactoryGirl.create(:payment)
|
|
617
|
+
allow(payment).to receive(:process!).and_raise(Spree::Core::GatewayError.new('processing failed'))
|
|
618
|
+
order.line_items.each { |li| li.inventory_units.create! }
|
|
619
|
+
order.payments << payment
|
|
620
|
+
|
|
621
|
+
# make sure we will actually capture a payment
|
|
622
|
+
allow(order).to receive_messages(payment_required?: true)
|
|
623
|
+
allow(order).to receive_messages(ensure_available_shipping_rates: true)
|
|
624
|
+
allow(order).to receive_messages(validate_line_item_availability: true)
|
|
625
|
+
order.line_items << FactoryGirl.create(:line_item)
|
|
626
|
+
order.create_proposed_shipments
|
|
627
|
+
Spree::OrderUpdater.new(order).update
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
it "transitions to the payment state" do
|
|
631
|
+
expect { order.complete! }.to raise_error StateMachines::InvalidTransition
|
|
632
|
+
expect(order.reload.state).to eq 'payment'
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
context 'the order is already paid' do
|
|
637
|
+
let(:order) { create(:order_with_line_items) }
|
|
638
|
+
|
|
639
|
+
it 'can complete the order' do
|
|
640
|
+
payment = create(:payment, state: 'completed', order: order, amount: order.total)
|
|
641
|
+
order.update!
|
|
642
|
+
expect(order.complete).to eq(true)
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
context "subclassed order" do
|
|
648
|
+
# This causes another test above to fail, but fixing this test should make
|
|
649
|
+
# the other test pass
|
|
650
|
+
class SubclassedOrder < Spree::Order
|
|
651
|
+
checkout_flow do
|
|
652
|
+
go_to_state :payment
|
|
653
|
+
go_to_state :complete
|
|
654
|
+
end
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
skip "should only call default transitions once when checkout_flow is redefined" do
|
|
658
|
+
order = SubclassedOrder.new
|
|
659
|
+
allow(order).to receive_messages :payment_required? => true
|
|
660
|
+
expect(order).to receive(:process_payments!).once
|
|
661
|
+
order.state = "payment"
|
|
662
|
+
order.next!
|
|
663
|
+
assert_state_changed(order, 'payment', 'complete')
|
|
664
|
+
expect(order.state).to eq("complete")
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
context "re-define checkout flow" do
|
|
669
|
+
before do
|
|
670
|
+
@old_checkout_flow = Spree::Order.checkout_flow
|
|
671
|
+
Spree::Order.class_eval do
|
|
672
|
+
checkout_flow do
|
|
673
|
+
go_to_state :payment
|
|
674
|
+
go_to_state :complete
|
|
675
|
+
end
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
after do
|
|
680
|
+
Spree::Order.checkout_flow(&@old_checkout_flow)
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
it "should not keep old event transitions when checkout_flow is redefined" do
|
|
684
|
+
expect(Spree::Order.next_event_transitions).to eq([{:cart=>:payment}, {:payment=>:complete}])
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
it "should not keep old events when checkout_flow is redefined" do
|
|
688
|
+
state_machine = Spree::Order.state_machine
|
|
689
|
+
expect(state_machine.states.any? { |s| s.name == :address }).to be false
|
|
690
|
+
known_states = state_machine.events[:next].branches.map(&:known_states).flatten
|
|
691
|
+
expect(known_states).not_to include(:address)
|
|
692
|
+
expect(known_states).not_to include(:delivery)
|
|
693
|
+
expect(known_states).not_to include(:confirm)
|
|
694
|
+
end
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
# Regression test for #3665
|
|
698
|
+
context "with only a complete step" do
|
|
699
|
+
let!(:line_item){ create :line_item, order: order }
|
|
700
|
+
|
|
701
|
+
before do
|
|
702
|
+
@old_checkout_flow = Spree::Order.checkout_flow
|
|
703
|
+
Spree::Order.class_eval do
|
|
704
|
+
checkout_flow do
|
|
705
|
+
go_to_state :complete
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
after do
|
|
711
|
+
Spree::Order.checkout_flow(&@old_checkout_flow)
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
it "does not attempt to process payments" do
|
|
715
|
+
order.email = 'user@example.com'
|
|
716
|
+
order.store = FactoryGirl.build(:store)
|
|
717
|
+
allow(order).to receive(:ensure_available_shipping_rates).and_return(true)
|
|
718
|
+
allow(order).to receive(:ensure_promotions_eligible).and_return(true)
|
|
719
|
+
allow(order).to receive(:ensure_line_item_variants_are_not_deleted).and_return(true)
|
|
720
|
+
allow(order).to receive_message_chain(:line_items, :present?).and_return(true)
|
|
721
|
+
allow(order).to receive_messages(validate_line_item_availability: true)
|
|
722
|
+
expect(order).not_to receive(:payment_required?)
|
|
723
|
+
expect(order).not_to receive(:process_payments!)
|
|
724
|
+
order.next!
|
|
725
|
+
assert_state_changed(order, 'cart', 'complete')
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
context "insert checkout step" do
|
|
731
|
+
before do
|
|
732
|
+
@old_checkout_flow = Spree::Order.checkout_flow
|
|
733
|
+
Spree::Order.class_eval do
|
|
734
|
+
remove_transition from: :delivery, to: :confirm
|
|
735
|
+
end
|
|
736
|
+
Spree::Order.class_eval do
|
|
737
|
+
insert_checkout_step :new_step, before: :address
|
|
738
|
+
end
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
after do
|
|
742
|
+
Spree::Order.checkout_flow(&@old_checkout_flow)
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
it "should maintain removed transitions" do
|
|
746
|
+
transition = Spree::Order.find_transition(:from => :delivery, :to => :confirm)
|
|
747
|
+
expect(transition).to be_nil
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
context "before" do
|
|
751
|
+
before do
|
|
752
|
+
Spree::Order.class_eval do
|
|
753
|
+
insert_checkout_step :before_address, before: :address
|
|
754
|
+
end
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
specify do
|
|
758
|
+
order = Spree::Order.new
|
|
759
|
+
expect(order.checkout_steps).to eq(%w(new_step before_address address delivery confirm complete))
|
|
760
|
+
end
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
context "after" do
|
|
764
|
+
before do
|
|
765
|
+
Spree::Order.class_eval do
|
|
766
|
+
insert_checkout_step :after_address, after: :address
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
specify do
|
|
771
|
+
order = Spree::Order.new
|
|
772
|
+
expect(order.checkout_steps).to eq(%w(new_step address after_address delivery confirm complete))
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
context "remove checkout step" do
|
|
778
|
+
before do
|
|
779
|
+
@old_checkout_flow = Spree::Order.checkout_flow
|
|
780
|
+
Spree::Order.class_eval do
|
|
781
|
+
remove_transition from: :delivery, to: :confirm
|
|
782
|
+
end
|
|
783
|
+
Spree::Order.class_eval do
|
|
784
|
+
remove_checkout_step :address
|
|
785
|
+
end
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
after do
|
|
789
|
+
Spree::Order.checkout_flow(&@old_checkout_flow)
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
it "should maintain removed transitions" do
|
|
793
|
+
transition = Spree::Order.find_transition(:from => :delivery, :to => :confirm)
|
|
794
|
+
expect(transition).to be_nil
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
specify do
|
|
798
|
+
order = Spree::Order.new
|
|
799
|
+
expect(order.checkout_steps).to eq(%w(delivery confirm complete))
|
|
800
|
+
end
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
describe 'update_from_params' do
|
|
804
|
+
let(:permitted_params) { {} }
|
|
805
|
+
let(:params) { {} }
|
|
806
|
+
|
|
807
|
+
it 'calls update_atributes without order params' do
|
|
808
|
+
expect(order).to receive(:update_attributes).with({})
|
|
809
|
+
order.update_from_params( params, permitted_params)
|
|
810
|
+
end
|
|
811
|
+
|
|
812
|
+
it 'runs the callbacks' do
|
|
813
|
+
expect(order).to receive(:run_callbacks).with(:updating_from_params)
|
|
814
|
+
order.update_from_params( params, permitted_params)
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
context "passing a credit card" do
|
|
818
|
+
let(:permitted_params) do
|
|
819
|
+
Spree::PermittedAttributes.checkout_attributes +
|
|
820
|
+
[payments_attributes: Spree::PermittedAttributes.payment_attributes]
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
let(:credit_card) { create(:credit_card, user_id: order.user_id) }
|
|
824
|
+
|
|
825
|
+
let(:params) do
|
|
826
|
+
ActionController::Parameters.new(
|
|
827
|
+
order: { payments_attributes: [{payment_method_id: 1}], existing_card: credit_card.id },
|
|
828
|
+
cvc_confirm: "737",
|
|
829
|
+
payment_source: {
|
|
830
|
+
"1" => { name: "Luis Braga",
|
|
831
|
+
number: "4111 1111 1111 1111",
|
|
832
|
+
expiry: "06 / 2016",
|
|
833
|
+
verification_value: "737",
|
|
834
|
+
cc_type: "" }
|
|
835
|
+
}
|
|
836
|
+
)
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
before { order.user_id = 3 }
|
|
840
|
+
|
|
841
|
+
it "sets confirmation value when its available via :cvc_confirm" do
|
|
842
|
+
allow(Spree::CreditCard).to receive_messages find: credit_card
|
|
843
|
+
expect(credit_card).to receive(:verification_value=)
|
|
844
|
+
order.update_from_params(params, permitted_params)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
it "sets existing card as source for new payment" do
|
|
848
|
+
expect {
|
|
849
|
+
order.update_from_params(params, permitted_params)
|
|
850
|
+
}.to change { Spree::Payment.count }.by(1)
|
|
851
|
+
|
|
852
|
+
expect(Spree::Payment.last.source).to eq credit_card
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
it "sets request_env on payment" do
|
|
856
|
+
request_env = { "USER_AGENT" => "Firefox" }
|
|
857
|
+
|
|
858
|
+
expected_hash = { "payments_attributes" => [hash_including("request_env" => request_env)] }
|
|
859
|
+
expect(order).to receive(:update_attributes).with expected_hash
|
|
860
|
+
|
|
861
|
+
order.update_from_params(params, permitted_params, request_env)
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
it "dont let users mess with others users cards" do
|
|
865
|
+
credit_card.update_column :user_id, 5
|
|
866
|
+
|
|
867
|
+
expect {
|
|
868
|
+
order.update_from_params(params, permitted_params)
|
|
869
|
+
}.to raise_error Spree::Core::GatewayError
|
|
870
|
+
end
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
context 'has params' do
|
|
874
|
+
let(:permitted_params) { [ :good_param ] }
|
|
875
|
+
let(:params) { ActionController::Parameters.new(order: { bad_param: 'okay' } ) }
|
|
876
|
+
|
|
877
|
+
it 'does not let through unpermitted attributes' do
|
|
878
|
+
expect(order).to receive(:update_attributes).with({})
|
|
879
|
+
order.update_from_params(params, permitted_params)
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
context 'has allowed params' do
|
|
883
|
+
let(:params) { ActionController::Parameters.new(order: { good_param: 'okay' } ) }
|
|
884
|
+
|
|
885
|
+
it 'accepts permitted attributes' do
|
|
886
|
+
expect(order).to receive(:update_attributes).with({"good_param" => 'okay'})
|
|
887
|
+
order.update_from_params(params, permitted_params)
|
|
888
|
+
end
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
context 'callbacks halt' do
|
|
892
|
+
before do
|
|
893
|
+
expect(order).to receive(:update_params_payment_source).and_return false
|
|
894
|
+
end
|
|
895
|
+
it 'does not let through unpermitted attributes' do
|
|
896
|
+
expect(order).not_to receive(:update_attributes).with({})
|
|
897
|
+
order.update_from_params(params, permitted_params)
|
|
898
|
+
end
|
|
899
|
+
end
|
|
900
|
+
end
|
|
901
|
+
end
|
|
902
|
+
end
|