solidus_core 2.0.3 → 2.1.0.beta1

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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +62 -3
  3. data/app/assets/javascripts/spree.js.coffee.erb +4 -1
  4. data/app/helpers/spree/base_helper.rb +7 -48
  5. data/app/models/spree/address.rb +5 -1
  6. data/app/models/spree/adjustment.rb +3 -3
  7. data/app/models/spree/app_configuration.rb +13 -0
  8. data/app/models/spree/calculator.rb +3 -2
  9. data/app/models/spree/calculator/default_tax.rb +6 -10
  10. data/app/models/spree/calculator/flat_percent_item_total.rb +0 -4
  11. data/app/models/spree/calculator/flat_rate.rb +0 -4
  12. data/app/models/spree/calculator/flexi_rate.rb +0 -4
  13. data/app/models/spree/calculator/free_shipping.rb +0 -3
  14. data/app/models/spree/calculator/percent_on_line_item.rb +0 -4
  15. data/app/models/spree/calculator/percent_per_item.rb +0 -4
  16. data/app/models/spree/calculator/price_sack.rb +0 -4
  17. data/app/models/spree/calculator/returns/default_refund_amount.rb +0 -3
  18. data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +0 -4
  19. data/app/models/spree/calculator/shipping/flat_rate.rb +0 -4
  20. data/app/models/spree/calculator/shipping/flexi_rate.rb +0 -4
  21. data/app/models/spree/calculator/shipping/per_item.rb +0 -4
  22. data/app/models/spree/calculator/shipping/price_sack.rb +0 -4
  23. data/app/models/spree/calculator/tiered_flat_rate.rb +0 -4
  24. data/app/models/spree/calculator/tiered_percent.rb +0 -4
  25. data/app/models/spree/credit_card.rb +27 -14
  26. data/app/models/spree/gateway.rb +4 -0
  27. data/app/models/spree/inventory_unit.rb +2 -0
  28. data/app/models/spree/line_item.rb +31 -26
  29. data/app/models/spree/option_type.rb +0 -3
  30. data/app/models/spree/order.rb +28 -31
  31. data/app/models/spree/order/checkout.rb +0 -2
  32. data/app/models/spree/order_contents.rb +0 -45
  33. data/app/models/spree/order_merger.rb +6 -6
  34. data/app/models/spree/order_update_attributes.rb +0 -2
  35. data/app/models/spree/order_updater.rb +91 -13
  36. data/app/models/spree/payment.rb +9 -2
  37. data/app/models/spree/payment/processing.rb +15 -9
  38. data/app/models/spree/payment_method.rb +48 -5
  39. data/app/models/spree/price.rb +7 -9
  40. data/app/models/spree/product.rb +1 -25
  41. data/app/models/spree/promotion.rb +22 -14
  42. data/app/models/spree/promotion/actions/create_adjustment.rb +12 -1
  43. data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -1
  44. data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +5 -3
  45. data/app/models/spree/promotion/actions/free_shipping.rb +14 -0
  46. data/app/models/spree/promotion/rules/taxon.rb +7 -2
  47. data/app/models/spree/promotion/rules/user_role.rb +43 -0
  48. data/app/models/spree/promotion_action.rb +19 -2
  49. data/app/models/spree/promotion_handler/coupon.rb +1 -4
  50. data/app/models/spree/promotion_handler/free_shipping.rb +22 -17
  51. data/app/models/spree/promotion_rule_role.rb +6 -0
  52. data/app/models/spree/property.rb +0 -3
  53. data/app/models/spree/return_authorization.rb +2 -0
  54. data/app/models/spree/shipment.rb +5 -21
  55. data/app/models/spree/shipping_method.rb +23 -2
  56. data/app/models/spree/shipping_rate.rb +3 -0
  57. data/app/models/spree/stock/estimator.rb +1 -1
  58. data/app/models/spree/stock_location.rb +3 -0
  59. data/app/models/spree/store.rb +7 -0
  60. data/app/models/spree/tax/item_adjuster.rb +27 -12
  61. data/app/models/spree/tax/order_adjuster.rb +2 -5
  62. data/app/models/spree/tax/tax_helpers.rb +4 -8
  63. data/app/models/spree/tax_rate.rb +1 -15
  64. data/app/models/spree/taxon.rb +0 -3
  65. data/app/models/spree/transfer_item.rb +1 -1
  66. data/app/models/spree/user_class_handle.rb +14 -9
  67. data/app/models/spree/variant/pricing_options.rb +1 -1
  68. data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +1 -1
  69. data/app/models/spree/zone.rb +20 -13
  70. data/config/locales/en.yml +144 -62
  71. data/db/migrate/20120831092320_spree_one_two.rb +0 -7
  72. data/db/migrate/20150723224133_remove_unnecessary_indexes.rb +0 -2
  73. data/db/migrate/20160924135758_remove_is_default_from_prices.rb +5 -0
  74. data/db/migrate/20161009141333_remove_currency_from_line_items.rb +5 -0
  75. data/db/migrate/20161014221052_add_available_to_columns_and_remove_display_on_from_payment_methods.rb +28 -0
  76. data/db/migrate/20161123154034_add_available_to_users_and_remove_display_on_from_shipping_methods.rb +20 -0
  77. data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +4 -0
  78. data/lib/generators/spree/dummy/dummy_generator.rb +0 -2
  79. data/lib/spree/core.rb +0 -5
  80. data/lib/spree/core/controller_helpers/pricing.rb +2 -1
  81. data/lib/spree/core/engine.rb +14 -0
  82. data/lib/spree/core/version.rb +1 -1
  83. data/lib/spree/deprecation.rb +1 -1
  84. data/lib/spree/localized_number.rb +3 -2
  85. data/lib/spree/permission_sets/configuration_display.rb +0 -1
  86. data/lib/spree/permission_sets/configuration_management.rb +0 -1
  87. data/lib/spree/permission_sets/product_display.rb +0 -1
  88. data/lib/spree/permission_sets/product_management.rb +0 -1
  89. data/lib/spree/permission_sets/user_management.rb +2 -4
  90. data/lib/spree/permitted_attributes.rb +3 -2
  91. data/lib/spree/testing_support/capybara_ext.rb +0 -12
  92. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  93. data/lib/spree/testing_support/factories/line_item_factory.rb +0 -1
  94. data/lib/spree/testing_support/factories/payment_factory.rb +4 -0
  95. data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -1
  96. data/lib/spree/testing_support/factories/user_factory.rb +2 -2
  97. data/solidus_core.gemspec +4 -3
  98. data/spec/helpers/base_helper_spec.rb +0 -40
  99. data/spec/lib/spree/core/controller_helpers/pricing_spec.rb +16 -0
  100. data/spec/lib/spree/core/importer/order_spec.rb +27 -18
  101. data/spec/lib/spree/core/price_migrator_spec.rb +3 -1
  102. data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +16 -0
  103. data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -2
  104. data/spec/lib/tasks/exchanges_spec.rb +4 -2
  105. data/spec/lib/tasks/migrations/create_vat_prices_spec.rb +5 -3
  106. data/spec/models/spree/adjustment_spec.rb +136 -0
  107. data/spec/models/spree/calculator/default_tax_spec.rb +13 -7
  108. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +3 -0
  109. data/spec/models/spree/calculator/flat_rate_spec.rb +3 -0
  110. data/spec/models/spree/calculator/flexi_rate_spec.rb +3 -0
  111. data/spec/models/spree/calculator/free_shipping_spec.rb +6 -0
  112. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +9 -4
  113. data/spec/models/spree/calculator/percent_per_item_spec.rb +10 -0
  114. data/spec/models/spree/calculator/price_sack_spec.rb +3 -0
  115. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +3 -0
  116. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +3 -0
  117. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +3 -0
  118. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +3 -0
  119. data/spec/models/spree/calculator/shipping/per_item_spec.rb +3 -0
  120. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +4 -1
  121. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +3 -0
  122. data/spec/models/spree/calculator/tiered_percent_spec.rb +3 -0
  123. data/spec/models/spree/credit_card_spec.rb +27 -1
  124. data/spec/models/spree/line_item_spec.rb +58 -65
  125. data/spec/models/spree/order/checkout_spec.rb +2 -1
  126. data/spec/models/spree/order/payment_spec.rb +9 -10
  127. data/spec/models/spree/order/tax_spec.rb +22 -7
  128. data/spec/models/spree/order/updating_spec.rb +1 -3
  129. data/spec/models/spree/order_cancellations_spec.rb +6 -4
  130. data/spec/models/spree/order_contents_spec.rb +34 -50
  131. data/spec/models/spree/order_inventory_spec.rb +3 -5
  132. data/spec/models/spree/order_merger_spec.rb +20 -0
  133. data/spec/models/spree/order_spec.rb +28 -64
  134. data/spec/models/spree/order_update_attributes_spec.rb +1 -5
  135. data/spec/models/spree/order_updater_spec.rb +251 -0
  136. data/spec/models/spree/payment_method_spec.rb +178 -28
  137. data/spec/models/spree/payment_spec.rb +35 -19
  138. data/spec/models/spree/permission_sets/configuration_display.rb +0 -4
  139. data/spec/models/spree/permission_sets/configuration_management_spec.rb +0 -2
  140. data/spec/models/spree/permission_sets/product_display_spec.rb +0 -4
  141. data/spec/models/spree/permission_sets/product_management_spec.rb +0 -2
  142. data/spec/models/spree/permission_sets/user_management_spec.rb +9 -2
  143. data/spec/models/spree/price_spec.rb +16 -1
  144. data/spec/models/spree/product_spec.rb +0 -75
  145. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +20 -0
  146. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +39 -15
  147. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +203 -22
  148. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +22 -3
  149. data/spec/models/spree/promotion/rules/taxon_spec.rb +26 -0
  150. data/spec/models/spree/promotion/rules/user_role_spec.rb +86 -0
  151. data/spec/models/spree/promotion_action_spec.rb +38 -0
  152. data/spec/models/spree/promotion_handler/coupon_spec.rb +36 -33
  153. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +21 -22
  154. data/spec/models/spree/promotion_spec.rb +46 -6
  155. data/spec/models/spree/reimbursement_spec.rb +1 -1
  156. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +2 -2
  157. data/spec/models/spree/shipment_spec.rb +68 -50
  158. data/spec/models/spree/shipping_method_spec.rb +41 -0
  159. data/spec/models/spree/shipping_rate_spec.rb +9 -3
  160. data/spec/models/spree/stock/estimator_spec.rb +4 -2
  161. data/spec/models/spree/store_credit_spec.rb +3 -3
  162. data/spec/models/spree/tax/item_adjuster_spec.rb +31 -21
  163. data/spec/models/spree/tax/order_adjuster_spec.rb +6 -10
  164. data/spec/models/spree/tax/taxation_integration_spec.rb +19 -0
  165. data/spec/models/spree/tax_rate_spec.rb +5 -26
  166. data/spec/models/spree/transfer_item_spec.rb +11 -0
  167. data/spec/models/spree/variant/pricing_options_spec.rb +7 -17
  168. data/spec/models/spree/variant_spec.rb +2 -4
  169. data/spec/models/spree/zone_spec.rb +60 -20
  170. data/spec/shared_examples/calculator_shared_examples.rb +8 -0
  171. metadata +19 -24
  172. data/app/models/spree/item_adjustments.rb +0 -89
  173. data/app/models/spree/option_type_prototype.rb +0 -6
  174. data/app/models/spree/property_prototype.rb +0 -6
  175. data/app/models/spree/prototype.rb +0 -14
  176. data/app/models/spree/prototype_taxon.rb +0 -6
  177. data/app/models/spree/tracker.rb +0 -8
  178. data/db/migrate/20150128032538_remove_environment_from_tracker.rb +0 -6
  179. data/lib/generators/spree/dummy/templates/initializers/custom_user.rb +0 -1
  180. data/lib/spree/core/delegate_belongs_to.rb +0 -94
  181. data/lib/spree/testing_support/factories/prototype_factory.rb +0 -8
  182. data/lib/spree/testing_support/factories/tracker_factory.rb +0 -6
  183. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +0 -24
  184. data/spec/lib/spree/core/testing_support/factories/prototype_factory_spec.rb +0 -12
  185. data/spec/lib/spree/core/testing_support/factories/tracker_factory_spec.rb +0 -12
  186. data/spec/models/spree/item_adjustments_spec.rb +0 -306
  187. data/spec/models/spree/tracker_spec.rb +0 -21
