solidus_core 1.3.0.beta1 → 1.3.0.rc1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/app/assets/images/noimage/large.png +0 -0
  4. data/app/assets/images/noimage/mini.png +0 -0
  5. data/app/assets/images/noimage/product.png +0 -0
  6. data/app/assets/images/noimage/small.png +0 -0
  7. data/app/models/spree/app_configuration.rb +9 -9
  8. data/app/models/spree/country.rb +1 -0
  9. data/app/models/spree/line_item.rb +7 -1
  10. data/app/models/spree/payment_method.rb +1 -1
  11. data/app/models/spree/preferences/preferable.rb +1 -0
  12. data/app/models/spree/preferences/statically_configurable.rb +2 -2
  13. data/app/models/spree/price.rb +30 -2
  14. data/app/models/spree/product.rb +4 -1
  15. data/app/models/spree/stock/inventory_unit_builder.rb +2 -2
  16. data/app/models/spree/tax/tax_location.rb +4 -0
  17. data/app/models/spree/tax_rate.rb +2 -11
  18. data/app/models/spree/variant/price_selector.rb +35 -0
  19. data/app/models/spree/variant/pricing_options.rb +69 -4
  20. data/app/models/spree/variant/vat_price_generator.rb +58 -0
  21. data/app/models/spree/variant.rb +38 -16
  22. data/config/locales/en.yml +22 -1
  23. data/db/migrate/20140410141842_add_many_missing_indexes.rb +15 -13
  24. data/db/migrate/20140410150358_correct_some_polymorphic_index_and_add_more_missing.rb +40 -38
  25. data/db/migrate/20141217215630_update_product_slug_index.rb +4 -2
  26. data/db/migrate/20150723224133_remove_unnecessary_indexes.rb +2 -10
  27. data/db/migrate/20151219020209_add_stock_item_unique_index.rb +2 -2
  28. data/db/migrate/20160509181311_add_country_iso_to_prices.rb +8 -0
  29. data/lib/spree/core/class_constantizer.rb +31 -0
  30. data/lib/spree/core/engine.rb +55 -59
  31. data/lib/spree/core/environment/calculators.rb +6 -1
  32. data/lib/spree/core/environment.rb +5 -2
  33. data/lib/spree/core/environment_extension.rb +16 -12
  34. data/lib/spree/core/price_migrator.rb +32 -0
  35. data/lib/spree/core/search/base.rb +2 -2
  36. data/lib/spree/core/version.rb +1 -1
  37. data/lib/spree/core.rb +4 -0
  38. data/lib/spree/migration_helpers.rb +19 -0
  39. data/lib/spree/money.rb +41 -15
  40. data/lib/spree/promo/environment.rb +2 -1
  41. data/lib/spree/testing_support/controller_requests.rb +22 -7
  42. data/lib/spree/testing_support/factories/state_factory.rb +7 -0
  43. data/lib/spree/testing_support/factories/stock_location_factory.rb +4 -1
  44. data/lib/tasks/migrations/create_vat_prices.rake +11 -0
  45. data/lib/tasks/upgrade.rake +2 -1
  46. data/spec/lib/spree/core/class_constantizer_spec.rb +68 -0
  47. data/spec/lib/spree/core/environment_extension_spec.rb +33 -0
  48. data/spec/lib/spree/core/price_migrator_spec.rb +356 -0
  49. data/spec/lib/spree/core/testing_support/factories/state_factory_spec.rb +9 -0
  50. data/spec/lib/spree/core/testing_support/factories/stock_location_factory_spec.rb +9 -0
  51. data/spec/lib/spree/money_spec.rb +75 -0
  52. data/spec/models/spree/app_configuration_spec.rb +5 -5
  53. data/spec/models/spree/country_spec.rb +16 -0
  54. data/spec/models/spree/line_item_spec.rb +6 -2
  55. data/spec/models/spree/preferences/preferable_spec.rb +5 -0
  56. data/spec/models/spree/preferences/statically_configurable_spec.rb +4 -0
  57. data/spec/models/spree/price_spec.rb +89 -0
  58. data/spec/models/spree/stock/coordinator_spec.rb +9 -0
  59. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +30 -32
  60. data/spec/models/spree/tax/tax_location_spec.rb +14 -5
  61. data/spec/models/spree/tax/taxation_integration_spec.rb +15 -42
  62. data/spec/models/spree/variant/{pricer_spec.rb → price_selector_spec.rb} +41 -1
  63. data/spec/models/spree/variant/pricing_options_spec.rb +87 -4
  64. data/spec/models/spree/variant/vat_price_generator_spec.rb +69 -0
  65. data/spec/models/spree/variant_spec.rb +57 -8
  66. metadata +14 -5
  67. data/app/models/spree/product_scope/scopes.rb +0 -47
  68. data/app/models/spree/variant/pricer.rb +0 -19
