spree_core 3.0.5 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile +3 -0
  4. data/Rakefile +30 -0
  5. data/app/assets/javascripts/spree.js.coffee.erb +1 -1
  6. data/app/models/spree/ability.rb +1 -1
  7. data/app/models/spree/base.rb +3 -1
  8. data/app/models/spree/order_updater.rb +2 -1
  9. data/app/models/spree/price.rb +7 -12
  10. data/app/models/spree/product.rb +3 -2
  11. data/app/models/spree/reimbursement.rb +1 -1
  12. data/app/models/spree/state.rb +2 -0
  13. data/app/models/spree/zone.rb +1 -1
  14. data/lib/spree/core/version.rb +1 -1
  15. data/lib/spree/testing_support/shoulda_matcher_configuration.rb +6 -0
  16. data/script/rails +9 -0
  17. data/spec/fixtures/thinking-cat.jpg +0 -0
  18. data/spec/helpers/base_helper_spec.rb +137 -0
  19. data/spec/helpers/products_helper_spec.rb +224 -0
  20. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  21. data/spec/lib/i18n_spec.rb +123 -0
  22. data/spec/lib/search/base_spec.rb +86 -0
  23. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +101 -0
  24. data/spec/lib/spree/core/controller_helpers/order_spec.rb +95 -0
  25. data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
  26. data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
  27. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
  28. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
  29. data/spec/lib/spree/core/importer/order_spec.rb +502 -0
  30. data/spec/lib/spree/core/validators/email_spec.rb +53 -0
  31. data/spec/lib/spree/localized_number_spec.rb +38 -0
  32. data/spec/lib/spree/migrations_spec.rb +34 -0
  33. data/spec/lib/spree/money_spec.rb +122 -0
  34. data/spec/lib/tasks/exchanges_spec.rb +136 -0
  35. data/spec/mailers/order_mailer_spec.rb +124 -0
  36. data/spec/mailers/reimbursement_mailer_spec.rb +47 -0
  37. data/spec/mailers/shipment_mailer_spec.rb +63 -0
  38. data/spec/mailers/test_mailer_spec.rb +24 -0
  39. data/spec/models/spree/ability_spec.rb +246 -0
  40. data/spec/models/spree/address_spec.rb +291 -0
  41. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +286 -0
  42. data/spec/models/spree/adjustment_spec.rb +163 -0
  43. data/spec/models/spree/app_configuration_spec.rb +23 -0
  44. data/spec/models/spree/asset_spec.rb +25 -0
  45. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  46. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  47. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  48. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  49. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  50. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  51. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
  52. data/spec/models/spree/calculator/shipping.rb +8 -0
  53. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  54. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  55. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  56. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  57. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +29 -0
  58. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +40 -0
  59. data/spec/models/spree/calculator/tiered_percent_spec.rb +51 -0
  60. data/spec/models/spree/calculator_spec.rb +69 -0
  61. data/spec/models/spree/classification_spec.rb +93 -0
  62. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  63. data/spec/models/spree/country_spec.rb +18 -0
  64. data/spec/models/spree/credit_card_spec.rb +324 -0
  65. data/spec/models/spree/customer_return_spec.rb +262 -0
  66. data/spec/models/spree/exchange_spec.rb +75 -0
  67. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  68. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  69. data/spec/models/spree/gateway_spec.rb +54 -0
  70. data/spec/models/spree/image_spec.rb +5 -0
  71. data/spec/models/spree/inventory_unit_spec.rb +242 -0
  72. data/spec/models/spree/line_item_spec.rb +267 -0
  73. data/spec/models/spree/option_type_spec.rb +14 -0
  74. data/spec/models/spree/option_value_spec.rb +13 -0
  75. data/spec/models/spree/order/address_spec.rb +50 -0
  76. data/spec/models/spree/order/adjustments_spec.rb +29 -0
  77. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  78. data/spec/models/spree/order/checkout_spec.rb +764 -0
  79. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  80. data/spec/models/spree/order/finalizing_spec.rb +117 -0
  81. data/spec/models/spree/order/helpers_spec.rb +5 -0
  82. data/spec/models/spree/order/payment_spec.rb +214 -0
  83. data/spec/models/spree/order/risk_assessment_spec.rb +84 -0
  84. data/spec/models/spree/order/shipments_spec.rb +43 -0
  85. data/spec/models/spree/order/state_machine_spec.rb +216 -0
  86. data/spec/models/spree/order/tax_spec.rb +84 -0
  87. data/spec/models/spree/order/totals_spec.rb +24 -0
  88. data/spec/models/spree/order/updating_spec.rb +18 -0
  89. data/spec/models/spree/order/validations_spec.rb +15 -0
  90. data/spec/models/spree/order_contents_spec.rb +256 -0
  91. data/spec/models/spree/order_inventory_spec.rb +228 -0
  92. data/spec/models/spree/order_merger_spec.rb +133 -0
  93. data/spec/models/spree/order_spec.rb +954 -0
  94. data/spec/models/spree/order_updater_spec.rb +283 -0
  95. data/spec/models/spree/payment/gateway_options_spec.rb +119 -0
  96. data/spec/models/spree/payment_method_spec.rb +95 -0
  97. data/spec/models/spree/payment_spec.rb +926 -0
  98. data/spec/models/spree/preference_spec.rb +80 -0
  99. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  100. data/spec/models/spree/preferences/preferable_spec.rb +348 -0
  101. data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
  102. data/spec/models/spree/preferences/store_spec.rb +46 -0
  103. data/spec/models/spree/price_spec.rb +42 -0
  104. data/spec/models/spree/product/scopes_spec.rb +148 -0
  105. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  106. data/spec/models/spree/product_filter_spec.rb +26 -0
  107. data/spec/models/spree/product_option_type_spec.rb +5 -0
  108. data/spec/models/spree/product_property_spec.rb +11 -0
  109. data/spec/models/spree/product_spec.rb +474 -0
  110. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +50 -0
  111. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +148 -0
  112. data/spec/models/spree/promotion/actions/create_line_items_spec.rb +86 -0
  113. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +36 -0
  114. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  115. data/spec/models/spree/promotion/rules/item_total_spec.rb +282 -0
  116. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  117. data/spec/models/spree/promotion/rules/option_value_spec.rb +90 -0
  118. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  119. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  120. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  121. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  122. data/spec/models/spree/promotion_action_spec.rb +10 -0
  123. data/spec/models/spree/promotion_category_spec.rb +17 -0
  124. data/spec/models/spree/promotion_handler/cart_spec.rb +102 -0
  125. data/spec/models/spree/promotion_handler/coupon_spec.rb +323 -0
  126. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +48 -0
  127. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  128. data/spec/models/spree/promotion_rule_spec.rb +29 -0
  129. data/spec/models/spree/promotion_spec.rb +603 -0
  130. data/spec/models/spree/property_spec.rb +5 -0
  131. data/spec/models/spree/prototype_spec.rb +5 -0
  132. data/spec/models/spree/refund_spec.rb +195 -0
  133. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  134. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  135. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  136. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  137. data/spec/models/spree/reimbursement_spec.rb +215 -0
  138. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  139. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  140. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  141. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +55 -0
  142. data/spec/models/spree/return_authorization_spec.rb +250 -0
  143. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  144. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  145. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +61 -0
  146. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  147. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  148. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  149. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  150. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  151. data/spec/models/spree/return_item_spec.rb +682 -0
  152. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  153. data/spec/models/spree/shipment_spec.rb +740 -0
  154. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  155. data/spec/models/spree/shipping_category_spec.rb +5 -0
  156. data/spec/models/spree/shipping_method_spec.rb +88 -0
  157. data/spec/models/spree/shipping_rate_spec.rb +141 -0
  158. data/spec/models/spree/state_spec.rb +18 -0
  159. data/spec/models/spree/stock/availability_validator_spec.rb +36 -0
  160. data/spec/models/spree/stock/content_item_spec.rb +22 -0
  161. data/spec/models/spree/stock/coordinator_spec.rb +51 -0
  162. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  163. data/spec/models/spree/stock/estimator_spec.rb +154 -0
  164. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  165. data/spec/models/spree/stock/package_spec.rb +194 -0
  166. data/spec/models/spree/stock/packer_spec.rb +70 -0
  167. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  168. data/spec/models/spree/stock/quantifier_spec.rb +97 -0
  169. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  170. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  171. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +47 -0
  172. data/spec/models/spree/stock/splitter/weight_spec.rb +32 -0
  173. data/spec/models/spree/stock_item_spec.rb +410 -0
  174. data/spec/models/spree/stock_location_spec.rb +243 -0
  175. data/spec/models/spree/stock_movement_spec.rb +56 -0
  176. data/spec/models/spree/stock_transfer_spec.rb +50 -0
  177. data/spec/models/spree/store_spec.rb +50 -0
  178. data/spec/models/spree/tax_category_spec.rb +27 -0
  179. data/spec/models/spree/tax_rate_spec.rb +382 -0
  180. data/spec/models/spree/taxon_spec.rb +74 -0
  181. data/spec/models/spree/taxonomy_spec.rb +18 -0
  182. data/spec/models/spree/tracker_spec.rb +21 -0
  183. data/spec/models/spree/user_spec.rb +130 -0
  184. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +24 -0
  185. data/spec/models/spree/variant_spec.rb +523 -0
  186. data/spec/models/spree/zone_spec.rb +444 -0
  187. data/spec/spec_helper.rb +74 -0
  188. data/spec/support/big_decimal.rb +5 -0
  189. data/spec/support/concerns/adjustment_source_spec.rb +23 -0
  190. data/spec/support/concerns/default_price_spec.rb +28 -0
  191. data/spec/support/rake.rb +13 -0
  192. data/spec/support/test_gateway.rb +2 -0
  193. data/spree_core.gemspec +48 -0
  194. metadata +185 -4