@@ -2,10 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe Spree::Promotion::Actions::FreeShipping, type: :model do
4
4
  let(:order) { create(:completed_order_with_totals) }
5
- let(:promotion_code) { create(:promotion_code, value: 'somecode') }
6
- let(:promotion) { promotion_code.promotion }
7
- let(:action) { Spree::Promotion::Actions::FreeShipping.create }
5
+ let(:shipment) { order.shipments.to_a.first }
6
+ let(:promotion) { create(:promotion, code: 'somecode', promotion_actions: [action]) }
7
+ let(:action) { Spree::Promotion::Actions::FreeShipping.new }
8
8
  let(:payload) { { order: order, promotion_code: promotion_code } }
9
+ let(:promotion_code) { promotion.codes.first! }
9
10
 
10
11
  # From promotion spec:
11
12
  context "#perform" do
@@ -37,4 +38,22 @@ describe Spree::Promotion::Actions::FreeShipping, type: :model do
37
38
  end
38
39
  end
39
40
  end
41
+
42
+ describe '#remove_from' do
43
+ # this adjustment should not get removed
44
+ let!(:other_adjustment) { create(:adjustment, adjustable: shipment, order: order, source: nil) }
45
+
46
+ before do
47
+ action.perform(payload)
48
+ @action_adjustment = shipment.adjustments.where(source: action).first!
49
+ end
50
+
51
+ it 'removes the action adjustment' do
52
+ expect(shipment.adjustments).to match_array([other_adjustment, @action_adjustment])
53
+
54
+ action.remove_from(order)
55
+
56
+ expect(shipment.adjustments).to eq([other_adjustment])
57
+ end
58
+ end
40
59
  end
