solidus_core 2.8.6 → 2.9.0.rc.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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/logo/solidus.svg +1 -18
  3. data/app/assets/images/logo/solidus_logo.png +0 -0
  4. data/app/mailers/spree/test_mailer.rb +2 -0
  5. data/app/models/concerns/spree/default_price.rb +1 -1
  6. data/app/models/concerns/spree/ransackable_attributes.rb +1 -1
  7. data/app/models/concerns/spree/user_reporting.rb +1 -1
  8. data/app/models/spree/billing_integration.rb +7 -2
  9. data/app/models/spree/country.rb +2 -0
  10. data/app/models/spree/customer_return.rb +1 -1
  11. data/app/models/spree/image.rb +2 -44
  12. data/app/models/spree/image/paperclip_attachment.rb +55 -0
  13. data/app/models/spree/inventory_unit.rb +0 -1
  14. data/app/models/spree/option_type.rb +2 -0
  15. data/app/models/spree/option_value.rb +1 -1
  16. data/app/models/spree/order.rb +8 -13
  17. data/app/models/spree/payment.rb +1 -1
  18. data/app/models/spree/payment_method.rb +8 -4
  19. data/app/models/spree/product.rb +1 -1
  20. data/app/models/spree/promotion.rb +18 -11
  21. data/app/models/spree/promotion/rules/first_order.rb +1 -3
  22. data/app/models/spree/promotion/rules/item_total.rb +9 -1
  23. data/app/models/spree/promotion/rules/one_use_per_user.rb +2 -2
  24. data/app/models/spree/promotion/rules/product.rb +3 -3
  25. data/app/models/spree/promotion/rules/taxon.rb +5 -8
  26. data/app/models/spree/promotion/rules/user_logged_in.rb +1 -1
  27. data/app/models/spree/promotion_handler/coupon.rb +19 -3
  28. data/app/models/spree/property.rb +2 -0
  29. data/app/models/spree/reimbursement.rb +5 -5
  30. data/app/models/spree/return_item.rb +6 -2
  31. data/app/models/spree/state.rb +6 -0
  32. data/app/models/spree/stock/location_filter/active.rb +14 -0
  33. data/app/models/spree/stock/location_filter/base.rb +43 -0
  34. data/app/models/spree/stock/simple_coordinator.rb +4 -1
  35. data/app/models/spree/stock_location.rb +2 -0
  36. data/app/models/spree/tax_category.rb +11 -0
  37. data/app/models/spree/taxon.rb +4 -11
  38. data/app/models/spree/taxon/paperclip_attachment.rb +21 -0
  39. data/app/models/spree/taxonomy.rb +2 -0
  40. data/app/models/spree/unit_cancel.rb +12 -1
  41. data/app/models/spree/variant.rb +1 -1
  42. data/app/models/spree/variant/pricing_options.rb +10 -0
  43. data/app/models/spree/wallet_payment_source.rb +26 -10
  44. data/app/models/spree/zone.rb +1 -1
  45. data/app/views/spree/order_mailer/inventory_cancellation_email.text.erb +3 -3
  46. data/config/locales/en.yml +26 -53
  47. data/db/default/spree/store_credit.rb +1 -0
  48. data/db/migrate/20161123154034_add_available_to_users_and_remove_display_on_from_shipping_methods.rb +1 -1
  49. data/db/migrate/20170608074534_rename_bogus_gateways.rb +9 -8
  50. data/db/migrate/20190220093635_drop_spree_store_credit_update_reasons.rb +19 -0
  51. data/lib/generators/spree/install/install_generator.rb +0 -3
  52. data/lib/generators/spree/install/templates/config/initializers/spree.rb.tt +3 -0
  53. data/lib/solidus/migrations/rename_gateways.rb +2 -0
  54. data/lib/spree/app_configuration.rb +24 -0
  55. data/lib/spree/core.rb +1 -0
  56. data/lib/spree/core/controller_helpers/pricing.rb +1 -4
  57. data/lib/spree/core/controller_helpers/strong_parameters.rb +7 -21
  58. data/lib/spree/core/engine.rb +5 -0
  59. data/lib/spree/core/importer/order.rb +1 -3
  60. data/lib/spree/core/stock_configuration.rb +5 -0
  61. data/lib/spree/core/version.rb +3 -1
  62. data/lib/spree/deprecation.rb +50 -0
  63. data/lib/spree/event.rb +111 -0
  64. data/lib/spree/event/adapters/active_support_notifications.rb +35 -0
  65. data/lib/spree/event/configuration.rb +17 -0
  66. data/lib/spree/event/processors/mailer_processor.rb +27 -0
  67. data/lib/spree/event/subscriber.rb +84 -0
  68. data/lib/spree/permitted_attributes.rb +7 -76
  69. data/lib/spree/testing_support/capybara_ext.rb +15 -0
  70. data/lib/spree/testing_support/common_rake.rb +1 -1
  71. data/lib/spree/testing_support/dummy_app.rb +3 -10
  72. data/lib/spree/testing_support/factories/promotion_factory.rb +10 -0
  73. data/lib/spree/testing_support/factories/return_item_factory.rb +1 -0
  74. data/lib/spree/testing_support/preferences.rb +62 -0
  75. data/lib/tasks/email.rake +2 -0
  76. data/lib/tasks/migrations/copy_order_bill_address_to_credit_card.rake +4 -0
  77. data/lib/tasks/migrations/migrate_shipping_rate_taxes.rake +2 -0
  78. data/lib/tasks/migrations/migrate_user_addresses.rake +3 -0
  79. data/lib/tasks/migrations/rename_gateways.rake +2 -0
  80. data/lib/tasks/order_capturing.rake +2 -0
  81. data/spec/helpers/base_helper_spec.rb +3 -3
  82. data/spec/helpers/products_helper_spec.rb +2 -2
  83. data/spec/{models → lib}/spree/app_configuration_spec.rb +11 -1
  84. data/spec/lib/spree/core/controller_helpers/pricing_spec.rb +13 -0
  85. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +1 -8
  86. data/spec/lib/spree/core/testing_support/factories/shipping_method_factory_spec.rb +1 -1
  87. data/spec/lib/spree/core/testing_support/preferences_spec.rb +33 -0
  88. data/spec/lib/spree/event/subscriber_spec.rb +85 -0
  89. data/spec/lib/spree/event_spec.rb +92 -0
  90. data/spec/lib/spree/money_spec.rb +3 -9
  91. data/spec/lib/tasks/migrations/migrate_shipping_rate_taxes_spec.rb +5 -3
  92. data/spec/mailers/order_mailer_spec.rb +1 -1
  93. data/spec/mailers/test_mailer_spec.rb +3 -1
  94. data/spec/models/spree/address_spec.rb +5 -4
  95. data/spec/models/spree/concerns/user_address_book_spec.rb +4 -4
  96. data/spec/models/spree/country_spec.rb +5 -5
  97. data/spec/models/spree/customer_return_spec.rb +1 -1
  98. data/spec/models/spree/order/checkout_spec.rb +3 -7
  99. data/spec/models/spree/order/finalizing_spec.rb +1 -1
  100. data/spec/models/spree/order/payment_spec.rb +3 -3
  101. data/spec/models/spree/order_inventory_spec.rb +1 -1
  102. data/spec/models/spree/order_spec.rb +67 -2
  103. data/spec/models/spree/order_updater_spec.rb +2 -2
  104. data/spec/models/spree/payment_spec.rb +12 -0
  105. data/spec/models/spree/product_spec.rb +3 -3
  106. data/spec/models/spree/promotion/rules/first_order_spec.rb +13 -3
  107. data/spec/models/spree/promotion/rules/item_total_spec.rb +15 -0
  108. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +10 -0
  109. data/spec/models/spree/promotion/rules/product_spec.rb +15 -0
  110. data/spec/models/spree/promotion/rules/taxon_spec.rb +59 -8
  111. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +5 -0
  112. data/spec/models/spree/promotion_handler/shipping_spec.rb +1 -1
  113. data/spec/models/spree/promotion_spec.rb +80 -0
  114. data/spec/models/spree/reimbursement_spec.rb +3 -2
  115. data/spec/models/spree/return_item_spec.rb +9 -0
  116. data/spec/models/spree/shipment_spec.rb +3 -3
  117. data/spec/models/spree/stock/availability_spec.rb +1 -1
  118. data/spec/models/spree/stock/estimator_spec.rb +5 -7
  119. data/spec/models/spree/stock/location_filter/active_spec.rb +22 -0
  120. data/spec/models/spree/stock/location_sorter/default_first_spec.rb +4 -2
  121. data/spec/models/spree/stock/location_sorter/unsorted_spec.rb +3 -1
  122. data/spec/models/spree/stock/quantifier_spec.rb +1 -1
  123. data/spec/models/spree/stock/simple_coordinator_spec.rb +5 -0
  124. data/spec/models/spree/stock_item_spec.rb +3 -2
  125. data/spec/models/spree/stock_movement_spec.rb +1 -1
  126. data/spec/models/spree/store_credit_spec.rb +1 -1
  127. data/spec/models/spree/tax/order_adjuster_spec.rb +1 -1
  128. data/spec/models/spree/tax/taxation_integration_spec.rb +1 -1
  129. data/spec/models/spree/tax_category_spec.rb +21 -0
  130. data/spec/models/spree/taxon_spec.rb +28 -0
  131. data/spec/models/spree/unit_cancel_spec.rb +41 -0
  132. data/spec/models/spree/user_spec.rb +3 -3
  133. data/spec/models/spree/variant/pricing_options_spec.rb +23 -0
  134. data/spec/models/spree/variant/vat_price_generator_spec.rb +1 -1
  135. data/spec/models/spree/variant_spec.rb +11 -8
  136. data/spec/models/spree/wallet_payment_source_spec.rb +35 -6
  137. data/spec/models/spree/wallet_spec.rb +1 -1
  138. data/spec/spec_helper.rb +0 -4
  139. data/spec/support/concerns/default_price.rb +8 -0
  140. metadata +18 -5
  141. data/spec/lib/spree/permitted_attributes_spec.rb +0 -41