@@ -1,21 +1,36 @@
1
1
  module Spree
2
2
  module TestingSupport
3
- # Use this module to easily test Spree actions within Spree components or
4
- # inside your application to test routes for the mounted Spree engine.
3
+ # A module providing convenience methods to test Solidus controllers
4
+ # in Rails controller/functional tests. Possibly from inside an
5
+ # application with a mounted Solidus engine.
5
6
  #
6
- # Inside your spec_helper.rb, include this module inside the
7
- # RSpec.configure block by doing this:
7
+ # *There is generaly no need* to use this module. Instead, in
8
+ # a functional/controller test against a Spree controller, just
9
+ # use standard Rails functionality by including:
10
+ #
11
+ # routes { Spree::Core::Engine.routes }
12
+ #
13
+ # And then use standard Rails test `get`, `post` etc methods.
14
+ #
15
+ # But some legacy code uses this ControllerRequests helper. It must
16
+ # be included only in tests against Spree controllers, it will interfere
17
+ # with tests against local app or other engine controllers, resulting
18
+ # in ActionController::UrlGenerationError.
19
+ #
20
+ # To use this module, inside your spec_helper.rb, include this module inside
21
+ # the RSpec.configure block by:
8
22
  #
9
23
  # require 'spree/testing_support/controller_requests'
10
24
  # RSpec.configure do |c|
11
- # c.include Spree::TestingSupport::ControllerRequests, :type => :controller
25
+ # c.include Spree::TestingSupport::ControllerRequests, spree_controller: true
12
26
  # end
13
27
  #
14
- # Then, in your controller tests, you can access spree routes like this:
28
+ # Then, in your controller tests against spree controllers, you can access
29
+ # tag to use this module, and access spree routes like this:
15
30
  #
16
31
  # require 'spec_helper'
17
32
  #
18
- # describe Spree::ProductsController do
33
+ # describe Spree::ProductsController, :spree_controller do
19
34
  # it "can see all the products" do
20
35
  # spree_get :index
21
36
  # end
@@ -8,6 +8,13 @@ FactoryGirl.define do
8
8
 
9
9
  carmen_subregion do
10
10
  carmen_country = Carmen::Country.coded(country.iso)
11
+
12
+ # TODO: This condition can be removed after this carmen update is
13
+ # available: https://github.com/jim/carmen/pull/177
14
+ if !carmen_country.subregions?
15
+ fail("Country #{country.iso} has no subregions")
16
+ end
17
+
11
18
  carmen_country.subregions.coded(state_code) ||
12
19
  carmen_country.subregions.sort_by(&:name).first ||
13
20
  fail("Country #{country.iso} has no subregions")
@@ -14,7 +14,10 @@ FactoryGirl.define do
14
14
 
15
15
  country { |stock_location| Spree::Country.first || stock_location.association(:country) }
16
16
  state do |stock_location|
17
- stock_location.country.states.first || stock_location.association(:state, country: stock_location.country)
17
+ carmen_country = Carmen::Country.coded(stock_location.country.iso)
18
+ if carmen_country.subregions?
19
+ stock_location.country.states.first || stock_location.association(:state, country: stock_location.country)
20
+ end
18
21
  end
19
22
 
20
23
  factory :stock_location_without_variant_propagation do
@@ -0,0 +1,11 @@
1
+ namespace :solidus do
2
+ namespace :migrations do
3
+ namespace :create_vat_prices do
4
+ task up: :environment do
5
+ print "Creating differentiated prices for VAT countries ... "
6
+ Spree::PriceMigrator.migrate_default_vat_prices
7
+ puts "Success."
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,7 +3,8 @@ namespace :solidus do
3
3
  desc "Upgrade Solidus to version 1.3"