@@ -97,6 +97,32 @@ describe Spree::Promotion::Rules::Taxon, type: :model do
97
97
  end
98
98
  end
99
99
 
100
+ context 'with none match policy' do
101
+ before do
102
+ rule.preferred_match_policy = 'none'
103
+ end
104
+
105
+ context "none of the order's products are in listed taxon" do
106
+ before { rule.taxons << taxon2 }
107
+ it { expect(rule).to be_eligible(order) }
108
+ end
109
+
110
+ context "one of the order's products is in a listed taxon" do
111
+ before do
112
+ order.products.first.taxons << taxon
113
+ rule.taxons << taxon
114
+ end
115
+ it "should not be eligible" do
116
+ expect(rule).not_to be_eligible(order)
117
+ end
118
+ it "sets an error message" do
119
+ rule.eligible?(order)
120
+ expect(rule.eligibility_errors.full_messages.first).
121
+ to eq "Your cart contains a product from an excluded category that prevents this coupon code from being applied."
122
+ end
123
+ end
124
+ end
125
+
100
126
  context 'with an invalid match policy' do
101
127
  before do
102
128
  order.products.first.taxons << taxon
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Promotion::Rules::UserRole, type: :model do
4
+ let(:rule) { described_class.new(preferred_role_ids: roles_for_rule) }
5
+ let(:user) { create(:user, spree_roles: roles_for_user) }
6
+ let(:roles_for_rule) { [] }
7
+ let(:roles_for_user) { [] }
8
+
9
+ subject { rule }
10
+
11
+ shared_examples 'eligibility' do
12
+ context 'no roles on rule' do
13
+ let(:roles_for_user) { [create(:role)] }
14
+ it 'should not be eligible' do
15
+ expect(rule).to_not be_eligible(order)
16
+ end
17
+ end
18
+
19
+ context 'no roles on user' do
20
+ let(:roles_for_rule) { [create(:role)] }
21
+ it 'should not be eligible' do
22
+ expect(rule).to_not be_eligible(order)
23
+ end
24
+ end
25
+
26
+ context 'mismatched roles' do
27
+ let(:roles_for_user) { [create(:role)] }
28
+ let(:roles_for_rule) { [create(:role)] }
29
+ it 'should not be eligible' do
30
+ expect(rule).to_not be_eligible(order)
31
+ end
32
+ end
33
+
34
+ context 'matching all roles' do
35
+ let(:roles_for_user) { [create(:role), create(:role)] }
36
+ let(:roles_for_rule) { roles_for_user }
37
+ it 'should be eligible' do
38
+ expect(rule).to be_eligible(order)
39
+ end
40
+ end
41
+ end
42
+
43
+ context '#eligible?(order)' do
44
+ context 'order with no user' do
45
+ let(:order) { Spree::Order.new }
46
+
47
+ it 'should not be eligible' do
48
+ expect(rule).to_not be_eligible(order)
49
+ end
50
+ end
51
+
52
+ context 'order with user' do
53
+ let(:order) { Spree::Order.new(user: user) }
54
+
55
+ context 'with any match policy' do
56
+ before { rule.preferred_match_policy = 'any' }
57
+
58
+ include_examples 'eligibility'
59
+
60
+ context 'one shared role' do
61
+ let(:shared_role) { create(:role) }
62
+ let(:roles_for_user) { [create(:role), shared_role] }
63
+ let(:roles_for_rule) { [create(:role), shared_role] }
64
+ it 'should be eligible' do
65
+ expect(rule).to be_eligible(order)
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'with all match policy' do
71
+ before { rule.preferred_match_policy = 'all' }
72
+
73
+ include_examples 'eligibility'
74
+
75
+ context 'one shared role' do
76
+ let(:shared_role) { create(:role) }
77
+ let(:roles_for_user) { [create(:role), shared_role] }
78
+ let(:roles_for_rule) { [create(:role), shared_role] }
79
+ it 'should not be eligible' do
80
+ expect(rule).to_not be_eligible(order)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PromotionAction, type: :model do
4
+ describe '#remove_from' do
5
+ class MyPromotionAction < Spree::PromotionAction
6
+ def perform(options = {})
7
+ order = options[:order]
8
+ order.adjustments.create!(amount: 1, order: order, source: self, label: 'foo')
9
+ true
10
+ end
11
+ end
12
+
13
+ let(:action) { promotion.actions.first! }
14
+ let!(:promotion) { create(:promotion, promotion_actions: [MyPromotionAction.new]) }
15
+ let(:order) { create(:order) }
16
+
17
+ # this adjustment should not get removed
18
+ let!(:other_adjustment) { create(:adjustment, order: order, source: nil) }
19
+
20
+ before do
21
+ action.perform(order: order)
22
+ @action_adjustment = order.adjustments.where(source: action).first!
23
+ end
24
+
25
+ it 'removes the action adjustment' do
26
+ expect(order.adjustments).to match_array([other_adjustment, @action_adjustment])
27
+
28
+ expect(Spree::Deprecation).to(
29
+ receive(:warn).
30
+ with(/"MyPromotionAction" does not define #remove_from/, anything)
31
+ )
32
+
33
+ action.remove_from(order)
34
+
35
+ expect(order.adjustments).to eq([other_adjustment])
36
+ end
37
+ end
38
+ end
@@ -252,57 +252,59 @@ module Spree
252
252
 
253
253
  context "for an order with taxable line items" do
254
254
  let(:store) { create(:store) }
255
+ let(:order) { create(:order, store: store) }
256
+ let(:tax_category) { create(:tax_category, name: "Taxable Foo") }
257
+ let(:zone) { create(:zone, :with_country) }
258
+ let!(:tax_rate) { create(:tax_rate, amount: 0.1, tax_category: tax_category, zone: zone )}
259
+
255
260
  before(:each) do
256
- @country = create(:country)
257
- @zone = create(:zone, name: "Country Zone", default_tax: true, zone_members: [])
258
- @zone.zone_members.create(zoneable: @country)
259
- @category = Spree::TaxCategory.create name: "Taxable Foo"
260
- @rate1 = Spree::TaxRate.create(
261
- amount: 0.10,
262
- calculator: Spree::Calculator::DefaultTax.create,
263
- tax_category: @category,
264
- zone: @zone
265
- )
266
-
267
- @order = Spree::Order.create!(store: store)
268
- allow(@order).to receive_messages coupon_code: "10off"
261
+ expect(order).to receive(:tax_address).at_least(:once).and_return(Spree::Tax::TaxLocation.new(country: zone.countries.first))
269
262
  end
263
+
270
264
  context "and the product price is less than promo discount" do
271
265
  before(:each) do
266
+ expect(order).to receive(:coupon_code).at_least(:once).and_return("10off")
267
+
272
268
  3.times do |_i|
273
- taxable = create(:product, tax_category: @category, price: 9.0)
274
- @order.contents.add(taxable.master, 1)
269
+ taxable = create(:product, tax_category: tax_category, price: 9.0)
270
+ order.contents.add(taxable.master, 1)
275
271
  end
276
272
  end
273
+
277
274
  it "successfully applies the promo" do
278
275
  # 3 * (9 + 0.9)
279
- expect(@order.total).to eq(29.7)
280
- coupon = Coupon.new(@order)
276
+ expect(order.total).to eq(29.7)
277
+ coupon = Coupon.new(order)
281
278
  coupon.apply
282
279
  expect(coupon.success).to be_present
283
280
  # 3 * ((9 - [9,10].min) + 0)
284
- expect(@order.reload.total).to eq(0)
285
- expect(@order.additional_tax_total).to eq(0)
281
+ expect(order.reload.total).to eq(0)
282
+ expect(order.additional_tax_total).to eq(0)
286
283
  end
287
284
  end
285
+
288
286
  context "and the product price is greater than promo discount" do
289
287
  before(:each) do
288
+ expect(order).to receive(:coupon_code).at_least(:once).and_return("10off")
289
+
290
290
  3.times do |_i|
291
- taxable = create(:product, tax_category: @category, price: 11.0)
292
- @order.contents.add(taxable.master, 2)
291
+ taxable = create(:product, tax_category: tax_category, price: 11.0)
292
+ order.contents.add(taxable.master, 2)
293
293
  end
294
294
  end
295
+
295
296
  it "successfully applies the promo" do
296
297
  # 3 * (22 + 2.2)
297
- expect(@order.total.to_f).to eq(72.6)
298
- coupon = Coupon.new(@order)
298
+ expect(order.total.to_f).to eq(72.6)
299
+ coupon = Coupon.new(order)
299
300
  coupon.apply
300
301
  expect(coupon.success).to be_present
301
302
  # 3 * ( (22 - 10) + 1.2)
302
- expect(@order.reload.total).to eq(39.6)
303
- expect(@order.additional_tax_total).to eq(3.6)
303
+ expect(order.reload.total).to eq(39.6)
304
+ expect(order.additional_tax_total).to eq(3.6)
304
305
  end
305
306
  end
307
+
306
308
  context "and multiple quantity per line item" do
307
309
  before(:each) do
308
310
  twnty_off = create(:promotion, name: "promo", code: "20off")
@@ -310,22 +312,23 @@ module Spree
310
312
  Promotion::Actions::CreateItemAdjustments.create(promotion: twnty_off,
311
313
  calculator: twnty_off_calc)
312
314
 
313
- allow(@order).to receive(:coupon_code).and_call_original
314
- allow(@order).to receive_messages coupon_code: "20off"
315
+ expect(order).to receive(:coupon_code).at_least(:once).and_return("20off")
316
+
315
317
  3.times do |_i|
316
- taxable = create(:product, tax_category: @category, price: 10.0)
317
- @order.contents.add(taxable.master, 2)
318
+ taxable = create(:product, tax_category: tax_category, price: 10.0)
319
+ order.contents.add(taxable.master, 2)
318
320
  end
319
321
  end
322
+
320
323
  it "successfully applies the promo" do
321
324
  # 3 * ((2 * 10) + 2.0)
322
- expect(@order.total.to_f).to eq(66)
323
- coupon = Coupon.new(@order)
325
+ expect(order.total.to_f).to eq(66)
326
+ coupon = Coupon.new(order)
324
327
  coupon.apply
325
328
  expect(coupon.success).to be_present
326
329
  # 0
327
- expect(@order.reload.total).to eq(0)
328
- expect(@order.additional_tax_total).to eq(0)
330
+ expect(order.reload.total).to eq(0)
331
+ expect(order.additional_tax_total).to eq(0)
329
332
  end
330
333
  end
331
334
  end
@@ -6,40 +6,39 @@ module Spree
6
6
  let(:order) { create(:order) }
7
7
  let(:shipment) { create(:shipment, order: order ) }
8
8
 
9
- let(:promotion) { Promotion.create!(name: "Free Shipping") }
10
- let(:calculator) { Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10) }
11
- let!(:action) { Promotion::Actions::FreeShipping.create(promotion: promotion) }
9
+ let(:action) { Spree::Promotion::Actions::FreeShipping.new }
12
10
 