@@ -77,7 +77,7 @@ module Spree::Stock
77
77
  end
78
78
 
79
79
  context 'with config.track_inventory_levels=false' do
80
- before { Spree::Config.track_inventory_levels = false }
80
+ before { stub_spree_preferences(track_inventory_levels: false) }
81
81
 
82
82
  it "has infinite inventory " do
83
83
  expect(subject).to eq(stock_location1.id => Spree::StockQuantities.new(variant => infinity))
@@ -195,13 +195,11 @@ module Spree
195
195
  Spree::ShippingRate.new
196
196
  end
197
197
  end
198
- Spree::Config.shipping_rate_selector_class = selector_class
198
+ stub_spree_preferences(shipping_rate_selector_class: selector_class)
199
199
 
200
200
  subject.shipping_rates(package)
201
201
 
202
202
  expect(shipping_rate.selected).to eq(true)
203
-
204
- Spree::Config.shipping_rate_selector_class = nil
205
203
  end
206
204
 
207
205
  it 'uses the configured shipping rate sorter' do
@@ -209,7 +207,8 @@ module Spree
209
207
  def initialize(_rates)
210
208
  end
211
209
  end
212
- Spree::Config.shipping_rate_sorter_class = Spree::Stock::TestSorter
210
+
211
+ stub_spree_preferences(shipping_rate_sorter_class: Spree::Stock::TestSorter)
213
212
 
