spree_core 3.3.0.rc1 → 3.3.0.rc2

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 (220) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/base_helper.rb +1 -1
  3. data/app/mailers/spree/base_mailer.rb +5 -0
  4. data/app/models/spree/ability.rb +4 -1
  5. data/app/models/spree/image.rb +6 -2
  6. data/app/models/spree/order.rb +10 -9
  7. data/app/models/spree/order/payments.rb +1 -1
  8. data/app/models/spree/payment_method/store_credit.rb +4 -0
  9. data/app/models/spree/shipment.rb +2 -0
  10. data/app/views/spree/shared/_base_mailer_header.html.erb +5 -1
  11. data/app/views/spree/shared/_mailer_line_item.html.erb +5 -1
  12. data/config/routes.rb +0 -3
  13. data/lib/spree/core/components.rb +17 -0
  14. data/lib/spree/core/controller_helpers/auth.rb +3 -1
  15. data/lib/spree/core/engine.rb +1 -0
  16. data/lib/spree/core/validators/email.rb +1 -5
  17. data/lib/spree/core/version.rb +1 -1
  18. data/spree_core.gemspec +1 -1
  19. metadata +4 -204
  20. data/lib/spree/testing_support/shoulda_matcher_configuration.rb +0 -6
  21. data/spec/fixtures/thinking-cat.jpg +0 -0
  22. data/spec/helpers/base_helper_spec.rb +0 -200
  23. data/spec/helpers/products_helper_spec.rb +0 -289
  24. data/spec/lib/calculated_adjustments_spec.rb +0 -7
  25. data/spec/lib/i18n_spec.rb +0 -123
  26. data/spec/lib/search/base_spec.rb +0 -86
  27. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +0 -103
  28. data/spec/lib/spree/core/controller_helpers/order_spec.rb +0 -110
  29. data/spec/lib/spree/core/controller_helpers/search_spec.rb +0 -17
  30. data/spec/lib/spree/core/controller_helpers/store_spec.rb +0 -72
  31. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +0 -39
  32. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +0 -22
  33. data/spec/lib/spree/core/importer/order_spec.rb +0 -607
  34. data/spec/lib/spree/core/number_generator_spec.rb +0 -139
  35. data/spec/lib/spree/core/token_generator_spec.rb +0 -24
  36. data/spec/lib/spree/core/validators/email_spec.rb +0 -54
  37. data/spec/lib/spree/core_spec.rb +0 -23
  38. data/spec/lib/spree/localized_number_spec.rb +0 -54
  39. data/spec/lib/spree/migrations_spec.rb +0 -36
  40. data/spec/lib/spree/money_spec.rb +0 -122
  41. data/spec/lib/tasks/exchanges_spec.rb +0 -136
  42. data/spec/mailers/order_mailer_spec.rb +0 -122
  43. data/spec/mailers/reimbursement_mailer_spec.rb +0 -52
  44. data/spec/mailers/shipment_mailer_spec.rb +0 -81
  45. data/spec/mailers/test_mailer_spec.rb +0 -38
  46. data/spec/models/spree/ability_spec.rb +0 -251
  47. data/spec/models/spree/address_spec.rb +0 -402
  48. data/spec/models/spree/adjustable/adjuster/base_spec.rb +0 -10
  49. data/spec/models/spree/adjustable/adjuster/promotion_spec.rb +0 -211
  50. data/spec/models/spree/adjustable/adjuster/tax_spec.rb +0 -86
  51. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +0 -26
  52. data/spec/models/spree/adjustment_spec.rb +0 -189
  53. data/spec/models/spree/app_configuration_spec.rb +0 -26
  54. data/spec/models/spree/asset_spec.rb +0 -28
  55. data/spec/models/spree/calculator/default_tax_spec.rb +0 -152
  56. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +0 -25
  57. data/spec/models/spree/calculator/flat_rate_spec.rb +0 -47
  58. data/spec/models/spree/calculator/flexi_rate_spec.rb +0 -41
  59. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +0 -15
  60. data/spec/models/spree/calculator/price_sack_spec.rb +0 -30
  61. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +0 -47
  62. data/spec/models/spree/calculator/shipping.rb +0 -8
  63. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +0 -23
  64. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +0 -13
  65. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +0 -52
  66. data/spec/models/spree/calculator/shipping/per_item_spec.rb +0 -20
  67. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +0 -29
  68. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +0 -40
  69. data/spec/models/spree/calculator/tiered_percent_spec.rb +0 -51
  70. data/spec/models/spree/calculator_spec.rb +0 -69
  71. data/spec/models/spree/classification_spec.rb +0 -93
  72. data/spec/models/spree/concerns/display_money_spec.rb +0 -43
  73. data/spec/models/spree/concerns/user_methods_spec.rb +0 -82
  74. data/spec/models/spree/concerns/vat_price_calculation_spec.rb +0 -66
  75. data/spec/models/spree/country_spec.rb +0 -55
  76. data/spec/models/spree/credit_card_spec.rb +0 -328
  77. data/spec/models/spree/customer_return_spec.rb +0 -240
  78. data/spec/models/spree/exchange_spec.rb +0 -75
  79. data/spec/models/spree/gateway/bogus_simple.rb +0 -20
  80. data/spec/models/spree/gateway/bogus_spec.rb +0 -13
  81. data/spec/models/spree/gateway_spec.rb +0 -61
  82. data/spec/models/spree/image_spec.rb +0 -8
  83. data/spec/models/spree/inventory_unit_spec.rb +0 -256
  84. data/spec/models/spree/line_item_spec.rb +0 -348
  85. data/spec/models/spree/option_type_prototype_spec.rb +0 -9
  86. data/spec/models/spree/option_type_spec.rb +0 -14
  87. data/spec/models/spree/option_value_spec.rb +0 -18
  88. data/spec/models/spree/order/address_spec.rb +0 -50
  89. data/spec/models/spree/order/adjustments_spec.rb +0 -29
  90. data/spec/models/spree/order/callbacks_spec.rb +0 -42
  91. data/spec/models/spree/order/checkout_spec.rb +0 -770
  92. data/spec/models/spree/order/currency_updater_spec.rb +0 -32
  93. data/spec/models/spree/order/finalizing_spec.rb +0 -114
  94. data/spec/models/spree/order/helpers_spec.rb +0 -5
  95. data/spec/models/spree/order/payment_spec.rb +0 -214
  96. data/spec/models/spree/order/risk_assessment_spec.rb +0 -84
  97. data/spec/models/spree/order/shipments_spec.rb +0 -43
  98. data/spec/models/spree/order/state_machine_spec.rb +0 -212
  99. data/spec/models/spree/order/store_credit_spec.rb +0 -457
  100. data/spec/models/spree/order/tax_spec.rb +0 -84
  101. data/spec/models/spree/order/totals_spec.rb +0 -24
  102. data/spec/models/spree/order/updating_spec.rb +0 -18
  103. data/spec/models/spree/order/validations_spec.rb +0 -15
  104. data/spec/models/spree/order_contents_spec.rb +0 -332
  105. data/spec/models/spree/order_inventory_spec.rb +0 -247
  106. data/spec/models/spree/order_merger_spec.rb +0 -135
  107. data/spec/models/spree/order_spec.rb +0 -1067
  108. data/spec/models/spree/order_updater_spec.rb +0 -305
  109. data/spec/models/spree/payment/gateway_options_spec.rb +0 -127
  110. data/spec/models/spree/payment/store_credit_spec.rb +0 -60
  111. data/spec/models/spree/payment_method/store_credit_spec.rb +0 -291
  112. data/spec/models/spree/payment_method_spec.rb +0 -108
  113. data/spec/models/spree/payment_spec.rb +0 -922
  114. data/spec/models/spree/preference_spec.rb +0 -80
  115. data/spec/models/spree/preferences/configuration_spec.rb +0 -30
  116. data/spec/models/spree/preferences/preferable_spec.rb +0 -344
  117. data/spec/models/spree/preferences/scoped_store_spec.rb +0 -58
  118. data/spec/models/spree/preferences/store_spec.rb +0 -46
  119. data/spec/models/spree/price_spec.rb +0 -128
  120. data/spec/models/spree/product/scopes_spec.rb +0 -174
  121. data/spec/models/spree/product_duplicator_spec.rb +0 -102
  122. data/spec/models/spree/product_filter_spec.rb +0 -26
  123. data/spec/models/spree/product_option_type_spec.rb +0 -9
  124. data/spec/models/spree/product_promotion_rule_spec.rb +0 -9
  125. data/spec/models/spree/product_property_spec.rb +0 -26
  126. data/spec/models/spree/product_spec.rb +0 -626
  127. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +0 -113
  128. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +0 -148
  129. data/spec/models/spree/promotion/actions/create_line_items_spec.rb +0 -86
  130. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +0 -36
  131. data/spec/models/spree/promotion/rules/country_spec.rb +0 -36
  132. data/spec/models/spree/promotion/rules/first_order_spec.rb +0 -75
  133. data/spec/models/spree/promotion/rules/item_total_spec.rb +0 -282
  134. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +0 -42
  135. data/spec/models/spree/promotion/rules/option_value_spec.rb +0 -90
  136. data/spec/models/spree/promotion/rules/product_spec.rb +0 -143
  137. data/spec/models/spree/promotion/rules/taxon_spec.rb +0 -102
  138. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +0 -27
  139. data/spec/models/spree/promotion/rules/user_spec.rb +0 -45
  140. data/spec/models/spree/promotion_action_spec.rb +0 -10
  141. data/spec/models/spree/promotion_category_spec.rb +0 -17
  142. data/spec/models/spree/promotion_handler/cart_spec.rb +0 -102
  143. data/spec/models/spree/promotion_handler/coupon_spec.rb +0 -323
  144. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +0 -48
  145. data/spec/models/spree/promotion_handler/page_spec.rb +0 -44
  146. data/spec/models/spree/promotion_rule_spec.rb +0 -29
  147. data/spec/models/spree/promotion_rule_taxon_spec.rb +0 -9
  148. data/spec/models/spree/promotion_rule_user_spec.rb +0 -9
  149. data/spec/models/spree/promotion_spec.rb +0 -674
  150. data/spec/models/spree/property_prototype_spec.rb +0 -9
  151. data/spec/models/spree/property_spec.rb +0 -5
  152. data/spec/models/spree/prototype_spec.rb +0 -5
  153. data/spec/models/spree/prototype_taxon_spec.rb +0 -9
  154. data/spec/models/spree/refund_reason_spec.rb +0 -20
  155. data/spec/models/spree/refund_spec.rb +0 -195
  156. data/spec/models/spree/reimbursement/credit_spec.rb +0 -36
  157. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +0 -140
  158. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +0 -83
  159. data/spec/models/spree/reimbursement_performer_spec.rb +0 -30
  160. data/spec/models/spree/reimbursement_spec.rb +0 -188
  161. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +0 -63
  162. data/spec/models/spree/reimbursement_type/credit_spec.rb +0 -53
  163. data/spec/models/spree/reimbursement_type/exchange_spec.rb +0 -46
  164. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +0 -55
  165. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +0 -101
  166. data/spec/models/spree/return_authorization_reason_spec.rb +0 -7
  167. data/spec/models/spree/return_authorization_spec.rb +0 -230
  168. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +0 -77
  169. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +0 -58
  170. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +0 -61
  171. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +0 -32
  172. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +0 -29
  173. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +0 -35
  174. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +0 -65
  175. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +0 -43
  176. data/spec/models/spree/return_item_spec.rb +0 -734
  177. data/spec/models/spree/returns_calculator_spec.rb +0 -14
  178. data/spec/models/spree/role_spec.rb +0 -7
  179. data/spec/models/spree/shipment_spec.rb +0 -744
  180. data/spec/models/spree/shipping_calculator_spec.rb +0 -45
  181. data/spec/models/spree/shipping_category_spec.rb +0 -19
  182. data/spec/models/spree/shipping_method_spec.rb +0 -125
  183. data/spec/models/spree/shipping_rate_spec.rb +0 -140
  184. data/spec/models/spree/state_spec.rb +0 -29
  185. data/spec/models/spree/stock/availability_validator_spec.rb +0 -42
  186. data/spec/models/spree/stock/content_item_spec.rb +0 -31
  187. data/spec/models/spree/stock/coordinator_spec.rb +0 -61
  188. data/spec/models/spree/stock/differentiator_spec.rb +0 -39
  189. data/spec/models/spree/stock/estimator_spec.rb +0 -202
  190. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +0 -37
  191. data/spec/models/spree/stock/package_spec.rb +0 -182
  192. data/spec/models/spree/stock/packer_spec.rb +0 -70
  193. data/spec/models/spree/stock/prioritizer_spec.rb +0 -125
  194. data/spec/models/spree/stock/quantifier_spec.rb +0 -126
  195. data/spec/models/spree/stock/splitter/backordered_spec.rb +0 -29
  196. data/spec/models/spree/stock/splitter/base_spec.rb +0 -21
  197. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +0 -47
  198. data/spec/models/spree/stock/splitter/weight_spec.rb +0 -32
  199. data/spec/models/spree/stock_item_spec.rb +0 -465
  200. data/spec/models/spree/stock_location_spec.rb +0 -243
  201. data/spec/models/spree/stock_movement_spec.rb +0 -120
  202. data/spec/models/spree/stock_transfer_spec.rb +0 -50
  203. data/spec/models/spree/store_credit_event_spec.rb +0 -101
  204. data/spec/models/spree/store_credit_spec.rb +0 -798
  205. data/spec/models/spree/store_spec.rb +0 -78
  206. data/spec/models/spree/tax_category_spec.rb +0 -32
  207. data/spec/models/spree/tax_rate_spec.rb +0 -561
  208. data/spec/models/spree/taxon_spec.rb +0 -93
  209. data/spec/models/spree/taxonomy_spec.rb +0 -18
  210. data/spec/models/spree/tracker_spec.rb +0 -21
  211. data/spec/models/spree/user_spec.rb +0 -203
  212. data/spec/models/spree/variant_spec.rb +0 -818
  213. data/spec/models/spree/zone_member_spec.rb +0 -38
  214. data/spec/models/spree/zone_spec.rb +0 -472
  215. data/spec/spec_helper.rb +0 -82
  216. data/spec/support/big_decimal.rb +0 -5
  217. data/spec/support/concerns/adjustment_source.rb +0 -23
  218. data/spec/support/concerns/default_price.rb +0 -37
  219. data/spec/support/rake.rb +0 -13
  220. data/spec/support/test_gateway.rb +0 -2