13
11
  subject { Spree::PromotionHandler::FreeShipping.new(order) }
14
12
 
15
- context "activates in Shipment level" do
13
+ context 'with apply_automatically' do
14
+ let!(:promotion) { create(:promotion, apply_automatically: true, promotion_actions: [action]) }
15
+
16
16
  it "creates the adjustment" do
17
17
  expect { subject.activate }.to change { shipment.adjustments.count }.by(1)
18
18
  end
19
19
  end
20
20
 
21
- context "if promo has a code" do
22
- let!(:promotion_code) { create(:promotion_code, promotion: promotion) }
23
-
24
- it "does adjust the shipment when applied to order" do
25
- pending "broken by 2-2-dev merge"
26
- order.order_promotions.create!(promotion: promotion, promotion_code: promotion_code)
27
-
28
- expect { subject.activate }.to change { shipment.adjustments.count }
29
- end
21
+ context 'with a code' do
22
+ let!(:promotion) { create(:promotion, code: 'freeshipping', promotion_actions: [action]) }
30
23
 
31
- it "does not adjust the shipment when not applied to order" do
32
- expect { subject.activate }.to_not change { shipment.adjustments.count }
33
- end
34
- end
24
+ context 'when already applied' do
25
+ before do
26
+ order.order_promotions.create!(promotion: promotion, promotion_code: promotion.codes.first)
27
+ end
35
28
 