214
213
  sorter = double(:sorter, sort: nil)
215
214
  allow(Spree::Stock::TestSorter).to receive(:new) { sorter }
@@ -217,8 +216,6 @@ module Spree
217
216
  subject.shipping_rates(package)
218
217
 
219
218
  expect(sorter).to have_received(:sort)
220
-
221
- Spree::Config.shipping_rate_sorter_class = nil
222
219
  end
223
220
 
224
221
  it 'uses the configured shipping rate taxer' do
@@ -232,7 +229,8 @@ module Spree
232
229
  ]
233
230
  end
234
231
  end
235
- Spree::Config.shipping_rate_tax_calculator_class = Spree::Tax::TestTaxCalculator
232
+
233
+ stub_spree_preferences(shipping_rate_tax_calculator_class: Spree::Tax::TestTaxCalculator)
236
234
 
237
235
  expect(Spree::Tax::TestTaxCalculator).to receive(:new).and_call_original
238
236
  subject.shipping_rates(package)
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ module Spree
6
+ module Stock
7
+ module LocationFilter
8
+ RSpec.describe Active, type: :model do
9
+ subject { described_class.new(stock_locations, order) }
10
+
11
+ let!(:active_stock_location) { create(:stock_location) }
12
+ let!(:inactive_stock_location) { create(:stock_location, active: false) }
13
+ let(:stock_locations) { Spree::StockLocation.all }
14
+ let(:order) { instance_double('Spree::Order') }
15
+
16
+ it 'returns only active stock locations' do
17
+ expect(subject.filter).to eq([active_stock_location])
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,8 +8,10 @@ module Spree
8
8
  RSpec.describe DefaultFirst, type: :model do