4
4
  task one_point_three: [
5
5
  'solidus:migrations:assure_store_on_orders:up',
6
- 'solidus:migrations:migrate_shipping_rate_taxes:up'
6
+ 'solidus:migrations:migrate_shipping_rate_taxes:up',
7
+ 'solidus:migrations:create_vat_prices'
7
8
  ] do
8
9
  puts "Your Solidus install is ready for Solidus 1.3."
9
10
  end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ module ClassConstantizerTest
4
+ ClassA = Class.new
5
+ ClassB = Class.new
6
+
7
+ def self.reload
8
+ [:ClassA, :ClassB].each do |klass|
9
+ remove_const(klass)
10
+ const_set(klass, Class.new)
11
+ end
12
+ end
13
+ end
14
+
15
+ describe Spree::Core::ClassConstantizer::Set do
16
+ let(:set) { described_class.new }
17
+
18
+ describe "#concat" do
19
+ it "can add one item" do
20
+ set.concat(['ClassConstantizerTest::ClassA'])
21
+ expect(set).to include(ClassConstantizerTest::ClassA)
22
+ end
23
+
24
+ it "can add two items" do
25
+ set.concat(['ClassConstantizerTest::ClassA', ClassConstantizerTest::ClassB])
26
+ expect(set).to include(ClassConstantizerTest::ClassA)
27
+ expect(set).to include(ClassConstantizerTest::ClassB)
28
+ end
29
+ end
30
+
31
+ describe "<<" do
32
+ it "can add by string" do
33
+ set << "ClassConstantizerTest::ClassA"
34
+ expect(set).to include(ClassConstantizerTest::ClassA)
35
+ end
36
+
37
+ it "can add by class" do
38
+ set << ClassConstantizerTest::ClassA
39
+ expect(set).to include(ClassConstantizerTest::ClassA)
40
+ end
41
+
42
+ describe "class redefinition" do
43
+ shared_examples "working code reloading" do
44
+ it "works with a class" do
45
+ original = ClassConstantizerTest::ClassA
46
+
47
+ ClassConstantizerTest.reload
48
+
49
+ # Sanity check
50
+ expect(original).not_to eq(ClassConstantizerTest::ClassA)
51
+
52
+ expect(set).to include(ClassConstantizerTest::ClassA)
53
+ expect(set).to_not include(original)
54
+ end
55
+ end
56
+
57
+ context "with a class" do
58
+ before { set << ClassConstantizerTest::ClassA }
59
+ it_should_behave_like "working code reloading"
60
+ end
61
+
62
+ context "with a string" do
63
+ before { set << "ClassConstantizerTest::ClassA" }
64
+ it_should_behave_like "working code reloading"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyClass
4
+ include Spree::Core::EnvironmentExtension
5
+ end
6
+
7
+ class C1; end
8
+ class C2; end
9
+ class C3; end
10
+
11
+ describe Spree::Core::EnvironmentExtension do
12
+ subject { DummyClass.new }
13
+
14
+ before { subject.add_class('random_name') }
15
+
16
+ describe 'Basis' do
17
+ it { respond_to?(:random_name) }
18
+ it { respond_to?(:random_name=) }
19
+ end
20
+
21
+ describe '#getter' do
22
+ it { expect(subject.random_name).to be_empty }
23
+ it { expect(subject.random_name).to be_kind_of Spree::Core::ClassConstantizer::Set }
24
+ end
25
+
26
+ describe '#setter' do
27
+ before { subject.random_name = [C1, C2]; @set = subject.random_name.to_a }
28
+
29
+ it { expect(@set).to include(C1) }
30
+ it { expect(@set).to include(C2) }
31
+ it { expect(@set).not_to include(C3) }
32
+ end
33
+ end
@@ -0,0 +1,356 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PriceMigrator do
4
+ let(:order) { create :order, ship_address: shipping_address, state: "delivery" }
5
+ let(:book_product) do
6
+ create :product,
7
+ price: 20,
8
+ name: "Book",
9
+ tax_category: books_category,
10
+ shipping_category: books_shipping_category
11
+ end
12
+ let(:download_product) do
13
+ create :product,
14
+ price: 10,
15
+ name: "Download",
16
+ tax_category: digital_category,
17
+ shipping_category: digital_shipping_category
18
+ end
19
+ let(:sweater_product) do
20
+ create :product,
21
+ price: 30,
22
+ name: "Download",
23
+ tax_category: normal_category,
24
+ shipping_category: normal_shipping_category
25
+ end
26
+
27
+ let!(:book) { book_product.master }
28
+ let!(:download) { download_product.master }
29
+ let!(:sweater) { sweater_product.master }
30
+
31
+ let(:books_category) { create :tax_category, name: "Books" }
32
+ let(:normal_category) { create :tax_category, name: "Normal" }
33
+ let(:digital_category) { create :tax_category, name: "Digital Goods" }
34
+
35
+ let(:books_shipping_category) { create :shipping_category, name: "Book Shipping" }
36
+ let(:normal_shipping_category) { create :shipping_category, name: "Normal Shipping" }
37
+ let(:digital_shipping_category) { create :shipping_category, name: "Digital Premium Download" }
38
+
39
+ let(:line_item) { order.line_items.first }
40
+ let(:shipment) { order.shipments.first }
41
+ let(:shipping_rate) { shipment.shipping_rates.first }
42
+
43
+ context 'selling from germany' do
44
+ let(:germany) { create :country, iso: "DE" }
45
+ # The weird default_tax boolean is what makes this context one with default included taxes
46
+ let!(:germany_zone) { create :zone, countries: [germany], default_tax: true }
47
+ let(:romania) { create(:country, iso: "RO") }
48
+ let(:romania_zone) { create(:zone, countries: [romania] ) }
49
+ let(:eu_zone) { create(:zone, countries: [romania, germany]) }
50
+ let(:world_zone) { create(:zone, :with_country) }
51
+
52
+ let!(:german_book_vat) do
53
+ create(
54
+ :tax_rate,
55
+ name: "German reduced VAT",
56
+ included_in_price: true,
57
+ amount: 0.07,
58
+ tax_category: books_category,
59
+ zone: eu_zone
60
+ )
61
+ end
62
+ let!(:german_normal_vat) do
63
+ create(
64
+ :tax_rate,
65
+ name: "German VAT",
66
+ included_in_price: true,
67
+ amount: 0.19,
68
+ tax_category: normal_category,
69
+ zone: eu_zone
70
+ )
71
+ end
72
+ let!(:german_digital_vat) do
73
+ create(
74
+ :tax_rate,
75
+ name: "German VAT",
76
+ included_in_price: true,
77
+ amount: 0.19,
78
+ tax_category: digital_category,
79
+ zone: germany_zone
80
+ )
81
+ end
82
+ let!(:romanian_digital_vat) do
83
+ create(
84
+ :tax_rate,
85
+ name: "Romanian VAT",
86
+ included_in_price: true,
87
+ amount: 0.24,
88
+ tax_category: digital_category,
89
+ zone: romania_zone
90
+ )
91
+ end
92
+ let!(:book_shipping_method) do
93
+ create :shipping_method,
94
+ cost: 8.00,
95
+ shipping_categories: [books_shipping_category],
96
+ tax_category: books_category,
97
+ zones: [eu_zone, world_zone]
98
+ end
99
+
100
+ let!(:sweater_shipping_method) do
101
+ create :shipping_method,
102
+ cost: 16.00,
103
+ shipping_categories: [normal_shipping_category],
104
+ tax_category: normal_category,
105
+ zones: [eu_zone, world_zone]
106
+ end
107
+
108
+ let!(:premium_download_shipping_method) do
109
+ create :shipping_method,
110
+ cost: 2.00,
111
+ shipping_categories: [digital_shipping_category],
112
+ tax_category: digital_category,
113
+ zones: [eu_zone, world_zone]
114
+ end
115
+
116
+ before do
117
+ Spree::PriceMigrator.migrate_default_vat_prices
118
+ order.contents.add(variant)
119
+ end
120
+
121
+ context 'to germany' do
122
+ let(:shipping_address) { create :address, country_iso_code: "DE" }
123
+
124
+ context 'an order with a book' do
125
+ let(:variant) { book }
126
+
127
+ it 'still has the original price' do
128
+ expect(line_item.price).to eq(20)
129
+ end
130
+
131
+ it 'has one tax adjustment' do
132
+ expect(line_item.adjustments.tax.count).to eq(1)
133
+ end
134
+
135
+ it 'has 1.13 cents of included tax' do
136
+ expect(line_item.included_tax_total).to eq(1.31)
137
+ end
138
+ end
139
+
140
+ context 'an order with a sweater' do
141
+ let(:variant) { sweater }
142
+
143
+ it 'still has the original price' do
144
+ expect(line_item.price).to eq(30)
145
+ end
146
+
147
+ it 'has one tax adjustment' do
148
+ expect(line_item.adjustments.tax.count).to eq(1)
149
+ end
150
+
151
+ it 'has 4,78 of included tax' do
152
+ expect(line_item.included_tax_total).to eq(4.79)
153
+ end
154
+ end
155
+
156
+ context 'an order with a download' do
157
+ let(:variant) { download }
158
+
159
+ it 'still has the original price' do
160
+ expect(line_item.price).to eq(10)
161
+ end
162
+
163
+ it 'has one tax adjustment' do
164
+ expect(line_item.adjustments.tax.count).to eq(1)
165
+ end
166
+
167
+ it 'has 1.60 of included tax' do
168
+ expect(line_item.included_tax_total).to eq(1.60)
169
+ end
170
+ end
171
+ end
172
+
173
+ context 'to romania' do
174
+ let(:shipping_address) { create :address, country_iso_code: "RO" }
175
+
176
+ context 'an order with a book' do
177
+ let(:variant) { book }
178
+
179
+ it 'still has the original price' do
180
+ expect(line_item.price).to eq(20)
181
+ end
182
+
183
+ it 'is adjusted to the original price' do
184
+ expect(line_item.total).to eq(20)
185
+ end
186
+
187
+ it 'has one tax adjustment' do
188
+ expect(line_item.adjustments.tax.count).to eq(1)
189
+ end
190
+
191
+ it 'has 1.13 cents of included tax' do
192
+ expect(line_item.included_tax_total).to eq(1.31)
193
+ end
194
+
195
+ it 'has a constant amount pre tax' do
196
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(18.69)
197
+ end
198
+ end
199
+
200
+ context 'an order with a sweater' do
201
+ let(:variant) { sweater }
202
+
203
+ it 'still has the original price' do
204
+ expect(line_item.price).to eq(30)
205
+ end
206
+
207
+ it 'has one tax adjustment' do
208
+ expect(line_item.adjustments.tax.count).to eq(1)
209
+ end
210
+
211
+ it 'has 4.79 of included tax' do
212
+ expect(line_item.included_tax_total).to eq(4.79)
213
+ end
214
+
215
+ it 'has a constant amount pre tax' do
216
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(25.21)
217
+ end
218
+ end
219
+
220
+ context 'an order with a download' do
221
+ let(:variant) { download }
222
+
223
+ it 'still has an adjusted price for romania' do
224
+ expect(line_item.price).to eq(10.42)
225
+ end
226
+
227
+ it 'has one tax adjustment' do
228
+ expect(line_item.adjustments.tax.count).to eq(1)
229
+ end
230
+
231
+ it 'has 2.02 of included tax' do
232
+ expect(line_item.included_tax_total).to eq(2.02)
233
+ end
234
+
235
+ it 'has a constant amount pre tax' do
236
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(8.40)
237
+ end
238
+ end
239
+ end
240
+
241
+ # Technically, this can't be the case yet as the order won't pass the shipment stage,
242
+ # but the taxation code shouldn't implicitly depend on the shipping code.
243
+ context 'to an address that does not have a zone associated' do
244
+ let(:shipping_address) { create :address, country_iso_code: "IT" }
245
+
246
+ context 'an order with a book' do
247
+ let(:variant) { book }
248
+
249
+ it 'should sell at the net price' do
250
+ expect(line_item.price).to eq(18.69)
251
+ end
252
+
253
+ it 'is adjusted to the net price' do
254
+ expect(line_item.total).to eq(18.69)
255
+ end
256
+
257
+ it 'has no tax adjustments' do
258
+ expect(line_item.adjustments.tax.count).to eq(0)
259
+ end
260
+
261
+ it 'has no included tax' do
262
+ expect(line_item.included_tax_total).to eq(0)
263
+ end
264
+
265
+ it 'has no additional tax' do
266
+ expect(line_item.additional_tax_total).to eq(0)
267
+ end
268
+
269
+ it 'has a constant amount pre tax' do
270
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(18.69)
271
+ end
272
+ end
273
+ end
274
+
275
+ # International delivery, no tax applies whatsoever
276
+ context 'to anywhere else in the world' do
277
+ let(:shipping_address) { create :address, country: world_zone.countries.first }
278
+
279
+ context 'an order with a book' do
280
+ let(:variant) { book }
281
+
282
+ it 'should sell at the net price' do
283
+ expect(line_item.price).to eq(18.69)
284
+ end
285
+
286
+ it 'is adjusted to the net price' do
287
+ expect(line_item.total).to eq(18.69)
288
+ end
289
+
290
+ it 'has no tax adjustments' do
291
+ expect(line_item.adjustments.tax.count).to eq(0)
292
+ end
293
+
294
+ it 'has no included tax' do
295
+ expect(line_item.included_tax_total).to eq(0)
296
+ end
297
+
298
+ it 'has no additional tax' do
299
+ expect(line_item.additional_tax_total).to eq(0)
300
+ end
301
+
302
+ it 'has a constant amount pre tax' do
303
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(18.69)
304
+ end
305
+ end
306
+
307
+ context 'an order with a sweater' do
308
+ let(:variant) { sweater }
309
+
310
+ it 'should sell at the net price' do
311
+ expect(line_item.price).to eq(25.21)
312
+ end
313
+
314
+ it 'has no tax adjustments' do
315
+ expect(line_item.adjustments.tax.count).to eq(0)
316
+ end
317
+
318
+ it 'has no included tax' do
319
+ expect(line_item.included_tax_total).to eq(0)
320
+ end
321
+
322
+ it 'has no additional tax' do
323
+ expect(line_item.additional_tax_total).to eq(0)
324
+ end
325
+
326
+ it 'has a constant amount pre tax' do
327
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(25.21)
328
+ end
329
+ end
330
+
331
+ context 'an order with a download' do
332
+ let(:variant) { download }
333
+
334
+ it 'should sell at the net price' do
335
+ expect(line_item.price).to eq(8.40)
336
+ end
337
+
338
+ it 'has no tax adjustments' do
339
+ expect(line_item.adjustments.tax.count).to eq(0)
340
+ end
341
+
342
+ it 'has no included tax' do
343
+ expect(line_item.included_tax_total).to eq(0)
344
+ end
345
+
346
+ it 'has no additional tax' do
347
+ expect(line_item.additional_tax_total).to eq(0)
348
+ end
349
+
350
+ it 'has a constant amount pre tax' do
351
+ expect(line_item.discounted_amount - line_item.included_tax_total).to eq(8.40)
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end
@@ -17,6 +17,7 @@ RSpec.describe 'state factory' do
17
17
 
