solidus_core 1.0.2 → 1.0.3

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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/Gemfile +3 -0
  4. data/Rakefile +16 -0
  5. data/script/rails +9 -0
  6. data/solidus_core.gemspec +48 -0
  7. data/spec/fixtures/thinking-cat.jpg +0 -0
  8. data/spec/helpers/base_helper_spec.rb +173 -0
  9. data/spec/helpers/order_helper_spec.rb +12 -0
  10. data/spec/helpers/products_helper_spec.rb +220 -0
  11. data/spec/helpers/taxons_helper_spec.rb +17 -0
  12. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  13. data/spec/lib/i18n_spec.rb +123 -0
  14. data/spec/lib/search/base_spec.rb +86 -0
  15. data/spec/lib/search/variant_spec.rb +92 -0
  16. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
  17. data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -0
  18. data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
  19. data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
  20. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
  21. data/spec/lib/spree/core/current_store_spec.rb +36 -0
  22. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
  23. data/spec/lib/spree/core/importer/order_spec.rb +431 -0
  24. data/spec/lib/spree/core/role_configuration_spec.rb +138 -0
  25. data/spec/lib/spree/core/validators/email_spec.rb +48 -0
  26. data/spec/lib/spree/localized_number_spec.rb +38 -0
  27. data/spec/lib/spree/migrations_spec.rb +36 -0
  28. data/spec/lib/spree/money_spec.rb +127 -0
  29. data/spec/lib/tasks/exchanges_spec.rb +231 -0
  30. data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
  31. data/spec/lib/tasks/order_capturing_spec.rb +56 -0
  32. data/spec/mailers/carton_mailer_spec.rb +43 -0
  33. data/spec/mailers/order_mailer_spec.rb +122 -0
  34. data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
  35. data/spec/mailers/test_mailer_spec.rb +15 -0
  36. data/spec/models/spree/ability_spec.rb +276 -0
  37. data/spec/models/spree/address_spec.rb +250 -0
  38. data/spec/models/spree/adjustment_reason_spec.rb +13 -0
  39. data/spec/models/spree/adjustment_spec.rb +177 -0
  40. data/spec/models/spree/app_configuration_spec.rb +20 -0
  41. data/spec/models/spree/asset_spec.rb +24 -0
  42. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  43. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  44. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  45. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  46. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  47. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  48. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
  49. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  50. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  51. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  52. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  53. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
  54. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
  55. data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
  56. data/spec/models/spree/calculator_spec.rb +36 -0
  57. data/spec/models/spree/carton_spec.rb +133 -0
  58. data/spec/models/spree/classification_spec.rb +15 -0
  59. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  60. data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
  61. data/spec/models/spree/credit_card_spec.rb +334 -0
  62. data/spec/models/spree/customer_return_spec.rb +276 -0
  63. data/spec/models/spree/exchange_spec.rb +79 -0
  64. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  65. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  66. data/spec/models/spree/gateway_spec.rb +82 -0
  67. data/spec/models/spree/inventory_unit_spec.rb +307 -0
  68. data/spec/models/spree/item_adjustments_spec.rb +256 -0
  69. data/spec/models/spree/line_item_spec.rb +191 -0
  70. data/spec/models/spree/option_type_spec.rb +14 -0
  71. data/spec/models/spree/option_value_spec.rb +22 -0
  72. data/spec/models/spree/order/address_spec.rb +50 -0
  73. data/spec/models/spree/order/adjustments_spec.rb +39 -0
  74. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  75. data/spec/models/spree/order/checkout_spec.rb +902 -0
  76. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  77. data/spec/models/spree/order/finalizing_spec.rb +111 -0
  78. data/spec/models/spree/order/payment_spec.rb +210 -0
  79. data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
  80. data/spec/models/spree/order/state_machine_spec.rb +221 -0
  81. data/spec/models/spree/order/tax_spec.rb +84 -0
  82. data/spec/models/spree/order/totals_spec.rb +24 -0
  83. data/spec/models/spree/order/updating_spec.rb +18 -0
  84. data/spec/models/spree/order/validations_spec.rb +15 -0
  85. data/spec/models/spree/order_cancellations_spec.rb +120 -0
  86. data/spec/models/spree/order_capturing_spec.rb +116 -0
  87. data/spec/models/spree/order_contents_spec.rb +265 -0
  88. data/spec/models/spree/order_inventory_spec.rb +228 -0
  89. data/spec/models/spree/order_mutex_spec.rb +85 -0
  90. data/spec/models/spree/order_promotion_spec.rb +31 -0
  91. data/spec/models/spree/order_shipping_spec.rb +247 -0
  92. data/spec/models/spree/order_spec.rb +1412 -0
  93. data/spec/models/spree/order_stock_location_spec.rb +18 -0
  94. data/spec/models/spree/order_updater_spec.rb +299 -0
  95. data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
  96. data/spec/models/spree/payment_method_spec.rb +96 -0
  97. data/spec/models/spree/payment_spec.rb +1044 -0
  98. data/spec/models/spree/permission_sets/base_spec.rb +12 -0
  99. data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
  100. data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
  101. data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
  102. data/spec/models/spree/permission_sets/order_display_spec.rb +49 -0
  103. data/spec/models/spree/permission_sets/order_management_spec.rb +36 -0
  104. data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
  105. data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
  106. data/spec/models/spree/permission_sets/promotion_display_spec.rb +34 -0
  107. data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
  108. data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
  109. data/spec/models/spree/permission_sets/restricted_transfer_management_spec.rb +132 -0
  110. data/spec/models/spree/permission_sets/stock_display_spec.rb +26 -0
  111. data/spec/models/spree/permission_sets/stock_management_spec.rb +24 -0
  112. data/spec/models/spree/permission_sets/user_display_spec.rb +36 -0
  113. data/spec/models/spree/permission_sets/user_management_spec.rb +28 -0
  114. data/spec/models/spree/preference_spec.rb +80 -0
  115. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  116. data/spec/models/spree/preferences/preferable_spec.rb +294 -0
  117. data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
  118. data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
  119. data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
  120. data/spec/models/spree/preferences/store_spec.rb +39 -0
  121. data/spec/models/spree/price_spec.rb +42 -0
  122. data/spec/models/spree/product/scopes_spec.rb +148 -0
  123. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  124. data/spec/models/spree/product_filter_spec.rb +26 -0
  125. data/spec/models/spree/product_property_spec.rb +20 -0
  126. data/spec/models/spree/product_spec.rb +437 -0
  127. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
  128. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
  129. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
  130. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
  131. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  132. data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
  133. data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
  134. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  135. data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
  136. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  137. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  138. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  139. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  140. data/spec/models/spree/promotion_builder_spec.rb +118 -0
  141. data/spec/models/spree/promotion_category_spec.rb +17 -0
  142. data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
  143. data/spec/models/spree/promotion_code_spec.rb +187 -0
  144. data/spec/models/spree/promotion_handler/cart_spec.rb +114 -0
  145. data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
  146. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
  147. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  148. data/spec/models/spree/promotion_rule_spec.rb +28 -0
  149. data/spec/models/spree/promotion_spec.rb +767 -0
  150. data/spec/models/spree/refund_spec.rb +204 -0
  151. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  152. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  153. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  154. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  155. data/spec/models/spree/reimbursement_spec.rb +231 -0
  156. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  157. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  158. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  159. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
  160. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
  161. data/spec/models/spree/return_authorization_spec.rb +290 -0
  162. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  163. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  164. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
  165. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  166. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  167. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  168. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  169. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  170. data/spec/models/spree/return_item_spec.rb +775 -0
  171. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  172. data/spec/models/spree/shipment_spec.rb +709 -0
  173. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  174. data/spec/models/spree/shipping_method_spec.rb +88 -0
  175. data/spec/models/spree/shipping_rate_spec.rb +142 -0
  176. data/spec/models/spree/state_spec.rb +14 -0
  177. data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
  178. data/spec/models/spree/stock/coordinator_spec.rb +116 -0
  179. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  180. data/spec/models/spree/stock/estimator_spec.rb +146 -0
  181. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  182. data/spec/models/spree/stock/package_spec.rb +163 -0
  183. data/spec/models/spree/stock/packer_spec.rb +91 -0
  184. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  185. data/spec/models/spree/stock/quantifier_spec.rb +115 -0
  186. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  187. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  188. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
  189. data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
  190. data/spec/models/spree/stock_item_spec.rb +426 -0
  191. data/spec/models/spree/stock_location_spec.rb +279 -0
  192. data/spec/models/spree/stock_movement_spec.rb +56 -0
  193. data/spec/models/spree/stock_transfer_spec.rb +290 -0
  194. data/spec/models/spree/store_credit_category_spec.rb +17 -0
  195. data/spec/models/spree/store_credit_event_spec.rb +314 -0
  196. data/spec/models/spree/store_credit_spec.rb +876 -0
  197. data/spec/models/spree/store_spec.rb +55 -0
  198. data/spec/models/spree/tax_category_spec.rb +27 -0
  199. data/spec/models/spree/tax_rate_spec.rb +378 -0
  200. data/spec/models/spree/taxon_spec.rb +74 -0
  201. data/spec/models/spree/taxonomy_spec.rb +18 -0
  202. data/spec/models/spree/tracker_spec.rb +21 -0
  203. data/spec/models/spree/transfer_item_spec.rb +264 -0
  204. data/spec/models/spree/unit_cancel_spec.rb +148 -0
  205. data/spec/models/spree/user_spec.rb +223 -0
  206. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
  207. data/spec/models/spree/variant/scopes_spec.rb +55 -0
  208. data/spec/models/spree/variant_spec.rb +546 -0
  209. data/spec/models/spree/zone_spec.rb +305 -0
  210. data/spec/spec_helper.rb +78 -0
  211. data/spec/support/big_decimal.rb +5 -0
  212. data/spec/support/concerns/default_price.rb +34 -0
  213. data/spec/support/dummy_ability.rb +4 -0
  214. data/spec/support/test_gateway.rb +2 -0
  215. metadata +229 -3
  216. data/lib/spree/testing_support/rspec-activemodel-mocks_patch.rb +0 -8
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ module PromotionHandler
5
+ describe Cart, :type => :model do
6
+ let(:line_item) { create(:line_item) }
7
+ let(:order) { line_item.order }
8
+ let(:promotion) { create(:promotion) }
9
+ let(:calculator) { Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10) }
10
+
11
+ subject { Cart.new(order, line_item) }
12
+
13
+ shared_context "creates the adjustment" do
14
+ it "creates the adjustment" do
15
+ expect {
16
+ subject.activate
17
+ }.to change { adjustable.adjustments.count }.by(1)
18
+ end
19
+ end
20
+
21
+ shared_context "creates an order promotion" do
22
+ it "connects the promotion to the order" do
23
+ expect {
24
+ subject.activate
25
+ }.to change { order.promotions.reload.to_a }.from([]).to([promotion])
26
+ end
27
+ end
28
+
29
+ context "activates in LineItem level" do
30
+ let!(:action) { Promotion::Actions::CreateItemAdjustments.create(promotion: promotion, calculator: calculator) }
31
+ let(:adjustable) { line_item }
32
+
33
+ context "promotion with no rules" do
34
+ include_context "creates the adjustment"
35
+ include_context "creates an order promotion"
36
+ end
37
+
38
+ context "promotion includes item involved" do
39
+ let!(:rule) { Promotion::Rules::Product.create(products: [line_item.product], promotion: promotion) }
40
+
41
+ include_context "creates the adjustment"
42
+ include_context "creates an order promotion"
43
+ end
44
+
45
+ context "promotion has item total rule" do
46
+ let(:shirt) { create(:product) }
47
+ let!(:rule) { Promotion::Rules::ItemTotal.create(preferred_operator: 'gt', preferred_amount: 50, promotion: promotion) }
48
+
49
+ before do
50
+ # Makes the order eligible for this promotion
51
+ order.item_total = 100
52
+ order.save
53
+ end
54
+
55
+ include_context "creates the adjustment"
56
+ include_context "creates an order promotion"
57
+ end
58
+ end
59
+
60
+ context "activates in Order level" do
61
+ let!(:action) { Promotion::Actions::CreateAdjustment.create(promotion: promotion, calculator: calculator) }
62
+ let(:adjustable) { order }
63
+
64
+ context "promotion with no rules" do
65
+ before do
66
+ # Gives the calculator something to discount
67
+ order.item_total = 10
68
+ order.save
69
+ end
70
+
71
+ include_context "creates the adjustment"
72
+ include_context "creates an order promotion"
73
+ end
74
+
75
+ context "promotion has item total rule" do
76
+ let(:shirt) { create(:product) }
77
+ let!(:rule) { Promotion::Rules::ItemTotal.create(preferred_operator: 'gt', preferred_amount: 50, promotion: promotion) }
78
+
79
+ before do
80
+ # Makes the order eligible for this promotion
81
+ order.item_total = 100
82
+ order.save
83
+ end
84
+
85
+ include_context "creates the adjustment"
86
+ include_context "creates an order promotion"
87
+ end
88
+ end
89
+
90
+ context "activates promotions associated with the order" do
91
+ let(:promotion) { create :promotion, :with_order_adjustment, code: 'promo' }
92
+ let(:promotion_code) { promotion.codes.first }
93
+ let(:adjustable) { order }
94
+
95
+ before do
96
+ Spree::OrderPromotion.create!(promotion: promotion, order: order, promotion_code: promotion_code)
97
+ order.update!
98
+ end
99
+
100
+ include_context "creates the adjustment"
101
+
102
+ it "records the promotion code in the adjustment" do
103
+ subject.activate
104
+ expect(adjustable.adjustments.map(&:promotion_code)).to eq [promotion_code]
105
+ end
106
+
107
+ it "checks if the promotion code is eligible" do
108
+ expect_any_instance_of(Spree::Promotion).to receive(:eligible?).at_least(2).times.with(anything, promotion_code: promotion_code).and_return(false)
109
+ subject.activate
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,335 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ module PromotionHandler
5
+ describe Coupon, :type => :model do
6
+ let(:order) { double("Order", coupon_code: "10off").as_null_object }
7
+
8
+ subject { Coupon.new(order) }
9
+
10
+ def expect_order_connection(order:, promotion:, promotion_code:nil)
11
+ expect(order.promotions.to_a).to include(promotion)
12
+ expect(order.order_promotions.flat_map(&:promotion_code)).to include(promotion_code)
13
+ end
14
+
15
+ def expect_adjustment_creation(adjustable:, promotion:, promotion_code:nil)
16
+ expect(adjustable.adjustments.map(&:source).map(&:promotion)).to include(promotion)
17
+ expect(adjustable.adjustments.map(&:promotion_code)).to include(promotion_code)
18
+ end
19
+
20
+
21
+ it "returns self in apply" do
22
+ expect(subject.apply).to be_a Coupon
23
+ end
24
+
25
+ context 'status messages' do
26
+ let(:coupon) { Coupon.new(order) }
27
+
28
+ describe "#set_success_code" do
29
+ let(:status) { :coupon_code_applied }
30
+ subject { coupon.set_success_code status }
31
+
32
+ it 'should have status_code' do
33
+ subject
34
+ expect(coupon.status_code).to eq(status)
35
+ end
36
+
37
+ it 'should have success message' do
38
+ subject
39
+ expect(coupon.success).to eq(Spree.t(status))
40
+ end
41
+ end
42
+
43
+ describe "#set_error_code" do
44
+ let(:status) { :coupon_code_not_found }
45
+
46
+ subject { coupon.set_error_code status }
47
+
48
+ it 'should have status_code' do
49
+ subject
50
+ expect(coupon.status_code).to eq(status)
51
+ end
52
+
53
+ it 'should have error message' do
54
+ subject
55
+ expect(coupon.error).to eq(Spree.t(status))
56
+ end
57
+ end
58
+ end
59
+
60
+ context "coupon code promotion doesnt exist" do
61
+ before { create(:promotion) }
62
+
63
+ it "doesnt fetch any promotion" do
64
+ expect(subject.promotion).to be_blank
65
+ end
66
+
67
+ context "with no actions defined" do
68
+ before { create(:promotion, code: "10off") }
69
+
70
+ it "populates error message" do
71
+ subject.apply
72
+ expect(subject.error).to eq Spree.t(:coupon_code_not_found)
73
+ end
74
+ end
75
+ end
76
+
77
+ context "existing coupon code promotion" do
78
+ let!(:promotion) { promotion_code.promotion }
79
+ let(:promotion_code) { create(:promotion_code, value: '10off') }
80
+ let!(:action) { Promotion::Actions::CreateItemAdjustments.create(promotion: promotion, calculator: calculator) }
81
+ let(:calculator) { Calculator::FlatRate.new(preferred_amount: 10) }
82
+
83
+ it "fetches with given code" do
84
+ expect(subject.promotion).to eq promotion
85
+ end
86
+
87
+ context "with a per-item adjustment action" do
88
+ let(:order) { create(:order_with_line_items, :line_items_count => 3) }
89
+
90
+ context "right coupon given" do
91
+ context "with correct coupon code casing" do
92
+ before { allow(order).to receive_messages :coupon_code => "10off" }
93
+
94
+ it "successfully activates promo" do
95
+ expect(order.total).to eq(130)
96
+ subject.apply
97
+ expect(subject.success).to be_present
98
+ expect_order_connection(order: order, promotion: promotion, promotion_code: promotion_code)
99
+ order.line_items.each do |line_item|
100
+ expect_adjustment_creation(adjustable: line_item, promotion: promotion, promotion_code: promotion_code)
101
+ end
102
+ # Ensure that applying the adjustment actually affects the order's total!
103
+ expect(order.reload.total).to eq(100)
104
+ end
105
+
106
+ it "coupon already applied to the order" do
107
+ subject.apply
108
+ expect(subject.success).to be_present
109
+ subject.apply
110
+ expect(subject.error).to eq Spree.t(:coupon_code_already_applied)
111
+ end
112
+ end
113
+
114
+ # Regression test for #4211
115
+ context "with incorrect coupon code casing" do
116
+ before { allow(order).to receive_messages :coupon_code => "10OFF" }
117
+ it "successfully activates promo" do
118
+ expect(order.total).to eq(130)
119
+ subject.apply
120
+ expect(subject.success).to be_present
121
+ expect_order_connection(order: order, promotion: promotion, promotion_code: promotion_code)
122
+ order.line_items.each do |line_item|
123
+ expect_adjustment_creation(adjustable: line_item, promotion: promotion, promotion_code: promotion_code)
124
+ end
125
+ # Ensure that applying the adjustment actually affects the order's total!
126
+ expect(order.reload.total).to eq(100)
127
+ end
128
+ end
129
+ end
130
+
131
+ context "coexists with a non coupon code promo" do
132
+ let!(:order) { Order.create }
133
+
134
+ before do
135
+ allow(order).to receive_messages :coupon_code => "10off"
136
+ calculator = Calculator::FlatRate.new(preferred_amount: 10)
137
+ general_promo = create(:promotion, name: "General Promo")
138
+ general_action = Promotion::Actions::CreateItemAdjustments.create(promotion: general_promo, calculator: calculator)
139
+
140
+ order.contents.add create(:variant)
141
+ end
142
+
143
+ # regression spec for #4515
144
+ it "successfully activates promo" do
145
+ subject.apply
146
+ expect(subject).to be_successful
147
+ expect_order_connection(order: order, promotion: promotion, promotion_code: promotion_code)
148
+ order.line_items.each do |line_item|
149
+ expect_adjustment_creation(adjustable: line_item, promotion: promotion, promotion_code: promotion_code)
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ context "with a free-shipping adjustment action" do
156
+ let!(:action) { Promotion::Actions::FreeShipping.create!(promotion: promotion) }
157
+ context "right coupon code given" do
158
+ let(:order) { create(:order_with_line_items, :line_items_count => 3) }
159
+
160
+ before { allow(order).to receive_messages :coupon_code => "10off" }
161
+
162
+ it "successfully activates promo" do
163
+ expect(order.total).to eq(130)
164
+ subject.apply
165
+ expect(subject.success).to be_present
166
+
167
+ expect_order_connection(order: order, promotion: promotion, promotion_code: promotion_code)
168
+ order.shipments.each do |shipment|
169
+ expect_adjustment_creation(adjustable: shipment, promotion: promotion, promotion_code: promotion_code)
170
+ end
171
+ end
172
+
173
+ it "coupon already applied to the order" do
174
+ subject.apply
175
+ expect(subject.success).to be_present
176
+ subject.apply
177
+ expect(subject.error).to eq Spree.t(:coupon_code_already_applied)
178
+ end
179
+ end
180
+ end
181
+
182
+ context "with a whole-order adjustment action" do
183
+ let!(:action) { Promotion::Actions::CreateAdjustment.create(promotion: promotion, calculator: calculator) }
184
+ context "right coupon given" do
185
+ let(:order) { create(:order) }
186
+ let(:calculator) { Calculator::FlatRate.new(preferred_amount: 10) }
187
+
188
+ before do
189
+ allow(order).to receive_messages({
190
+ :coupon_code => "10off",
191
+ # These need to be here so that promotion adjustment "wins"
192
+ :item_total => 50,
193
+ :ship_total => 10
194
+ })
195
+ end
196
+
197
+ it "successfully activates promo" do
198
+ subject.apply
199
+ expect(subject.success).to be_present
200
+ expect(order.adjustments.count).to eq(1)
201
+ expect_order_connection(order: order, promotion: promotion, promotion_code: promotion_code)
202
+ expect_adjustment_creation(adjustable: order, promotion: promotion, promotion_code: promotion_code)
203
+ end
204
+
205
+ context "when the coupon is already applied to the order" do
206
+ before { subject.apply }
207
+
208
+ it "is not successful" do
209
+ subject.apply
210
+ expect(subject.successful?).to be false
211
+ end
212
+
213
+ it "returns a coupon has already been applied error" do
214
+ subject.apply
215
+ expect(subject.error).to eq Spree.t(:coupon_code_already_applied)
216
+ end
217
+ end
218
+
219
+ context "when the coupon fails to activate" do
220
+ before { allow_any_instance_of(Spree::Promotion).to receive(:activate).and_return false }
221
+
222
+ it "is not successful" do
223
+ subject.apply
224
+ expect(subject.successful?).to be false
225
+ end
226
+
227
+ it "returns a coupon failed to activate error" do
228
+ subject.apply
229
+ expect(subject.error).to eq Spree.t(:coupon_code_unknown_error)
230
+ end
231
+ end
232
+
233
+ context "when the promotion exceeds its usage limit" do
234
+ let!(:second_order) { FactoryGirl.create(:completed_order_with_promotion, promotion: promotion) }
235
+
236
+ before do
237
+ promotion.update!(usage_limit: 1)
238
+ Coupon.new(second_order).apply
239
+ end
240
+
241
+ it "is not successful" do
242
+ subject.apply
243
+ expect(subject.successful?).to be false
244
+ end
245
+
246
+ it "returns a coupon is at max usage error" do
247
+ subject.apply
248
+ expect(subject.error).to eq Spree.t(:coupon_code_max_usage)
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ context "for an order with taxable line items" do
255
+ before(:each) do
256
+ @country = create(:country)
257
+ @zone = create(:zone, :name => "Country Zone", :default_tax => true, :zone_members => [])
258
+ @zone.zone_members.create(:zoneable => @country)
259
+ @category = Spree::TaxCategory.create :name => "Taxable Foo"
260
+ @rate1 = Spree::TaxRate.create(
261
+ :amount => 0.10,
262
+ :calculator => Spree::Calculator::DefaultTax.create,
263
+ :tax_category => @category,
264
+ :zone => @zone
265
+ )
266
+
267
+ @order = Spree::Order.create!
268
+ allow(@order).to receive_messages :coupon_code => "10off"
269
+ end
270
+ context "and the product price is less than promo discount" do
271
+ before(:each) do
272
+ 3.times do |i|
273
+ taxable = create(:product, :tax_category => @category, :price => 9.0)
274
+ @order.contents.add(taxable.master, 1)
275
+ end
276
+ end
277
+ it "successfully applies the promo" do
278
+ # 3 * (9 + 0.9)
279
+ expect(@order.total).to eq(29.7)
280
+ coupon = Coupon.new(@order)
281
+ coupon.apply
282
+ expect(coupon.success).to be_present
283
+ # 3 * ((9 - [9,10].min) + 0)
284
+ expect(@order.reload.total).to eq(0)
285
+ expect(@order.additional_tax_total).to eq(0)
286
+ end
287
+ end
288
+ context "and the product price is greater than promo discount" do
289
+ before(:each) do
290
+ 3.times do |i|
291
+ taxable = create(:product, :tax_category => @category, :price => 11.0)
292
+ @order.contents.add(taxable.master, 2)
293
+ end
294
+ end
295
+ it "successfully applies the promo" do
296
+ # 3 * (22 + 2.2)
297
+ expect(@order.total.to_f).to eq(72.6)
298
+ coupon = Coupon.new(@order)
299
+ coupon.apply
300
+ expect(coupon.success).to be_present
301
+ # 3 * ( (22 - 10) + 1.2)
302
+ expect(@order.reload.total).to eq(39.6)
303
+ expect(@order.additional_tax_total).to eq(3.6)
304
+ end
305
+ end
306
+ context "and multiple quantity per line item" do
307
+ before(:each) do
308
+ twnty_off = create(:promotion, name: "promo", code: "20off")
309
+ twnty_off_calc = Calculator::FlatRate.new(preferred_amount: 20)
310
+ Promotion::Actions::CreateItemAdjustments.create(promotion: twnty_off,
311
+ calculator: twnty_off_calc)
312
+
313
+ allow(@order).to receive(:coupon_code).and_call_original
314
+ allow(@order).to receive_messages :coupon_code => "20off"
315
+ 3.times do |i|
316
+ taxable = create(:product, :tax_category => @category, :price => 10.0)
317
+ @order.contents.add(taxable.master, 2)
318
+ end
319
+ end
320
+ it "successfully applies the promo" do
321
+ # 3 * ((2 * 10) + 2.0)
322
+ expect(@order.total.to_f).to eq(66)
323
+ coupon = Coupon.new(@order)
324
+ coupon.apply
325
+ expect(coupon.success).to be_present
326
+ # 0
327
+ expect(@order.reload.total).to eq(0)
328
+ expect(@order.additional_tax_total).to eq(0)
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,47 @@
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
+ let!(:promotion_code) { create(:promotion_code, promotion: promotion) }
23
+
24
+ it "does adjust the shipment when applied to order" do
25
+ pending "broken by 2-2-dev merge"
26
+ order.order_promotions.create!(promotion: promotion, promotion_code: promotion_code)
27
+
28
+ expect { subject.activate }.to change { shipment.adjustments.count }
29
+ end
30
+
31
+ it "does not adjust the shipment when not applied to order" do
32
+ expect { subject.activate }.to_not change { shipment.adjustments.count }
33
+ end
34
+ end
35
+
36
+ context "if promo has a path" do
37
+ before do
38
+ promotion.update_column(:path, "path")
39
+ end
40
+
41
+ it "does not adjust the shipment" do
42
+ expect { subject.activate }.to_not change { shipment.adjustments.count }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end