9
9
  subject { described_class.new(stock_locations) }
10
10
 
11
- let(:stock_locations) { OpenStruct.new(order_default: sorted_stock_locations) }
12
- let(:sorted_stock_locations) { instance_double('Spree::StockLocation::ActiveRecord_Relation') }
11
+ let!(:first_stock_location) { create(:stock_location, default: false) }
12
+ let!(:second_stock_location) { create(:stock_location, default: true) }
13
+ let(:stock_locations) { Spree::StockLocation.all }
14
+ let(:sorted_stock_locations) { stock_locations.reverse }
13
15
 
14
16
  it 'returns the default stock location first' do
15
17
  expect(subject.sort).to eq(sorted_stock_locations)
@@ -8,7 +8,9 @@ module Spree
8
8
  RSpec.describe Unsorted, type: :model do
9
9
  subject { described_class.new(stock_locations) }
10
10
 
11
- let(:stock_locations) { instance_double('Spree::StockLocation::ActiveRecord_Relation') }
11
+ let!(:first_stock_location) { create(:stock_location) }
12
+ let!(:second_stock_location) { create(:stock_location) }
13
+ let(:stock_locations) { Spree::StockLocation.all }
12
14
 
13
15
  it 'returns the original stock locations unsorted' do
14
16
  expect(subject.sort).to eq(stock_locations)
@@ -27,7 +27,7 @@ module Spree
27
27
  end
28
28
 
29
29
  context 'when track_inventory_levels is false' do
30
- before { configure_spree_preferences { |config| config.track_inventory_levels = false } }
30
+ before { stub_spree_preferences track_inventory_levels: false }
31
31
 
32
32
  specify { expect(subject.total_on_hand).to eq(Float::INFINITY) }
33
33
 
@@ -15,6 +15,11 @@ module Spree
15
15
  subject.shipments
16
16
  end
17
17
 
18
+ it 'uses the configured stock location filter' do
19
+ expect(Spree::Config.stock).to receive(:location_filter_class).and_call_original
20
+ subject.shipments
21
+ end
22
+
18
23
  it 'uses the configured stock location sorter' do
19
24
  expect(Spree::Config.stock).to receive(:location_sorter_class).and_call_original
20
25
  subject.shipments
@@ -196,7 +196,7 @@ RSpec.describe Spree::StockItem, type: :model do
196
196
 
197
197
  context "inventory_cache_threshold is set" do
198
198
  before do
199
- Spree::Config.inventory_cache_threshold = inventory_cache_threshold
199
+ stub_spree_preferences(inventory_cache_threshold: inventory_cache_threshold)
200
200
  end
201
201
 
202
202
  let(:inventory_cache_threshold) { 5 }
@@ -241,7 +241,7 @@ RSpec.describe Spree::StockItem, type: :model do
241
241
 
242
242
  context "when deprecated binary_inventory_cache is used" do
243
243
  before do
244
- Spree::Config.binary_inventory_cache = binary_inventory_cache
244
+ stub_spree_preferences(binary_inventory_cache: binary_inventory_cache)
245
245
  allow(Spree::Deprecation).to receive(:warn)