18
18
  describe 'when given a country iso code' do
19
19
  let(:state) { build(:state, country_iso: "DE") }
20
+
20
21
  it 'creates the first state for that country it finds in carmen' do
21
22
  expect(state.abbr).to eq("BW")
22
23
  expect(state.name).to eq("Baden-Württemberg")
@@ -45,4 +46,12 @@ RSpec.describe 'state factory' do
45
46
  expect{ build(:state, country_iso: "ZZ") }.to raise_error(RuntimeError, 'Unknown country iso code: "ZZ"')
46
47
  end
47
48
  end
49
+
50
+ context 'with a country that does not have subregions' do
51
+ it 'raises an exception' do
52
+ expect {
53
+ create(:state, country_iso: 'HK')
54
+ }.to raise_error('Country HK has no subregions')
55
+ end
56
+ end
48
57
  end
@@ -21,4 +21,13 @@ RSpec.describe 'stock location factory' do
21
21
 
22
22
  it_behaves_like 'a working factory'
23
23
  end
24
+
25
+ describe 'stock location for a country without subregions' do
26
+ let(:country) { create(:country, iso: 'HK') }
27
+ it 'succeeds' do
28
+ expect(
29
+ create(:stock_location, country: country)
30
+ ).to be_a(Spree::StockLocation)
31
+ end
32
+ end
24
33
  end
