solidus_core 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_core might be problematic. Click here for more details.

Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Rakefile +16 -0
  4. data/script/rails +9 -0
  5. data/solidus_core.gemspec +48 -0
  6. data/spec/fixtures/thinking-cat.jpg +0 -0
  7. data/spec/helpers/base_helper_spec.rb +173 -0
  8. data/spec/helpers/order_helper_spec.rb +12 -0
  9. data/spec/helpers/products_helper_spec.rb +208 -0
  10. data/spec/helpers/taxons_helper_spec.rb +17 -0
  11. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  12. data/spec/lib/i18n_spec.rb +106 -0
  13. data/spec/lib/search/base_spec.rb +86 -0
  14. data/spec/lib/search/variant_spec.rb +112 -0
  15. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
  16. data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -0
  17. data/spec/lib/spree/core/controller_helpers/payment_parameters_spec.rb +80 -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 +24 -0
  23. data/spec/lib/spree/core/importer/order_spec.rb +431 -0
  24. data/spec/lib/spree/core/role_configuration_spec.rb +156 -0
  25. data/spec/lib/spree/core/unreturned_item_charger_spec.rb +130 -0
  26. data/spec/lib/spree/core/validators/email_spec.rb +48 -0
  27. data/spec/lib/spree/localized_number_spec.rb +38 -0
  28. data/spec/lib/spree/migrations_spec.rb +36 -0
  29. data/spec/lib/spree/money_spec.rb +127 -0
  30. data/spec/lib/tasks/exchanges_spec.rb +231 -0
  31. data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
  32. data/spec/lib/tasks/order_capturing_spec.rb +56 -0
  33. data/spec/mailers/carton_mailer_spec.rb +55 -0
  34. data/spec/mailers/order_mailer_spec.rb +135 -0
  35. data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
  36. data/spec/mailers/test_mailer_spec.rb +15 -0
  37. data/spec/models/spree/ability_spec.rb +276 -0
  38. data/spec/models/spree/address_spec.rb +376 -0
  39. data/spec/models/spree/adjustment_reason_spec.rb +13 -0
  40. data/spec/models/spree/adjustment_spec.rb +169 -0
  41. data/spec/models/spree/app_configuration_spec.rb +24 -0
  42. data/spec/models/spree/asset_spec.rb +24 -0
  43. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  44. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  45. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  46. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  47. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  48. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  49. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +60 -0
  50. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  51. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  52. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  53. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  54. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
  55. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
  56. data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
  57. data/spec/models/spree/calculator_spec.rb +36 -0
  58. data/spec/models/spree/carton_spec.rb +133 -0
  59. data/spec/models/spree/classification_spec.rb +93 -0
  60. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  61. data/spec/models/spree/concerns/ordered_property_value_list_spec.rb +25 -0
  62. data/spec/models/spree/concerns/user_address_book_spec.rb +332 -0
  63. data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
  64. data/spec/models/spree/credit_card_spec.rb +341 -0
  65. data/spec/models/spree/customer_return_spec.rb +276 -0
  66. data/spec/models/spree/exchange_spec.rb +79 -0
  67. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  68. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  69. data/spec/models/spree/gateway_spec.rb +104 -0
  70. data/spec/models/spree/inventory_unit_spec.rb +307 -0
  71. data/spec/models/spree/item_adjustments_spec.rb +275 -0
  72. data/spec/models/spree/line_item_spec.rb +199 -0
  73. data/spec/models/spree/option_type_spec.rb +14 -0
  74. data/spec/models/spree/option_value_spec.rb +45 -0
  75. data/spec/models/spree/order/address_spec.rb +50 -0
  76. data/spec/models/spree/order/adjustments_spec.rb +27 -0
  77. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  78. data/spec/models/spree/order/checkout_spec.rb +884 -0
  79. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  80. data/spec/models/spree/order/finalizing_spec.rb +110 -0
  81. data/spec/models/spree/order/payment_spec.rb +243 -0
  82. data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
  83. data/spec/models/spree/order/state_machine_spec.rb +209 -0
  84. data/spec/models/spree/order/tax_spec.rb +84 -0
  85. data/spec/models/spree/order/totals_spec.rb +24 -0
  86. data/spec/models/spree/order/updating_spec.rb +18 -0
  87. data/spec/models/spree/order/validations_spec.rb +15 -0
  88. data/spec/models/spree/order_cancellations_spec.rb +120 -0
  89. data/spec/models/spree/order_capturing_spec.rb +150 -0
  90. data/spec/models/spree/order_contents_spec.rb +307 -0
  91. data/spec/models/spree/order_inventory_spec.rb +228 -0
  92. data/spec/models/spree/order_mutex_spec.rb +85 -0
  93. data/spec/models/spree/order_promotion_spec.rb +31 -0
  94. data/spec/models/spree/order_shipping_spec.rb +241 -0
  95. data/spec/models/spree/order_spec.rb +1482 -0
  96. data/spec/models/spree/order_stock_location_spec.rb +18 -0
  97. data/spec/models/spree/order_updater_spec.rb +283 -0
  98. data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
  99. data/spec/models/spree/payment_method_spec.rb +147 -0
  100. data/spec/models/spree/payment_spec.rb +1087 -0
  101. data/spec/models/spree/permission_sets/base_spec.rb +12 -0
  102. data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
  103. data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
  104. data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
  105. data/spec/models/spree/permission_sets/order_display_spec.rb +55 -0
  106. data/spec/models/spree/permission_sets/order_management_spec.rb +42 -0
  107. data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
  108. data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
  109. data/spec/models/spree/permission_sets/promotion_display_spec.rb +40 -0
  110. data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
  111. data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
  112. data/spec/models/spree/permission_sets/restricted_stock_display_spec.rb +41 -0
  113. data/spec/models/spree/permission_sets/restricted_stock_management_spec.rb +41 -0
  114. data/spec/models/spree/permission_sets/restricted_stock_transfer_display_spec.rb +50 -0
  115. data/spec/models/spree/permission_sets/restricted_stock_transfer_management_spec.rb +160 -0
  116. data/spec/models/spree/permission_sets/stock_display_spec.rb +24 -0
  117. data/spec/models/spree/permission_sets/stock_management_spec.rb +22 -0
  118. data/spec/models/spree/permission_sets/stock_transfer_display_spec.rb +24 -0
  119. data/spec/models/spree/permission_sets/stock_transfer_management_spec.rb +25 -0
  120. data/spec/models/spree/permission_sets/user_display_spec.rb +38 -0
  121. data/spec/models/spree/permission_sets/user_management_spec.rb +48 -0
  122. data/spec/models/spree/preference_spec.rb +80 -0
  123. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  124. data/spec/models/spree/preferences/preferable_spec.rb +294 -0
  125. data/spec/models/spree/preferences/scoped_store_spec.rb +60 -0
  126. data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
  127. data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
  128. data/spec/models/spree/preferences/store_spec.rb +39 -0
  129. data/spec/models/spree/price_spec.rb +42 -0
  130. data/spec/models/spree/product/scopes_spec.rb +116 -0
  131. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  132. data/spec/models/spree/product_filter_spec.rb +26 -0
  133. data/spec/models/spree/product_property_spec.rb +18 -0
  134. data/spec/models/spree/product_spec.rb +504 -0
  135. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
  136. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
  137. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
  138. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
  139. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  140. data/spec/models/spree/promotion/rules/first_repeat_purchase_since_spec.rb +69 -0
  141. data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
  142. data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
  143. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  144. data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
  145. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  146. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  147. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  148. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  149. data/spec/models/spree/promotion_builder_spec.rb +118 -0
  150. data/spec/models/spree/promotion_category_spec.rb +17 -0
  151. data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
  152. data/spec/models/spree/promotion_code_spec.rb +187 -0
  153. data/spec/models/spree/promotion_handler/cart_spec.rb +130 -0
  154. data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
  155. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
  156. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  157. data/spec/models/spree/promotion_rule_spec.rb +28 -0
  158. data/spec/models/spree/promotion_spec.rb +776 -0
  159. data/spec/models/spree/refund_spec.rb +192 -0
  160. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  161. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  162. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  163. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  164. data/spec/models/spree/reimbursement_spec.rb +231 -0
  165. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  166. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  167. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  168. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
  169. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
  170. data/spec/models/spree/return_authorization_spec.rb +290 -0
  171. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  172. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  173. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
  174. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  175. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  176. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  177. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  178. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  179. data/spec/models/spree/return_item_spec.rb +776 -0
  180. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  181. data/spec/models/spree/shipment_spec.rb +753 -0
  182. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  183. data/spec/models/spree/shipping_manifest_spec.rb +94 -0
  184. data/spec/models/spree/shipping_method_spec.rb +88 -0
  185. data/spec/models/spree/shipping_rate_spec.rb +142 -0
  186. data/spec/models/spree/state_spec.rb +14 -0
  187. data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
  188. data/spec/models/spree/stock/coordinator_spec.rb +116 -0
  189. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  190. data/spec/models/spree/stock/estimator_spec.rb +146 -0
  191. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  192. data/spec/models/spree/stock/package_spec.rb +163 -0
  193. data/spec/models/spree/stock/packer_spec.rb +91 -0
  194. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  195. data/spec/models/spree/stock/quantifier_spec.rb +115 -0
  196. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  197. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  198. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
  199. data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
  200. data/spec/models/spree/stock_item_spec.rb +444 -0
  201. data/spec/models/spree/stock_location_spec.rb +279 -0
  202. data/spec/models/spree/stock_movement_spec.rb +56 -0
  203. data/spec/models/spree/stock_transfer_spec.rb +290 -0
  204. data/spec/models/spree/store_credit_category_spec.rb +17 -0
  205. data/spec/models/spree/store_credit_event_spec.rb +314 -0
  206. data/spec/models/spree/store_credit_spec.rb +876 -0
  207. data/spec/models/spree/store_spec.rb +55 -0
  208. data/spec/models/spree/tax_category_spec.rb +27 -0
  209. data/spec/models/spree/tax_rate_spec.rb +378 -0
  210. data/spec/models/spree/taxon_spec.rb +74 -0
  211. data/spec/models/spree/taxonomy_spec.rb +18 -0
  212. data/spec/models/spree/tracker_spec.rb +21 -0
  213. data/spec/models/spree/transfer_item_spec.rb +264 -0
  214. data/spec/models/spree/unit_cancel_spec.rb +149 -0
  215. data/spec/models/spree/user_spec.rb +246 -0
  216. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
  217. data/spec/models/spree/variant/scopes_spec.rb +55 -0
  218. data/spec/models/spree/variant_property_rule_condition_spec.rb +15 -0
  219. data/spec/models/spree/variant_property_rule_spec.rb +83 -0
  220. data/spec/models/spree/variant_property_rule_value_spec.rb +18 -0
  221. data/spec/models/spree/variant_spec.rb +601 -0
  222. data/spec/models/spree/zone_spec.rb +305 -0
  223. data/spec/spec_helper.rb +80 -0
  224. data/spec/support/big_decimal.rb +5 -0
  225. data/spec/support/concerns/default_price.rb +34 -0
  226. data/spec/support/dummy_ability.rb +4 -0
  227. data/spec/support/test_gateway.rb +2 -0
  228. metadata +242 -2
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe ReturnsCalculator, :type => :model do
5
+ let(:return_item) { build(:return_item) }
6
+ subject { ReturnsCalculator.new }
7
+
8
+ it 'compute_shipment must be overridden' do
9
+ expect {
10
+ subject.compute(return_item)
11
+ }.to raise_error NotImplementedError
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,753 @@
1
+ require 'spec_helper'
2
+ require 'benchmark'
3
+
4
+ describe Spree::Shipment, :type => :model do
5
+ let(:stock_location) { create(:stock_location) }
6
+ let(:order) { create(:order_ready_to_ship, line_items_count: 1) }
7
+ let(:shipping_method) { create(:shipping_method, name: "UPS") }
8
+ let(:stock_location) { create(:stock_location) }
9
+ let(:shipment) do
10
+ order.shipments.create!(
11
+ state: 'pending',
12
+ cost: 1,
13
+ address: order.ship_address,
14
+ inventory_units: order.inventory_units,
15
+ shipping_rates: [
16
+ Spree::ShippingRate.new(
17
+ shipping_method: shipping_method,
18
+ selected: true,
19
+ ),
20
+ ],
21
+ stock_location: stock_location,
22
+ )
23
+ end
24
+
25
+ let(:variant) { mock_model(Spree::Variant) }
26
+ let(:line_item) { mock_model(Spree::LineItem, variant: variant) }
27
+
28
+ describe "precision of pre_tax_amount" do
29
+ let!(:line_item) { create :line_item, pre_tax_amount: 4.2051 }
30
+
31
+ it "keeps four digits of precision even when reloading" do
32
+ expect(line_item.reload.pre_tax_amount).to eq(4.2051)
33
+ end
34
+ end
35
+
36
+ # Regression test for #4063
37
+ context "number generation" do
38
+ before do
39
+ allow(order).to receive :update!
40
+ end
41
+
42
+ it "generates a number containing a letter + 11 numbers" do
43
+ shipment.save
44
+ expect(shipment.number[0]).to eq("H")
45
+ expect(/\d{11}/.match(shipment.number)).not_to be_nil
46
+ expect(shipment.number.length).to eq(12)
47
+ end
48
+ end
49
+
50
+ it 'is backordered if one if its inventory_units is backordered' do
51
+ shipment.inventory_units = [
52
+ build(:inventory_unit, state: 'backordered', shipment: nil),
53
+ build(:inventory_unit, state: 'shipped', shipment: nil),
54
+ ]
55
+ expect(shipment).to be_backordered
56
+ end
57
+
58
+ context '#determine_state' do
59
+ it 'returns canceled if order is canceled?' do
60
+ allow(order).to receive_messages canceled?: true
61
+ expect(shipment.determine_state(order)).to eq 'canceled'
62
+ end
63
+
64
+ it 'returns pending unless order.can_ship?' do
65
+ allow(order).to receive_messages can_ship?: false
66
+ expect(shipment.determine_state(order)).to eq 'pending'
67
+ end
68
+
69
+ it 'returns pending if backordered' do
70
+ allow(shipment).to receive_messages inventory_units: [mock_model(Spree::InventoryUnit, backordered?: true)]
71
+ expect(shipment.determine_state(order)).to eq 'pending'
72
+ end
73
+
74
+ it 'returns shipped when already shipped' do
75
+ allow(shipment).to receive_messages state: 'shipped'
76
+ expect(shipment.determine_state(order)).to eq 'shipped'
77
+ end
78
+
79
+ it 'returns pending when unpaid' do
80
+ allow(order).to receive_messages paid?: false
81
+ expect(shipment.determine_state(order)).to eq 'pending'
82
+ end
83
+
84
+ it 'returns ready when paid' do
85
+ allow(order).to receive_messages paid?: true
86
+ expect(shipment.determine_state(order)).to eq 'ready'
87
+ end
88
+ end
89
+
90
+ context "display_amount" do
91
+ it "retuns a Spree::Money" do
92
+ shipment.cost = 21.22
93
+ expect(shipment.display_amount).to eq(Spree::Money.new(21.22))
94
+ end
95
+ end
96
+
97
+ context "display_final_price" do
98
+ it "retuns a Spree::Money" do
99
+ allow(shipment).to receive(:final_price) { 21.22 }
100
+ expect(shipment.display_final_price).to eq(Spree::Money.new(21.22))
101
+ end
102
+ end
103
+
104
+ context "display_item_cost" do
105
+ it "retuns a Spree::Money" do
106
+ allow(shipment).to receive(:item_cost) { 21.22 }
107
+ expect(shipment.display_item_cost).to eq(Spree::Money.new(21.22))
108
+ end
109
+ end
110
+
111
+ context "#item_cost" do
112
+ it 'should equal line items final amount with tax' do
113
+ shipment = create(:shipment, order: create(:order_with_totals))
114
+ create :tax_adjustment, adjustable: shipment.order.line_items.first, order: shipment.order
115
+ expect(shipment.item_cost).to eql(11.0)
116
+ end
117
+ end
118
+
119
+ it "#discounted_cost" do
120
+ shipment = create(:shipment)
121
+ shipment.cost = 10
122
+ shipment.promo_total = -1
123
+ expect(shipment.discounted_cost).to eq(9)
124
+ end
125
+
126
+ it "#tax_total with included taxes" do
127
+ shipment = Spree::Shipment.new
128
+ expect(shipment.tax_total).to eq(0)
129
+ shipment.included_tax_total = 10
130
+ expect(shipment.tax_total).to eq(10)
131
+ end
132
+
133
+ it "#tax_total with additional taxes" do
134
+ shipment = Spree::Shipment.new
135
+ expect(shipment.tax_total).to eq(0)
136
+ shipment.additional_tax_total = 10
137
+ expect(shipment.tax_total).to eq(10)
138
+ end
139
+
140
+ it "#final_price" do
141
+ shipment = Spree::Shipment.new
142
+ shipment.cost = 10
143
+ shipment.adjustment_total = -2
144
+ shipment.included_tax_total = 1
145
+ expect(shipment.final_price).to eq(8)
146
+ end
147
+
148
+ context "manifest" do
149
+ let(:order) { Spree::Order.create }
150
+ let(:variant) { create(:variant) }
151
+ let!(:line_item) { order.contents.add variant }
152
+ let!(:shipment) { order.create_proposed_shipments.first }
153
+
154
+ it "returns variant expected" do
155
+ expect(shipment.manifest.first.variant).to eq variant
156
+ end
157
+
158
+ context "variant was removed" do
159
+ before { variant.destroy }
160
+
161
+ it "still returns variant expected" do
162
+ expect(shipment.manifest.first.variant).to eq variant
163
+ end
164
+ end
165
+ end
166
+
167
+ context 'shipping_rates' do
168
+ let(:shipment) { create(:shipment) }
169
+ let(:shipping_method1) { create(:shipping_method) }
170
+ let(:shipping_method2) { create(:shipping_method) }
171
+ let(:shipping_rates) { [
172
+ Spree::ShippingRate.new(shipping_method: shipping_method1, cost: 10.00, selected: true),
173
+ Spree::ShippingRate.new(shipping_method: shipping_method2, cost: 20.00)
174
+ ] }
175
+
176
+ it 'returns shipping_method from selected shipping_rate' do
177
+ shipment.shipping_rates.delete_all
178
+ shipment.shipping_rates.create shipping_method: shipping_method1, cost: 10.00, selected: true
179
+ expect(shipment.shipping_method).to eq shipping_method1
180
+ end
181
+
182
+ context 'refresh_rates' do
183
+ let(:mock_estimator) { double('estimator', shipping_rates: shipping_rates) }
184
+ before { allow(shipment).to receive(:can_get_rates?){ true } }
185
+
186
+ it 'should request new rates, and maintain shipping_method selection' do
187
+ expect(Spree::Stock::Estimator).to receive(:new).with(shipment.order).and_return(mock_estimator)
188
+ allow(shipment).to receive_messages(shipping_method: shipping_method2)
189
+
190
+ expect(shipment.refresh_rates).to eq(shipping_rates)
191
+ expect(shipment.reload.selected_shipping_rate.shipping_method_id).to eq(shipping_method2.id)
192
+ end
193
+
194
+ it 'should handle no shipping_method selection' do
195
+ expect(Spree::Stock::Estimator).to receive(:new).with(shipment.order).and_return(mock_estimator)
196
+ allow(shipment).to receive_messages(shipping_method: nil)
197
+ expect(shipment.refresh_rates).to eq(shipping_rates)
198
+ expect(shipment.reload.selected_shipping_rate).not_to be_nil
199
+ end
200
+
201
+ it 'should not refresh if shipment is shipped' do
202
+ expect(Spree::Stock::Estimator).not_to receive(:new)
203
+ shipment.shipping_rates.delete_all
204
+ allow(shipment).to receive_messages(shipped?: true)
205
+ expect(shipment.refresh_rates).to eq([])
206
+ end
207
+
208
+ it "can't get rates without a shipping address" do
209
+ shipment.order(ship_address: nil)
210
+ expect(shipment.refresh_rates).to eq([])
211
+ end
212
+
213
+ context 'to_package' do
214
+ let(:inventory_units) do
215
+ [build(:inventory_unit, line_item: line_item, variant: variant, state: 'on_hand'),
216
+ build(:inventory_unit, line_item: line_item, variant: variant, state: 'backordered')]
217
+ end
218
+
219
+ before do
220
+ allow(shipment).to receive(:inventory_units) { inventory_units }
221
+ allow(inventory_units).to receive_message_chain(:includes, :joins).and_return inventory_units
222
+ end
223
+
224
+ it 'should use symbols for states when adding contents to package' do
225
+ package = shipment.to_package
226
+ expect(package.on_hand.count).to eq 1
227
+ expect(package.backordered.count).to eq 1
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ context "#update!" do
234
+ shared_examples_for "immutable once shipped" do
235
+ it "should remain in shipped state once shipped" do
236
+ shipment.state = 'shipped'
237
+ expect(shipment).to receive(:update_columns).with(state: 'shipped', updated_at: kind_of(Time))
238
+ shipment.update!(order)
239
+ end
240
+ end
241
+
242
+ shared_examples_for "pending if backordered" do
243
+ it "should have a state of pending if backordered" do
244
+ allow(shipment).to receive_messages(inventory_units: [mock_model(Spree::InventoryUnit, backordered?: true)])
245
+ expect(shipment).to receive(:update_columns).with(state: 'pending', updated_at: kind_of(Time))
246
+ shipment.update!(order)
247
+ end
248
+ end
249
+
250
+ context "when order cannot ship" do
251
+ before { allow(order).to receive_messages can_ship?: false }
252
+ it "should result in a 'pending' state" do
253
+ expect(shipment).to receive(:update_columns).with(state: 'pending', updated_at: kind_of(Time))
254
+ shipment.update!(order)
255
+ end
256
+ end
257
+
258
+ context "when order is paid" do
259
+ before { allow(order).to receive_messages paid?: true }
260
+ it "should result in a 'ready' state" do
261
+ expect(shipment).to receive(:update_columns).with(state: 'ready', updated_at: kind_of(Time))
262
+ shipment.update!(order)
263
+ end
264
+ it_should_behave_like 'immutable once shipped'
265
+ it_should_behave_like 'pending if backordered'
266
+ end
267
+
268
+ context "when payment is not required" do
269
+ before do
270
+ @original_require_payment = Spree::Config[:require_payment_to_ship]
271
+ Spree::Config[:require_payment_to_ship] = false
272
+ end
273
+
274
+ after do
275
+ Spree::Config[:require_payment_to_ship] = @original_require_payment
276
+ end
277
+
278
+ it "should result in a 'ready' state" do
279
+ expect(shipment).to receive(:update_columns).with(state: 'ready', updated_at: kind_of(Time))
280
+ shipment.update!(order)
281
+ end
282
+ it_should_behave_like 'immutable once shipped'
283
+ it_should_behave_like 'pending if backordered'
284
+ end
285
+
286
+ context "when order has balance due" do
287
+ before { allow(order).to receive_messages paid?: false }
288
+ it "should result in a 'pending' state" do
289
+ shipment.state = 'ready'
290
+ expect(shipment).to receive(:update_columns).with(state: 'pending', updated_at: kind_of(Time))
291
+ shipment.update!(order)
292
+ end
293
+ it_should_behave_like 'immutable once shipped'
294
+ it_should_behave_like 'pending if backordered'
295
+ end
296
+
297
+ context "when order has a credit owed" do
298
+ before { allow(order).to receive_messages payment_state: 'credit_owed', paid?: true }
299
+ it "should result in a 'ready' state" do
300
+ shipment.state = 'pending'
301
+ expect(shipment).to receive(:update_columns).with(state: 'ready', updated_at: kind_of(Time))
302
+ shipment.update!(order)
303
+ end
304
+ it_should_behave_like 'immutable once shipped'
305
+ it_should_behave_like 'pending if backordered'
306
+ end
307
+
308
+ context "when shipment state changes to shipped" do
309
+ it "should call after_ship" do
310
+ shipment.state = 'pending'
311
+ expect(shipment).to receive :after_ship
312
+ allow(shipment).to receive_messages determine_state: 'shipped'
313
+ expect(shipment).to receive(:update_columns).with(state: 'shipped', updated_at: kind_of(Time))
314
+ shipment.update!(order)
315
+ end
316
+
317
+ # Regression test for #4347
318
+ context "with adjustments" do
319
+ before do
320
+ shipment.adjustments << Spree::Adjustment.create(order: order, label: "Label", amount: 5)
321
+ end
322
+
323
+ it "transitions to shipped" do
324
+ shipment.update_column(:state, "ready")
325
+ expect { shipment.ship! }.not_to raise_error
326
+ end
327
+ end
328
+ end
329
+ end
330
+
331
+ context "when order is completed" do
332
+ after { Spree::Config.set track_inventory_levels: true }
333
+
334
+ before do
335
+ allow(order).to receive_messages completed?: true
336
+ allow(order).to receive_messages canceled?: false
337
+ end
338
+
339
+ context "with inventory tracking" do
340
+ before { Spree::Config.set track_inventory_levels: true }
341
+
342
+ it "should validate with inventory" do
343
+ shipment.inventory_units = [create(:inventory_unit)]
344
+ expect(shipment.valid?).to be true
345
+ end
346
+ end
347
+
348
+ context "without inventory tracking" do
349
+ before { Spree::Config.set track_inventory_levels: false }
350
+
351
+ it "should validate with no inventory" do
352
+ expect(shipment.valid?).to be true
353
+ end
354
+ end
355
+ end
356
+
357
+ context "#cancel" do
358
+ it 'cancels the shipment' do
359
+ allow(shipment.order).to receive(:update!)
360
+
361
+ shipment.state = 'pending'
362
+ expect(shipment).to receive(:after_cancel)
363
+ shipment.cancel!
364
+ expect(shipment.state).to eq 'canceled'
365
+ end
366
+
367
+ it 'restocks the items' do
368
+ variant = shipment.inventory_units.first.variant
369
+ shipment.stock_location = mock_model(Spree::StockLocation)
370
+ expect(shipment.stock_location).to receive(:restock).with(variant, 1, shipment)
371
+ shipment.after_cancel
372
+ end
373
+
374
+ context "with backordered inventory units" do
375
+ let(:order) { create(:order) }
376
+ let(:variant) { create(:variant) }
377
+ let(:other_order) { create(:order) }
378
+
379
+ before do
380
+ order.contents.add variant
381
+ order.create_proposed_shipments
382
+
383
+ other_order.contents.add variant
384
+ other_order.create_proposed_shipments
385
+ end
386
+
387
+ it "doesn't fill backorders when restocking inventory units" do
388
+ shipment = order.shipments.first
389
+ expect(shipment.inventory_units.count).to eq 1
390
+ expect(shipment.inventory_units.first).to be_backordered
391
+
392
+ other_shipment = other_order.shipments.first
393
+ expect(other_shipment.inventory_units.count).to eq 1
394
+ expect(other_shipment.inventory_units.first).to be_backordered
395
+
396
+ expect {
397
+ shipment.cancel!
398
+ }.not_to change { other_shipment.inventory_units.first.state }
399
+ end
400
+ end
401
+ end
402
+
403
+ context "#resume" do
404
+ let(:inventory_unit) { create(:inventory_unit) }
405
+
406
+ before { shipment.state = 'canceled' }
407
+
408
+ context "when order cannot ship" do
409
+ before { allow(order).to receive_messages(can_ship?: false) }
410
+ it "should result in a 'pending' state" do
411
+ shipment.resume!
412
+ expect(shipment.state).to eq 'pending'
413
+ end
414
+ end
415
+
416
+ context "when order is not paid" do
417
+ before { allow(order).to receive_messages(paid?: false) }
418
+ it "should result in a 'ready' state" do
419
+ shipment.resume!
420
+ expect(shipment.state).to eq 'pending'
421
+ end
422
+ end
423
+
424
+ context "when any inventory is backordered" do
425
+ before { allow_any_instance_of(Spree::InventoryUnit).to receive(:backordered?).and_return(true) }
426
+ it "should result in a 'ready' state" do
427
+ shipment.resume!
428
+ expect(shipment.state).to eq 'pending'
429
+ end
430
+ end
431
+
432
+ context "when the order is paid, shippable, and not backordered" do
433
+ before do
434
+ allow(order).to receive_messages(can_ship?: true)
435
+ allow(order).to receive_messages(paid?: true)
436
+ allow_any_instance_of(Spree::InventoryUnit).to receive(:backordered?).and_return(false)
437
+ end
438
+
439
+ it "should result in a 'ready' state" do
440
+ shipment.resume!
441
+ expect(shipment.state).to eq 'ready'
442
+ end
443
+ end
444
+
445
+ it 'unstocks them items' do
446
+ variant = shipment.inventory_units.first.variant
447
+ shipment.stock_location = mock_model(Spree::StockLocation)
448
+ expect(shipment.stock_location).to receive(:unstock).with(variant, 1, shipment)
449
+ shipment.after_resume
450
+ end
451
+ end
452
+
453
+ context "#ship" do
454
+ context "when the shipment is canceled" do
455
+ let(:address){ create(:address) }
456
+ let(:order){ create(:order_with_line_items, ship_address: address) }
457
+ let(:shipment_with_inventory_units) { create(:shipment, order: order, address: address, state: 'canceled') }
458
+ let(:subject) { shipment_with_inventory_units.ship! }
459
+ before do
460
+ allow(order).to receive(:update!)
461
+ allow(shipment_with_inventory_units).to receive_messages(require_inventory: false, update_order: true)
462
+ end
463
+
464
+ it 'unstocks them items' do
465
+ expect(shipment_with_inventory_units.stock_location).to receive(:unstock).with(an_instance_of(Spree::Variant), 1, shipment_with_inventory_units)
466
+ subject
467
+ end
468
+ end
469
+
470
+ ['ready', 'canceled'].each do |state|
471
+ context "from #{state}" do
472
+ before do
473
+ allow(order).to receive(:update!)
474
+ allow(shipment).to receive_messages(require_inventory: false, update_order: true, state: state)
475
+ end
476
+
477
+ it "should call fulfill_order_with_stock_location" do
478
+ expect(Spree::OrderStockLocation).to(
479
+ receive(:fulfill_for_order_with_stock_location).
480
+ with(order, stock_location)
481
+ )
482
+ shipment.ship!
483
+ end
484
+
485
+ it "finalizes adjustments" do
486
+ shipment.adjustments.each do |adjustment|
487
+ expect(adjustment).to receive(:finalize!)
488
+ end
489
+ shipment.ship!
490
+ end
491
+ end
492
+ end
493
+ end
494
+
495
+ context "#ready" do
496
+ # Regression test for #2040
497
+ it "cannot ready a shipment for an order if the order is unpaid" do
498
+ expect(order).to receive_messages(paid?: false)
499
+ expect(shipment).not_to be_can_ready
500
+ end
501
+ end
502
+
503
+ context "updates cost when selected shipping rate is present" do
504
+ let(:shipment) { create(:shipment) }
505
+
506
+ before { allow(shipment).to receive_message_chain :selected_shipping_rate, cost: 5 }
507
+
508
+ it "updates shipment totals" do
509
+ shipment.update_amounts
510
+ expect(shipment.reload.cost).to eq(5)
511
+ end
512
+
513
+ it "factors in additional adjustments to adjustment total" do
514
+ shipment.adjustments.create!(
515
+ order: order,
516
+ label: "Additional",
517
+ amount: 5,
518
+ included: false,
519
+ finalized: true
520
+ )
521
+ shipment.update_amounts
522
+ expect(shipment.reload.adjustment_total).to eq(5)
523
+ end
524
+
525
+ it "does not factor in included adjustments to adjustment total" do
526
+ shipment.adjustments.create!(
527
+ order: order,
528
+ label: "Included",
529
+ amount: 5,
530
+ included: true,
531
+ finalized: true
532
+ )
533
+ shipment.update_amounts
534
+ expect(shipment.reload.adjustment_total).to eq(0)
535
+ end
536
+ end
537
+
538
+ context "changes shipping rate via general update" do
539
+ let(:order) do
540
+ Spree::Order.create(
541
+ payment_total: 100, payment_state: 'paid', total: 100, item_total: 100
542
+ )
543
+ end
544
+
545
+ let(:shipment) { Spree::Shipment.create order_id: order.id }
546
+
547
+ let(:shipping_rate) do
548
+ Spree::ShippingRate.create shipment_id: shipment.id, cost: 10
549
+ end
550
+
551
+ before do
552
+ shipment.update_attributes_and_order selected_shipping_rate_id: shipping_rate.id
553
+ end
554
+
555
+ it "updates everything around order shipment total and state" do
556
+ expect(shipment.cost.to_f).to eq 10
557
+ expect(shipment.state).to eq 'pending'
558
+ expect(shipment.order.total.to_f).to eq 110
559
+ expect(shipment.order.payment_state).to eq 'balance_due'
560
+ end
561
+ end
562
+
563
+ context "after_save" do
564
+ context "line item changes" do
565
+ before do
566
+ shipment.cost = shipment.cost + 10
567
+ end
568
+
569
+ it "triggers adjustment total recalculation" do
570
+ expect(shipment).to receive(:recalculate_adjustments)
571
+ shipment.save
572
+ end
573
+
574
+ it "does not trigger adjustment recalculation if shipment has shipped" do
575
+ shipment.state = 'shipped'
576
+ expect(shipment).not_to receive(:recalculate_adjustments)
577
+ shipment.save
578
+ end
579
+ end
580
+
581
+ context "line item does not change" do
582
+ it "does not trigger adjustment total recalculation" do
583
+ expect(shipment).not_to receive(:recalculate_adjustments)
584
+ shipment.save
585
+ end
586
+ end
587
+ end
588
+
589
+ context "currency" do
590
+ it "returns the order currency" do
591
+ expect(shipment.currency).to eq(order.currency)
592
+ end
593
+ end
594
+
595
+ context "nil costs" do
596
+ it "sets cost to 0" do
597
+ shipment = Spree::Shipment.new
598
+ shipment.valid?
599
+ expect(shipment.cost).to eq 0
600
+ end
601
+ end
602
+
603
+ context "#tracking_url" do
604
+ subject do
605
+ shipment.tracking_url
606
+ end
607
+
608
+ before do
609
+ shipping_method.update!(tracking_url: "https://example.com/:tracking")
610
+ shipment.tracking = '1Z12345'
611
+ end
612
+
613
+ it "uses shipping method to determine url" do
614
+ is_expected.to eq("https://example.com/1Z12345")
615
+ end
616
+ end
617
+
618
+ context "set up new inventory units" do
619
+ # let(:line_item) { double(
620
+ let(:variant) { double("Variant", id: 9) }
621
+
622
+ let(:inventory_units) { double }
623
+
624
+ let(:params) do
625
+ { variant_id: variant.id, state: 'on_hand', order_id: order.id, line_item_id: line_item.id }
626
+ end
627
+
628
+ before { allow(shipment).to receive_messages inventory_units: inventory_units }
629
+
630
+ it "associates variant and order" do
631
+ expect(inventory_units).to receive(:create).with(params)
632
+ unit = shipment.set_up_inventory('on_hand', variant, order, line_item)
633
+ end
634
+ end
635
+
636
+ # Regression test for #3349
637
+ context "#destroy" do
638
+ it "destroys linked shipping_rates" do
639
+ reflection = Spree::Shipment.reflect_on_association(:shipping_rates)
640
+ expect(reflection.options[:dependent]).to be(:delete_all)
641
+ end
642
+ end
643
+
644
+ # Regression test for #4072 (kinda)
645
+ # The need for this was discovered in the research for #4702
646
+ context "state changes" do
647
+ before do
648
+ # Must be stubbed so transition can succeed
649
+ allow(order).to receive_messages :paid? => true
650
+ end
651
+
652
+ it "are logged to the database" do
653
+ expect(shipment.state_changes).to be_empty
654
+ expect(shipment.ready!).to be true
655
+ expect(shipment.state_changes.count).to eq(1)
656
+ state_change = shipment.state_changes.first
657
+ expect(state_change.previous_state).to eq('pending')
658
+ expect(state_change.next_state).to eq('ready')
659
+ end
660
+ end
661
+
662
+ context "don't require shipment" do
663
+ let(:stock_location) { create(:stock_location, fulfillable: false)}
664
+ let(:unshippable_shipment) do
665
+ create(
666
+ :shipment,
667
+ address: create(:address),
668
+ stock_location: stock_location,
669
+ inventory_units: [build(:inventory_unit)],
670
+ )
671
+ end
672
+
673
+ before { allow(order).to receive_messages paid?: true }
674
+
675
+ it 'proceeds automatically to shipped state' do
676
+ unshippable_shipment.ready!
677
+ expect(unshippable_shipment.state).to eq('shipped')
678
+ end
679
+
680
+ it 'does not send a confirmation email' do
681
+ expect {
682
+ unshippable_shipment.ready!
683
+ unshippable_shipment.inventory_units(true).each do |unit|
684
+ expect(unit.state).to eq('shipped')
685
+ end
686
+ }.not_to change{ ActionMailer::Base.deliveries.count }
687
+ end
688
+ end
689
+
690
+ context "destroy prevention" do
691
+ it "can be destroyed when pending" do
692
+ shipment = create(:shipment, state: "pending")
693
+ expect(shipment.destroy).to be_truthy
694
+ expect { shipment.reload }.to raise_error(ActiveRecord::RecordNotFound)
695
+ end
696
+
697
+ it "cannot be destroyed when ready" do
698
+ shipment = create(:shipment, state: "ready")
699
+ expect(shipment.destroy).to eq false
700
+ expect(shipment.errors.full_messages.join).to match /Cannot destroy/
701
+ expect { shipment.reload }.not_to raise_error
702
+ end
703
+
704
+ it "cannot be destroyed when shipped" do
705
+ shipment = create(:shipment, state: "shipped")
706
+ expect(shipment.destroy).to eq false
707
+ expect(shipment.errors.full_messages.join).to match /Cannot destroy/
708
+ expect { shipment.reload }.not_to raise_error
709
+ end
710
+
711
+ it "cannot be destroyed when canceled" do
712
+ shipment = create(:shipment, state: "canceled")
713
+ expect(shipment.destroy).to eq false
714
+ expect(shipment.errors.full_messages.join).to match /Cannot destroy/
715
+ expect { shipment.reload }.not_to raise_error
716
+ end
717
+ end
718
+
719
+ describe "#finalize!" do
720
+ let(:inventory_unit) { shipment.inventory_units.first }
721
+ let(:stock_item) { inventory_unit.variant.stock_items.find_by(stock_location: stock_location) }
722
+
723
+ before do
724
+ stock_item.set_count_on_hand(10)
725
+ stock_item.update_attributes!(backorderable: false)
726
+ end
727
+
728
+ subject { shipment.finalize! }
729
+
730
+ it "updates the associated inventory units" do
731
+ inventory_unit.update_columns(updated_at: 1.hour.ago)
732
+ expect { subject }.to change { inventory_unit.reload.updated_at }
733
+ end
734
+
735
+ it "unstocks the variant" do
736
+ expect { subject }.to change { stock_item.reload.count_on_hand }.from(10).to(9)
737
+ end
738
+
739
+ context "inventory unit already finalized" do
740
+ before do
741
+ inventory_unit.update_attributes!(pending: false)
742
+ end
743
+
744
+ it "doesn't update the associated inventory units" do
745
+ expect { subject }.to_not change { inventory_unit.reload.updated_at }
746
+ end
747
+
748
+ it "doesn't unstock the variant" do
749
+ expect { subject }.to_not change { stock_item.reload.count_on_hand }
750
+ end
751
+ end
752
+ end
753
+ end