246
246
  subject.set_count_on_hand(9)
247
247
  end
@@ -256,6 +256,7 @@ RSpec.describe Spree::StockItem, type: :model do
256
256
 
257
257
  context "binary_inventory_cache is set to false" do
258
258
  let(:binary_inventory_cache) { false }
259
+
259
260
  it "inventory_cache_threshold remains nil" do
260
261
  expect(Spree::Config.inventory_cache_threshold).to be_nil
261
262
  end
@@ -19,7 +19,7 @@ RSpec.describe Spree::StockMovement, type: :model do
19
19
  end
20
20
 
21
21
  it 'does not update count on hand when track inventory levels is false' do
22
- Spree::Config[:track_inventory_levels] = false
22
+ stub_spree_preferences(track_inventory_levels: false)
23
23
  subject.quantity = 1
24
24
  subject.save
25
25
  stock_item.reload
@@ -507,7 +507,7 @@ RSpec.describe Spree::StoreCredit do
507
507
  let(:auth_code) { event_auth_code }
508
508
 
509
509
  context "credit_to_new_allocation is set" do
510
- before { Spree::Config[:credit_to_new_allocation] = true }
510
+ before { stub_spree_preferences(credit_to_new_allocation: true) }
511
511
 
512
512
  it "returns true" do
513
513
  expect(subject).to be true
@@ -20,7 +20,7 @@ RSpec.describe Spree::Tax::OrderAdjuster do
20
20
  let(:custom_calculator_instance) { double }
21
21
 
22
22
  before do
23
- Spree::Config.tax_calculator_class = custom_calculator_class
23
+ stub_spree_preferences(tax_calculator_class: custom_calculator_class)
24
24
  end
25
25
 
26
26
  it 'calls the configured tax calculator' do
@@ -135,7 +135,7 @@ RSpec.describe "Taxation system integration tests" do
135
135
  end
136
136
 
137
137
  before do
138
- Spree::Config.admin_vat_country_iso = "DE"
138
+ stub_spree_preferences(admin_vat_country_iso: "DE")
139
139
  order.contents.add(variant)
140
140
  end
141
141
 
@@ -26,4 +26,25 @@ RSpec.describe Spree::TaxCategory, type: :model do
26
26
  expect(tax_category.is_default).to be true
27
27
  end
28
28
  end
29
+
30
+ context ".discard" do
31
+ let(:tax_category) { create(:tax_category) }
32
+
33
+ it "set deleted_at correctly" do
34
+ tax_category.discard
35
+ expect(tax_category.deleted_at).not_to be_blank
36
+ end
37
+
38
+ context "when there are tax_rates associated" do
39
+ let(:tax_rate) { create(:tax_rate) }
40
+ let(:tax_category) { tax_rate.tax_categories.first }
41
+
42
+ it 'correctly discard association records' do
43
+ expect { tax_category.discard }
44
+ .to change { tax_category.tax_rates.size }
45
+ .from(1)
46
+ .to(0)
47
+ end
48
+ end
49
+ end
29
50
  end
@@ -26,6 +26,14 @@ RSpec.describe Spree::Taxon, type: :model do
26
26
  expect(taxon.permalink).to eql "ruby-on-rails"
27
27
  end
28
28
 
29
+ context "updating a taxon permalink" do
30
+ it 'parameterizes permalink correctly' do
31
+ taxon.save!
32
+ taxon.update_attributes(permalink: 'spécial&charactèrs')
33
+ expect(taxon.permalink).to eql "special-characters"
34
+ end
35
+ end
36
+
29
37
  context "with parent taxon" do
30
38
  let(:parent) { FactoryBot.build(:taxon, permalink: "brands") }
31
39
  before { allow(taxon).to receive_messages parent: parent }
@@ -41,6 +49,12 @@ RSpec.describe Spree::Taxon, type: :model do
41
49
  expect(taxon.permalink).to eql "brands/rubyonrails"
42
50
  end
43
51
 