@@ -8,6 +8,81 @@ describe Spree::Money do
8
8
  end
9
9
  end
10
10
 
11
+ describe '#initialize' do
12
+ subject do
13
+ Spree::Deprecation.silence do
14
+ described_class.new(amount, currency: currency, with_currency: true).to_s
15
+ end
16
+ end
17
+
18
+ context 'with no currency' do
19
+ let(:currency) { nil }
20
+ let(:amount){ 10 }
21
+ it { should == "$10.00 USD" }
22
+ end
23
+
24
+ context 'with currency' do
25
+ let(:currency){ 'USD' }
26
+
27
+ context "CAD" do
28
+ let(:amount){ '10.00' }
29
+ let(:currency){ 'CAD' }
30
+ it { should == "$10.00 CAD" }
31
+ end
32
+
33
+ context "with string amount" do
34
+ let(:amount){ '10.00' }
35
+ it { should == "$10.00 USD" }
36
+ end
37
+
38
+ context "with no decimal point" do
39
+ let(:amount){ '10' }
40
+ it { should == "$10.00 USD" }
41
+ end
42
+
43
+ context "with symbol" do
44
+ let(:amount){ '$10.00' }
45
+ it { should == "$10.00 USD" }
46
+ end
47
+
48
+ context "with extra currency" do
49
+ let(:amount){ '$10.00 USD' }
50
+ it { should == "$10.00 USD" }
51
+ end
52
+
53
+ context "with different currency" do
54
+ let(:currency){ 'USD' }
55
+ let(:amount){ '$10.00 CAD' }
56
+ it { should == "$10.00 CAD" }
57
+ end
58
+
59
+ context "with commas" do
60
+ let(:amount){ '1,000.00' }
61
+ it { should == "$1,000.00 USD" }
62
+ end
63
+
64
+ context "with comma for decimal point" do
65
+ let(:amount){ '10,00' }
66
+ it { should == "$10.00 USD" }
67
+ end
68
+
69
+ context 'with fixnum' do
70
+ let(:amount){ 10 }
71
+ it { should == "$10.00 USD" }
72
+ end
73
+
74
+ context 'with float' do
75
+ let(:amount){ 10.00 }
76
+ it { should == "$10.00 USD" }
77
+ end
78
+
79
+ context 'with BigDecimal' do
80
+ let(:amount){ BigDecimal.new('10.00') }
81
+ it { should == "$10.00 USD" }
82
+ end
83
+ end
84
+ end
85
+
11
86
  it "formats correctly" do