36
- context "if promo has a path" do
37
- before do
38
- promotion.update_column(:path, "path")
29
+ it 'adjusts the shipment' do
30
+ expect {
31
+ subject.activate
32
+ }.to change { shipment.adjustments.count }
33
+ end
39
34
  end
40
35
 
41
- it "does not adjust the shipment" do
42
- expect { subject.activate }.to_not change { shipment.adjustments.count }
36
+ context 'when not already applied' do
37
+ it 'does not adjust the shipment' do
38
+ expect {
39
+ subject.activate
40
+ }.to_not change { shipment.adjustments.count }
41
+ end
43
42
  end
44
43
  end
45
44
  end
@@ -142,6 +142,30 @@ describe Spree::Promotion, type: :model do
142
142
  expect(promotion.activate(@payload)).to be true
143
143
  expect(promotion.orders.first).to eql @order
144
144
  end
145
+
146
+ it 'keeps in-memory associations updated' do
147
+ # load all the relevant associations into memory
148
+ promotion.order_promotions.to_a
149
+ promotion.orders.to_a
150
+ @order.order_promotions.to_a
151
+ @order.promotions.to_a
152
+
153
+ expect(promotion.order_promotions.size).to eq(0)
154
+ expect(promotion.orders.size).to eq(0)
155
+ expect(@order.order_promotions.size).to eq(0)
156
+ expect(@order.promotions.size).to eq(0)
157
+
158
+ expect(
159
+ promotion.activate(@payload)
160
+ ).to eq(true)
161
+
162
+ aggregate_failures do
163
+ expect(promotion.order_promotions.size).to eq(1)
164
+ expect(promotion.orders.size).to eq(1)
165
+ expect(@order.order_promotions.size).to eq(1)
166
+ expect(@order.promotions.size).to eq(1)
167
+ end
168
+ end
145
169
  end