52
+ it 'parameterizes permalink correctly' do
53
+ taxon.save!
54
+ taxon.update_attributes(permalink_part: 'spécial&charactèrs')
55
+ expect(taxon.reload.permalink).to eql "brands/special-characters"
56
+ end
57
+
44
58
  # Regression test for https://github.com/spree/spree/issues/3390
45
59
  context "setting a new node sibling position via :child_index=" do
46
60
  let(:idx) { rand(0..100) }
@@ -121,6 +135,20 @@ RSpec.describe Spree::Taxon, type: :model do
121
135
  is_expected.to change{ taxon2_child.reload.permalink }.from('t/t2/t2_child').to('t/t1/foo/t2_child')
122
136
  end
123
137
  end
138
+
139
+ context 'changing parent permalink with special characters ' do
140
+ subject do
141
+ -> { taxon2.update!(permalink: 'spécial&charactèrs') }
142
+ end
143
+
144
+ it 'changes own permalink with parameterized characters' do
145
+ is_expected.to change{ taxon2.reload.permalink }.from('t/t2').to('t/special-characters')
146
+ end
147
+
148
+ it 'changes child permalink with parameterized characters' do
149
+ is_expected.to change{ taxon2_child.reload.permalink }.from('t/t2/t2_child').to('t/special-characters/t2_child')
150
+ end
151
+ end
124
152
  end
125
153
 
126
154
  # Regression test for https://github.com/spree/spree/issues/2620
@@ -76,5 +76,46 @@ RSpec.describe Spree::UnitCancel do
76
76
  expect(line_item.reload.total.to_d).to eq(0)
77
77
  end
78
78
  end
79
+
80
+ context 'when line item has additional taxes' do
81
+ let(:world_zone) { create(:zone, :with_country) }
82
+ let(:tax_category) { create :tax_category }
83
+ let(:product) { create :product, tax_category: tax_category }
84
+ let!(:additional_tax_rate) do
85
+ create(
86
+ :tax_rate,
87
+ name: 'Additional tax',
88
+ tax_categories: [tax_category],
89
+ zone: world_zone,
90
+ included_in_price: false,
91
+ amount: 0.15
92
+ )
93
+ end
94
+ let(:shipping_category) { create :shipping_category }
95
+ let(:shipping_method) do
96
+ create :shipping_method,
97
+ cost: 8.00,
98
+ shipping_categories: [shipping_category],
99
+ tax_category: tax_category,
100
+ zones: [world_zone]
101
+ end
102
+ let(:shipping_address) { create :address, country_iso_code: world_zone.countries.first.iso }
103
+ let(:order) do
104
+ create(
105
+ :order_with_line_items,
106
+ ship_address: shipping_address,
107
+ line_items_attributes: [{ product: product }]
108
+ )
109
+ end
110
+ let(:line_item) { order.line_items.first }
111
+ let(:inventory_unit) { line_item.inventory_units.first }
112
+
113
+ before { order.recalculate }
114
+
115
+ it 'does not include line item additional taxes' do
116
+ expect(line_item.additional_tax_total).not_to eq 0
117
+ expect(subject).to eq(-5.0)
118
+ end
119
+ end
79
120
  end
80
121
  end
@@ -36,7 +36,7 @@ RSpec.describe Spree::LegacyUser, type: :model do
36
36
 
37
37
  context "with completable_order_created_cutoff set" do
38
38
  before do
39
- Spree::Config.completable_order_created_cutoff_days = 1
39
+ stub_spree_preferences(completable_order_created_cutoff_days: 1)
40
40
  end
41
41
 
42
42
  it "excludes orders updated outside of the cutoff date" do
@@ -47,7 +47,7 @@ RSpec.describe Spree::LegacyUser, type: :model do
47
47
 
48
48
  context "with completable_order_created_cutoff set" do
49
49
  before do
50
- Spree::Config.completable_order_updated_cutoff_days = 1
50
+ stub_spree_preferences(completable_order_updated_cutoff_days: 1)
51
51
  end
52
52
 
53
53
  it "excludes orders updated outside of the cutoff date" do
@@ -142,7 +142,7 @@ RSpec.describe Spree.user_class, type: :model do
142
142
  describe "#order_count" do
