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,45 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe ShippingCalculator, :type => :model do
5
+ let(:variant1) { build(:variant, :price => 10) }
6
+ let(:variant2) { build(:variant, :price => 20) }
7
+
8
+ let(:package) do
9
+ build(:stock_package, variants_contents: { variant1 => 2, variant2 => 1 })
10
+ end
11
+
12
+ subject { ShippingCalculator.new }
13
+
14
+ it 'computes with a shipment' do
15
+ shipment = mock_model(Spree::Shipment)
16
+ expect(subject).to receive(:compute_shipment).with(shipment)
17
+ subject.compute(shipment)
18
+ end
19
+
20
+ it 'computes with a package' do
21
+ expect(subject).to receive(:compute_package).with(package)
22
+ subject.compute(package)
23
+ end
24
+
25
+ it 'compute_shipment must be overridden' do
26
+ expect {
27
+ subject.compute_shipment(shipment)
28
+ }.to raise_error NameError
29
+ end
30
+
31
+ it 'compute_package must be overridden' do
32
+ expect {
33
+ subject.compute_package(package)
34
+ }.to raise_error NotImplementedError
35
+ end
36
+
37
+ it 'checks availability for a package' do
38
+ expect(subject.available?(package)).to be true
39
+ end
40
+
41
+ it 'calculates totals for content_items' do
42
+ expect(subject.send(:total, package.contents)).to eq 40.00
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyShippingCalculator < Spree::ShippingCalculator
4
+ end
5
+
6
+ describe Spree::ShippingMethod, :type => :model do
7
+ let(:shipping_method){ create(:shipping_method) }
8
+
9
+ context 'calculators' do
10
+ it "Should reject calculators that don't inherit from Spree::ShippingCalculator" do
11
+ allow(Spree::ShippingMethod).to receive_message_chain(:spree_calculators, :shipping_methods).and_return([
12
+ Spree::Calculator::Shipping::FlatPercentItemTotal,
13
+ Spree::Calculator::Shipping::PriceSack,
14
+ Spree::Calculator::DefaultTax,
15
+ DummyShippingCalculator # included as regression test for https://github.com/spree/spree/issues/3109
16
+ ])
17
+
18
+ expect(Spree::ShippingMethod.calculators).to eq([Spree::Calculator::Shipping::FlatPercentItemTotal, Spree::Calculator::Shipping::PriceSack, DummyShippingCalculator ])
19
+ expect(Spree::ShippingMethod.calculators).not_to eq([Spree::Calculator::DefaultTax])
20
+ end
21
+ end
22
+
23
+ # Regression test for #4492
24
+ context "#shipments" do
25
+ let!(:shipping_method) { create(:shipping_method) }
26
+ let!(:shipment) do
27
+ shipment = create(:shipment)
28
+ shipment.shipping_rates.create!(:shipping_method => shipping_method)
29
+ shipment
30
+ end
31
+
32
+ it "can gather all the related shipments" do
33
+ expect(shipping_method.shipments).to include(shipment)
34
+ end
35
+ end
36
+
37
+ context "validations" do
38
+ before { subject.valid? }
39
+
40
+ it "validates presence of name" do
41
+ expect(subject.error_on(:name).size).to eq(1)
42
+ end
43
+
44
+ context "shipping category" do
45
+ it "validates presence of at least one" do
46
+ expect(subject.error_on(:base).size).to eq(1)
47
+ end
48
+
49
+ context "one associated" do
50
+ before { subject.shipping_categories.push create(:shipping_category) }
51
+ it { expect(subject.error_on(:base).size).to eq(0) }
52
+ end
53
+ end
54
+ end
55
+
56
+ context 'factory' do
57
+ it "should set calculable correctly" do
58
+ expect(shipping_method.calculator.calculable).to eq(shipping_method)
59
+ end
60
+ end
61
+
62
+ context "generating tracking URLs" do
63
+ context "shipping method has a tracking URL mask on file" do
64
+ let(:tracking_url) { "https://track-o-matic.com/:tracking" }
65
+ before { allow(subject).to receive(:tracking_url) { tracking_url } }
66
+
67
+ context 'tracking number has spaces' do
68
+ let(:tracking_numbers) { ["1234 5678 9012 3456", "a bcdef"] }
69
+ let(:expectations) { %w[https://track-o-matic.com/1234%205678%209012%203456 https://track-o-matic.com/a%20bcdef] }
70
+
71
+ it "should return a single URL with '%20' in lieu of spaces" do
72
+ tracking_numbers.each_with_index do |num, i|
73
+ expect(subject.build_tracking_url(num)).to eq(expectations[i])
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # Regression test for #4320
81
+ context "soft deletion" do
82
+ let(:shipping_method) { create(:shipping_method) }
83
+ it "soft-deletes when destroy is called" do
84
+ shipping_method.destroy
85
+ expect(shipping_method.deleted_at).not_to be_blank
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::ShippingRate, :type => :model do
6
+ let(:shipment) { create(:shipment) }
7
+ let(:shipping_method) { create(:shipping_method) }
8
+ let(:shipping_rate) { Spree::ShippingRate.new(:shipment => shipment,
9
+ :shipping_method => shipping_method,
10
+ :cost => 10) }
11
+
12
+ context "#display_price" do
13
+ context "when tax included in price" do
14
+ context "when the tax rate is from the default zone" do
15
+ before { shipment.order.update_attributes!(ship_address_id: nil) }
16
+ let!(:zone) { create(:zone, :default_tax => true) }
17
+ let(:tax_rate) do
18
+ create(:tax_rate,
19
+ :name => "VAT",
20
+ :amount => 0.1,
21
+ :included_in_price => true,
22
+ :zone => zone)
23
+ end
24
+
25
+ before { shipping_rate.tax_rate = tax_rate }
26
+
27
+ it "shows correct tax amount" do
28
+ expect(shipping_rate.display_price.to_s).to eq("$10.00 (incl. $0.91 #{tax_rate.name})")
29
+ end
30
+
31
+ context "when cost is zero" do
32
+ before do
33
+ shipping_rate.cost = 0
34
+ end
35
+
36
+ it "shows no tax amount" do
37
+ expect(shipping_rate.display_price.to_s).to eq("$0.00")
38
+ end
39
+ end
40
+ end
41
+
42
+ context "when the tax rate is from a non-default zone" do
43
+ let!(:default_zone) { create(:zone, :default_tax => true) }
44
+ let!(:non_default_zone) { create(:zone, :default_tax => false) }
45
+ let(:tax_rate) do
46
+ create(:tax_rate,
47
+ :name => "VAT",
48
+ :amount => 0.1,
49
+ :included_in_price => true,
50
+ :zone => non_default_zone)
51
+ end
52
+ before { shipping_rate.tax_rate = tax_rate }
53
+
54
+ it "shows correct tax amount" do
55
+ expect(shipping_rate.display_price.to_s).to eq("$10.00 (excl. $0.91 #{tax_rate.name})")
56
+ end
57
+
58
+ context "when cost is zero" do
59
+ before do
60
+ shipping_rate.cost = 0
61
+ end
62
+
63
+ it "shows no tax amount" do
64
+ expect(shipping_rate.display_price.to_s).to eq("$0.00")
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ context "when tax is additional to price" do
71
+ let(:tax_rate) { create(:tax_rate, :name => "Sales Tax", :amount => 0.1) }
72
+ before { shipping_rate.tax_rate = tax_rate }
73
+
74
+ it "shows correct tax amount" do
75
+ expect(shipping_rate.display_price.to_s).to eq("$10.00 (+ $1.00 #{tax_rate.name})")
76
+ end
77
+
78
+ context "when cost is zero" do
79
+ before do
80
+ shipping_rate.cost = 0
81
+ end
82
+
83
+ it "shows no tax amount" do
84
+ expect(shipping_rate.display_price.to_s).to eq("$0.00")
85
+ end
86
+ end
87
+ end
88
+
89
+ context "when the currency is JPY" do
90
+ let(:shipping_rate) { shipping_rate = Spree::ShippingRate.new(:cost => 205)
91
+ allow(shipping_rate).to receive_messages(:currency => "JPY")
92
+ shipping_rate }
93
+
94
+ it "displays the price in yen" do
95
+ expect(shipping_rate.display_price.to_s).to eq("¥205")
96
+ end
97
+ end
98
+ end
99
+
100
+ # Regression test for #3829
101
+ context "#shipping_method" do
102
+ it "can be retrieved" do
103
+ expect(shipping_rate.shipping_method.reload).to eq(shipping_method)
104
+ end
105
+
106
+ it "can be retrieved even when deleted" do
107
+ shipping_method.update_column(:deleted_at, Time.now)
108
+ shipping_rate.save
109
+ shipping_rate.reload
110
+ expect(shipping_rate.shipping_method).to eq(shipping_method)
111
+ end
112
+ end
113
+
114
+ context "#tax_rate" do
115
+ let!(:tax_rate) { create(:tax_rate) }
116
+
117
+ before do
118
+ shipping_rate.tax_rate = tax_rate
119
+ end
120
+
121
+ it "can be retrieved" do
122
+ expect(shipping_rate.tax_rate.reload).to eq(tax_rate)
123
+ end
124
+
125
+ it "can be retrieved even when deleted" do
126
+ tax_rate.update_column(:deleted_at, Time.now)
127
+ shipping_rate.save
128
+ shipping_rate.reload
129
+ expect(shipping_rate.tax_rate).to eq(tax_rate)
130
+ end
131
+ end
132
+
133
+ context "#shipping_method_code" do
134
+ before do
135
+ shipping_method.code = "THE_CODE"
136
+ end
137
+
138
+ it 'should be shipping_method.code' do
139
+ expect(shipping_rate.shipping_method_code).to eq("THE_CODE")
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::State, :type => :model do
4
+ it "can find a state by name or abbr" do
5
+ state = create(:state, :name => "California", :abbr => "CA")
6
+ expect(Spree::State.find_all_by_name_or_abbr("California")).to include(state)
7
+ expect(Spree::State.find_all_by_name_or_abbr("CA")).to include(state)
8
+ end
9
+
10
+ it "can find all states group by country id" do
11
+ state = create(:state)
12
+ expect(Spree::State.states_group_by_country_id).to eq({ state.country_id.to_s => [[state.id, state.name]] })
13
+ end
14
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ module Stock
5
+ describe AvailabilityValidator do
6
+ let(:validator) { Spree::Stock::AvailabilityValidator.new }
7
+
8
+ subject { validator.validate(line_item) }
9
+
10
+ shared_examples_for "fails validation" do
11
+ it "returns false" do
12
+ expect(subject).to eq false
13
+ end
14
+
15
+ it "adds a validation error" do
16
+ subject
17
+ display_name = "#{line_item.variant.name}"
18
+ display_name += " (#{line_item.variant.options_text})" unless line_item.variant.options_text.blank?
19
+ expect(line_item.errors).to match_array ["Quantity selected of #{display_name.inspect} is not available."]
20
+ end
21
+ end
22
+
23
+ shared_examples_for "passes validation" do
24
+ it "returns true" do
25
+ expect(subject).to eq true
26
+ end
27
+
28
+ it "doesn't add a validation error" do
29
+ expect(line_item.errors).to be_empty
30
+ end
31
+ end
32
+
33
+ context "line_item is not part of a shipment" do
34
+ let(:line_item) { create(:line_item) }
35
+
36
+ context "has stock in all stock locations" do
37
+ before do
38
+ Spree::StockItem.where(variant_id: line_item.variant_id).update_all(count_on_hand: 10, backorderable: false)
39
+ end
40
+
41
+ include_examples "passes validation"
42
+ end
43
+
44
+ context "doesn't have stock in any stock location" do
45
+ before do
46
+ Spree::StockItem.where(variant_id: line_item.variant_id).update_all(count_on_hand: 0, backorderable: false)
47
+ end
48
+
49
+ include_examples "fails validation"
50
+ end
51
+ end
52
+
53
+ context "line_item is part of a shipment" do
54
+ let!(:order) { create(:order_with_line_items) }
55
+
56
+ context "has stock in all stock locations" do
57
+ let(:line_item) { order.line_items.first }
58
+
59
+ before do
60
+ variant_ids = order.line_items.map(&:variant_id)
61
+ Spree::StockItem.where(variant_id: variant_ids).update_all(count_on_hand: 10, backorderable: false)
62
+ end
63
+
64
+ include_examples "passes validation"
65
+ end
66
+
67
+ context "doesn't have stock in a particular stock location" do
68
+ let(:variant) { create(:variant) }
69
+ let(:line_item) { order.line_items.find_by(variant_id: variant.id) }
70
+ let!(:stock_location_1) { create(:stock_location, name: "Test Warehouse", active: false) }
71
+
72
+ before do
73
+ order.contents.add(variant, 1, stock_location_quantities: { stock_location_1.id => 1})
74
+ order.contents.advance
75
+ stock_location_1.stock_items.update_all(count_on_hand: 0, backorderable: false)
76
+ end
77
+
78
+ include_examples "fails validation"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ module Stock
5
+ describe Coordinator, :type => :model do
6
+ let!(:order) { create(:order_with_line_items, line_items_count: 2) }
7
+
8
+ subject { Coordinator.new(order) }
9
+
10
+ context "packages" do
11
+ it "builds, prioritizes and estimates" do
12
+ expect(subject).to receive(:build_location_configured_packages).ordered
13
+ expect(subject).to receive(:build_packages).ordered
14
+ expect(subject).to receive(:prioritize_packages).ordered
15
+ expect(subject).to receive(:estimate_packages).ordered
16
+ subject.packages
17
+ end
18
+ end
19
+
20
+ describe "#shipments" do
21
+ let(:packages) { [build(:stock_package_fulfilled), build(:stock_package_fulfilled)] }
22
+
23
+ before { allow(subject).to receive(:packages).and_return(packages) }
24
+
25
+ it "turns packages into shipments" do
26
+ shipments = subject.shipments
27
+ expect(shipments.count).to eq packages.count
28
+ shipments.each { |shipment| expect(shipment).to be_a Shipment }
29
+ end
30
+
31
+ it "puts the order's ship address on the shipments" do
32
+ shipments = subject.shipments
33
+ shipments.each { |shipment| expect(shipment.address).to eq order.ship_address }
34
+ end
35
+ end
36
+
37
+ context "build packages" do
38
+ it "builds a package for all active stock locations" do
39
+ subject.packages.count == StockLocation.count
40
+ end
41
+
42
+ context "missing stock items in active stock location" do
43
+ let!(:another_location) { create(:stock_location, propagate_all_variants: false) }
44
+
45
+ it "builds packages only for valid active stock locations" do
46
+ expect(subject.build_packages.count).to eq(StockLocation.count - 1)
47
+ end
48
+ end
49
+ end
50
+
51
+ # regression spec
52
+ context "when there is one unit that has stock in a stock location that a non-tracked unit has no stock item in" do
53
+ let!(:stock_location_1) { create(:stock_location, propagate_all_variants: false, active: true) }
54
+ let!(:stock_location_2) { create(:stock_location, propagate_all_variants: false, active: true) }
55
+
56
+ let!(:variant_1) do
57
+ create(:variant, track_inventory: true).tap do |variant|
58
+ variant.stock_items.destroy_all
59
+ stock_item = variant.stock_items.create!(stock_location: stock_location_1)
60
+ stock_item.set_count_on_hand(10)
61
+ end
62
+ end
63
+ let!(:variant_2) do
64
+ create(:variant, track_inventory: false).tap do |variant|
65
+ variant.stock_items.destroy_all
66
+ stock_item = variant.stock_items.create!(stock_location: stock_location_2)
67
+ stock_item.set_count_on_hand(0)
68
+ end
69
+ end
70
+
71
+ let!(:order) { create(:order, line_items: [create(:line_item, variant: variant_1), create(:line_item, variant: variant_2)]) }
72
+
73
+ it "splits the inventory units to stock locations that they have stock items for" do
74
+ packages = subject.packages
75
+
76
+ expect(subject.packages.size).to eq 2
77
+
78
+ location_1_package = packages.detect { |p| p.stock_location == stock_location_1 }
79
+ location_2_package = packages.detect { |p| p.stock_location == stock_location_2 }
80
+
81
+ expect(location_1_package).to be_present
82
+ expect(location_2_package).to be_present
83
+
84
+ expect(location_1_package.contents.map(&:inventory_unit).map(&:variant)).to eq [variant_1]
85
+ expect(location_2_package.contents.map(&:inventory_unit).map(&:variant)).to eq [variant_2]
86
+ end
87
+ end
88
+
89
+ context "build location configured packages" do
90
+ context "there are configured stock locations" do
91
+ let(:stock_location) { order.variants.first.stock_locations.first }
92
+ let!(:stock_location_2) { create(:stock_location) }
93
+
94
+ before do
95
+ line_item_1 = order.line_items.first
96
+ line_item_2 = order.line_items.last
97
+ order.order_stock_locations.create(stock_location_id: stock_location.id, quantity: line_item_1.quantity, variant_id: line_item_1.variant_id)
98
+ order.order_stock_locations.create(stock_location_id: stock_location_2.id, quantity: line_item_2.quantity, variant_id: line_item_2.variant_id)
99
+ end
100
+
101
+ it "builds a package for each associated stock location" do
102
+ packages = subject.build_location_configured_packages
103
+ expect(packages.count).to eq(2)
104
+ expect(packages.map(&:stock_location)).to eq([stock_location, stock_location_2])
105
+ end
106
+ end
107
+ context "there are no configured stock locations" do
108
+ it "doesn't build any packages" do
109
+ packages = subject.build_location_configured_packages
110
+ expect(packages.count).to eq(0)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end