@@ -1,48 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Spree
4
- module PromotionHandler
5
- describe FreeShipping, type: :model do
6
- let(:order) { create(:order) }
7
- let(:shipment) { create(:shipment, order: order ) }
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) }
12
-
13
- subject { Spree::PromotionHandler::FreeShipping.new(order) }
14
-
15
- context "activates in Shipment level" do
16
- it "creates the adjustment" do
17
- expect { subject.activate }.to change { shipment.adjustments.count }.by(1)
18
- end
19
- end
20
-
21
- context "if promo has a code" do
22
- before do
23
- promotion.update_column(:code, "code")
24
- end
25
-
26
- it "does adjust the shipment when applied to order" do
27
- order.promotions << promotion
28
-
29
- expect { subject.activate }.to change { shipment.adjustments.count }
30
- end
31
-
32
- it "does not adjust the shipment when not applied to order" do
33
- expect { subject.activate }.to_not change { shipment.adjustments.count }
34
- end
35
- end
36
-
37
- context "if promo has a path" do
38
- before do
39
- promotion.update_column(:path, "path")
40
- end
41
-
42
- it "does not adjust the shipment" do
43
- expect { subject.activate }.to_not change { shipment.adjustments.count }
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,44 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Spree
4
- module PromotionHandler
5
- describe Page, type: :model do
6
- let(:order) { create(:order_with_line_items, line_items_count: 1) }
7
-
8
- let(:promotion) { Promotion.create(name: "10% off", path: '10off') }
9
- before do
10
- calculator = Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10)
11
- action = Promotion::Actions::CreateItemAdjustments.create(calculator: calculator)
12
- promotion.actions << action
13
- end
14
-
15
- it "activates at the right path" do
16
- expect(order.line_item_adjustments.count).to eq(0)
17
- Spree::PromotionHandler::Page.new(order, '10off').activate
18
- expect(order.line_item_adjustments.count).to eq(1)
19
- end
20
-
21
- context "when promotion is expired" do
22
- before do
23
- promotion.update_columns(
24
- starts_at: 1.week.ago,
25
- expires_at: 1.day.ago
26
- )
27
- end
28
-
29
- it "is not activated" do
30
- expect(order.line_item_adjustments.count).to eq(0)
31
- Spree::PromotionHandler::Page.new(order, '10off').activate
32
- expect(order.line_item_adjustments.count).to eq(0)
33
- end
34
- end
35
-
36
- it "does not activate at the wrong path" do
37
- expect(order.line_item_adjustments.count).to eq(0)
38
- Spree::PromotionHandler::Page.new(order, 'wrongpath').activate
39
- expect(order.line_item_adjustments.count).to eq(0)
40
- end
41
- end
42
- end
43
- end
44
-
@@ -1,29 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Spree
4
- describe Spree::PromotionRule, type: :model do
5
-
6
- class BadTestRule < Spree::PromotionRule; end
7
-
8
- class TestRule < Spree::PromotionRule
9
- def eligible?
10
- true
11
- end
12
- end
13
-
14
- it "should force developer to implement eligible? method" do
15
- expect { BadTestRule.new.eligible? }.to raise_error(ArgumentError)
16
- end
17
-
18
- it "validates unique rules for a promotion" do
19
- p1 = TestRule.new
20
- p1.promotion_id = 1
21
- p1.save
22
-
23
- p2 = TestRule.new
24
- p2.promotion_id = 1
25
- expect(p2).not_to be_valid
26
- end
27
-
28
- end
29
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Spree::PromotionRuleTaxon do
4
- describe 'Validations' do
5
- it { is_expected.to validate_presence_of(:promotion_rule) }
6
- it { is_expected.to validate_presence_of(:taxon) }
7
- it { is_expected.to validate_uniqueness_of(:promotion_rule_id).scoped_to(:taxon_id).allow_nil }
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Spree::PromotionRuleUser do
4
- describe 'Validations' do
5
- it { is_expected.to validate_presence_of(:promotion_rule) }
6
- it { is_expected.to validate_presence_of(:user) }
7
- it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:promotion_rule_id).allow_nil }
8
- end
9
- end
@@ -1,674 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Spree::Promotion, type: :model do
4
- let(:promotion) { Spree::Promotion.new }
5
-
6
- describe "validations" do
7
- before :each do
8
- @valid_promotion = Spree::Promotion.new name: "A promotion"
9
- end
10
-
11
- it { is_expected.to validate_presence_of(:name) }
12
- it { is_expected.to validate_uniqueness_of(:path).case_insensitive.allow_blank }
13
- it { is_expected.to validate_uniqueness_of(:code).case_insensitive.allow_blank }
14
- it { is_expected.to validate_numericality_of(:usage_limit).is_greater_than(0).allow_nil }
15
- it { is_expected.to validate_length_of(:description).is_at_most(255) }
16
- it { is_expected.to allow_values('', nil).for(:description) }
17
-
18
- it "valid_promotion is valid" do
19
- expect(@valid_promotion).to be_valid
20
- end
21
-
22
- it "validates usage limit" do
23
- @valid_promotion.usage_limit = -1
24
- expect(@valid_promotion).not_to be_valid
25
-
26
- @valid_promotion.usage_limit = 100
27
- expect(@valid_promotion).to be_valid
28
- end
29
-
30
- it "validates name" do
31
- @valid_promotion.name = nil
32
- expect(@valid_promotion).not_to be_valid
33
- end
34
-
35
- describe "expires_at_must_be_later_than_starts_at" do
36
- before do
37
- @valid_promotion.starts_at = Date.today
38
- end
39
-
40
- context "starts_at is a date earlier than expires_at" do
41
- before { @valid_promotion.expires_at = 5.days.from_now }
42
-
43
- it "is valid" do
44
- expect(@valid_promotion).to be_valid
45
- end
46
- end
47
-
48
- context "starts_at is a date earlier than expires_at" do
49
- before { @valid_promotion.expires_at = 5.days.ago }
50
-
51
- context "is not valid" do
52
- before { @valid_promotion.valid? }
53
- it { expect(@valid_promotion).not_to be_valid }
54
- it { expect(@valid_promotion.errors[:expires_at]).to include(I18n.t(:invalid_date_range, scope: 'activerecord.errors.models.spree/promotion.attributes.expires_at')) }
55
- end
56
- end
57
-
58
- context "starts_at and expires_at are nil" do
59
- before do
60
- @valid_promotion.expires_at = nil
61
- @valid_promotion.starts_at = nil
62
- end
63
-
64
- it "is valid" do
65
- expect(@valid_promotion).to be_valid
66
- end
67
- end
68
- end
69
- end
70
-
71
- describe 'scopes' do
72
- describe '.coupons' do
73
- let!(:promotion_without_code) { Spree::Promotion.create! name: 'test', code: '' }
74
- let!(:promotion_with_code) { Spree::Promotion.create! name: 'test1', code: 'code' }
75
-
76
- subject { Spree::Promotion.coupons }
77
-
78
- it 'is expected to not include promotion without code' do
79
- is_expected.to_not include(promotion_without_code)
80
- end
81
-
82
- it 'is expected to include promotion with code' do
83
- is_expected.to include(promotion_with_code)
84
- end
85
- end
86
-
87
- describe '.applied' do
88
- let!(:promotion_not_applied) { Spree::Promotion.create! name: 'test', code: '' }
89
- let(:order) { create(:order) }
90
- let!(:promotion_applied) do
91
- promotion = Spree::Promotion.create!(name: 'test1', code: '')
92
- promotion.orders << order
93
- promotion
94
- end
95
-
96
- subject { Spree::Promotion.applied }
97
-
98
- it 'is expected to not include promotion not applied' do
99
- is_expected.to_not include(promotion_not_applied)
100
- end
101
-
102
- it 'is expected to include promotion applied' do
103
- is_expected.to include(promotion_applied)
104
- end
105
- end
106
-
107
- describe '.advertised' do
108
- let!(:promotion_not_advertised) { Spree::Promotion.create! name: 'test', advertise: false }
109
- let!(:promotion_advertised) { Spree::Promotion.create! name: 'test1', advertise: true }
110
-
111
- subject { Spree::Promotion.advertised }
112
-
113
- it 'is expected to not include promotion not advertised' do
114
- is_expected.to_not include(promotion_not_advertised)
115
- end
116
-
117
- it 'is expected to include promotion advertised' do
118
- is_expected.to include(promotion_advertised)
119
- end
120
- end
121
- end
122
-
123
- describe "#destroy" do
124
- let(:promotion) { Spree::Promotion.create(name: "delete me") }
125
-
126
- before(:each) do
127
- promotion.actions << Spree::Promotion::Actions::CreateAdjustment.new
128
- promotion.rules << Spree::Promotion::Rules::FirstOrder.new
129
- promotion.save!
130
- promotion.destroy
131
- end
132
-
133
- it "should delete actions" do
134
- expect(Spree::PromotionAction.count).to eq(0)
135
- end
136
-
137
- it "should delete rules" do
138
- expect(Spree::PromotionRule.count).to eq(0)
139
- end
140
- end
141
-
142
- describe "#save" do
143
- let(:promotion) { Spree::Promotion.create(name: "delete me") }
144
-
145
- before(:each) do
146
- promotion.actions << Spree::Promotion::Actions::CreateAdjustment.new
147
- promotion.rules << Spree::Promotion::Rules::FirstOrder.new
148
- promotion.save!
149
- end
150
-
151
- it "should deeply autosave records and preferences" do
152
- promotion.actions[0].calculator.preferred_flat_percent = 10
153
- promotion.save!
154
- expect(Spree::Calculator.first.preferred_flat_percent).to eq(10)
155
- end
156
- end
157
-
158
- describe "#activate" do
159
- before do
160
- @action1 = Spree::Promotion::Actions::CreateAdjustment.create!
161
- @action2 = Spree::Promotion::Actions::CreateAdjustment.create!
162
- allow(@action1).to receive_messages perform: true
163
- allow(@action2).to receive_messages perform: true
164
-
165
- promotion.promotion_actions = [@action1, @action2]
166
- promotion.created_at = 2.days.ago
167
-
168
- @user = stub_model(Spree::LegacyUser, email: "spree@example.com")
169
- @order = Spree::Order.create user: @user
170
- @payload = { order: @order, user: @user }
171
- end
172
-
173
- it "should check path if present" do
174
- promotion.path = 'content/cvv'
175
- @payload[:path] = 'content/cvv'
176
- expect(@action1).to receive(:perform).with(@payload)
177
- expect(@action2).to receive(:perform).with(@payload)
178
- promotion.activate(@payload)
179
- end
180
-
181
- it "does not perform actions against an order in a finalized state" do
182
- expect(@action1).not_to receive(:perform).with(@payload)
183
-
184
- @order.state = 'complete'
185
- promotion.activate(@payload)
186
-
187
- @order.state = 'awaiting_return'
188
- promotion.activate(@payload)
189
-
190
- @order.state = 'returned'
191
- promotion.activate(@payload)
192
- end
193
-
194
- it "does activate if newer then order" do
195
- expect(@action1).to receive(:perform).with(@payload)
196
- promotion.created_at = DateTime.current + 2
197
- expect(promotion.activate(@payload)).to be true
198
- end
199
-
200
- context "keeps track of the orders" do
201
- context "when activated" do
202
- it "assigns the order" do
203
- expect(promotion.orders).to be_empty
204
- expect(promotion.activate(@payload)).to be true
205
- expect(promotion.orders.first).to eql @order
206
- end
207
- end
208
- context "when not activated" do
209
- it "will not assign the order" do
210
- @order.state = 'complete'
211
- expect(promotion.orders).to be_empty
212
- expect(promotion.activate(@payload)).to be_falsey
213
- expect(promotion.orders).to be_empty
214
- end
215
- end
216
-
217
- end
218
-
219
- end
220
-
221
- context "#usage_limit_exceeded" do
222
- let(:promotable) { double('Promotable') }
223
- it "should not have its usage limit exceeded with no usage limit" do
224
- promotion.usage_limit = 0
225
- expect(promotion.usage_limit_exceeded?(promotable)).to be false
226
- end
227
-
228
- it "should have its usage limit exceeded" do
229
- promotion.usage_limit = 2
230
- allow(promotion).to receive_messages(adjusted_credits_count: 2)
231
- expect(promotion.usage_limit_exceeded?(promotable)).to be true
232
-
233
- allow(promotion).to receive_messages(adjusted_credits_count: 3)
234
- expect(promotion.usage_limit_exceeded?(promotable)).to be true
235
- end
236
- end
237
-
238
- context "#expired" do
239
- it "should not be exipired" do
240
- expect(promotion).not_to be_expired
241
- end
242
-
243
- it "should be expired if it hasn't started yet" do
244
- promotion.starts_at = Time.current + 1.day
245
- expect(promotion).to be_expired
246
- end
247
-
248
- it "should be expired if it has already ended" do
249
- promotion.expires_at = Time.current - 1.day
250
- expect(promotion).to be_expired
251
- end
252
-
253
- it "should not be expired if it has started already" do
254
- promotion.starts_at = Time.current - 1.day
255
- expect(promotion).not_to be_expired
256
- end
257
-
258
- it "should not be expired if it has not ended yet" do
259
- promotion.expires_at = Time.current + 1.day
260
- expect(promotion).not_to be_expired
261
- end
262
-
263
- it "should not be expired if current time is within starts_at and expires_at range" do
264
- promotion.starts_at = Time.current - 1.day
265
- promotion.expires_at = Time.current + 1.day
266
- expect(promotion).not_to be_expired
267
- end
268
-
269
- it "should not be expired if usage limit is not exceeded" do
270
- promotion.usage_limit = 2
271
- allow(promotion).to receive_messages(credits_count: 1)
272
- expect(promotion).not_to be_expired
273
- end
274
- end
275
-
276
- context "#credits_count" do
277
- let!(:promotion) do
278
- promotion = Spree::Promotion.new
279
- promotion.name = "Foo"
280
- promotion.code = "XXX"
281
- calculator = Spree::Calculator::FlatRate.new
282
- promotion.tap(&:save)
283
- end
284
-
285
- let!(:action) do
286
- calculator = Spree::Calculator::FlatRate.new
287
- action_params = { promotion: promotion, calculator: calculator }
288
- action = Spree::Promotion::Actions::CreateAdjustment.create(action_params)
289
- promotion.actions << action
290
- action
291
- end
292
-
293
- let!(:adjustment) do
294
- order = create(:order)
295
- Spree::Adjustment.create!(
296
- order: order,
297
- adjustable: order,
298
- source: action,
299
- amount: 10,
300
- label: 'Promotional adjustment'
301
- )
302
- end
303
-
304
- it "counts eligible adjustments" do
305
- adjustment.update_column(:eligible, true)
306
- expect(promotion.credits_count).to eq(1)
307
- end
308
-
309
- # Regression test for #4112
310
- it "does not count ineligible adjustments" do
311
- adjustment.update_column(:eligible, false)
312
- expect(promotion.credits_count).to eq(0)
313
- end
314
- end
315
-
316
- context "#adjusted_credits_count" do
317
- let(:order) { create :order }
318
- let(:line_item) { create :line_item, order: order }
319
- let(:promotion) { Spree::Promotion.create name: "promo", code: "10off" }
320
- let(:order_action) {
321
- action = Spree::Promotion::Actions::CreateAdjustment.create(calculator: Spree::Calculator::FlatPercentItemTotal.new)
322
- promotion.actions << action
323
- action
324
- }
325
- let(:item_action) {
326
- action = Spree::Promotion::Actions::CreateItemAdjustments.create(calculator: Spree::Calculator::FlatPercentItemTotal.new)
327
- promotion.actions << action
328
- action
329
- }
330
- let(:order_adjustment) do
331
- Spree::Adjustment.create!(
332
- source: order_action,
333
- amount: 10,
334
- adjustable: order,
335
- order: order,
336
- label: "Promotional adjustment"
337
- )
338
- end
339
- let(:item_adjustment) do
340
- Spree::Adjustment.create!(
341
- source: item_action,
342
- amount: 10,
343
- adjustable: line_item,
344
- order: order,
345
- label: "Promotional adjustment"
346
- )
347
- end
348
-
349
- it "counts order level adjustments" do
350
- expect(order_adjustment.adjustable).to eq(order)
351
- expect(promotion.credits_count).to eq(1)
352
- expect(promotion.adjusted_credits_count(order)).to eq(0)
353
- end
354
-
355
- it "counts item level adjustments" do
356
- expect(item_adjustment.adjustable).to eq(line_item)
357
- expect(promotion.credits_count).to eq(1)
358
- expect(promotion.adjusted_credits_count(order)).to eq(0)
359
- end
360
- end
361
-
362
- context "#products" do
363
- let(:product) { create(:product) }
364
- let(:promotion) { create(:promotion) }
365
-
366
- context "when it has product rules with products associated" do
367
- let(:promotion_rule) { create(:promotion_rule, promotion: promotion, type: 'Spree::Promotion::Rules::Product') }
368
-
369
- before do
370
- promotion.promotion_rules << promotion_rule
371
- product.product_promotion_rules.create(promotion_rule_id: promotion_rule.id)
372
- end
373
-
374
- it "should have products" do
375
- expect(promotion.reload.products.size).to eq(1)
376
- end
377
- end
378
-
379
- context "when there's no product rule associated" do
380
- it "should not have products but still return an empty array" do
381
- expect(promotion.products).to be_blank
382
- end
383
- end
384
- end
385
-
386
- context "#eligible?" do
387
- let(:promotable) { create :order }
388
- subject { promotion.eligible?(promotable) }
389
- context "when promotion is expired" do
390
- before { promotion.expires_at = Time.current - 10.days }
391
- it { is_expected.to be false }
392
- end
393
- context "when promotable is a Spree::LineItem" do
394
- let(:promotable) { create :line_item }
395
- let(:product) { promotable.product }
396
- before do
397
- product.promotionable = promotionable
398
- end
399
- context "and product is promotionable" do
400
- let(:promotionable) { true }
401
- it { is_expected.to be true }
402
- end
403
- context "and product is not promotionable" do
404
- let(:promotionable) { false }
405
- it { is_expected.to be false }
406
- end
407
- end
408
- context "when promotable is a Spree::Order" do
409
- let(:promotable) { create :order }
410
- context "and it is empty" do
411
- it { is_expected.to be true }
412
- end
413
- context "and it contains items" do
414
- let!(:line_item) { create(:line_item, order: promotable) }
415
- context "and the items are all non-promotionable" do
416
- before do
417
- line_item.product.update_column(:promotionable, false)
418
- end
419
- it { is_expected.to be false }
420
- end
421
- context "and at least one item is promotionable" do
422
- it { is_expected.to be true }
423
- end
424
- end
425
- end
426
- end
427
-
428
- context "#eligible_rules" do
429
- let(:promotable) { double('Promotable') }
430
- it "true if there are no rules" do
431
- expect(promotion.eligible_rules(promotable)).to eq []
432
- end
433
-
434
- it "true if there are no applicable rules" do
435
- promotion.promotion_rules = [stub_model(Spree::PromotionRule, eligible?: true, applicable?: false)]
436
- allow(promotion.promotion_rules).to receive(:for).and_return([])
437
- expect(promotion.eligible_rules(promotable)).to eq []
438
- end
439
-
440
- context "with 'all' match policy" do
441
- let(:promo1) { Spree::PromotionRule.create! }
442
- let(:promo2) { Spree::PromotionRule.create! }
443
-
444
- before { promotion.match_policy = 'all' }
445
-
446
- context "when all rules are eligible" do
447
- before do
448
- allow(promo1).to receive_messages(eligible?: true, applicable?: true)
449
- allow(promo2).to receive_messages(eligible?: true, applicable?: true)
450
-
451
- promotion.promotion_rules = [promo1, promo2]
452
- allow(promotion.promotion_rules).to receive(:for).and_return(promotion.promotion_rules)
453
- end
454
- it "returns the eligible rules" do
455
- expect(promotion.eligible_rules(promotable)).to eq [promo1, promo2]
456
- end
457
- it "does set anything to eligiblity errors" do
458
- promotion.eligible_rules(promotable)
459
- expect(promotion.eligibility_errors).to be_nil
460
- end
461
- end
462
-
463
- context "when any of the rules is not eligible" do
464
- let(:errors) { double ActiveModel::Errors, empty?: false }
465
- before do
466
- allow(promo1).to receive_messages(eligible?: true, applicable?: true, eligibility_errors: nil)
467
- allow(promo2).to receive_messages(eligible?: false, applicable?: true, eligibility_errors: errors)
468
-
469
- promotion.promotion_rules = [promo1, promo2]
470
- allow(promotion.promotion_rules).to receive(:for).and_return(promotion.promotion_rules)
471
- end
472
- it "returns nil" do
473
- expect(promotion.eligible_rules(promotable)).to be_nil
474
- end
475
- it "sets eligibility errors to the first non-nil one" do
476
- promotion.eligible_rules(promotable)
477
- expect(promotion.eligibility_errors).to eq errors
478
- end
479
- end
480
- end
481
-
482
- context "with 'any' match policy" do
483
- let(:promotion) { Spree::Promotion.create(name: "Promo", match_policy: 'any') }
484
- let(:promotable) { double('Promotable') }
485
-
486
- it "should have eligible rules if any of the rules are eligible" do
487
- allow_any_instance_of(Spree::PromotionRule).to receive_messages(applicable?: true)
488
- true_rule = Spree::PromotionRule.create(promotion: promotion)
489
- allow(true_rule).to receive_messages(eligible?: true)
490
- allow(promotion).to receive_messages(rules: [true_rule])
491
- allow(promotion).to receive_message_chain(:rules, :for).and_return([true_rule])
492
- expect(promotion.eligible_rules(promotable)).to eq [true_rule]
493
- end
494
-
495
- context "when none of the rules are eligible" do
496
- let(:promo) { Spree::PromotionRule.create! }
497
- let(:errors) { double ActiveModel::Errors, empty?: false }
498
- before do
499
- allow(promo).to receive_messages(eligible?: false, applicable?: true, eligibility_errors: errors)
500
-
501
- promotion.promotion_rules = [promo]
502
- allow(promotion.promotion_rules).to receive(:for).and_return(promotion.promotion_rules)
503
- end
504
- it "returns nil" do
505
- expect(promotion.eligible_rules(promotable)).to be_nil
506
- end
507
- it "sets eligibility errors to the first non-nil one" do
508
- promotion.eligible_rules(promotable)
509
- expect(promotion.eligibility_errors).to eq errors
510
- end
511
- end
512
- end
513
- end
514
-
515
- describe '#line_item_actionable?' do
516
- let(:order) { double Spree::Order }
517
- let(:line_item) { double Spree::LineItem}
518
- let(:true_rule) { double Spree::PromotionRule, eligible?: true, applicable?: true, actionable?: true }
519
- let(:false_rule) { double Spree::PromotionRule, eligible?: true, applicable?: true, actionable?: false }
520
- let(:rules) { [] }
521
-
522
- before do
523
- allow(promotion).to receive(:rules) { rules }
524
- allow(rules).to receive(:for) { rules }
525
- end
526
-
527
- subject { promotion.line_item_actionable? order, line_item }
528
-
529
- context 'when the order is eligible for promotion' do
530
- context 'when there are no rules' do
531
- it { is_expected.to be }
532
- end
533
-
534
- context 'when there are rules' do
535
- context 'when the match policy is all' do
536
- before { promotion.match_policy = 'all' }
537
-
538
- context 'when all rules allow action on the line item' do
539
- let(:rules) { [true_rule] }
540
- it { is_expected.to be}
541
- end
542
-
543
- context 'when at least one rule does not allow action on the line item' do
544
- let(:rules) { [true_rule, false_rule] }
545
- it { is_expected.not_to be}
546
- end
547
- end
548
-
549
- context 'when the match policy is any' do
550
- before { promotion.match_policy = 'any' }
551
-
552
- context 'when at least one rule allows action on the line item' do
553
- let(:rules) { [true_rule, false_rule] }
554
- it { is_expected.to be }
555
- end
556
-
557
- context 'when no rules allow action on the line item' do
558
- let(:rules) { [false_rule] }
559
- it { is_expected.not_to be}
560
- end
561
- end
562
- end
563
- end
564
-
565
- context 'when the order is not eligible for the promotion' do
566
- before { promotion.starts_at = Time.current + 2.days }
567
- it { is_expected.not_to be }
568
- end
569
- end
570
-
571
- # regression for #4059
572
- # admin form posts the code and path as empty string
573
- describe "normalize blank values for code & path" do
574
- it "will save blank value as nil value instead" do
575
- promotion = Spree::Promotion.create(name: "A promotion", code: "", path: "")
576
- expect(promotion.code).to be_nil
577
- expect(promotion.path).to be_nil
578
- end
579
- end
580
-
581
- # Regression test for #4081
582
- describe "#with_coupon_code" do
583
- context "and code stored in uppercase" do
584
- let!(:promotion) { create(:promotion, :with_order_adjustment, code: "MY-COUPON-123") }
585
- it "finds the code with lowercase" do
586
- expect(Spree::Promotion.with_coupon_code("my-coupon-123")).to eql promotion
587
- end
588
- end
589
-
590
- context "when promotion has no actions" do
591
- let!(:promotion_without_actions) { create(:promotion, code: "MY-COUPON-123").actions.clear }
592
-
593
- it "then returns the one with an action" do
594
- expect(Spree::Promotion.with_coupon_code("MY-COUPON-123")).to be_nil
595
- end
596
- end
597
- end
598
-
599
- describe '#used_by?' do
600
- subject { promotion.used_by? user, [excluded_order] }
601
-
602
- let(:promotion) { create :promotion, :with_order_adjustment }
603
- let(:user) { create :user }
604
- let(:order) { create :order_with_line_items, user: user }
605
- let(:excluded_order) { create :order_with_line_items, user: user }
606
-
607
- before do
608
- order.user_id = user.id
609
- order.save!
610
- end
611
-
612
- context 'when the user has used this promo' do
613
- before do
614
- promotion.activate(order: order)
615
- order.update_with_updater!
616
- order.completed_at = Time.current
617
- order.save!
618
- end
619
-
620
- context 'when the order is complete' do
621
- it { is_expected.to be true }
622
-
623
- context 'when the promotion was not eligible' do
624
- let(:adjustment) { order.adjustments.first }
625
-
626
- before do
627
- adjustment.eligible = false
628
- adjustment.save!
629
- end
630
-
631
- it { is_expected.to be false }
632
- end
633
-
634
- context 'when the only matching order is the excluded order' do
635
- let(:excluded_order) { order }
636
- it { is_expected.to be false }
637
- end
638
- end
639
-
640
- context 'when the order is not complete' do
641
- let(:order) { create :order, user: user }
642
- it { is_expected.to be false }
643
- end
644
- end
645
-
646
- context 'when the user has not used this promo' do
647
- it { is_expected.to be false }
648
- end
649
- end
650
-
651
- describe "adding items to the cart" do
652
- let(:order) { create :order }
653
- let(:line_item) { create :line_item, order: order }
654
- let(:promo) { create :promotion_with_item_adjustment, adjustment_rate: 5, code: 'promo' }
655
- let(:variant) { create :variant }
656
-
657
- it "updates the promotions for new line items" do
658
- expect(line_item.adjustments).to be_empty
659
- expect(order.adjustment_total).to eq 0
660
-
661
- promo.activate order: order
662
- order.update_with_updater!
663
-
664
- expect(line_item.adjustments.size).to eq(1)
665
- expect(order.adjustment_total).to eq -5
666
-
667
- other_line_item = order.contents.add(variant, 1, currency: order.currency)
668
-
669
- expect(other_line_item).not_to eq line_item
670
- expect(other_line_item.adjustments.size).to eq(1)
671
- expect(order.adjustment_total).to eq -10
672
- end
673
- end
674
- end