143
143
  before { load_orders }
144
144
  it "returns the count of completed orders for the user" do
145
- expect(subject.order_count).to eq BigDecimal(order_count)
145
+ expect(subject.order_count).to eq order_count
146
146
  end
147
147
  end
148
148
 
@@ -70,6 +70,29 @@ RSpec.describe Spree::Variant::PricingOptions do
70
70
  end
71
71
  end
72
72
 
73
+ context ".from_context" do
74
+ let(:view_context) { double(ApplicationController, current_store: store) }
75
+ subject { described_class.from_context(view_context) }
76
+
77
+ context "if the store has not defined default_currency" do
78
+ let(:store) { FactoryBot.create :store, default_currency: nil, cart_tax_country_iso: nil }
79
+
80
+ it "fallbacks to Spree::Config.currency" do
81
+ expect(Spree::Variant::PricingOptions).to receive(:new).with(currency: Spree::Config.currency, country_iso: nil)
82
+ expect(subject).to be_nil
83
+ end
84
+ end
85
+
86
+ context 'if the store has default_currency and cart_tax_country_iso' do
87
+ let(:store) { FactoryBot.create :store, default_currency: 'MXN' }
88
+
89
+ it "uses current_store information" do
90
+ expect(Spree::Variant::PricingOptions).to receive(:new).with(currency: store.default_currency, country_iso: store.cart_tax_country_iso)
91
+ expect(subject).to be_nil
92
+ end
93
+ end
94
+ end
95
+
73
96
  describe '#desired_attributes' do
74
97
  context "when called with no arguments" do
75
98
  it "returns the default pricing options" do
@@ -18,7 +18,7 @@ RSpec.describe Spree::Variant::VatPriceGenerator do
18
18
  let!(:french_vat) { create(:tax_rate, included_in_price: true, amount: 0.20, zone: france_zone, tax_categories: [tax_category]) }
19
19
 
20
20
  before do
21
- Spree::Config.admin_vat_country_iso = "DE"
21
+ stub_spree_preferences(admin_vat_country_iso: "DE")
22
22
  end
23
23
 
24
24
  it "builds a correct price including VAT for all VAT countries" do
@@ -516,7 +516,7 @@ RSpec.describe Spree::Variant, type: :model do
516
516
 
517
517
  describe '#in_stock?' do
518
518
  before do
519
- Spree::Config.track_inventory_levels = true
519
+ stub_spree_preferences(track_inventory_levels: true)
520
520
  end
521
521
 
522
522
  context 'when stock_items are not backorderable' do
@@ -597,7 +597,7 @@ RSpec.describe Spree::Variant, type: :model do
597
597
 
598
598
  describe '#total_on_hand' do
599
599
  it 'should be infinite if track_inventory_levels is false' do
600
- Spree::Config[:track_inventory_levels] = false
600
+ stub_spree_preferences(track_inventory_levels: false)
601
601
  expect(build(:variant).total_on_hand).to eql(Float::INFINITY)
602
602
  end
603
603
 
@@ -640,19 +640,19 @@ RSpec.describe Spree::Variant, type: :model do
640
640
 
641
641
  describe "#should_track_inventory?" do
642
642
  it 'should not track inventory when global setting is off' do
643
- Spree::Config[:track_inventory_levels] = false
643
+ stub_spree_preferences(track_inventory_levels: false)
644
644
 
645
645
  expect(build(:variant).should_track_inventory?).to eq(false)
646
646
  end
647
647
 
648
648
  it 'should not track inventory when variant is turned off' do
649
- Spree::Config[:track_inventory_levels] = true
649
+ stub_spree_preferences(track_inventory_levels: true)
650
650
 
651
651
  expect(build(:on_demand_variant).should_track_inventory?).to eq(false)
652
652
  end
653
653
 
654
654
  it 'should track inventory when global and variant are on' do
655
- Spree::Config[:track_inventory_levels] = true
655
+ stub_spree_preferences(track_inventory_levels: true)
656
656
 
657
657
  expect(build(:variant).should_track_inventory?).to eq(true)
