solidus_core 1.1.0 → 1.1.1

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 (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,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::OrderCapturing do
4
+ describe '#capture_payments' do
5
+ subject { Spree::OrderCapturing.new(order, payment_methods).capture_payments }
6
+
7
+ # Regression for the order.update! in the ensure block.
8
+ # See the comment there.
9
+ context "updating the order" do
10
+ let(:order) { create :completed_order_with_totals }
11
+ let(:payment_methods) { [] }
12
+ let!(:payment) { create(:payment, order: order, amount: order.total) }
13
+ let(:changes_spy) { spy('changes_spy') }
14
+
15
+ before do
16
+ payment.pend!
17
+
18
+ allow_any_instance_of(Spree::Order).to receive(:thingamajig) do |order|
19
+ changes_spy.change_callback_occured if order.changes.any?
20
+ end
21
+
22
+ @update_hooks = Spree::Order.update_hooks.dup
23
+ Spree::Order.register_update_hook :thingamajig
24
+ end
25
+
26
+ after do
27
+ Spree::Order.update_hooks = @update_hooks
28
+ end
29
+
30
+ it "keeps the order up to date when updating and only changes it once" do
31
+ subject
32
+ expect(changes_spy).to have_received(:change_callback_occured).once
33
+ end
34
+ end
35
+
36
+ context "payment methods specified" do
37
+ let!(:order) { create(:order, ship_address: create(:address)) }
38
+
39
+ let!(:product) { create(:product, price: 10.00) }
40
+ let!(:variant) do
41
+ create(:variant, price: 10, product: product, track_inventory: false, tax_category: tax_rate.tax_category)
42
+ end
43
+ let!(:shipping_method) { create(:free_shipping_method) }
44
+ let(:tax_rate) { create(:tax_rate, amount: 0.1, zone: create(:global_zone, name: "Some Tax Zone")) }
45
+ let(:secondary_total) { 10.0 }
46
+ let(:bogus_total) { order.total - secondary_total }
47
+
48
+ before do
49
+ order.contents.add(variant, 3)
50
+ order.update!
51
+ @secondary_bogus_payment = create(:payment, order: order, amount: secondary_total, payment_method: secondary_payment_method.create!(name: 'So bogus'))
52
+ @bogus_payment = create(:payment, order: order, amount: bogus_total)
53
+ order.contents.advance
54
+ order.complete!
55
+ order.reload
56
+ end
57
+
58
+ context "payment method ordering" do
59
+ let(:secondary_payment_method) { SecondaryBogusPaymentMethod }
60
+
61
+ class SecondaryBogusPaymentMethod < Spree::Gateway::Bogus; end
62
+
63
+ context "SecondaryBogusPaymentMethod payments are prioritized" do
64
+ let(:payment_methods) { [SecondaryBogusPaymentMethod, Spree::Gateway::Bogus] }
65
+
66
+ it "captures SecondaryBogusPaymentMethod payments first" do
67
+ @bogus_payment.update!(amount: bogus_total + 100)
68
+ subject
69
+ expect(@secondary_bogus_payment.reload.capture_events.sum(:amount)).to eq(10.0)
70
+ expect(@bogus_payment.reload.capture_events.sum(:amount)).to eq(order.total - 10.0)
71
+ end
72
+ end
73
+
74
+ context "Bogus payments are prioritized" do
75
+ let(:payment_methods) { [Spree::Gateway::Bogus, SecondaryBogusPaymentMethod] }
76
+
77
+ it "captures Bogus payments first" do
78
+ @secondary_bogus_payment.update!(amount: secondary_total + 100)
79
+ subject
80
+ expect(@bogus_payment.reload.capture_events.sum(:amount)).to eq(order.total - 10.0)
81
+ expect(@secondary_bogus_payment.reload.capture_events.sum(:amount)).to eq(10.0)
82
+ end
83
+ end
84
+
85
+ context "when the payment method ordering is configured" do
86
+ subject { Spree::OrderCapturing.new(order, payment_methods).capture_payments }
87
+
88
+ let(:payment_methods) { nil }
89
+
90
+ before do
91
+ allow(Spree::OrderCapturing).to receive(:sorted_payment_method_classes).and_return(
92
+ [SecondaryBogusPaymentMethod, Spree::Gateway::Bogus]
93
+ )
94
+ end
95
+
96
+ it "captures in the order specified" do
97
+ subject
98
+ expect(@secondary_bogus_payment.reload.capture_events.sum(:amount)).to eq(10.0)
99
+ expect(@bogus_payment.reload.capture_events.sum(:amount)).to eq(order.total - 10.0)
100
+ end
101
+ end
102
+ end
103
+
104
+ context "when a payment is not needed to capture the entire order" do
105
+ let(:secondary_payment_method) { SecondaryBogusPaymentMethod }
106
+ let(:payment_methods) { [Spree::Gateway::Bogus, SecondaryBogusPaymentMethod] }
107
+
108
+ before do
109
+ @bogus_payment.update!(amount: order.total)
110
+ end
111
+
112
+ context "when void_unused_payments is true" do
113
+ before { allow(Spree::OrderCapturing).to receive(:void_unused_payments).and_return(true) }
114
+
115
+ it "captures for the order and voids the unused payment" do
116
+ subject
117
+ expect(order.reload.payment_state).to eq 'paid'
118
+ expect(@secondary_bogus_payment.reload.state).to eq 'void'
119
+ end
120
+ end
121
+
122
+ context "when void_unused_payments is false" do
123
+ it "captures for the order and leaves the unused payment in a pending state" do
124
+ subject
125
+ expect(order.reload.payment_state).to eq 'paid'
126
+ expect(@secondary_bogus_payment.reload.state).to eq 'pending'
127
+ end
128
+ end
129
+ end
130
+
131
+ context "when there is an error processing a payment" do
132
+ let(:secondary_payment_method) { ExceptionallyBogusPaymentMethod }
133
+ let(:bogus_total) { order.total - 1 }
134
+ let(:secondary_total) { 1 }
135
+ let(:payment_methods) { [Spree::Gateway::Bogus, ExceptionallyBogusPaymentMethod] }
136
+
137
+ class ExceptionallyBogusPaymentMethod < Spree::Gateway::Bogus
138
+ def capture(*args)
139
+ raise ActiveMerchant::ConnectionError.new("foo", nil)
140
+ end
141
+ end
142
+
143
+ it "raises an error and leaves the order in a reasonable state" do
144
+ expect { subject }.to raise_error(Spree::Core::GatewayError)
145
+ expect(order.payments.to_a.sum(&:uncaptured_amount)).to eq 1.0
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,307 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::OrderContents, :type => :model do
4
+ let(:order) { Spree::Order.create }
5
+ let(:variant) { create(:variant) }
6
+ let!(:stock_location) { variant.stock_locations.first }
7
+ let(:stock_location_2) { create(:stock_location) }
8
+
9
+ subject { described_class.new(order) }
10
+
11
+ context "#add" do
12
+ context 'given quantity is not explicitly provided' do
13
+ it 'should add one line item' do
14
+ line_item = subject.add(variant)
15
+ expect(line_item.quantity).to eq(1)
16
+ expect(order.line_items.size).to eq(1)
17
+ end
18
+ end
19
+
20
+ context 'given a shipment' do
21
+ it "ensure shipment calls update_amounts instead of order calling ensure_updated_shipments" do
22
+ shipment = create(:shipment)
23
+ expect(subject.order).to_not receive(:ensure_updated_shipments)
24
+ expect(shipment).to receive(:update_amounts)
25
+ subject.add(variant, 1, shipment: shipment)
26
+ end
27
+ end
28
+
29
+ context 'not given a shipment' do
30
+ it "ensures updated shipments" do
31
+ expect(subject.order).to receive(:ensure_updated_shipments)
32
+ subject.add(variant)
33
+ end
34
+ end
35
+
36
+ it 'should add line item if one does not exist' do
37
+ line_item = subject.add(variant, 1)
38
+ expect(line_item.quantity).to eq(1)
39
+ expect(order.line_items.size).to eq(1)
40
+ end
41
+
42
+ it 'should update line item if one exists' do
43
+ subject.add(variant, 1)
44
+ line_item = subject.add(variant, 1)
45
+ expect(line_item.quantity).to eq(2)
46
+ expect(order.line_items.size).to eq(1)
47
+ end
48
+
49
+ it "should update order totals" do
50
+ expect(order.item_total.to_f).to eq(0.00)
51
+ expect(order.total.to_f).to eq(0.00)
52
+
53
+ subject.add(variant, 1)
54
+
55
+ expect(order.item_total.to_f).to eq(19.99)
56
+ expect(order.total.to_f).to eq(19.99)
57
+ end
58
+
59
+ it "should create stock location associations if provided" do
60
+ line_item = subject.add(variant, 3, stock_location_quantities: {stock_location.id => 1, stock_location_2.id => 2})
61
+ order_stock_locations = line_item.order.order_stock_locations
62
+ expect(order_stock_locations.count).to eq(2)
63
+ expect(order_stock_locations.map(&:quantity)).to eq([1, 2])
64
+ expect(order_stock_locations.map(&:stock_location_id)).to eq([stock_location.id, stock_location_2.id])
65
+ end
66
+
67
+ context "running promotions" do
68
+ let(:promotion) { create(:promotion, apply_automatically: true) }
69
+ let(:calculator) { Spree::Calculator::FlatRate.new(:preferred_amount => 10) }
70
+
71
+ shared_context "discount changes order total" do
72
+ before { subject.add(variant, 1) }
73
+ it { expect(subject.order.total).not_to eq variant.price }
74
+ end
75
+
76
+ context "one active order promotion" do
77
+ let!(:action) { Spree::Promotion::Actions::CreateAdjustment.create(promotion: promotion, calculator: calculator) }
78
+
79
+ it "creates valid discount on order" do
80
+ subject.add(variant, 1)
81
+ expect(subject.order.adjustments.to_a.sum(&:amount)).not_to eq 0
82
+ end
83
+
84
+ include_context "discount changes order total"
85
+ end
86
+
87
+ context "one active line item promotion" do
88
+ let!(:action) { Spree::Promotion::Actions::CreateItemAdjustments.create(promotion: promotion, calculator: calculator) }
89
+
90
+ it "creates valid discount on order" do
91
+ subject.add(variant, 1)
92
+ expect(subject.order.line_item_adjustments.to_a.sum(&:amount)).not_to eq 0
93
+ end
94
+
95
+ include_context "discount changes order total"
96
+ end
97
+ end
98
+ end
99
+
100
+ context "#remove" do
101
+ context "given an invalid variant" do
102
+ it "raises an exception" do
103
+ expect {
104
+ subject.remove(variant, 1)
105
+ }.to raise_error(ActiveRecord::RecordNotFound)
106
+ end
107
+ end
108
+
109
+ context 'given quantity is not explicitly provided' do
110
+ it 'should remove one line item' do
111
+ line_item = subject.add(variant, 3)
112
+ subject.remove(variant)
113
+
114
+ expect(line_item.reload.quantity).to eq(2)
115
+ end
116
+ end
117
+
118
+ context 'given a shipment' do
119
+ it "ensure shipment calls update_amounts instead of order calling ensure_updated_shipments" do
120
+ line_item = subject.add(variant, 1)
121
+ shipment = create(:shipment)
122
+ expect(subject.order).to_not receive(:ensure_updated_shipments)
123
+ expect(shipment).to receive(:update_amounts)
124
+ subject.remove(variant, 1, shipment: shipment)
125
+ end
126
+ end
127
+
128
+ context 'not given a shipment' do
129
+ it "ensures updated shipments" do
130
+ line_item = subject.add(variant, 1)
131
+ expect(subject.order).to receive(:ensure_updated_shipments)
132
+ subject.remove(variant)
133
+ end
134
+ end
135
+
136
+ it 'should reduce line_item quantity if quantity is less the line_item quantity' do
137
+ line_item = subject.add(variant, 3)
138
+ subject.remove(variant, 1)
139
+
140
+ expect(line_item.reload.quantity).to eq(2)
141
+ end
142
+
143
+ it 'should remove line_item if quantity matches line_item quantity' do
144
+ subject.add(variant, 1)
145
+ subject.remove(variant, 1)
146
+
147
+ expect(order.reload.find_line_item_by_variant(variant)).to be_nil
148
+ end
149
+
150
+ it "should update order totals" do
151
+ expect(order.item_total.to_f).to eq(0.00)
152
+ expect(order.total.to_f).to eq(0.00)
153
+
154
+ subject.add(variant,2)
155
+
156
+ expect(order.item_total.to_f).to eq(39.98)
157
+ expect(order.total.to_f).to eq(39.98)
158
+
159
+ subject.remove(variant,1)
160
+ expect(order.item_total.to_f).to eq(19.99)
161
+ expect(order.total.to_f).to eq(19.99)
162
+ end
163
+ end
164
+
165
+ context "#remove_line_item" do
166
+ context 'given a shipment' do
167
+ it "ensure shipment calls update_amounts instead of order calling ensure_updated_shipments" do
168
+ line_item = subject.add(variant, 1)
169
+ shipment = create(:shipment)
170
+ expect(subject.order).to_not receive(:ensure_updated_shipments)
171
+ expect(shipment).to receive(:update_amounts)
172
+ subject.remove_line_item(line_item, shipment: shipment)
173
+ end
174
+ end
175
+
176
+ context 'not given a shipment' do
177
+ it "ensures updated shipments" do
178
+ line_item = subject.add(variant, 1)
179
+ expect(subject.order).to receive(:ensure_updated_shipments)
180
+ subject.remove_line_item(line_item)
181
+ end
182
+ end
183
+
184
+ it 'should remove line_item' do
185
+ line_item = subject.add(variant, 1)
186
+ subject.remove_line_item(line_item)
187
+
188
+ expect(order.reload.line_items).to_not include(line_item)
189
+ end
190
+
191
+ it "should update order totals" do
192
+ expect(order.item_total.to_f).to eq(0.00)
193
+ expect(order.total.to_f).to eq(0.00)
194
+
195
+ line_item = subject.add(variant,2)
196
+
197
+ expect(order.item_total.to_f).to eq(39.98)
198
+ expect(order.total.to_f).to eq(39.98)
199
+
200
+ subject.remove_line_item(line_item)
201
+ expect(order.item_total.to_f).to eq(0.00)
202
+ expect(order.total.to_f).to eq(0.00)
203
+ end
204
+ end
205
+
206
+
207
+ context "update cart" do
208
+ let!(:shirt) { subject.add variant, 1 }
209
+
210
+ let(:params) do
211
+ { line_items_attributes: {
212
+ "0" => { id: shirt.id, quantity: 3 }
213
+ } }
214
+ end
215
+
216
+ it "changes item quantity" do
217
+ subject.update_cart params
218
+ expect(shirt.reload.quantity).to eq 3
219
+ end
220
+
221
+ it "updates order totals" do
222
+ expect {
223
+ subject.update_cart params
224
+ }.to change { subject.order.total }
225
+ end
226
+
227
+ context "submits item quantity 0" do
228
+ let(:params) do
229
+ { line_items_attributes: {
230
+ "0" => { id: shirt.id, quantity: 0 },
231
+ } }
232
+ end
233
+
234
+ it "removes item from order" do
235
+ expect {
236
+ subject.update_cart params
237
+ }.to change { subject.order.line_items.count }
238
+ end
239
+ end
240
+
241
+ it "ensures updated shipments" do
242
+ expect(subject.order).to receive(:ensure_updated_shipments)
243
+ subject.update_cart params
244
+ end
245
+ end
246
+
247
+ context "completed order" do
248
+ let(:order) { Spree::Order.create! state: 'complete', completed_at: Time.now }
249
+
250
+ before { order.shipments.create! stock_location_id: variant.stock_location_ids.first }
251
+
252
+ it "updates order payment state" do
253
+ expect {
254
+ subject.add variant
255
+ }.to change { order.payment_state }
256
+
257
+ expect {
258
+ subject.remove variant
259
+ }.to change { order.payment_state }
260
+ end
261
+ end
262
+
263
+ describe "#approve" do
264
+ context 'when a name is supplied' do
265
+ it 'approves the order' do
266
+ order.contents.approve(name: 'Jordan')
267
+ expect(order.approver).to be_nil
268
+ expect(order.approver_name).to eq('Jordan')
269
+ expect(order.approved_at).to be_present
270
+ expect(order.approved?).to be_truthy
271
+ end
272
+ end
273
+
274
+ context 'when a user is supplied' do
275
+ let(:user) { create(:user) }
276
+
277
+ it 'approves the order' do
278
+ order.contents.approve(user: user)
279
+ expect(order.approver).to eq(user)
280
+ expect(order.approver_name).to be_nil
281
+ expect(order.approved_at).to be_present
282
+ expect(order.approved?).to be_truthy
283
+ end
284
+ end
285
+
286
+ context 'when a user and a name are supplied' do
287
+ let(:user) { create(:user) }
288
+
289
+ it 'approves the order' do
290
+ order.contents.approve(user: user, name: 'Jordan')
291
+ expect(order.approver).to eq(user)
292
+ expect(order.approver_name).to eq('Jordan')
293
+ expect(order.approved_at).to be_present
294
+ expect(order.approved?).to be_truthy
295
+ end
296
+ end
297
+
298
+ context 'when neither a user nor a name are supplied' do
299
+ it 'raises' do
300
+ expect {
301
+ order.contents.approve
302
+ }.to raise_error(ArgumentError, 'user or name must be specified')
303
+ end
304
+ end
305
+ end
306
+
307
+ end