146
170
  context "when not activated" do
147
171
  it "will not assign the order" do
@@ -176,6 +200,25 @@ describe Spree::Promotion, type: :model do
176
200
  end
177
201
  end
178
202
 
203
+ describe '#remove_from' do
204
+ let(:promotion) { create(:promotion, :with_line_item_adjustment) }
205
+ let(:order) { create(:order_with_line_items) }
206
+
207
+ before do
208
+ promotion.activate(order: order)
209
+ end
210
+
211
+ it 'removes the promotion' do
212
+ expect(order.promotions).to include(promotion)
213
+ expect(order.line_items.flat_map(&:adjustments)).to be_present
214
+
215
+ promotion.remove_from(order)
216
+
217
+ expect(order.promotions).to be_empty
218
+ expect(order.line_items.flat_map(&:adjustments)).to be_empty
219
+ end
220
+ end
221
+
179
222
  describe "#usage_limit_exceeded?" do
180
223
  subject { promotion.usage_limit_exceeded? }
181
224
 
@@ -554,8 +597,7 @@ describe Spree::Promotion, type: :model do
554
597
  allow(rule2).to receive_messages(eligible?: true, applicable?: true)
555
598
 
556
599
  promotion.promotion_rules = [rule1, rule2]
557
- allow(promotion).to receive_message_chain(:rules, :none?).and_return(false)
558
- allow(promotion).to receive_message_chain(:rules, :for).and_return(promotion.promotion_rules)
600
+ allow(promotion.promotion_rules).to receive(:for).and_return(promotion.promotion_rules)
559
601
  end