658
658
  end
@@ -749,8 +749,7 @@ RSpec.describe Spree::Variant, type: :model do
749
749
  end
750
750
 
751
751
  context "inventory levels globally not tracked" do
752
- before { Spree::Config.track_inventory_levels = false }
753
- after { Spree::Config.track_inventory_levels = true }
752
+ before { stub_spree_preferences(track_inventory_levels: false) }
754
753
 
755
754
  it 'includes items without inventory' do
756
755
  expect( subject ).to include out_of_stock_variant
@@ -783,8 +782,12 @@ RSpec.describe Spree::Variant, type: :model do
783
782
  expect( subject ).not_to include(out_of_stock_variant)
784
783
  end
785
784
 
785
+ it "includes variants only once" do
786
+ expect(subject.to_a.count(in_stock_variant)).to be 1
787
+ end
788
+
786
789
  context "inventory levels globally not tracked" do
787
- before { Spree::Config.track_inventory_levels = false }
790
+ before { stub_spree_preferences(track_inventory_levels: false) }
788
791
 
789
792
  it "includes all variants" do
790
793
  expect( subject ).to include(in_stock_variant, backordered_variant, out_of_stock_variant)
@@ -6,6 +6,8 @@ RSpec.describe Spree::WalletPaymentSource, type: :model do
6
6
  subject { Spree::WalletPaymentSource }
7
7
 
8
8
  describe "validation" do
9
+ let(:user) { create(:user) }
10
+
9
11
  context 'with a non-PaymentSource model' do
10
12
  with_model 'NonPaymentSource', scope: :all do
11
13
  model do
@@ -19,28 +21,55 @@ RSpec.describe Spree::WalletPaymentSource, type: :model do
19
21
  it "errors when `payment_source` is not a `Spree::PaymentSource`" do
20
22
  wallet_payment_source = Spree::WalletPaymentSource.new(
21
23
  payment_source: payment_source,
22
- user: create(:user)
24
+ user: user
23
25
  )
24
26
 
25
27
  expect(wallet_payment_source).not_to be_valid
26
28
  expect(wallet_payment_source.errors.messages).to eq(
27
- { payment_source: ["has to be a Spree::PaymentSource"] }
29
+ { payment_source: ["is not a valid payment source"] }
28
30
  )
29
31
  end
30
32
  end
31
33
 
34
+ it "is invalid if `payment_source` is already in the user's wallet" do
35
+ credit_card = create(:credit_card, user: user)
36
+ Spree::WalletPaymentSource.create(
37
+ payment_source: credit_card,
38
+ user: user
39
+ )
40
+ wallet_payment_source = subject.new(
41
+ payment_source: credit_card,
42
+ user: user
43
+ )
44
+ expect(wallet_payment_source).not_to be_valid
45
+ expect(wallet_payment_source.errors.messages).to eq(
46
+ { user_id: ["already has this payment source in their wallet"] }
47
+ )
48
+ end
49
+
50
+ it "is invalid when `payment_source` is not owned by the user" do
51
+ wallet_payment_source = subject.new(
52
+ payment_source: create(:credit_card),
53
+ user: user
54
+ )
55
+ expect(wallet_payment_source).not_to be_valid
56
+ expect(wallet_payment_source.errors.messages).to eq(
57
+ { payment_source: ["does not belong to the user associated with the order"] }
58
+ )
59
+ end
60
+
32
61
  it "is valid with a `credit_card` as `payment_source`" do
33
62
  valid_attrs = {
34
- payment_source: create(:credit_card),
35
- user: create(:user)
63
+ payment_source: create(:credit_card, user: user),
64
+ user: user
36
65
  }
37
66
  expect(subject.new(valid_attrs)).to be_valid
38
67
  end
39
68
 
40
69
  it "is valid with `store_credit` as `payment_source`" do
41
70
  valid_attrs = {
42
- payment_source: create(:store_credit),
43
- user: create(:user)
71
+ payment_source: create(:store_credit, user: user),
72
+ user: user
44
73
  }
45
74
  expect(subject.new(valid_attrs)).to be_valid
46
75
  end