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
@@ -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