560
602
  it "returns the eligible rules" do
561
603
  expect(promotion.eligible_rules(promotable)).to eq [rule1, rule2]
@@ -573,8 +615,7 @@ describe Spree::Promotion, type: :model do
573
615
  allow(rule2).to receive_messages(eligible?: false, applicable?: true, eligibility_errors: errors)
574
616
 
575
617
  promotion.promotion_rules = [rule1, rule2]
576
- allow(promotion).to receive_message_chain(:rules, :none?).and_return(false)
577
- allow(promotion).to receive_message_chain(:rules, :for).and_return(promotion.promotion_rules)
618
+ allow(promotion.promotion_rules).to receive(:for).and_return(promotion.promotion_rules)
578
619
  end
579
620
  it "returns nil" do
580
621
  expect(promotion.eligible_rules(promotable)).to be_nil
@@ -606,8 +647,7 @@ describe Spree::Promotion, type: :model do
606
647
  allow(rule).to receive_messages(eligible?: false, applicable?: true, eligibility_errors: errors)
607
648
 
608
649
  promotion.promotion_rules = [rule]
609
- allow(promotion).to receive_message_chain(:rules, :for).and_return(promotion.promotion_rules)
610
- allow(promotion).to receive_message_chain(:rules, :none?).and_return(false)
650
+ allow(promotion.promotion_rules).to receive(:for).and_return(promotion.promotion_rules)
611
651
  end
612
652
  it "returns nil" do
613
653
  expect(promotion.eligible_rules(promotable)).to be_nil