solidus_core 2.0.3 → 2.1.0.beta1

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 (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
@@ -20,8 +20,15 @@ describe Spree::PermissionSets::UserManagement do
20
20
  it { is_expected.to be_able_to(:orders, Spree.user_class) }
21
21
  it { is_expected.to be_able_to(:items, Spree.user_class) }
22
22
 
23
- it { is_expected.to be_able_to(:update_email, Spree.user_class.new(spree_roles: [])) }
24
- it { is_expected.not_to be_able_to(:update_email, Spree.user_class.new(spree_roles: [create(:role)])) }
23
+ context 'when the user does not have a role' do
24
+ let(:user) { create(:user) }
25
+ it { is_expected.to be_able_to(:update_email, user) }
26
+ end
27
+
28
+ context 'when the user has a role' do
29
+ let(:user) { create(:user, spree_roles: [create(:role)]) }
30
+ it { is_expected.not_to be_able_to(:update_email, user) }
31
+ end
25
32
 
26
33
  it { is_expected.not_to be_able_to(:delete, Spree.user_class) }
27
34
  it { is_expected.not_to be_able_to(:destroy, Spree.user_class) }
@@ -55,6 +55,12 @@ describe Spree::Price, type: :model do
55
55
  it { is_expected.to be_valid }
56
56
  end
57
57
 
58
+ context 'when country iso is an empty string' do
59
+ let(:country_iso) { "" }
60
+
61
+ it { is_expected.to be_valid }
62
+ end
63
+
58
64
  context 'when country iso is a country code' do
59
65
  let!(:country) { create(:country, iso: "DE") }
60
66
  let(:country_iso) { "DE" }
@@ -69,9 +75,18 @@ describe Spree::Price, type: :model do
69
75
  end
70
76
  end
71
77
 
78
+ describe "country_iso=" do
79
+ let(:price) { Spree::Price.new(country_iso: "de") }
80
+
81
+ it "assigns nil if passed nil" do
82
+ price.country_iso = nil
83
+ expect(price.country_iso).to be_nil
84
+ end
85
+ end
86
+
72
87
  describe '#country' do
73
88
  let!(:country) { create(:country, iso: "DE") }
74
- let(:price) { create(:price, country_iso: "DE", is_default: false) }
89
+ let(:price) { create(:price, country_iso: "DE") }
75
90
 
76
91
  it 'returns the country object' do
77
92
  expect(price.country).to eq(country)
@@ -429,81 +429,6 @@ describe Spree::Product, type: :model do
429
429
  end
430
430
  end
431
431
 
432
- context '#create' do
433
- let!(:prototype) { create(:prototype) }
434
- let!(:product) { Spree::Product.new(name: "Foo", price: 1.99, shipping_category_id: create(:shipping_category).id) }
435
-
436
- before { product.prototype_id = prototype.id }
437
-
438
- context "when prototype is supplied" do
439
- it "should create properties based on the prototype" do
440
- product.save
441
- expect(product.properties.count).to eq(1)
442
- end
443
- end
444
-
445
- context "when prototype with option types is supplied" do
446
- def build_option_type_with_values(name, values)
447
- ot = create(:option_type, name: name)
448
- values.each do |val|
449
- ot.option_values.create(name: val.downcase, presentation: val)
450
- end
451
- ot
452
- end
453
-
454
- let(:prototype) do
455
- size = build_option_type_with_values("size", %w(Small Medium Large))
456
- create(:prototype, name: "Size", option_types: [size])
457
- end
458
-
459
- let(:option_values_hash) do
460
- hash = {}
461
- prototype.option_types.each do |i|
462
- hash[i.id.to_s] = i.option_value_ids
463
- end
464
- hash
465
- end
466
-
467
- it "should create option types based on the prototype" do
468
- product.save
469
- expect(product.option_type_ids.length).to eq(1)
470
- expect(product.option_type_ids).to eq(prototype.option_type_ids)
471
- end
472
-
473
- it "should create product option types based on the prototype" do
474
- product.save
475
- expect(product.product_option_types.pluck(:option_type_id)).to eq(prototype.option_type_ids)
476
- end
477
-
478
- it "should create variants from an option values hash with one option type" do
479
- product.option_values_hash = option_values_hash
480
- product.save
481
- expect(product.variants.length).to eq(3)
482
- end
483
-
484
- it "should still create variants when option_values_hash is given but prototype id is nil" do
485
- product.option_values_hash = option_values_hash
486
- product.prototype_id = nil
487
- product.save
488
- expect(product.option_type_ids.length).to eq(1)
489
- expect(product.option_type_ids).to eq(prototype.option_type_ids)
490
- expect(product.variants.length).to eq(3)
491
- end
492
-
493
- it "should create variants from an option values hash with multiple option types" do
494
- color = build_option_type_with_values("color", %w(Red Green Blue))
495
- logo = build_option_type_with_values("logo", %w(Ruby Rails Nginx))
496
- option_values_hash[color.id.to_s] = color.option_value_ids
497
- option_values_hash[logo.id.to_s] = logo.option_value_ids
498
- product.option_values_hash = option_values_hash
499
- product.save
500
- product.reload
501
- expect(product.option_type_ids.length).to eq(3)
502
- expect(product.variants.length).to eq(27)
503
- end
504
- end
505
- end
506
-
507
432
  context "#images" do
508
433
  let(:product) { create(:product) }
509
434
  let(:image) { File.open(File.expand_path('../../../fixtures/thinking-cat.jpg', __FILE__)) }
@@ -58,6 +58,26 @@ describe Spree::Promotion::Actions::CreateAdjustment, type: :model do
58
58
  end
59
59
  end
60
60
 
61
+ describe '#remove_from' do
62
+ let(:action) { promotion.actions.first! }
63
+ let(:promotion) { create(:promotion, :with_order_adjustment) }
64
+
65
+ let!(:unrelated_adjustment) { create(:adjustment, order: order, source: nil) }
66
+
67
+ before do
68
+ action.perform(payload)
69
+ @action_adjustment = order.adjustments.where(source: action).first!
70
+ end
71
+
72
+ it 'removes the action adjustment' do
73
+ expect(order.adjustments).to match_array([unrelated_adjustment, @action_adjustment])
74
+
75
+ action.remove_from(order)
76
+
77
+ expect(order.adjustments).to eq([unrelated_adjustment])
78
+ end
79
+ end
80
+
61
81
  context "#destroy" do
62
82
  before(:each) do
63
83
  action.calculator = Spree::Calculator::FlatRate.new(preferred_amount: 10)
@@ -4,11 +4,11 @@ module Spree
4
4
  class Promotion
5
5
  module Actions
6
6
  describe CreateItemAdjustments, type: :model do
7
- let(:order) { create(:order) }
7
+ let(:order) { create(:order_with_line_items, line_items_count: 1) }
8
8
  let(:promotion) { create(:promotion, :with_line_item_adjustment, adjustment_rate: adjustment_amount) }
9
9
  let(:adjustment_amount) { 10 }
10
10
  let(:action) { promotion.actions.first! }
11
- let!(:line_item) { create(:line_item, order: order) }
11
+ let(:line_item) { order.line_items.to_a.first }
12
12
  let(:payload) { { order: order, promotion: promotion } }
13
13
 
14
14
  before do
@@ -122,32 +122,56 @@ module Spree
122
122
  end
123
123
  end
124
124
 
125
+ describe '#remove_from' do
126
+ # this adjustment should not get removed
127
+ let!(:other_adjustment) { create(:adjustment, adjustable: line_item, order: order, source: nil) }
128
+
129
+ before do
130
+ action.perform(payload)
131
+ @action_adjustment = line_item.adjustments.where(source: action).first!
132
+ end
133
+
134
+ it 'removes the action adjustment' do
135
+ expect(line_item.adjustments).to match_array([other_adjustment, @action_adjustment])
136
+
137
+ action.remove_from(order)
138
+
139
+ expect(line_item.adjustments).to eq([other_adjustment])
140
+ end
141
+ end
142
+
125
143
  context "#destroy" do
126
144
  let!(:action) { promotion.actions.first }
127
145
  let(:other_action) { other_promotion.actions.first }
128
146
  let(:promotion) { create(:promotion, :with_line_item_adjustment) }
129
147
  let(:other_promotion) { create(:promotion, :with_line_item_adjustment) }
130
148
 
131
- it "destroys adjustments for incompleted orders" do
132
- order = Order.create
133
- action.adjustments.create!(label: "Check", amount: 0, order: order, adjustable: order)
149
+ context 'with incomplete orders' do
150
+ let(:order) { create(:order) }
134
151
 
135
- expect {
136
- action.destroy
137
- }.to change { Adjustment.count }.by(-1)
152
+ it 'destroys adjustments' do
153
+ order.adjustments.create!(label: 'Check', amount: 0, order: order, source: action)
154
+
155
+ expect {
156
+ action.destroy
157
+ }.to change { Adjustment.count }.by(-1)
158
+ end
138
159
  end
139
160
 
140
- it "nullifies adjustments for completed orders" do
141
- order = Order.create(completed_at: Time.current)
142
- adjustment = action.adjustments.create!(label: "Check", amount: 0, order: order, adjustable: order)
161
+ context 'with complete orders' do
162
+ let(:order) { create(:completed_order_with_totals) }
143
163
 
144
- expect {
145
- action.destroy
146
- }.to change { adjustment.reload.source_id }.from(action.id).to nil
164
+ it 'nullifies adjustments for completed orders' do
165
+ adjustment = order.adjustments.create!(label: 'Check', amount: 0, order: order, source: action)
166
+
167
+ expect {
168
+ action.destroy
169
+ }.to change { adjustment.reload.source_id }.from(action.id).to nil
170
+ end
147
171
  end
148
172
 
149
173
  it "doesnt mess with unrelated adjustments" do
150
- other_action.adjustments.create!(label: "Check", amount: 0, order: order, adjustable: order)
174
+ order.adjustments.create!(label: "Check", amount: 0, order: order, source: action)
151
175
 
152
176
  expect {
153
177
  action.destroy
@@ -4,36 +4,53 @@ module Spree::Promotion::Actions
4
4
  RSpec.describe CreateQuantityAdjustments do
5
5
  let(:action) { CreateQuantityAdjustments.create!(calculator: calculator, promotion: promotion) }
6
6
 
7
- let(:order) { FactoryGirl.create :order }
7
+ let(:order) do
8
+ create(
9
+ :order_with_line_items,
10
+ line_items_attributes: line_items_attributes
11
+ )
12
+ end
13
+
14
+ let(:line_items_attributes) do
15
+ [
16
+ { price: 10, quantity: quantity }
17
+ ]
18
+ end
19
+
20
+ let(:quantity) { 1 }
8
21
  let(:promotion) { FactoryGirl.create :promotion }
9
22
 
10
23
  describe "#compute_amount" do
11
24
  subject { action.compute_amount(line_item) }
12
25
 
13
- let!(:item_a) { FactoryGirl.create :line_item, order: order, quantity: quantity, price: 10 }
14
-
15
26
  context "with a flat rate adjustment" do
16
27
  let(:calculator) { FactoryGirl.create :flat_rate_calculator, preferred_amount: 5 }
17
28
 
18
29
  context "with a quantity group of 2" do
19
- let(:line_item) { item_a }
30
+ let(:line_item) { order.line_items.first }
31
+
20
32
  before { action.preferred_group_size = 2 }
33
+
21
34
  context "and an item with a quantity of 0" do
22
35
  let(:quantity) { 0 }
23
36
  it { is_expected.to eq 0 }
24
37
  end
38
+
25
39
  context "and an item with a quantity of 1" do
26
40
  let(:quantity) { 1 }
27
41
  it { is_expected.to eq 0 }
28
42
  end
43
+
29
44
  context "and an item with a quantity of 2" do
30
45
  let(:quantity) { 2 }
31
46
  it { is_expected.to eq(-10) }
32
47
  end
48
+
33
49
  context "and an item with a quantity of 3" do
34
50
  let(:quantity) { 3 }
35
51
  it { is_expected.to eq(-10) }
36
52
  end
53
+
37
54
  context "and an item with a quantity of 4" do
38
55
  let(:quantity) { 4 }
39
56
  it { is_expected.to eq(-20) }
@@ -41,36 +58,51 @@ module Spree::Promotion::Actions
41
58
  end
42
59
 
43
60
  context "with a quantity group of 3" do
44
- let(:quantity) { 2 }
45
- let!(:item_b) { FactoryGirl.create :line_item, order: order, quantity: 1 }
46
- let!(:item_c) { FactoryGirl.create :line_item, order: order, quantity: 1 }
47
61
  before { action.preferred_group_size = 3 }
62
+
48
63
  context "and 2x item A, 1x item B and 1x item C" do
64
+ let(:line_items_attributes) do
65
+ [
66
+ { price: 10, quantity: 2 },
67
+ { price: 10, quantity: 1 },
68
+ { price: 10, quantity: 1 },
69
+ ]
70
+ end
71
+
49
72
  before { action.perform({ order: order, promotion: promotion }) }
73
+
50
74
  describe "the adjustment for the first item" do
51
- let(:line_item) { item_a }
75
+ let(:line_item) { order.line_items.first }
52
76
  it { is_expected.to eq(-10) }
53
77
  end
54
78
  describe "the adjustment for the second item" do
55
- let(:line_item) { item_b }
79
+ let(:line_item) { order.line_items.second }
56
80
  it { is_expected.to eq(-5) }
57
81
  end
58
82
  describe "the adjustment for the third item" do
59
- let(:line_item) { item_c }
83
+ let(:line_item) { order.line_items.third }
60
84
  it { is_expected.to eq 0 }
61
85
  end
62
86
  end
63
87
  end
64
88
 
65
89
  context "with multiple orders using the same action" do
66
- let(:quantity) { 2 }
67
- let(:line_item) { item_a }
90
+ let(:other_order) do
91
+ create(
92
+ :order_with_line_items,
93
+ line_items_attributes: [
94
+ { quantity: 3 }
95
+ ]
96
+ )
97
+ end
98
+
99
+ let(:line_item) { other_order.line_items.first }
100
+
68
101
  before do
69
102
  action.preferred_group_size = 2
70
- other_order = FactoryGirl.create :order
71
- FactoryGirl.create :line_item, order: other_order, quantity: 3
72
103
  action.perform({ order: other_order, promotion: promotion })
73
104
  end
105
+
74
106
  it { is_expected.to eq(-10) }
75
107
  end
76
108
  end
@@ -78,38 +110,187 @@ module Spree::Promotion::Actions
78
110
  context "with a percentage based adjustment" do
79
111
  let(:calculator) { FactoryGirl.create :percent_on_item_calculator, preferred_percent: 10 }
80
112
 
113
+ let(:line_items_attributes) do
114
+ [
115
+ { price: 10, quantity: 1 }.merge(line_one_options),
116
+ { price: 10, quantity: 1 }.merge(line_two_options),
117
+ ]
118
+ end
119
+
120
+ let(:line_one_options) { {} }
121
+ let(:line_two_options) { {} }
122
+
81
123
  context "with a quantity group of 3" do
82
124
  before do
83
125
  action.preferred_group_size = 3
84
126
  action.perform({ order: order, promotion: promotion })
85
127
  end
128
+
86
129
  context "and 2x item A and 1x item B" do
87
- let(:quantity) { 2 }
88
- let!(:item_b) { FactoryGirl.create :line_item, order: order, quantity: 1, price: 10 }
130
+ let(:line_one_options) { { quantity: 2 } }
131
+
89
132
  describe "the adjustment for the first item" do
90
- let(:line_item) { item_a }
133
+ let(:line_item) { order.line_items.first }
91
134
  it { is_expected.to eq(-2) }
92
135
  end
93
136
  describe "the adjustment for the second item" do
94
- let(:line_item) { item_b }
137
+ let(:line_item) { order.line_items.second }
95
138
  it { is_expected.to eq(-1) }
96
139
  end
97
140
  end
98
141
 
99
142
  context "and the items cost different amounts" do
100
- let(:quantity) { 3 }
101
- let!(:item_b) { FactoryGirl.create :line_item, order: order, quantity: 1, price: 20 }
143
+ let(:line_one_options) { { quantity: 3 } }
144
+ let(:line_two_options) { { price: 20 } }
145
+
102
146
  describe "the adjustment for the first item" do
103
- let(:line_item) { item_a }
147
+ let(:line_item) { order.line_items.first }
104
148
  it { is_expected.to eq(-3) }
105
149
  end
106
150
  describe "the adjustment for the second item" do
107
- let(:line_item) { item_b }
151
+ let(:line_item) { order.line_items.second }
108
152
  it { is_expected.to eq 0 }
109
153
  end
110
154
  end
111
155
  end
112
156
  end
157
+
158
+ context "with a tiered percentage based adjustment" do
159
+ let(:tiers) do
160
+ {
161
+ 20 => 20,
162
+ 40 => 30
163
+ }
164
+ end
165
+
166
+ let(:calculator) do
167
+ Spree::Calculator::TieredPercent.create(preferred_base_percent: 10, preferred_tiers: tiers)
168
+ end
169
+ let(:line_items_attributes) do
170
+ [
171
+ { price: 10, quantity: 1 }.merge(line_one_options),
172
+ { price: 10, quantity: 1 }.merge(line_two_options),
173
+ ]
174
+ end
175
+
176
+ let(:line_one_options) { {} }
177
+ let(:line_two_options) { {} }
178
+
179
+ context "with a quantity group of 3" do
180
+ before do
181
+ action.preferred_group_size = 3
182
+ action.perform({ order: order, promotion: promotion })
183
+ end
184
+
185
+ context "and 2x item A and 1x item B" do
186
+ let(:line_one_options) { { quantity: 2 } }
187
+
188
+ context "when amount falls within the first tier" do
189
+ describe "the adjustment for the first item" do
190
+ let(:line_item) { order.line_items.first }
191
+ it { is_expected.to eq(-4) }
192
+ end
193
+ describe "the adjustment for the second item" do
194
+ let(:line_item) { order.line_items.second }
195
+ it { is_expected.to eq(-2) }
196
+ end
197
+ end
198
+
199
+ context "when amount falls within the second tier" do
200
+ let(:line_two_options) { { price: 20 } }
201
+
202
+ describe "the adjustment for the first item" do
203
+ let(:line_item) { order.line_items.first }
204
+ it { is_expected.to eq(-6) }
205
+ end
206
+
207
+ describe "the adjustment for the second item" do
208
+ let(:line_item) { order.line_items.second }
209
+ it { is_expected.to eq(-6) }
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ # Regression test for https://github.com/solidusio/solidus/pull/1591
218
+ context "with unsaved line_item changes" do
219
+ let(:calculator) { FactoryGirl.create :flat_rate_calculator }
220
+ let(:line_item) { order.line_items.first }
221
+
222
+ before do
223
+ order.line_items.first.promo_total = -11
224
+ action.compute_amount(line_item)
225
+ end
226
+
227
+ it "doesn't reload the line_items association" do
228
+ expect(order.line_items.first.promo_total).to eq -11
229
+ end
230
+ end
231
+
232
+ # Regression test for https://github.com/solidusio/solidus/pull/1591
233
+ context "applied to the order" do
234
+ let(:calculator) { FactoryGirl.create :flat_rate_calculator }
235
+
236
+ before do
237
+ action.perform(order: order, promotion: promotion)
238
+ order.update!
239
+ end
240
+
241
+ it 'updates the order totals' do
242
+ expect(order).to have_attributes(
243
+ total: 100,
244
+ adjustment_total: -10
245
+ )
246
+ end
247
+
248
+ context "after updating item quantity" do
249
+ before do
250
+ order.line_items.first.update!(quantity: 2, price: 30)
251
+ order.update!
252
+ end
253
+
254
+ it 'updates the order totals' do
255
+ expect(order).to have_attributes(
256
+ total: 140,
257
+ adjustment_total: -20
258
+ )
259
+ end
260
+ end
261
+
262
+ context "after updating promotion amount" do
263
+ before do
264
+ calculator.update!(preferred_amount: 5)
265
+ order.update!
266
+ end
267
+
268
+ it 'updates the order totals' do
269
+ expect(order).to have_attributes(
270
+ total: 105,
271
+ adjustment_total: -5
272
+ )
273
+ end
274
+ end
275
+ end
276
+
277
+ describe Spree::Promotion::Actions::CreateQuantityAdjustments::PartialLineItem do
278
+ let!(:item) { FactoryGirl.create :line_item, order: order, quantity: quantity, price: 10 }
279
+ let(:quantity) { 5 }
280
+
281
+ subject { described_class.new(item) }
282
+
283
+ it "has a reference to the parent order" do
284
+ expect(subject.order.id).to eq order.id
285
+ end
286
+
287
+ it "uses the `line_item.price` as a `line_item.amount`" do
288
+ expect(subject.amount).to eq item.price
289
+ end
290
+
291
+ it "has a currency" do
292
+ expect(subject.currency).to eq item.currency
293
+ end
113
294
  end
114
295
  end
115
296
  end