solidus_core 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_core might be problematic. Click here for more details.

Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/Gemfile +3 -0
  4. data/Rakefile +16 -0
  5. data/script/rails +9 -0
  6. data/solidus_core.gemspec +48 -0
  7. data/spec/fixtures/thinking-cat.jpg +0 -0
  8. data/spec/helpers/base_helper_spec.rb +173 -0
  9. data/spec/helpers/order_helper_spec.rb +12 -0
  10. data/spec/helpers/products_helper_spec.rb +220 -0
  11. data/spec/helpers/taxons_helper_spec.rb +17 -0
  12. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  13. data/spec/lib/i18n_spec.rb +123 -0
  14. data/spec/lib/search/base_spec.rb +86 -0
  15. data/spec/lib/search/variant_spec.rb +92 -0
  16. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
  17. data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -0
  18. data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
  19. data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
  20. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
  21. data/spec/lib/spree/core/current_store_spec.rb +36 -0
  22. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
  23. data/spec/lib/spree/core/importer/order_spec.rb +431 -0
  24. data/spec/lib/spree/core/role_configuration_spec.rb +138 -0
  25. data/spec/lib/spree/core/validators/email_spec.rb +48 -0
  26. data/spec/lib/spree/localized_number_spec.rb +38 -0
  27. data/spec/lib/spree/migrations_spec.rb +36 -0
  28. data/spec/lib/spree/money_spec.rb +127 -0
  29. data/spec/lib/tasks/exchanges_spec.rb +231 -0
  30. data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
  31. data/spec/lib/tasks/order_capturing_spec.rb +56 -0
  32. data/spec/mailers/carton_mailer_spec.rb +43 -0
  33. data/spec/mailers/order_mailer_spec.rb +122 -0
  34. data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
  35. data/spec/mailers/test_mailer_spec.rb +15 -0
  36. data/spec/models/spree/ability_spec.rb +276 -0
  37. data/spec/models/spree/address_spec.rb +250 -0
  38. data/spec/models/spree/adjustment_reason_spec.rb +13 -0
  39. data/spec/models/spree/adjustment_spec.rb +177 -0
  40. data/spec/models/spree/app_configuration_spec.rb +20 -0
  41. data/spec/models/spree/asset_spec.rb +24 -0
  42. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  43. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  44. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  45. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  46. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  47. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  48. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
  49. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  50. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  51. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  52. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  53. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
  54. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
  55. data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
  56. data/spec/models/spree/calculator_spec.rb +36 -0
  57. data/spec/models/spree/carton_spec.rb +133 -0
  58. data/spec/models/spree/classification_spec.rb +15 -0
  59. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  60. data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
  61. data/spec/models/spree/credit_card_spec.rb +334 -0
  62. data/spec/models/spree/customer_return_spec.rb +276 -0
  63. data/spec/models/spree/exchange_spec.rb +79 -0
  64. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  65. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  66. data/spec/models/spree/gateway_spec.rb +82 -0
  67. data/spec/models/spree/inventory_unit_spec.rb +307 -0
  68. data/spec/models/spree/item_adjustments_spec.rb +256 -0
  69. data/spec/models/spree/line_item_spec.rb +191 -0
  70. data/spec/models/spree/option_type_spec.rb +14 -0
  71. data/spec/models/spree/option_value_spec.rb +22 -0
  72. data/spec/models/spree/order/address_spec.rb +50 -0
  73. data/spec/models/spree/order/adjustments_spec.rb +39 -0
  74. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  75. data/spec/models/spree/order/checkout_spec.rb +902 -0
  76. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  77. data/spec/models/spree/order/finalizing_spec.rb +111 -0
  78. data/spec/models/spree/order/payment_spec.rb +210 -0
  79. data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
  80. data/spec/models/spree/order/state_machine_spec.rb +221 -0
  81. data/spec/models/spree/order/tax_spec.rb +84 -0
  82. data/spec/models/spree/order/totals_spec.rb +24 -0
  83. data/spec/models/spree/order/updating_spec.rb +18 -0
  84. data/spec/models/spree/order/validations_spec.rb +15 -0
  85. data/spec/models/spree/order_cancellations_spec.rb +120 -0
  86. data/spec/models/spree/order_capturing_spec.rb +116 -0
  87. data/spec/models/spree/order_contents_spec.rb +265 -0
  88. data/spec/models/spree/order_inventory_spec.rb +228 -0
  89. data/spec/models/spree/order_mutex_spec.rb +85 -0
  90. data/spec/models/spree/order_promotion_spec.rb +31 -0
  91. data/spec/models/spree/order_shipping_spec.rb +247 -0
  92. data/spec/models/spree/order_spec.rb +1412 -0
  93. data/spec/models/spree/order_stock_location_spec.rb +18 -0
  94. data/spec/models/spree/order_updater_spec.rb +299 -0
  95. data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
  96. data/spec/models/spree/payment_method_spec.rb +96 -0
  97. data/spec/models/spree/payment_spec.rb +1044 -0
  98. data/spec/models/spree/permission_sets/base_spec.rb +12 -0
  99. data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
  100. data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
  101. data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
  102. data/spec/models/spree/permission_sets/order_display_spec.rb +49 -0
  103. data/spec/models/spree/permission_sets/order_management_spec.rb +36 -0
  104. data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
  105. data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
  106. data/spec/models/spree/permission_sets/promotion_display_spec.rb +34 -0
  107. data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
  108. data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
  109. data/spec/models/spree/permission_sets/restricted_transfer_management_spec.rb +132 -0
  110. data/spec/models/spree/permission_sets/stock_display_spec.rb +26 -0
  111. data/spec/models/spree/permission_sets/stock_management_spec.rb +24 -0
  112. data/spec/models/spree/permission_sets/user_display_spec.rb +36 -0
  113. data/spec/models/spree/permission_sets/user_management_spec.rb +28 -0
  114. data/spec/models/spree/preference_spec.rb +80 -0
  115. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  116. data/spec/models/spree/preferences/preferable_spec.rb +294 -0
  117. data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
  118. data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
  119. data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
  120. data/spec/models/spree/preferences/store_spec.rb +39 -0
  121. data/spec/models/spree/price_spec.rb +42 -0
  122. data/spec/models/spree/product/scopes_spec.rb +148 -0
  123. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  124. data/spec/models/spree/product_filter_spec.rb +26 -0
  125. data/spec/models/spree/product_property_spec.rb +20 -0
  126. data/spec/models/spree/product_spec.rb +437 -0
  127. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
  128. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
  129. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
  130. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
  131. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  132. data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
  133. data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
  134. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  135. data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
  136. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  137. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  138. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  139. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  140. data/spec/models/spree/promotion_builder_spec.rb +118 -0
  141. data/spec/models/spree/promotion_category_spec.rb +17 -0
  142. data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
  143. data/spec/models/spree/promotion_code_spec.rb +187 -0
  144. data/spec/models/spree/promotion_handler/cart_spec.rb +114 -0
  145. data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
  146. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
  147. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  148. data/spec/models/spree/promotion_rule_spec.rb +28 -0
  149. data/spec/models/spree/promotion_spec.rb +767 -0
  150. data/spec/models/spree/refund_spec.rb +204 -0
  151. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  152. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  153. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  154. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  155. data/spec/models/spree/reimbursement_spec.rb +231 -0
  156. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  157. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  158. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  159. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
  160. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
  161. data/spec/models/spree/return_authorization_spec.rb +290 -0
  162. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  163. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  164. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
  165. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  166. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  167. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  168. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  169. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  170. data/spec/models/spree/return_item_spec.rb +775 -0
  171. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  172. data/spec/models/spree/shipment_spec.rb +709 -0
  173. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  174. data/spec/models/spree/shipping_method_spec.rb +88 -0
  175. data/spec/models/spree/shipping_rate_spec.rb +142 -0
  176. data/spec/models/spree/state_spec.rb +14 -0
  177. data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
  178. data/spec/models/spree/stock/coordinator_spec.rb +116 -0
  179. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  180. data/spec/models/spree/stock/estimator_spec.rb +146 -0
  181. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  182. data/spec/models/spree/stock/package_spec.rb +163 -0
  183. data/spec/models/spree/stock/packer_spec.rb +91 -0
  184. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  185. data/spec/models/spree/stock/quantifier_spec.rb +115 -0
  186. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  187. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  188. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
  189. data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
  190. data/spec/models/spree/stock_item_spec.rb +426 -0
  191. data/spec/models/spree/stock_location_spec.rb +279 -0
  192. data/spec/models/spree/stock_movement_spec.rb +56 -0
  193. data/spec/models/spree/stock_transfer_spec.rb +290 -0
  194. data/spec/models/spree/store_credit_category_spec.rb +17 -0
  195. data/spec/models/spree/store_credit_event_spec.rb +314 -0
  196. data/spec/models/spree/store_credit_spec.rb +876 -0
  197. data/spec/models/spree/store_spec.rb +55 -0
  198. data/spec/models/spree/tax_category_spec.rb +27 -0
  199. data/spec/models/spree/tax_rate_spec.rb +378 -0
  200. data/spec/models/spree/taxon_spec.rb +74 -0
  201. data/spec/models/spree/taxonomy_spec.rb +18 -0
  202. data/spec/models/spree/tracker_spec.rb +21 -0
  203. data/spec/models/spree/transfer_item_spec.rb +264 -0
  204. data/spec/models/spree/unit_cancel_spec.rb +148 -0
  205. data/spec/models/spree/user_spec.rb +223 -0
  206. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
  207. data/spec/models/spree/variant/scopes_spec.rb +55 -0
  208. data/spec/models/spree/variant_spec.rb +546 -0
  209. data/spec/models/spree/zone_spec.rb +305 -0
  210. data/spec/spec_helper.rb +78 -0
  211. data/spec/support/big_decimal.rb +5 -0
  212. data/spec/support/concerns/default_price.rb +34 -0
  213. data/spec/support/dummy_ability.rb +4 -0
  214. data/spec/support/test_gateway.rb +2 -0
  215. metadata +229 -3
  216. 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