12
87
  money = Spree::Money.new(10)
13
88
  expect(money.to_s).to eq("$10.00")
@@ -20,16 +20,16 @@ describe Spree::AppConfiguration, type: :model do
20
20
  expect(prefs.variant_search_class).to eq Spree::Core::Search::Variant
21
21
  end
22
22
 
23
- it "uses variant pricer class by default" do
24
- expect(prefs.variant_pricer_class).to eq Spree::Variant::Pricer
23
+ it "uses variant price selector class by default" do
24
+ expect(prefs.variant_price_selector_class).to eq Spree::Variant::PriceSelector
25
25
  end
26
26
 
27
- it "has a getter for the pricing options class provided by the variant pricer class" do
28
- expect(prefs.pricing_options_class).to eq Spree::Variant::Pricer.pricing_options_class
27
+ it "has a getter for the pricing options class provided by the variant price selector class" do
28
+ expect(prefs.pricing_options_class).to eq Spree::Variant::PriceSelector.pricing_options_class
29
29
  end
30
30
 
31
31
  it "has an instacached getter for the default pricing options" do
32
- expect(prefs.default_pricing_options).to be_a Spree::Variant::Pricer.pricing_options_class
32
+ expect(prefs.default_pricing_options).to be_a Spree::Variant::PriceSelector.pricing_options_class
33
33
  expect(prefs.default_pricing_options.object_id).to eq prefs.default_pricing_options.object_id
34
34
  end
35
35