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,20 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ module Calculator::Shipping
5
+ describe PerItem, :type => :model do
6
+ let(:variant1) { build(:variant) }
7
+ let(:variant2) { build(:variant) }
8
+
9
+ let(:package) do
10
+ build(:stock_package, variants_contents: { variant1 => 5, variant2 => 3 })
11
+ end
12
+
13
+ subject { PerItem.new(:preferred_amount => 10) }
14
+
15
+ it "correctly calculates per item shipping" do
16
+ expect(subject.compute(package).to_f).to eq(80) # 5 x 10 + 3 x 10
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Calculator::PriceSack, :type => :model do
4
+ let(:calculator) do
5
+ calculator = Spree::Calculator::PriceSack.new
6
+ calculator.preferred_minimal_amount = 5
7
+ calculator.preferred_normal_amount = 10
8
+ calculator.preferred_discount_amount = 1
9
+ calculator
10
+ end
11
+
12
+ let(:order) { stub_model(Spree::Order) }
13
+ let(:shipment) { stub_model(Spree::Shipment, :amount => 10) }
14
+
15
+ # Regression test for #714 and #739
16
+ it "computes with an order object" do
17
+ calculator.compute(order)
18
+ end
19
+
20
+ # Regression test for #1156
21
+ it "computes with a shipment object" do
22
+ calculator.compute(shipment)
23
+ end
24
+
25
+ # Regression test for #2055
26
+ it "computes the correct amount" do
27
+ expect(calculator.compute(2)).to eq(calculator.preferred_normal_amount)
28
+ expect(calculator.compute(6)).to eq(calculator.preferred_discount_amount)
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Calculator::TieredFlatRate, :type => :model do
4
+ let(:calculator) { Spree::Calculator::TieredFlatRate.new }
5
+
6
+ describe "#valid?" do
7
+ subject { calculator.valid? }
8
+ context "when tiers is a hash" do
9
+ context "and one of the keys is not a positive number" do
10
+ before { calculator.preferred_tiers = { "nope" => 20 } }
11
+ it { is_expected.to be false }
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "#compute" do
17
+ let(:line_item) { mock_model Spree::LineItem, amount: amount }
18
+ before do
19
+ calculator.preferred_base_amount = 10
20
+ calculator.preferred_tiers = {
21
+ 100 => 15,
22
+ 200 => 20
23
+ }
24
+ end
25
+ subject { calculator.compute(line_item) }
26
+ context "when amount falls within the first tier" do
27
+ let(:amount) { 50 }
28
+ it { is_expected.to eq 10 }
29
+ end
30
+ context "when amount falls within the second tier" do
31
+ let(:amount) { 150 }
32
+ it { is_expected.to eq 15 }
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Calculator::TieredPercent, :type => :model do
4
+ let(:calculator) { Spree::Calculator::TieredPercent.new }
5
+
6
+ describe "#valid?" do
7
+ subject { calculator.valid? }
8
+ context "when base percent is less than zero" do
9
+ before { calculator.preferred_base_percent = -1 }
10
+ it { is_expected.to be false }
11
+ end
12
+ context "when base percent is greater than 100" do
13
+ before { calculator.preferred_base_percent = 110 }
14
+ it { is_expected.to be false }
15
+ end
16
+ context "when tiers is a hash" do
17
+ context "and one of the keys is not a positive number" do
18
+ before { calculator.preferred_tiers = { "nope" => 20 } }
19
+ it { is_expected.to be false }
20
+ end
21
+ context "and one of the values is not a percent" do
22
+ before { calculator.preferred_tiers = { 10 => 110 } }
23
+ it { is_expected.to be false }
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "#compute" do
29
+ let(:line_item) { mock_model Spree::LineItem, amount: amount }
30
+ before do
31
+ calculator.preferred_base_percent = 10
32
+ calculator.preferred_tiers = {
33
+ 100 => 15,
34
+ 200 => 20
35
+ }
36
+ end
37
+ subject { calculator.compute(line_item) }
38
+ context "when amount falls within the first tier" do
39
+ let(:amount) { 50 }
40
+ it { is_expected.to eq 5 }
41
+ end
42
+ context "when amount falls within the second tier" do
43
+ let(:amount) { 150 }
44
+ it { is_expected.to eq 22 }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe Spree::Calculator, :type => :model do
5
+
6
+ class SimpleCalculator < Spree::Calculator
7
+ def compute_simple_computable line_item
8
+ 'computed'
9
+ end
10
+ end
11
+
12
+ class SimpleComputable
13
+ end
14
+
15
+
16
+ context "with computable" do
17
+
18
+ let(:calculator) { SimpleCalculator.new }
19
+ let(:computable) { SimpleComputable.new }
20
+
21
+ subject { SimpleCalculator.new.compute computable }
22
+
23
+ it 'calls compute method of class type' do
24
+ expect(subject).to eq ( 'computed' )
25
+ end
26
+
27
+ context 'computable does not implement right function name' do
28
+ let(:computable) { Spree::LineItem.new }
29
+
30
+ it 'raises an error' do
31
+ expect { subject }.to raise_error NotImplementedError, /Please implement \'compute_line_item\(line_item\)\' in your calculator/
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Carton do
4
+ let(:carton) { create(:carton) }
5
+
6
+ describe "#create" do
7
+ subject { carton }
8
+
9
+ it { expect { subject }.to_not raise_error }
10
+ end
11
+
12
+ describe "#tracking_url" do
13
+ subject do
14
+ carton.tracking_url
15
+ end
16
+
17
+ let(:carton) { create(:carton, shipping_method: shipping_method) }
18
+ let(:shipping_method) do
19
+ create(:shipping_method, tracking_url: "https://example.com/:tracking")
20
+ end
21
+
22
+ context "when tracking is not present" do
23
+ it { is_expected.to be_nil }
24
+ end
25
+
26
+ context "when tracking is present" do
27
+ let(:carton) do
28
+ create(:carton, shipping_method: shipping_method, tracking: "1Z12345")
29
+ end
30
+
31
+ it "uses shipping method to determine url" do
32
+ is_expected.to eq("https://example.com/1Z12345")
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "#to_param" do
38
+ subject do
39
+ carton.to_param
40
+ end
41
+
42
+ it { is_expected.to eq carton.number }
43
+ end
44
+
45
+ describe "#order_numbers" do
46
+ subject { carton.order_numbers }
47
+ let(:order) { carton.orders.first }
48
+
49
+ it "returns a list of the order numbers it is associated to" do
50
+ expect(subject).to eq [order.number]
51
+ end
52
+ end
53
+
54
+ describe "#shipment_numbers" do
55
+ subject { carton.shipment_numbers }
56
+ let(:shipment) { carton.shipments.first }
57
+
58
+ it "returns a list of the order numbers it is associated to" do
59
+ expect(subject).to eq [shipment.number]
60
+ end
61
+ end
62
+
63
+ describe "#order_emails" do
64
+ subject { carton.order_emails }
65
+
66
+ let(:carton) { create(:carton, inventory_units: [first_order.inventory_units, second_order.inventory_units].flatten) }
67
+ let(:first_order) { create(:order_ready_to_ship, line_items_count: 1) }
68
+ let(:second_order) { create(:order_ready_to_ship, line_items_count: 1) }
69
+ let(:email) { 'something@something.com' }
70
+
71
+ before do
72
+ first_order.update_attributes!(email: email)
73
+ second_order.update_attributes!(email: email)
74
+ end
75
+
76
+ it "returns a unique list of the order emails it is associated to" do
77
+ expect(subject).to eq [email]
78
+ end
79
+ end
80
+
81
+ describe "#manifest" do
82
+ subject { carton.manifest }
83
+
84
+ let(:carton) { create(:carton, inventory_units: [first_order.inventory_units, second_order.inventory_units].flatten) }
85
+ let(:first_order) { create(:order_ready_to_ship, line_items_count: 1) }
86
+ let(:first_line_item) { first_order.line_items.first }
87
+ let(:second_order) { create(:order_ready_to_ship, line_items_count: 1) }
88
+ let(:second_line_item) { second_order.line_items.first }
89
+
90
+ it "contains only the items in both the carton and order" do
91
+ expect(subject.map(&:line_item)).to match_array([first_line_item, second_line_item])
92
+ end
93
+ end
94
+
95
+ describe "#manifest_for_order" do
96
+ subject { carton.manifest_for_order(first_order) }
97
+
98
+ let(:carton) { create(:carton, inventory_units: [first_order.inventory_units, second_order.inventory_units].flatten) }
99
+ let(:first_order) { create(:order_ready_to_ship, line_items_count: 1) }
100
+ let(:first_line_item) { first_order.line_items.first }
101
+ let(:second_order) { create(:order_ready_to_ship, line_items_count: 1) }
102
+
103
+ it "contains only the items in both the carton and order" do
104
+ expect(subject.map(&:line_item)).to eq [first_line_item]
105
+ end
106
+ end
107
+
108
+ describe "#any_exchanges?" do
109
+ subject { carton.any_exchanges? }
110
+
111
+ let(:carton) { create(:carton, inventory_units: [first_order.inventory_units, second_order.inventory_units].flatten) }
112
+ let(:first_order) { create(:order_ready_to_ship, line_items_count: 1) }
113
+ let(:second_order) { create(:order_ready_to_ship, line_items_count: 1) }
114
+
115
+ context "when any of the inventory has an original return item" do
116
+ let(:return_item) { create(:return_item) }
117
+ before do
118
+ first_order.inventory_units.first.original_return_item = return_item
119
+ first_order.save
120
+ end
121
+
122
+ it "is true" do
123
+ expect(subject).to be_truthy
124
+ end
125
+ end
126
+
127
+ context "when none of the inventory has an original return item" do
128
+ it "is false" do
129
+ expect(subject).to be_falsey
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Classification, :type => :model do
5
+ # Regression test for #3494
6
+ it "cannot link the same taxon to the same product more than once" do
7
+ product = create(:product)
8
+ taxon = create(:taxon)
9
+ add_taxon = lambda { product.taxons << taxon }
10
+ expect(add_taxon).not_to raise_error
11
+ expect(add_taxon).to raise_error(ActiveRecord::RecordInvalid)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+
5
+ describe DisplayMoney do
6
+ let(:test_class) do
7
+ Class.new do
8
+ extend DisplayMoney
9
+ def total; 10.0; end
10
+ end
11
+ end
12
+
13
+ describe ".money_methods" do
14
+ before { test_class.money_methods :total }
15
+
16
+ context "currency is not defined" do
17
+ it "generates a display_method that builds a Spree::Money without options" do
18
+ expect(test_class.new.display_total).to eq Spree::Money.new(10.0)
19
+ end
20
+ end
21
+
22
+ context "currency is defined" do
23
+ before { test_class.class_eval { def currency; "USD"; end } }
24
+
25
+ it "generates a display_* method that builds a Spree::Money with currency" do
26
+ expect(test_class.new.display_total).to eq Spree::Money.new(10.0, currency: "USD")
27
+ end
28
+ end
29
+
30
+ context "with multiple + options" do
31
+ before do
32
+ test_class.class_eval { def amount; 20.0; end }
33
+ test_class.money_methods :total, amount: { no_cents: true }
34
+ end
35
+
36
+ it "generates a display_* method that builds a Spree::Money with the specified options" do
37
+ expect(test_class.new.display_total).to eq Spree::Money.new(10.0)
38
+ expect(test_class.new.display_amount).to eq Spree::Money.new(20.0, no_cents: true)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::UserMethods do
4
+ let(:test_user) { create :user }
5
+
6
+ describe '#has_spree_role?' do
7
+ subject { test_user.has_spree_role? name }
8
+
9
+ let(:role) { Spree::Role.create(name: name) }
10
+ let(:name) { 'test' }
11
+
12
+ context 'with a role' do
13
+ before { test_user.spree_roles << role }
14
+ it { is_expected.to be_truthy }
15
+ end
16
+
17
+ context 'without a role' do
18
+ it { is_expected.to be_falsy }
19
+ end
20
+ end
21
+
22
+ describe '#last_incomplete_spree_order' do
23
+ subject { test_user.last_incomplete_spree_order }
24
+
25
+ context 'with an incomplete order' do
26
+ let(:last_incomplete_order) { create :order, user: test_user }
27
+
28
+ before do
29
+ create(:order, user: test_user, created_at: 1.day.ago)
30
+ create(:order, user: create(:user))
31
+ last_incomplete_order
32
+ end
33
+
34
+ it { is_expected.to eq last_incomplete_order }
35
+ end
36
+
37
+ context 'without an incomplete order' do
38
+ it { is_expected.to be_nil }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,334 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::CreditCard, type: :model do
4
+ let(:valid_credit_card_attributes) do
5
+ {
6
+ number: '4111111111111111',
7
+ verification_value: '123',
8
+ expiry: "12 / #{(Time.now.year + 1).to_s.last(2)}",
9
+ name: 'Spree Commerce'
10
+ }
11
+ end
12
+
13
+ def self.payment_states
14
+ Spree::Payment.state_machine.states.keys
15
+ end
16
+
17
+ def stub_rails_env(environment)
18
+ allow(Rails).to receive_messages(env: ActiveSupport::StringInquirer.new(environment))
19
+ end
20
+
21
+ let(:credit_card) { Spree::CreditCard.new }
22
+
23
+ before(:each) do
24
+
25
+ @order = create(:order)
26
+ @payment = Spree::Payment.create(:amount => 100, :order => @order)
27
+
28
+ @success_response = double('gateway_response', success?: true, authorization: '123', avs_result: { 'code' => 'avs-code' })
29
+ @fail_response = double('gateway_response', success?: false)
30
+
31
+ @payment_gateway = mock_model(Spree::PaymentMethod,
32
+ payment_profiles_supported?: true,
33
+ authorize: @success_response,
34
+ purchase: @success_response,
35
+ capture: @success_response,
36
+ void: @success_response,
37
+ credit: @success_response,
38
+ environment: 'test'
39
+ )
40
+
41
+ allow(@payment).to receive_messages payment_method: @payment_gateway
42
+ end
43
+
44
+ context "#can_capture?" do
45
+ it "should be true if payment is pending" do
46
+ payment = mock_model(Spree::Payment, pending?: true, created_at: Time.now)
47
+ expect(credit_card.can_capture?(payment)).to be true
48
+ end
49
+
50
+ it "should be true if payment is checkout" do
51
+ payment = mock_model(Spree::Payment, pending?: false, checkout?: true, created_at: Time.now)
52
+ expect(credit_card.can_capture?(payment)).to be true
53
+ end
54
+ end
55
+
56
+ context "#can_void?" do
57
+ it "should be true if payment is not void" do
58
+ payment = mock_model(Spree::Payment, failed?: false, void?: false)
59
+ expect(credit_card.can_void?(payment)).to be true
60
+ end
61
+ end
62
+
63
+ context "#can_credit?" do
64
+ it "should be false if payment is not completed" do
65
+ payment = mock_model(Spree::Payment, completed?: false)
66
+ expect(credit_card.can_credit?(payment)).to be false
67
+ end
68
+
69
+ it "should be false when credit_allowed is zero" do
70
+ payment = mock_model(Spree::Payment, completed?: true, credit_allowed: 0, order: mock_model(Spree::Order, payment_state: 'credit_owed'))
71
+ expect(credit_card.can_credit?(payment)).to be false
72
+ end
73
+ end
74
+
75
+ context "#valid?" do
76
+ it "should validate presence of number" do
77
+ credit_card.attributes = valid_credit_card_attributes.except(:number)
78
+ expect(credit_card).not_to be_valid
79
+ expect(credit_card.errors[:number]).to eq(["can't be blank"])
80
+ end
81
+
82
+ it "should validate presence of security code" do
83
+ credit_card.attributes = valid_credit_card_attributes.except(:verification_value)
84
+ expect(credit_card).not_to be_valid
85
+ expect(credit_card.errors[:verification_value]).to eq(["can't be blank"])
86
+ end
87
+
88
+ it "validates name presence" do
89
+ credit_card.valid?
90
+ expect(credit_card.error_on(:name).size).to eq(1)
91
+ end
92
+
93
+ it "should only validate on create" do
94
+ credit_card.attributes = valid_credit_card_attributes
95
+ credit_card.save
96
+ expect(credit_card).to be_valid
97
+ end
98
+
99
+ context "encrypted data is present" do
100
+ it "does not validate presence of number or cvv" do
101
+ credit_card.encrypted_data = "$fdgsfgdgfgfdg&gfdgfdgsf-"
102
+ credit_card.valid?
103
+ expect(credit_card.errors[:number]).to be_empty
104
+ expect(credit_card.errors[:verification_value]).to be_empty
105
+ end
106
+ end
107
+
108
+ context "imported is true" do
109
+ it "does not validate presence of number or cvv" do
110
+ credit_card.imported = true
111
+ credit_card.valid?
112
+ expect(credit_card.errors[:number]).to be_empty
113
+ expect(credit_card.errors[:verification_value]).to be_empty
114
+ end
115
+ end
116
+ end
117
+
118
+ context "#save" do
119
+ before do
120
+ credit_card.attributes = valid_credit_card_attributes
121
+ credit_card.save!
122
+ end
123
+
124
+ let!(:persisted_card) { Spree::CreditCard.find(credit_card.id) }
125
+
126
+ it "should not actually store the number" do
127
+ expect(persisted_card.number).to be_blank
128
+ end
129
+
130
+ it "should not actually store the security code" do
131
+ expect(persisted_card.verification_value).to be_blank
132
+ end
133
+ end
134
+
135
+ context "#number=" do
136
+ it "should strip non-numeric characters from card input" do
137
+ credit_card.number = "6011000990139424"
138
+ expect(credit_card.number).to eq("6011000990139424")
139
+
140
+ credit_card.number = " 6011-0009-9013-9424 "
141
+ expect(credit_card.number).to eq("6011000990139424")
142
+ end
143
+
144
+ it "should not raise an exception on non-string input" do
145
+ credit_card.number = Hash.new
146
+ expect(credit_card.number).to be_nil
147
+ end
148
+ end
149
+
150
+ # Regression test for #3847 & #3896
151
+ context "#expiry=" do
152
+ it "can set with a 2-digit month and year" do
153
+ credit_card.expiry = '04 / 15'
154
+ expect(credit_card.month).to eq('4')
155
+ expect(credit_card.year).to eq('2015')
156
+ end
157
+
158
+ it "can set with a 2-digit month and 4-digit year" do
159
+ credit_card.expiry = '04 / 2015'
160
+ expect(credit_card.month).to eq('4')
161
+ expect(credit_card.year).to eq('2015')
162
+ end
163
+
164
+ it "can set with a 2-digit month and 4-digit year without whitespace" do
165
+ credit_card.expiry = '04/15'
166
+ expect(credit_card.month).to eq('4')
167
+ expect(credit_card.year).to eq('2015')
168
+ end
169
+
170
+ it "can set with a 2-digit month and 4-digit year without whitespace" do
171
+ credit_card.expiry = '04/2015'
172
+ expect(credit_card.month).to eq('4')
173
+ expect(credit_card.year).to eq('2015')
174
+ end
175
+
176
+ it "can set with a 2-digit month and 4-digit year without whitespace and slash" do
177
+ credit_card.expiry = '042015'
178
+ expect(credit_card.month).to eq('4')
179
+ expect(credit_card.year).to eq('2015')
180
+ end
181
+
182
+ it "can set with a 2-digit month and 2-digit year without whitespace and slash" do
183
+ credit_card.expiry = '0415'
184
+ expect(credit_card.month).to eq('4')
185
+ expect(credit_card.year).to eq('2015')
186
+ end
187
+
188
+ it "does not blow up when passed an empty string" do
189
+ expect { credit_card.expiry = '' }.not_to raise_error
190
+ end
191
+
192
+ # Regression test for #4725
193
+ it "does not blow up when passed one number" do
194
+ expect { credit_card.expiry = '12' }.not_to raise_error
195
+ end
196
+
197
+ end
198
+
199
+ context "#cc_type=" do
200
+ it "converts between the different types" do
201
+ credit_card.cc_type = 'mastercard'
202
+ expect(credit_card.cc_type).to eq('master')
203
+
204
+ credit_card.cc_type = 'maestro'
205
+ expect(credit_card.cc_type).to eq('master')
206
+
207
+ credit_card.cc_type = 'amex'
208
+ expect(credit_card.cc_type).to eq('american_express')
209
+
210
+ credit_card.cc_type = 'dinersclub'
211
+ expect(credit_card.cc_type).to eq('diners_club')
212
+
213
+ credit_card.cc_type = 'some_outlandish_cc_type'
214
+ expect(credit_card.cc_type).to eq('some_outlandish_cc_type')
215
+ end
216
+
217
+ it "assigns the type based on card number in the event of js failure" do
218
+ credit_card.number = '4242424242424242'
219
+ credit_card.cc_type = ''
220
+ expect(credit_card.cc_type).to eq('visa')
221
+
222
+ credit_card.number = '5555555555554444'
223
+ credit_card.cc_type = ''
224
+ expect(credit_card.cc_type).to eq('master')
225
+
226
+ credit_card.number = '378282246310005'
227
+ credit_card.cc_type = ''
228
+ expect(credit_card.cc_type).to eq('american_express')
229
+
230
+ credit_card.number = '30569309025904'
231
+ credit_card.cc_type = ''
232
+ expect(credit_card.cc_type).to eq('diners_club')
233
+
234
+ credit_card.number = '3530111333300000'
235
+ credit_card.cc_type = ''
236
+ expect(credit_card.cc_type).to eq('jcb')
237
+
238
+ credit_card.number = ''
239
+ credit_card.cc_type = ''
240
+ expect(credit_card.cc_type).to eq('')
241
+
242
+ credit_card.number = nil
243
+ credit_card.cc_type = ''
244
+ expect(credit_card.cc_type).to eq('')
245
+ end
246
+ end
247
+
248
+ context "#associations" do
249
+ it "should be able to access its payments" do
250
+ expect { credit_card.payments.to_a }.not_to raise_error
251
+ end
252
+ end
253
+
254
+ context "#first_name" do
255
+ before do
256
+ credit_card.name = "Ludwig van Beethoven"
257
+ end
258
+
259
+ it "extracts the first name" do
260
+ expect(credit_card.first_name).to eq "Ludwig"
261
+ end
262
+ end
263
+
264
+ context "#last_name" do
265
+ before do
266
+ credit_card.name = "Ludwig van Beethoven"
267
+ end
268
+
269
+ it "extracts the last name" do
270
+ expect(credit_card.last_name).to eq "van Beethoven"
271
+ end
272
+ end
273
+
274
+ context "#to_active_merchant" do
275
+ before do
276
+ credit_card.number = "4111111111111111"
277
+ credit_card.year = Time.now.year
278
+ credit_card.month = Time.now.month
279
+ credit_card.name = "Ludwig van Beethoven"
280
+ credit_card.verification_value = 123
281
+ end
282
+
283
+ it "converts to an ActiveMerchant::Billing::CreditCard object" do
284
+ am_card = credit_card.to_active_merchant
285
+ expect(am_card.number).to eq("4111111111111111")
286
+ expect(am_card.year).to eq(Time.now.year)
287
+ expect(am_card.month).to eq(Time.now.month)
288
+ expect(am_card.first_name).to eq("Ludwig")
289
+ expect(am_card.last_name).to eq("van Beethoven")
290
+ expect(am_card.verification_value).to eq(123)
291
+ end
292
+ end
293
+
294
+ it 'ensures only one credit card per user is default at a time' do
295
+ user = FactoryGirl.create(:user)
296
+ first = FactoryGirl.create(:credit_card, user: user, default: true)
297
+ second = FactoryGirl.create(:credit_card, user: user, default: true)
298
+
299
+ expect(first.reload.default).to eq false
300
+ expect(second.reload.default).to eq true
301
+
302
+ first.default = true
303
+ first.save!
304
+
305
+ expect(first.reload.default).to eq true
306
+ expect(second.reload.default).to eq false
307
+ end
308
+
309
+ it 'allows default credit cards for different users' do
310
+ first = FactoryGirl.create(:credit_card, user: FactoryGirl.create(:user), default: true)
311
+ second = FactoryGirl.create(:credit_card, user: FactoryGirl.create(:user), default: true)
312
+
313
+ expect(first.reload.default).to eq true
314
+ expect(second.reload.default).to eq true
315
+ end
316
+
317
+ it 'allows this card to save even if the previously default card has expired' do
318
+ user = FactoryGirl.create(:user)
319
+ first = FactoryGirl.create(:credit_card, user: user, default: true)
320
+ second = FactoryGirl.create(:credit_card, user: user, default: false)
321
+ first.update_columns(year: DateTime.now.year, month: 1.month.ago.month)
322
+
323
+ expect { second.update_attributes!(default: true) }.not_to raise_error
324
+ end
325
+
326
+ it 'allows this card to save even if the previously default card has expired' do
327
+ user = FactoryGirl.create(:user)
328
+ first = FactoryGirl.create(:credit_card, user: user, default: true)
329
+ second = FactoryGirl.create(:credit_card, user: user, default: false)
330
+ first.update_columns(year: DateTime.now.year, month: 1.month.ago.month)
331
+
332
+ expect { second.update_attributes!(default: true) }.not_to raise_error
333
+ end
334
+ end