@@ -0,0 +1,267 @@
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
+ before { create(:store) }
8
+
9
+ context '#save' do
10
+ it 'touches the order' do
11
+ expect(line_item.order).to receive(:touch)
12
+ line_item.touch
13
+ end
14
+ end
15
+
16
+ context '#destroy' do
17
+ it "fetches deleted products" do
18
+ line_item.product.destroy
19
+ expect(line_item.reload.product).to be_a Spree::Product
20
+ end
21
+
22
+ it "fetches deleted variants" do
23
+ line_item.variant.destroy
24
+ expect(line_item.reload.variant).to be_a Spree::Variant
25
+ end
26
+
27
+ it "returns inventory when a line item is destroyed" do
28
+ expect_any_instance_of(Spree::OrderInventory).to receive(:verify)
29
+ line_item.destroy
30
+ end
31
+
32
+ it "deletes inventory units" do
33
+ expect { line_item.destroy }.to change { line_item.inventory_units.count }.from(1).to(0)
34
+ end
35
+ end
36
+
37
+ context "#save" do
38
+ context "line item changes" do
39
+ before do
40
+ line_item.quantity = line_item.quantity + 1
41
+ end
42
+
43
+ it "triggers adjustment total recalculation" do
44
+ expect(line_item).to receive(:update_tax_charge) # Regression test for https://github.com/spree/spree/issues/4671
45
+ expect(line_item).to receive(:recalculate_adjustments)
46
+ line_item.save
47
+ end
48
+ end
49
+
50
+ context "line item does not change" do
51
+ it "does not trigger adjustment total recalculation" do
52
+ expect(line_item).not_to receive(:recalculate_adjustments)
53
+ line_item.save
54
+ end
55
+ end
56
+
57
+ context "target_shipment is provided" do
58
+ it "verifies inventory" do
59
+ line_item.target_shipment = Spree::Shipment.new
60
+ expect_any_instance_of(Spree::OrderInventory).to receive(:verify)
61
+ line_item.save
62
+ end
63
+ end
64
+ end
65
+
66
+ context "#create" do
67
+ let(:variant) { create(:variant) }
68
+
69
+ before do
70
+ create(:tax_rate, :zone => order.tax_zone, :tax_category => variant.tax_category)
71
+ end
72
+
73
+ context "when order has a tax zone" do
74
+ before do
75
+ expect(order.tax_zone).to be_present
76
+ end
77
+
78
+ it "creates a tax adjustment" do
79
+ order.contents.add(variant)
80
+ line_item = order.find_line_item_by_variant(variant)
81
+ expect(line_item.adjustments.tax.count).to eq(1)
82
+ end
83
+ end
84
+
85
+ context "when order does not have a tax zone" do
86
+ before do
87
+ order.bill_address = nil
88
+ order.ship_address = nil
89
+ order.save
90
+ expect(order.reload.tax_zone).to be_nil
91
+ end
92
+
93
+ it "does not create a tax adjustment" do
94
+ order.contents.add(variant)
95
+ line_item = order.find_line_item_by_variant(variant)
96
+ expect(line_item.adjustments.tax.count).to eq(0)
97
+ end
98
+ end
99
+ end
100
+
101
+ # Test for #3391
102
+ context '#copy_price' do
103
+ it "copies over a variant's prices" do
104
+ line_item.price = nil
105
+ line_item.cost_price = nil
106
+ line_item.currency = nil
107
+ line_item.copy_price
108
+ variant = line_item.variant
109
+ expect(line_item.price).to eq(variant.price)
110
+ expect(line_item.cost_price).to eq(variant.cost_price)
111
+ expect(line_item.currency).to eq(variant.currency)
112
+ end
113
+ end
114
+
115
+ # Test for #3481
116
+ context '#copy_tax_category' do
117
+ it "copies over a variant's tax category" do
118
+ line_item.tax_category = nil
119
+ line_item.copy_tax_category
120
+ expect(line_item.tax_category).to eq(line_item.variant.tax_category)
121
+ end
122
+ end
123
+
124
+ describe '.discounted_amount' do
125
+ it "returns the amount minus any discounts" do
126
+ line_item.price = 10
127
+ line_item.quantity = 2
128
+ line_item.promo_total = -5
129
+ expect(line_item.discounted_amount).to eq(15)
130
+ end
131
+ end
132
+
133
+ describe "#discounted_money" do
134
+ it "should return a money object with the discounted amount" do
135
+ expect(line_item.discounted_money.to_s).to eq "$10.00"
136
+ end
137
+ end
138
+
139
+ describe '.currency' do
140
+ it 'returns the globally configured currency' do
141
+ line_item.currency == 'USD'
142
+ end
143
+ end
144
+
145
+ describe ".money" do
146
+ before do
147
+ line_item.price = 3.50
148
+ line_item.quantity = 2
149
+ end
150
+
151
+ it "returns a Spree::Money representing the total for this line item" do
152
+ expect(line_item.money.to_s).to eq("$7.00")
153
+ end
154
+ end
155
+
156
+ describe '.single_money' do
157
+ before { line_item.price = 3.50 }
158
+ it "returns a Spree::Money representing the price for one variant" do
159
+ expect(line_item.single_money.to_s).to eq("$3.50")
160
+ end
161
+ end
162
+
163
+ context "has inventory (completed order so items were already unstocked)" do
164
+ let(:order) { Spree::Order.create(email: 'spree@example.com') }
165
+ let(:variant) { create(:variant) }
166
+
167
+ context "nothing left on stock" do
168
+ before do
169
+ variant.stock_items.update_all count_on_hand: 5, backorderable: false
170
+ order.contents.add(variant, 5)
171
+ order.create_proposed_shipments
172
+ order.finalize!
173
+ end
174
+
175
+ it "allows to decrease item quantity" do
176
+ line_item = order.line_items.first
177
+ line_item.quantity -= 1
178
+ line_item.target_shipment = order.shipments.first
179
+
180
+ line_item.save
181
+ expect(line_item.errors_on(:quantity).size).to eq(0)
182
+ end
183
+
184
+ it "doesnt allow to increase item quantity" do
185
+ line_item = order.line_items.first
186
+ line_item.quantity += 2
187
+ line_item.target_shipment = order.shipments.first
188
+
189
+ line_item.save
190
+ expect(line_item.errors_on(:quantity).size).to eq(1)
191
+ end
192
+ end
193
+
194
+ context "2 items left on stock" do
195
+ before do
196
+ variant.stock_items.update_all count_on_hand: 7, backorderable: false
197
+ order.contents.add(variant, 5)
198
+ order.create_proposed_shipments
199
+ order.finalize!
200
+ end
201
+
202
+ it "allows to increase quantity up to stock availability" do
203
+ line_item = order.line_items.first
204
+ line_item.quantity += 2
205
+ line_item.target_shipment = order.shipments.first
206
+
207
+ line_item.save
208
+ expect(line_item.errors_on(:quantity).size).to eq(0)
209
+ end
210
+
211
+ it "doesnt allow to increase quantity over stock availability" do
212
+ line_item = order.line_items.first
213
+ line_item.quantity += 3
214
+ line_item.target_shipment = order.shipments.first
215
+
216
+ line_item.save
217
+ expect(line_item.errors_on(:quantity).size).to eq(1)
218
+ end
219
+ end
220
+ end
221
+
222
+ context "currency same as order.currency" do
223
+ it "is a valid line item" do
224
+ line_item = order.line_items.first
225
+ line_item.currency = order.currency
226
+ line_item.valid?
227
+
228
+ expect(line_item.error_on(:currency).size).to eq(0)
229
+ end
230
+ end
231
+
232
+ context "currency different than order.currency" do
233
+ it "is not a valid line item" do
234
+ line_item = order.line_items.first
235
+ line_item.currency = "no currency"
236
+ line_item.valid?
237
+
238
+ expect(line_item.error_on(:currency).size).to eq(1)
239
+ end
240
+ end
241
+
242
+ describe "#options=" do
243
+ it "can handle updating a blank line item with no order" do
244
+ line_item.options = { price: 123 }
245
+ end
246
+
247
+ it "updates the data provided in the options" do
248
+ line_item.options = { price: 123 }
249
+ expect(line_item.price).to eq 123
250
+ end
251
+
252
+ it "updates the price based on the options provided" do
253
+ expect(line_item).to receive(:gift_wrap=).with(true)
254
+ expect(line_item.variant).to receive(:gift_wrap_price_modifier_amount_in).with("USD", true).and_return 1.99
255
+ line_item.options = { gift_wrap: true }
256
+ expect(line_item.price).to eq 21.98
257
+ end
258
+ end
259
+
260
+ describe "precision of pre_tax_amount" do
261
+ let!(:line_item) { create :line_item, pre_tax_amount: 4.2051 }
262
+
263
+ it "keeps four digits of precision even when reloading" do
264
+ expect(line_item.reload.pre_tax_amount).to eq(4.2051)
265
+ end
266
+ end
267
+ 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,13 @@
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
+ 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,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Order do
4
+ context "when an order has an adjustment that zeroes the total, but another adjustment for shipping that raises it above zero" do
5
+ let!(:persisted_order) { create(:order) }
6
+ let!(:line_item) { create(:line_item) }
7
+ let!(:shipping_method) do
8
+ sm = create(:shipping_method)
9
+ sm.calculator.preferred_amount = 10
10
+ sm.save
11
+ sm
12
+ end
13
+
14
+ before do
15
+ # Don't care about available payment methods in this test
16
+ allow(persisted_order).to receive_messages(:has_available_payment => false)
17
+ persisted_order.line_items << line_item
18
+ create(:adjustment, amount: -line_item.amount, label: "Promotion", adjustable: line_item, order: persisted_order)
19
+ persisted_order.state = 'delivery'
20
+ persisted_order.save # To ensure new state_change event
21
+ end
22
+
23
+ it "transitions from delivery to payment" do
24
+ allow(persisted_order).to receive_messages(payment_required?: true)
25
+ persisted_order.next!
26
+ expect(persisted_order.state).to eq("payment")
27
+ end
28
+ end
29
+ 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,764 @@
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
+ before { create(:store) }
8
+
9
+ def assert_state_changed(order, from, to)
10
+ state_change_exists = order.state_changes.where(:previous_state => from, :next_state => to).exists?
11
+ assert state_change_exists, "Expected order to transition from #{from} to #{to}, but didn't."
12
+ end
13
+
14
+ context "with default state machine" do
15
+ let(:transitions) do
16
+ [
17
+ { :address => :delivery },
18
+ { :delivery => :payment },
19
+ { :payment => :confirm },
20
+ { :confirm => :complete },
21
+ { :payment => :complete },
22
+ { :delivery => :complete }
23
+ ]
24
+ end
25
+
26
+ it "has the following transitions" do
27
+ transitions.each do |transition|
28
+ transition = Spree::Order.find_transition(:from => transition.keys.first, :to => transition.values.first)
29
+ expect(transition).not_to be_nil
30
+ end
31
+ end
32
+
33
+ it "does not have a transition from delivery to confirm" do
34
+ transition = Spree::Order.find_transition(:from => :delivery, :to => :confirm)
35
+ expect(transition).to be_nil
36
+ end
37
+
38
+ it '.find_transition when contract was broken' do
39
+ expect(Spree::Order.find_transition({foo: :bar, baz: :dog})).to be_falsey
40
+ end
41
+
42
+ it '.remove_transition' do
43
+ options = {:from => transitions.first.keys.first, :to => transitions.first.values.first}
44
+ expect(Spree::Order).to receive_messages(
45
+ removed_transitions: [],
46
+ next_event_transitions: transitions.dup
47
+ )
48
+ expect(Spree::Order.remove_transition(options)).to be_truthy
49
+ expect(Spree::Order.removed_transitions).to eql([options])
50
+ expect(Spree::Order.next_event_transitions).to_not include(transitions.first)
51
+ end
52
+
53
+ it '.remove_transition when contract was broken' do
54
+ expect(Spree::Order.remove_transition(nil)).to be_falsey
55
+ end
56
+
57
+ it "always return integer on checkout_step_index" do
58
+ expect(order.checkout_step_index("imnotthere")).to be_a Integer
59
+ expect(order.checkout_step_index("delivery")).to be > 0
60
+ end
61
+
62
+ it "passes delivery state when transitioning from address over delivery to payment" do
63
+ allow(order).to receive_messages :payment_required? => true
64
+ order.state = "address"
65
+ expect(order.passed_checkout_step?("delivery")).to be false
66
+ order.state = "delivery"
67
+ expect(order.passed_checkout_step?("delivery")).to be false
68
+ order.state = "payment"
69
+ expect(order.passed_checkout_step?("delivery")).to be true
70
+ end
71
+
72
+ context "#checkout_steps" do
73
+ context "when confirmation not required" do
74
+ before do
75
+ allow(order).to receive_messages :confirmation_required? => false
76
+ allow(order).to receive_messages :payment_required? => true
77
+ end
78
+
79
+ specify do
80
+ expect(order.checkout_steps).to eq(%w(address delivery payment complete))
81
+ end
82
+ end
83
+
84
+ context "when confirmation required" do
85
+ before do
86
+ allow(order).to receive_messages :confirmation_required? => true
87
+ allow(order).to receive_messages :payment_required? => true
88
+ end
89
+
90
+ specify do
91
+ expect(order.checkout_steps).to eq(%w(address delivery payment confirm complete))
92
+ end
93
+ end
94
+
95
+ context "when payment not required" do
96
+ before { allow(order).to receive_messages :payment_required? => false }
97
+ specify do
98
+ expect(order.checkout_steps).to eq(%w(address delivery complete))
99
+ end
100
+ end
101
+
102
+ context "when payment required" do
103
+ before { allow(order).to receive_messages :payment_required? => true }
104
+ specify do
105
+ expect(order.checkout_steps).to eq(%w(address delivery payment complete))
106
+ end
107
+ end
108
+ end
109
+
110
+ it "starts out at cart" do
111
+ expect(order.state).to eq("cart")
112
+ end
113
+
114
+ context "to address" do
115
+ before do
116
+ order.email = "user@example.com"
117
+ order.save!
118
+ end
119
+
120
+ context "with a line item" do
121
+ before do
122
+ order.line_items << FactoryGirl.create(:line_item)
123
+ end
124
+
125
+ it "transitions to address" do
126
+ order.next!
127
+ assert_state_changed(order, 'cart', 'address')
128
+ expect(order.state).to eq("address")
129
+ end
130
+
131
+ it "doesn't raise an error if the default address is invalid" do
132
+ order.user = mock_model(Spree::LegacyUser, ship_address: Spree::Address.new, bill_address: Spree::Address.new)
133
+ expect { order.next! }.to_not raise_error
134
+ end
135
+
136
+ context "with default addresses" do
137
+ let(:default_address) { FactoryGirl.create(:address) }
138
+
139
+ before do
140
+ order.user = FactoryGirl.create(:user, "#{address_kind}_address" => default_address)
141
+ order.next!
142
+ order.reload
143
+ end
144
+
145
+ shared_examples "it cloned the default address" do
146
+ it do
147
+ default_attributes = default_address.attributes
148
+ order_attributes = order.send("#{address_kind}_address".to_sym).try(:attributes) || {}
149
+
150
+ expect(order_attributes.except('id', 'created_at', 'updated_at')).to eql(default_attributes.except('id', 'created_at', 'updated_at'))
151
+ end
152
+ end
153
+
154
+ it_behaves_like "it cloned the default address" do
155
+ let(:address_kind) { 'ship' }
156
+ end
157
+
158
+ it_behaves_like "it cloned the default address" do
159
+ let(:address_kind) { 'bill' }
160
+ end
161
+ end
162
+ end
163
+
164
+ it "cannot transition to address without any line items" do
165
+ expect(order.line_items).to be_blank
166
+ expect { order.next! }.to raise_error(StateMachines::InvalidTransition, /#{Spree.t(:there_are_no_items_for_this_order)}/)
167
+ end
168
+ end
169
+
170
+ context "from address" do
171
+ before do
172
+ order.state = 'address'
173
+ allow(order).to receive(:has_available_payment)
174
+ shipment = FactoryGirl.create(:shipment, :order => order)
175
+ order.email = "user@example.com"
176
+ order.save!
177
+ end
178
+
179
+ it "updates totals" do
180
+ allow(order).to receive_messages(:ensure_available_shipping_rates => true)
181
+ line_item = FactoryGirl.create(:line_item, :price => 10, :adjustment_total => 10)
182
+ order.line_items << line_item
183
+ tax_rate = create(:tax_rate, :tax_category => line_item.tax_category, :amount => 0.05)
184
+ allow(Spree::TaxRate).to receive_messages :match => [tax_rate]
185
+ FactoryGirl.create(:tax_adjustment, :adjustable => line_item, :source => tax_rate, order: order)
186
+ order.email = "user@example.com"
187
+ order.next!
188
+ expect(order.adjustment_total).to eq(0.5)
189
+ expect(order.additional_tax_total).to eq(0.5)
190
+ expect(order.included_tax_total).to eq(0)
191
+ expect(order.total).to eq(10.5)
192
+ end
193
+
194
+ it "transitions to delivery" do
195
+ allow(order).to receive_messages(:ensure_available_shipping_rates => true)
196
+ order.next!
197
+ assert_state_changed(order, 'address', 'delivery')
198
+ expect(order.state).to eq("delivery")
199
+ end
200
+
201
+ it "does not call persist_order_address if there is no address on the order" do
202
+ # otherwise, it will crash
203
+ allow(order).to receive_messages(:ensure_available_shipping_rates => true)
204
+
205
+ order.user = FactoryGirl.create(:user)
206
+ order.save!
207
+
208
+ expect(order.user).to_not receive(:persist_order_address).with(order)
209
+ order.next!
210
+ end
211
+
212
+ it "calls persist_order_address on the order's user" do
213
+ allow(order).to receive_messages(:ensure_available_shipping_rates => true)
214
+
215
+ order.user = FactoryGirl.create(:user)
216
+ order.ship_address = FactoryGirl.create(:address)
217
+ order.bill_address = FactoryGirl.create(:address)
218
+ order.save!
219
+
220
+ expect(order.user).to receive(:persist_order_address).with(order)
221
+ order.next!
222
+ end
223
+
224
+ it "does not call persist_order_address on the order's user for a temporary address" do
225
+ allow(order).to receive_messages(:ensure_available_shipping_rates => true)
226
+
227
+ order.user = FactoryGirl.create(:user)
228
+ order.temporary_address = true
229
+ order.save!
230
+
231
+ expect(order.user).to_not receive(:persist_order_address)
232
+ order.next!
233
+ end
234
+
235
+ context "cannot transition to delivery" do
236
+ context "with an existing shipment" do
237
+ before do
238
+ line_item = FactoryGirl.create(:line_item, :price => 10)
239
+ order.line_items << line_item
240
+ end
241
+
242
+ context "if there are no shipping rates for any shipment" do
243
+ it "raises an InvalidTransitionError" do
244
+ transition = lambda { order.next! }
245
+ expect(transition).to raise_error(StateMachines::InvalidTransition, /#{Spree.t(:items_cannot_be_shipped)}/)
246
+ end
247
+
248
+ it "deletes all the shipments" do
249
+ order.next
250
+ expect(order.shipments).to be_empty
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ context "to delivery" do
258
+ context 'when order has default selected_shipping_rate_id' do
259
+ let(:shipment) { create(:shipment, order: order) }
260
+ let(:shipping_method) { create(:shipping_method) }
261
+ let(:shipping_rate) { [
262
+ Spree::ShippingRate.create!(shipping_method: shipping_method, cost: 10.00, shipment: shipment)
263
+ ] }
264
+
265
+ before do
266
+ order.state = 'address'
267
+ shipment.selected_shipping_rate_id = shipping_rate.first.id
268
+ order.email = "user@example.com"
269
+ order.save!
270
+
271
+ allow(order).to receive(:has_available_payment)
272
+ allow(order).to receive(:create_proposed_shipments)
273
+ allow(order).to receive(:ensure_available_shipping_rates) { true }
274
+ end
275
+
276
+ it 'should invoke set_shipment_cost' do
277
+ expect(order).to receive(:set_shipments_cost)
278
+ order.next!
279
+ end
280
+
281
+ it 'should update shipment_total' do
282
+ expect { order.next! }.to change{ order.shipment_total }.by(10.00)
283
+ end
284
+ end
285
+ end
286
+
287
+ context "from delivery" do
288
+ before do
289
+ order.state = 'delivery'
290
+ allow(order).to receive(:apply_free_shipping_promotions)
291
+ end
292
+
293
+ it "attempts to apply free shipping promotions" do
294
+ expect(order).to receive(:apply_free_shipping_promotions)
295
+ order.next!
296
+ end
297
+
298
+ context "with payment required" do
299
+ before do
300
+ allow(order).to receive_messages :payment_required? => true
301
+ end
302
+
303
+ it "transitions to payment" do
304
+ expect(order).to receive(:set_shipments_cost)
305
+ order.next!
306
+ assert_state_changed(order, 'delivery', 'payment')
307
+ expect(order.state).to eq('payment')
308
+ end
309
+ end
310
+
311
+ context "without payment required" do
312
+ before do
313
+ allow(order).to receive_messages :payment_required? => false
314
+ end
315
+
316
+ it "transitions to complete" do
317
+ order.next!
318
+ expect(order.state).to eq("complete")
319
+ end
320
+ end
321
+
322
+ context "correctly determining payment required based on shipping information" do
323
+ let(:shipment) do
324
+ FactoryGirl.create(:shipment)
325
+ end
326
+
327
+ before do
328
+ # Needs to be set here because we're working with a persisted order object
329
+ order.email = "test@example.com"
330
+ order.save!
331
+ order.shipments << shipment
332
+ end
333
+
334
+ context "with a shipment that has a price" do
335
+ before do
336
+ shipment.shipping_rates.first.update_column(:cost, 10)
337
+ order.set_shipments_cost
338
+ end
339
+
340
+ it "transitions to payment" do
341
+ order.next!
342
+ expect(order.state).to eq("payment")
343
+ end
344
+ end
345
+
346
+ context "with a shipment that is free" do
347
+ before do
348
+ shipment.shipping_rates.first.update_column(:cost, 0)
349
+ order.set_shipments_cost
350
+ end
351
+
352
+ it "skips payment, transitions to complete" do
353
+ order.next!
354
+ expect(order.state).to eq("complete")
355
+ end
356
+ end
357
+ end
358
+ end
359
+
360
+ context "to payment" do
361
+ before do
362
+ @default_credit_card = FactoryGirl.create(:credit_card)
363
+ order.user = mock_model(Spree::LegacyUser, default_credit_card: @default_credit_card, email: 'spree@example.org')
364
+
365
+ allow(order).to receive_messages(payment_required?: true)
366
+ allow(order).to receive_messages(total: 20.00)
367
+ order.state = 'delivery'
368
+ order.save!
369
+ end
370
+
371
+ it "assigns the user's default credit card" do
372
+ order.next!
373
+ order.reload
374
+
375
+ expect(order.state).to eq 'payment'
376
+ expect(order.payments.count).to eq 1
377
+ expect(order.payments.first.amount).to eq 20.00
378
+ expect(order.payments.first.source).to eq @default_credit_card
379
+ end
380
+
381
+ it "only generates payment if payment required" do
382
+ allow(order).to receive_messages(payment_required?: false)
383
+ order.next!
384
+ order.reload
385
+
386
+ expect(order.state).to eq 'complete'
387
+ expect(order.payments.count).to eq 0
388
+ end
389
+ end
390
+
391
+ context "from payment" do
392
+ before do
393
+ order.state = 'payment'
394
+ end
395
+
396
+ context "with confirmation required" do
397
+ before do
398
+ allow(order).to receive_messages :confirmation_required? => true
399
+ end
400
+
401
+ it "transitions to confirm" do
402
+ order.next!
403
+ assert_state_changed(order, 'payment', 'confirm')
404
+ expect(order.state).to eq("confirm")
405
+ end
406
+ end
407
+
408
+ context "without confirmation required" do
409
+ before do
410
+ order.email = "spree@example.com"
411
+ allow(order).to receive_messages :confirmation_required? => false
412
+ allow(order).to receive_messages :payment_required? => true
413
+ order.payments << FactoryGirl.create(:payment, state: payment_state, order: order)
414
+ end
415
+
416
+ context 'when there is at least one valid payment' do
417
+ let(:payment_state) { 'checkout' }
418
+
419
+ before do
420
+ expect(order).to receive(:process_payments!).once { true }
421
+ end
422
+
423
+ it "transitions to complete" do
424
+ order.next!
425
+ assert_state_changed(order, 'payment', 'complete')
426
+ expect(order.state).to eq('complete')
427
+ end
428
+ end
429
+
430
+ context 'when there is only an invalid payment' do
431
+ let(:payment_state) { 'failed' }
432
+
433
+ it "raises a StateMachine::InvalidTransition" do
434
+ expect {
435
+ order.next!
436
+ }.to raise_error(StateMachines::InvalidTransition, /#{Spree.t(:no_payment_found)}/)
437
+
438
+ expect(order.errors[:base]).to include(Spree.t(:no_payment_found))
439
+ end
440
+ end
441
+ end
442
+
443
+ # Regression test for #2028
444
+ context "when payment is not required" do
445
+ before do
446
+ allow(order).to receive_messages :payment_required? => false
447
+ end
448
+
449
+ it "does not call process payments" do
450
+ expect(order).not_to receive(:process_payments!)
451
+ order.next!
452
+ assert_state_changed(order, 'payment', 'complete')
453
+ expect(order.state).to eq("complete")
454
+ end
455
+ end
456
+ end
457
+ end
458
+
459
+ context "to complete" do
460
+ before do
461
+ order.state = 'confirm'
462
+ order.save!
463
+ end
464
+
465
+ context "default credit card" do
466
+ before do
467
+ order.user = FactoryGirl.create(:user)
468
+ order.email = 'spree@example.org'
469
+ order.payments << FactoryGirl.create(:payment)
470
+
471
+ # make sure we will actually capture a payment
472
+ allow(order).to receive_messages(payment_required?: true)
473
+ order.line_items << FactoryGirl.create(:line_item)
474
+ Spree::OrderUpdater.new(order).update
475
+
476
+ order.save!
477
+ end
478
+
479
+ it "makes the current credit card a user's default credit card" do
480
+ order.next!
481
+ expect(order.state).to eq 'complete'
482
+ expect(order.user.reload.default_credit_card.try(:id)).to eq(order.credit_cards.first.id)
483
+ end
484
+
485
+ it "does not assign a default credit card if temporary_credit_card is set" do
486
+ order.temporary_credit_card = true
487
+ order.next!
488
+ expect(order.user.reload.default_credit_card).to be_nil
489
+ end
490
+ end
491
+ end
492
+
493
+ context "subclassed order" do
494
+ # This causes another test above to fail, but fixing this test should make
495
+ # the other test pass
496
+ class SubclassedOrder < Spree::Order
497
+ checkout_flow do
498
+ go_to_state :payment
499
+ go_to_state :complete
500
+ end
501
+ end
502
+
503
+ skip "should only call default transitions once when checkout_flow is redefined" do
504
+ order = SubclassedOrder.new
505
+ allow(order).to receive_messages :payment_required? => true
506
+ expect(order).to receive(:process_payments!).once
507
+ order.state = "payment"
508
+ order.next!
509
+ assert_state_changed(order, 'payment', 'complete')
510
+ expect(order.state).to eq("complete")
511
+ end
512
+ end
513
+
514
+ context "re-define checkout flow" do
515
+ before do
516
+ @old_checkout_flow = Spree::Order.checkout_flow
517
+ Spree::Order.class_eval do
518
+ checkout_flow do
519
+ go_to_state :payment
520
+ go_to_state :complete
521
+ end
522
+ end
523
+ end
524
+
525
+ after do
526
+ Spree::Order.checkout_flow(&@old_checkout_flow)
527
+ end
528
+
529
+ it "should not keep old event transitions when checkout_flow is redefined" do
530
+ expect(Spree::Order.next_event_transitions).to eq([{:cart=>:payment}, {:payment=>:complete}])
531
+ end
532
+
533
+ it "should not keep old events when checkout_flow is redefined" do
534
+ state_machine = Spree::Order.state_machine
535
+ expect(state_machine.states.any? { |s| s.name == :address }).to be false
536
+ known_states = state_machine.events[:next].branches.map(&:known_states).flatten
537
+ expect(known_states).not_to include(:address)
538
+ expect(known_states).not_to include(:delivery)
539
+ expect(known_states).not_to include(:confirm)
540
+ end
541
+ end
542
+
543
+ # Regression test for #3665
544
+ context "with only a complete step" do
545
+ before do
546
+ @old_checkout_flow = Spree::Order.checkout_flow
547
+ Spree::Order.class_eval do
548
+ checkout_flow do
549
+ go_to_state :complete
550
+ end
551
+ end
552
+ end
553
+
554
+ after do
555
+ Spree::Order.checkout_flow(&@old_checkout_flow)
556
+ end
557
+
558
+ it "does not attempt to process payments" do
559
+ allow(order).to receive_message_chain(:line_items, :present?) { true }
560
+ allow(order).to receive(:ensure_line_items_are_in_stock) { true }
561
+ allow(order).to receive(:ensure_line_item_variants_are_not_deleted) { true }
562
+ expect(order).not_to receive(:payment_required?)
563
+ expect(order).not_to receive(:process_payments!)
564
+ order.next!
565
+ assert_state_changed(order, 'cart', 'complete')
566
+ end
567
+
568
+ end
569
+
570
+ context "insert checkout step" do
571
+ before do
572
+ @old_checkout_flow = Spree::Order.checkout_flow
573
+ Spree::Order.class_eval do
574
+ insert_checkout_step :new_step, before: :address
575
+ end
576
+ end
577
+
578
+ after do
579
+ Spree::Order.checkout_flow(&@old_checkout_flow)
580
+ end
581
+
582
+ it "should maintain removed transitions" do
583
+ transition = Spree::Order.find_transition(:from => :delivery, :to => :confirm)
584
+ expect(transition).to be_nil
585
+ end
586
+
587
+ context "before" do
588
+ before do
589
+ Spree::Order.class_eval do
590
+ insert_checkout_step :before_address, before: :address
591
+ end
592
+ end
593
+
594
+ specify do
595
+ order = Spree::Order.new
596
+ expect(order.checkout_steps).to eq(%w(new_step before_address address delivery complete))
597
+ end
598
+ end
599
+
600
+ context "after" do
601
+ before do
602
+ Spree::Order.class_eval do
603
+ insert_checkout_step :after_address, after: :address
604
+ end
605
+ end
606
+
607
+ specify do
608
+ order = Spree::Order.new
609
+ expect(order.checkout_steps).to eq(%w(new_step address after_address delivery complete))
610
+ end
611
+ end
612
+ end
613
+
614
+ context "remove checkout step" do
615
+ before do
616
+ @old_checkout_flow = Spree::Order.checkout_flow
617
+ Spree::Order.class_eval do
618
+ remove_checkout_step :address
619
+ end
620
+ end
621
+
622
+ after do
623
+ Spree::Order.checkout_flow(&@old_checkout_flow)
624
+ end
625
+
626
+ it "should maintain removed transitions" do
627
+ transition = Spree::Order.find_transition(:from => :delivery, :to => :confirm)
628
+ expect(transition).to be_nil
629
+ end
630
+
631
+ specify do
632
+ order = Spree::Order.new
633
+ expect(order.checkout_steps).to eq(%w(delivery complete))
634
+ end
635
+ end
636
+
637
+ describe 'update_from_params' do
638
+ let(:permitted_params) { {} }
639
+ let(:params) { {} }
640
+
641
+ it 'calls update_atributes without order params' do
642
+ expect(order).to receive(:update_attributes).with({})
643
+ order.update_from_params( params, permitted_params)
644
+ end
645
+
646
+ it 'runs the callbacks' do
647
+ expect(order).to receive(:run_callbacks).with(:updating_from_params)
648
+ order.update_from_params( params, permitted_params)
649
+ end
650
+
651
+ context "passing a credit card" do
652
+ let(:permitted_params) do
653
+ Spree::PermittedAttributes.checkout_attributes +
654
+ [payments_attributes: Spree::PermittedAttributes.payment_attributes]
655
+ end
656
+
657
+ let(:credit_card) { create(:credit_card, user_id: order.user_id) }
658
+
659
+ let(:params) do
660
+ ActionController::Parameters.new(
661
+ order: { payments_attributes: [{payment_method_id: 1}], existing_card: credit_card.id },
662
+ cvc_confirm: "737",
663
+ payment_source: {
664
+ "1" => { name: "Luis Braga",
665
+ number: "4111 1111 1111 1111",
666
+ expiry: "06 / 2016",
667
+ verification_value: "737",
668
+ cc_type: "" }
669
+ }
670
+ )
671
+ end
672
+
673
+ before { order.user_id = 3 }
674
+
675
+ it "sets confirmation value when its available via :cvc_confirm" do
676
+ allow(Spree::CreditCard).to receive_messages find: credit_card
677
+ expect(credit_card).to receive(:verification_value=)
678
+ order.update_from_params(params, permitted_params)
679
+ end
680
+
681
+ it "sets existing card as source for new payment" do
682
+ expect {
683
+ order.update_from_params(params, permitted_params)
684
+ }.to change { Spree::Payment.count }.by(1)
685
+
686
+ expect(Spree::Payment.last.source).to eq credit_card
687
+ end
688
+
689
+ it "sets request_env on payment" do
690
+ request_env = { "USER_AGENT" => "Firefox" }
691
+
692
+ expected_hash = { "payments_attributes" => [hash_including("request_env" => request_env)] }
693
+ expect(order).to receive(:update_attributes).with expected_hash
694
+
695
+ order.update_from_params(params, permitted_params, request_env)
696
+ end
697
+
698
+ it "dont let users mess with others users cards" do
699
+ credit_card.update_column :user_id, 5
700
+
701
+ expect {
702
+ order.update_from_params(params, permitted_params)
703
+ }.to raise_error
704
+ end
705
+ end
706
+
707
+ context 'has params' do
708
+ let(:permitted_params) { [ :good_param ] }
709
+ let(:params) { ActionController::Parameters.new(order: { bad_param: 'okay' } ) }
710
+
711
+ it 'does not let through unpermitted attributes' do
712
+ expect(order).to receive(:update_attributes).with({})
713
+ order.update_from_params(params, permitted_params)
714
+ end
715
+
716
+ context 'has existing_card param' do
717
+ let(:permitted_params) do
718
+ Spree::PermittedAttributes.checkout_attributes +
719
+ [payments_attributes: Spree::PermittedAttributes.payment_attributes]
720
+ end
721
+ let(:credit_card) { create(:credit_card, user_id: order.user_id) }
722
+ let(:params) do
723
+ ActionController::Parameters.new(
724
+ order: { payments_attributes: [{payment_method_id: 1}], existing_card: credit_card.id }
725
+ )
726
+ end
727
+
728
+ before do
729
+ Dummy::Application.config.action_controller.action_on_unpermitted_parameters = :raise
730
+ order.user_id = 3
731
+ end
732
+
733
+ after do
734
+ Dummy::Application.config.action_controller.action_on_unpermitted_parameters = :log
735
+ end
736
+
737
+ it 'does not attempt to permit existing_card' do
738
+ expect {
739
+ order.update_from_params(params, permitted_params)
740
+ }.not_to raise_error
741
+ end
742
+ end
743
+
744
+ context 'has allowed params' do
745
+ let(:params) { ActionController::Parameters.new(order: { good_param: 'okay' } ) }
746
+
747
+ it 'accepts permitted attributes' do
748
+ expect(order).to receive(:update_attributes).with({"good_param" => 'okay'})
749
+ order.update_from_params(params, permitted_params)
750
+ end
751
+ end
752
+
753
+ context 'callbacks halt' do
754
+ before do
755
+ expect(order).to receive(:update_params_payment_source).and_return false
756
+ end
757
+ it 'does not let through unpermitted attributes' do
758
+ expect(order).not_to receive(:update_attributes).with({})
759
+ order.update_from_params(params, permitted_params)
760
+ end
761
+ end
762
+ end
763
+ end
764
+ end