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,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Promotion::Rules::UserLoggedIn, :type => :model do
4
+ let(:rule) { Spree::Promotion::Rules::UserLoggedIn.new }
5
+
6
+ context "#eligible?(order)" do
7
+ let(:order) { Spree::Order.new }
8
+
9
+ it "should be eligible if order has an associated user" do
10
+ user = double('User')
11
+ allow(order).to receive_messages(:user => user)
12
+
13
+ expect(rule).to be_eligible(order)
14
+ end
15
+
16
+ context "when user is not logged in" do
17
+ before { allow(order).to receive_messages(:user => nil) } # better to be explicit here
18
+ it { expect(rule).not_to be_eligible(order) }
19
+ it "sets an error message" do
20
+ rule.eligible?(order)
21
+ expect(rule.eligibility_errors.full_messages.first).
22
+ to eq "You need to login before applying this coupon code."
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Promotion::Rules::User, :type => :model do
4
+ let(:rule) { Spree::Promotion::Rules::User.new }
5
+
6
+ context "#eligible?(order)" do
7
+ let(:order) { Spree::Order.new }
8
+
9
+ it "should not be eligible if users are not provided" do
10
+ expect(rule).not_to be_eligible(order)
11
+ end
12
+
13
+ it "should be eligible if users include user placing the order" do
14
+ user = mock_model(Spree::LegacyUser)
15
+ users = [user, mock_model(Spree::LegacyUser)]
16
+ allow(rule).to receive_messages(:users => users)
17
+ allow(order).to receive_messages(:user => user)
18
+
19
+ expect(rule).to be_eligible(order)
20
+ end
21
+
22
+ it "should not be eligible if user placing the order is not listed" do
23
+ allow(order).to receive_messages(:user => mock_model(Spree::LegacyUser))
24
+ users = [mock_model(Spree::LegacyUser), mock_model(Spree::LegacyUser)]
25
+ allow(rule).to receive_messages(:users => users)
26
+
27
+ expect(rule).not_to be_eligible(order)
28
+ end
29
+
30
+ # Regression test for #3885
31
+ it "can assign to user_ids" do
32
+ user1 = Spree::LegacyUser.create!(:email => "test1@example.com")
33
+ user2 = Spree::LegacyUser.create!(:email => "test2@example.com")
34
+ expect { rule.user_ids = "#{user1.id}, #{user2.id}" }.not_to raise_error
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PromotionBuilder do
4
+ let(:promotion) { build(:promotion) }
5
+ let(:base_code) { 'abc' }
6
+ let(:number_of_codes) { 1 }
7
+ let(:promotion_attrs) { { name: 'some promo' } }
8
+ let(:builder) { Spree::PromotionBuilder.new(
9
+ {
10
+ base_code: base_code,
11
+ number_of_codes: number_of_codes
12
+ },
13
+ promotion_attrs,
14
+ ) }
15
+
16
+ describe '#initialize' do
17
+ subject { builder }
18
+ it 'has the right base code' do
19
+ expect(subject.base_code).to eq 'abc'
20
+ end
21
+
22
+ it 'has the right base code' do
23
+ expect(subject.number_of_codes).to eq 1
24
+ end
25
+ end
26
+
27
+ describe '#valid?' do
28
+ subject { builder.valid? }
29
+
30
+ it 'is true' do
31
+ expect(subject).to be
32
+ end
33
+
34
+ context 'promotion is not valid' do
35
+ let(:promotion_attrs) { { name: nil } }
36
+
37
+ it 'is true' do
38
+ expect(subject).to_not be
39
+ end
40
+
41
+ it 'has errors on the promotion' do
42
+ subject
43
+ expect(builder.errors).to_not be_empty
44
+ end
45
+ end
46
+
47
+ context 'number of codes is invalid' do
48
+ let(:number_of_codes) { -1 }
49
+
50
+ it 'is false ' do
51
+ expect(subject).to_not be
52
+ end
53
+
54
+ it 'validates numericality' do
55
+ subject
56
+ expect(builder.errors.full_messages).to eq ["Number of codes must be greater than 0"]
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#number_of_codes=' do
62
+ it 'coerces a string' do
63
+ builder.number_of_codes = '3'
64
+ expect(builder.number_of_codes).to eq 3
65
+ end
66
+
67
+ it 'is nil for empty string' do
68
+ builder.number_of_codes = ''
69
+ expect(builder.number_of_codes).to be_nil
70
+ end
71
+ end
72
+
73
+ describe "#perform" do
74
+ subject { builder.perform }
75
+
76
+ context 'when the builder is invalid' do
77
+ let(:number_of_codes) { 'sups' }
78
+
79
+ it 'returns false' do
80
+ expect(subject).to_not be
81
+ end
82
+ end
83
+
84
+ context "when the builder is valid" do
85
+ context "when the builder cant build promotion codes" do
86
+ let(:number_of_codes) { nil }
87
+
88
+ it "doesn't create any new codes" do
89
+ subject
90
+ expect(builder.promotion.codes).to be_empty
91
+ end
92
+ end
93
+
94
+ context "when the builder can build promotion codes" do
95
+ let(:number_of_codes) { 1 }
96
+
97
+ it "creates the correct number of codes" do
98
+ subject
99
+ expect(builder.promotion.codes.length).to eq number_of_codes
100
+ end
101
+
102
+ it "creates the promotion with the correct code" do
103
+ subject
104
+ expect(builder.promotion.codes.first.value).to eq base_code
105
+ end
106
+ end
107
+
108
+ it "saves the promotion" do
109
+ subject
110
+ expect(builder.promotion).to be_persisted
111
+ end
112
+
113
+ it "returns true on success" do
114
+ expect(subject).to be true
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PromotionCategory, :type => :model do
4
+ describe 'validation' do
5
+ let(:name) { 'Nom' }
6
+ subject { Spree::PromotionCategory.new name: name }
7
+
8
+ context 'when all required attributes are specified' do
9
+ it { is_expected.to be_valid }
10
+ end
11
+
12
+ context 'when name is missing' do
13
+ let(:name) { nil }
14
+ it { is_expected.not_to be_valid }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PromotionCode::CodeBuilder do
4
+ let(:promotion) { build_stubbed :promotion }
5
+ let(:base_code) { "abc" }
6
+ let(:builder) do
7
+ described_class.new promotion, base_code, num_codes
8
+ end
9
+
10
+ describe "#build_promotion_codes" do
11
+ subject { builder.build_promotion_codes }
12
+
13
+ context "with one code" do
14
+ let(:num_codes) { 1 }
15
+
16
+ it "builds a single promotion code" do
17
+ subject
18
+ expect(builder.promotion.codes.size).to eq(num_codes)
19
+ end
20
+
21
+ it "creates the promotion code with the correct value" do
22
+ subject
23
+ expect(builder.promotion.codes.first.value).to eq base_code
24
+ end
25
+ end
26
+
27
+ context "with more than one code" do
28
+ let(:num_codes) { 2 }
29
+
30
+ it "builds the correct number of codes" do
31
+ subject
32
+ expect(builder.promotion.codes.size).to eq(num_codes)
33
+ end
34
+
35
+ it "builds codes with distinct values" do
36
+ subject
37
+ expect(builder.promotion.codes.map(&:value).uniq.size).to eq(num_codes)
38
+ end
39
+
40
+ it "builds codes with the same base prefix" do
41
+ subject
42
+ values = builder.promotion.codes.map &:value
43
+ expect(values.all? { |val| val.starts_with?("#{base_code}_") }).to be true
44
+ end
45
+
46
+ context 'when every possible code must be used' do
47
+ before do
48
+ @old_length = described_class.random_code_length
49
+ described_class.random_code_length = 1
50
+ end
51
+ after { described_class.random_code_length = @old_length }
52
+
53
+ let(:num_codes) { 26 }
54
+
55
+ it "resolves the collision" do
56
+ subject
57
+ expect(builder.promotion.codes.map(&:value).uniq.size).to eq(num_codes)
58
+ end
59
+ end
60
+
61
+ context "when collisions occur" do
62
+ before do
63
+ @old_length = described_class.random_code_length
64
+ described_class.random_code_length = 1
65
+ end
66
+ after { described_class.random_code_length = @old_length }
67
+
68
+ let(:num_codes) { 25 } # every possible code except 1
69
+
70
+ it "resolves the collisions and returns the correct number of codes" do
71
+ subject
72
+ expect(builder.promotion.codes.map(&:value).uniq.size).to eq(num_codes)
73
+ end
74
+ end
75
+
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Spree::PromotionCode do
4
+ context 'callbacks' do
5
+ subject { promotion_code.save }
6
+
7
+ describe '#downcase_value' do
8
+ let(:promotion) { create(:promotion, code: 'NewCoDe') }
9
+ let(:promotion_code) { promotion.codes.first }
10
+
11
+ it 'downcases the value before saving' do
12
+ subject
13
+ expect(promotion_code.value).to eq('newcode')
14
+ end
15
+ end
16
+ end
17
+
18
+ describe "#usage_limit_exceeded?" do
19
+ subject { code.usage_limit_exceeded? }
20
+
21
+ shared_examples "it should" do
22
+ context "when there is a usage limit" do
23
+ context "and the limit is not exceeded" do
24
+ let(:usage_limit) { 10 }
25
+ it { is_expected.to be_falsy }
26
+ end
27
+ context "and the limit is exceeded" do
28
+ let(:usage_limit) { 1 }
29
+ context "on a different order" do
30
+ before do
31
+ FactoryGirl.create(
32
+ :completed_order_with_promotion,
33
+ promotion: promotion
34
+ )
35
+ code.adjustments.update_all(eligible: true)
36
+ end
37
+ it { is_expected.to be_truthy }
38
+ end
39
+ context "on the same order" do
40
+ it { is_expected.to be_falsy }
41
+ end
42
+ end
43
+ end
44
+ context "when there is no usage limit" do
45
+ let(:usage_limit) { nil }
46
+ it { is_expected.to be_falsy }
47
+ end
48
+ end
49
+
50
+ let(:code) { promotion.codes.first }
51
+
52
+ context "with an order-level adjustment" do
53
+ let(:promotion) do
54
+ FactoryGirl.create(
55
+ :promotion,
56
+ :with_order_adjustment,
57
+ code: "discount",
58
+ per_code_usage_limit: usage_limit
59
+ )
60
+ end
61
+ let(:promotable) do
62
+ FactoryGirl.create(
63
+ :completed_order_with_promotion,
64
+ promotion: promotion
65
+ )
66
+ end
67
+ it_behaves_like "it should"
68
+ end
69
+
70
+ context "with an item-level adjustment" do
71
+ let(:promotion) do
72
+ FactoryGirl.create(
73
+ :promotion,
74
+ :with_line_item_adjustment,
75
+ code: "discount",
76
+ per_code_usage_limit: usage_limit
77
+ )
78
+ end
79
+ before do
80
+ promotion.actions.first.perform({
81
+ order: order,
82
+ promotion: promotion,
83
+ promotion_code: code
84
+ })
85
+ end
86
+ context "when there are multiple line items" do
87
+ let(:order) { FactoryGirl.create(:order_with_line_items, line_items_count: 2) }
88
+ describe "the first item" do
89
+ let(:promotable) { order.line_items.first }
90
+ it_behaves_like "it should"
91
+ end
92
+ describe "the second item" do
93
+ let(:promotable) { order.line_items.last }
94
+ it_behaves_like "it should"
95
+ end
96
+ end
97
+ context "when there is a single line item" do
98
+ let(:order) { FactoryGirl.create(:order_with_line_items) }
99
+ let(:promotable) { order.line_items.first }
100
+ it_behaves_like "it should"
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "#usage_count" do
106
+ let(:promotion) do
107
+ FactoryGirl.create(
108
+ :promotion,
109
+ :with_order_adjustment,
110
+ code: "discount"
111
+ )
112
+ end
113
+ let(:code) { promotion.codes.first }
114
+
115
+ subject { code.usage_count }
116
+
117
+ context "when the code is applied to a non-complete order" do
118
+ let(:order) { FactoryGirl.create(:order_with_line_items) }
119
+ before { promotion.activate(order: order, promotion_code: code) }
120
+ it { is_expected.to eq 0 }
121
+ end
122
+ context "when the code is applied to a complete order" do
123
+ let!(:order) do
124
+ FactoryGirl.create(
125
+ :completed_order_with_promotion,
126
+ promotion: promotion
127
+ )
128
+ end
129
+ context "and the promo is eligible" do
130
+ it { is_expected.to eq 1 }
131
+ end
132
+ context "and the promo is ineligible" do
133
+ before { order.adjustments.promotion.update_all(eligible: false) }
134
+ it { is_expected.to eq 0 }
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "completing multiple orders with the same code", slow: true do
140
+ let(:promotion) do
141
+ FactoryGirl.create(
142
+ :promotion,
143
+ :with_order_adjustment,
144
+ code: "discount",
145
+ per_code_usage_limit: 1
146
+ )
147
+ end
148
+ let(:code) { promotion.codes.first }
149
+ let(:order) do
150
+ FactoryGirl.create(:order_with_line_items).tap do |order|
151
+ FactoryGirl.create(:payment, amount: order.total, order: order)
152
+ promotion.activate(order: order, promotion_code: code)
153
+ end
154
+ end
155
+ let(:promo_adjustment) { order.adjustments.promotion.first }
156
+ before do
157
+ order.next! until order.confirm?
158
+
159
+ FactoryGirl.create(:order_with_line_items).tap do |order|
160
+ FactoryGirl.create(:payment, amount: order.total, order: order)
161
+ promotion.activate(order: order, promotion_code: code)
162
+ order.next! until order.confirm?
163
+ order.complete!
164
+ end
165
+ end
166
+ it "makes the promotion ineligible" do
167
+ expect{
168
+ order.complete
169
+ }.to change{ promo_adjustment.reload.eligible }.to(false)
170
+ end
171
+ it "adjusts the promo_total" do
172
+ expect{
173
+ order.complete
174
+ }.to change(order, :promo_total).by(10)
175
+ end
176
+ it "adjusts the total" do
177
+ expect{
178
+ order.complete
179
+ }.to change(order, :total).by(10)
180
+ end
181
+ it "resets the state of the order" do
182
+ expect{
183
+ order.complete
184
+ }.to change{ order.reload.state }.from("confirm").to("address")
185
+ end
186
+ end
187
+ end