solidus_volume_pricing 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.hound.yml +40 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +14 -0
  7. data/CONTRIBUTING.md +81 -0
  8. data/Gemfile +13 -0
  9. data/Guardfile +9 -0
  10. data/LICENSE.md +26 -0
  11. data/README.md +112 -0
  12. data/Rakefile +21 -0
  13. data/app/assets/javascripts/spree/backend/solidus_volume_pricing.js +16 -0
  14. data/app/controllers/spree/admin/variants_controller_decorator.rb +32 -0
  15. data/app/controllers/spree/admin/volume_price_models_controller.rb +27 -0
  16. data/app/controllers/spree/admin/volume_prices_controller.rb +11 -0
  17. data/app/helpers/spree/base_helper_decorator.rb +19 -0
  18. data/app/models/spree/line_item_decorator.rb +27 -0
  19. data/app/models/spree/user_decorator.rb +10 -0
  20. data/app/models/spree/variant_decorator.rb +104 -0
  21. data/app/models/spree/volume_price.rb +35 -0
  22. data/app/models/spree/volume_price_model.rb +8 -0
  23. data/app/overrides/spree/admin/shared/sub_menu/_configuration/add_volume_price_model_admin_menu_links.html.erb.deface +3 -0
  24. data/app/overrides/views_decorator.rb +13 -0
  25. data/app/views/spree/admin/shared/_vp_product_tab.html.erb +3 -0
  26. data/app/views/spree/admin/variants/_edit_fields.html.erb +33 -0
  27. data/app/views/spree/admin/variants/volume_prices.html.erb +39 -0
  28. data/app/views/spree/admin/volume_price_models/_form.html.erb +9 -0
  29. data/app/views/spree/admin/volume_price_models/_list.html.erb +23 -0
  30. data/app/views/spree/admin/volume_price_models/edit.html.erb +12 -0
  31. data/app/views/spree/admin/volume_price_models/index.html.erb +18 -0
  32. data/app/views/spree/admin/volume_price_models/new.html.erb +12 -0
  33. data/app/views/spree/admin/volume_prices/_edit_fields.html.erb +31 -0
  34. data/app/views/spree/admin/volume_prices/_volume_price_fields.html.erb +33 -0
  35. data/app/views/spree/products/_volume_pricing.html.erb +15 -0
  36. data/bin/rails +7 -0
  37. data/config/locales/de.yml +18 -0
  38. data/config/locales/en.yml +18 -0
  39. data/config/locales/pt.yml +18 -0
  40. data/config/locales/ru.yml +18 -0
  41. data/config/locales/sv.yml +18 -0
  42. data/config/locales/tr.yml +18 -0
  43. data/config/routes.rb +12 -0
  44. data/db/migrate/20081119145604_create_volume_prices.rb +16 -0
  45. data/db/migrate/20110203174010_change_display_name_for_volume_prices.rb +9 -0
  46. data/db/migrate/20111206173307_prefix_volume_pricing_table_names.rb +5 -0
  47. data/db/migrate/20121115043422_add_discount_type_column.rb +5 -0
  48. data/db/migrate/20150513200904_add_role_to_volume_price.rb +5 -0
  49. data/db/migrate/20150603143015_create_spree_volume_price_models.rb +18 -0
  50. data/lib/generators/solidus_volume_pricing/install/install_generator.rb +24 -0
  51. data/lib/solidus_volume_pricing.rb +6 -0
  52. data/lib/solidus_volume_pricing/engine.rb +42 -0
  53. data/lib/solidus_volume_pricing/version.rb +18 -0
  54. data/solidus_volume_pricing.gemspec +40 -0
  55. data/spec/controllers/spree/admin/variants_controller_spec.rb +27 -0
  56. data/spec/factories/volume_price_factory.rb +12 -0
  57. data/spec/helpers/base_helper_spec.rb +22 -0
  58. data/spec/models/spree/line_item_spec.rb +34 -0
  59. data/spec/models/spree/order_spec.rb +49 -0
  60. data/spec/models/spree/variant_spec.rb +306 -0
  61. data/spec/models/spree/volume_price_spec.rb +121 -0
  62. data/spec/spec_helper.rb +41 -0
  63. data/spec/support/capybara.rb +12 -0
  64. data/spec/support/database_cleaner.rb +24 -0
  65. data/spec/support/factory_girl.rb +7 -0
  66. data/spec/support/spree.rb +10 -0
  67. metadata +337 -0
@@ -0,0 +1,49 @@
1
+ RSpec.describe Spree::Order, type: :model do
2
+ before do
3
+ @order = create(:order)
4
+ @variant = create(:variant, price: 10)
5
+
6
+ @variant_with_prices = create(:variant, price: 10)
7
+ @variant_with_prices.volume_prices << create(:volume_price, range: '1..5', amount: 9, position: 2)
8
+ @variant_with_prices.volume_prices << create(:volume_price, range: '(5..9)', amount: 8, position: 1)
9
+ end
10
+
11
+ context 'add_variant' do
12
+ it 'uses the variant price if there are no volume prices' do
13
+ @order.contents.add(@variant)
14
+ expect(@order.line_items.first.price).to eq(10)
15
+ end
16
+
17
+ it 'uses the volume price if quantity falls within a quantity range of a volume price' do
18
+ @variant.volume_prices << create(:volume_price, range: '(5..10)', amount: 9)
19
+ @order.contents.add(@variant_with_prices, 7)
20
+ expect(@order.line_items.first.price).to eq(8)
21
+ end
22
+
23
+ it 'uses the variant price if the quantity fails to satisfy any of the volume price ranges' do
24
+ @order.contents.add(@variant, 10)
25
+ expect(@order.line_items.first.price).to eq(10)
26
+ end
27
+
28
+ it 'uses the first matching volume price in the event of more then one matching volume prices' do
29
+ @order.contents.add(@variant_with_prices, 5)
30
+ expect(@order.line_items.first.price).to eq(8)
31
+ end
32
+
33
+ it 'uses the master variant volume price in case variant has no volume price if config is true' do
34
+ Spree::Config.use_master_variant_volume_pricing = true
35
+ @master = @variant.product.master
36
+ @master.volume_prices << create(:volume_price, range: '(1..5)', amount: 9, position: 2)
37
+ @order.contents.add(@variant, 5)
38
+ expect(@order.line_items.first.price).to eq(9)
39
+ end
40
+
41
+ it 'doesnt use the master variant volume price in case variant has no volume price if config is false' do
42
+ Spree::Config.use_master_variant_volume_pricing = false
43
+ @master = @variant.product.master
44
+ @master.volume_prices << create(:volume_price, range: '(1..5)', amount: 9, position: 2)
45
+ @order.contents.add(@variant, 5)
46
+ expect(@order.line_items.first.price).to eq(10)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,306 @@
1
+ RSpec.describe Spree::Variant, type: :model do
2
+ it { is_expected.to have_many(:volume_prices) }
3
+
4
+ describe '#volume_price' do
5
+
6
+ context 'discount_type = price' do
7
+ before :each do
8
+ @variant = create :variant, price: 10
9
+ @variant.volume_prices.create! amount: 9, discount_type: 'price', range: '(10+)'
10
+ @role = create(:role)
11
+ @user = create(:user)
12
+ end
13
+
14
+ it 'uses the variants price when it does not match a range' do
15
+ expect(@variant.volume_price(1).to_f).to be(10.00)
16
+ end
17
+
18
+ it 'uses the variants price when it does not match role with null role' do
19
+ @variant.volume_prices.first.update(role_id: @role.id)
20
+ expect(@variant.volume_price(10).to_f).to be(10.00)
21
+ end
22
+
23
+ it 'uses the variants price when it does not match roles' do
24
+ other_role = create(:role)
25
+ @user.spree_roles << other_role
26
+ @variant.volume_prices.first.update(role_id: @role.id)
27
+ expect(@variant.volume_price(10, @user).to_f).to be(10.00)
28
+ end
29
+
30
+ it 'uses the volume price when it does match a range' do
31
+ expect(@variant.volume_price(10).to_f).to be(9.00)
32
+ end
33
+
34
+ it 'uses the volume price when it does match a range and role' do
35
+ @user.spree_roles << @role
36
+ Spree::Config.volume_pricing_role = @role.name
37
+ @variant.volume_prices.first.update(role_id: @role.id)
38
+ expect(@variant.volume_price(10, @user).to_f).to be(9.00)
39
+ end
40
+
41
+ it 'uses the volume price when it does match from a volume price model' do
42
+ @variant.volume_price_models << create(:volume_price_model)
43
+ @variant.volume_price_models.first.volume_prices.create!(amount: 5, discount_type: 'price', range: '(5+)')
44
+ expect(@variant.volume_price(6).to_f).to be(5.00)
45
+ end
46
+
47
+ it 'gives percent of earning without role' do
48
+ expect(@variant.volume_price_earning_percent(10)).to be(10)
49
+ end
50
+
51
+ it 'gives percent of earning if role matches' do
52
+ @user.spree_roles << @role
53
+ Spree::Config.volume_pricing_role = @role.name
54
+ @variant.volume_prices.first.update(role_id: @role.id)
55
+ expect(@variant.volume_price_earning_percent(10, @user)).to be(10)
56
+ end
57
+
58
+ it 'gives zero percent earning if doesnt match' do
59
+ expect(@variant.volume_price_earning_percent(1)).to be(0)
60
+ end
61
+
62
+ it 'gives zero percent earning if role doesnt match with null' do
63
+ @variant.volume_prices.first.update(role_id: @role.id)
64
+ expect(@variant.volume_price_earning_percent(10)).to be(0)
65
+ end
66
+
67
+ it 'gives zero percent earning if role doesnt match' do
68
+ other_role = create(:role)
69
+ @user.spree_roles << other_role
70
+ @variant.volume_prices.first.update(role_id: @role.id)
71
+ expect(@variant.volume_price_earning_percent(10, @user)).to be(0)
72
+ end
73
+
74
+ it 'gives amount earning without role' do
75
+ expect(@variant.volume_price_earning_amount(10)).to eq(1)
76
+ end
77
+
78
+ it 'gives amount earning if role matches' do
79
+ @user.spree_roles << @role
80
+ Spree::Config.volume_pricing_role = @role.name
81
+ @variant.volume_prices.first.update(role_id: @role.id)
82
+ expect(@variant.volume_price_earning_amount(10, @user)).to eq(1)
83
+ end
84
+
85
+ it 'gives zero earning amount if doesnt match' do
86
+ expect(@variant.volume_price_earning_amount(1)).to eq(0)
87
+ end
88
+
89
+ it 'gives zero earning amount if role doesnt match with null' do
90
+ @variant.volume_prices.first.update(role_id: @role.id)
91
+ expect(@variant.volume_price_earning_amount(10)).to be(0)
92
+ end
93
+
94
+ it 'gives zero earning amount if role doesnt match' do
95
+ other_role = create(:role)
96
+ @user.spree_roles << other_role
97
+ @variant.volume_prices.first.update(role_id: @role.id)
98
+ expect(@variant.volume_price_earning_amount(10, @user)).to be(0)
99
+ end
100
+ end
101
+
102
+ context 'discount_type = dollar' do
103
+ before :each do
104
+ @variant = create :variant, price: 10
105
+ @variant.volume_prices.create! amount: 1, discount_type: 'dollar', range: '(10+)'
106
+ @role = create(:role)
107
+ @user = create(:user)
108
+ end
109
+
110
+ it 'uses the variants price when it does not match a range' do
111
+ expect(@variant.volume_price(1).to_f).to be(10.00)
112
+ end
113
+
114
+ it 'uses the variants price when it does not match role with null role' do
115
+ @variant.volume_prices.first.update(role_id: @role.id)
116
+ expect(@variant.volume_price(10).to_f).to be(10.00)
117
+ end
118
+
119
+ it 'uses the variants price when it does not match roles' do
120
+ other_role = create(:role)
121
+ @user.spree_roles << other_role
122
+ @variant.volume_prices.first.update(role_id: @role.id)
123
+ expect(@variant.volume_price(10, @user).to_f).to be(10.00)
124
+ end
125
+
126
+ it 'uses the volume price when it does match a range' do
127
+ expect(@variant.volume_price(10).to_f).to be(9.00)
128
+ end
129
+
130
+ it 'uses the volume price when it does match a range and role' do
131
+ @user.spree_roles << @role
132
+ Spree::Config.volume_pricing_role = @role.name
133
+ @variant.volume_prices.first.update(role_id: @role.id)
134
+ expect(@variant.volume_price(10, @user).to_f).to be(9.00)
135
+ end
136
+
137
+ it 'uses the volume price when it does match from a volume price model' do
138
+ @variant.volume_price_models << create(:volume_price_model)
139
+ @variant.volume_price_models.first.volume_prices.create!(amount: 5, discount_type: 'dollar', range: '(5+)')
140
+ expect(@variant.volume_price(6).to_f).to be(5.00)
141
+ end
142
+
143
+ it 'gives percent of earning without role' do
144
+ expect(@variant.volume_price_earning_percent(10)).to be(10)
145
+ end
146
+
147
+ it 'gives percent of earning if role matches' do
148
+ @user.spree_roles << @role
149
+ Spree::Config.volume_pricing_role = @role.name
150
+ @variant.volume_prices.first.update(role_id: @role.id)
151
+ expect(@variant.volume_price_earning_percent(10, @user)).to be(10)
152
+ end
153
+
154
+ it 'gives zero percent earning if doesnt match' do
155
+ expect(@variant.volume_price_earning_percent(1)).to be(0)
156
+ end
157
+
158
+ it 'gives zero percent earning if role doesnt match with null' do
159
+ @variant.volume_prices.first.update(role_id: @role.id)
160
+ expect(@variant.volume_price_earning_percent(10)).to be(0)
161
+ end
162
+
163
+ it 'gives zero percent earning if role doesnt match' do
164
+ other_role = create(:role)
165
+ @user.spree_roles << other_role
166
+ @variant.volume_prices.first.update(role_id: @role.id)
167
+ expect(@variant.volume_price_earning_percent(10, @user)).to be(0)
168
+ end
169
+
170
+ it 'gives amount earning without role' do
171
+ expect(@variant.volume_price_earning_amount(10)).to eq(1)
172
+ end
173
+
174
+ it 'gives amount earning if role matches' do
175
+ @user.spree_roles << @role
176
+ Spree::Config.volume_pricing_role = @role.name
177
+ @variant.volume_prices.first.update(role_id: @role.id)
178
+ expect(@variant.volume_price_earning_amount(10, @user)).to eq(1)
179
+ end
180
+
181
+ it 'gives zero earning amount if doesnt match' do
182
+ expect(@variant.volume_price_earning_amount(1)).to eq(0)
183
+ end
184
+
185
+ it 'gives zero earning amount if role doesnt match with null' do
186
+ @variant.volume_prices.first.update(role_id: @role.id)
187
+ expect(@variant.volume_price_earning_amount(10)).to be(0)
188
+ end
189
+
190
+ it 'gives zero earning amount if role doesnt match' do
191
+ other_role = create(:role)
192
+ @user.spree_roles << other_role
193
+ @variant.volume_prices.first.update(role_id: @role.id)
194
+ expect(@variant.volume_price_earning_amount(10, @user)).to be(0)
195
+ end
196
+ end
197
+
198
+ context 'discount_type = percent' do
199
+ before :each do
200
+ @variant = create :variant, price: 10
201
+ @variant.volume_prices.create! amount: 0.1, discount_type: 'percent', range: '(10+)'
202
+ @role = create(:role)
203
+ @user = create(:user)
204
+ end
205
+
206
+ it 'uses the variants price when it does not match a range' do
207
+ expect(@variant.volume_price(1).to_f).to be(10.00)
208
+ end
209
+
210
+ it 'uses the variants price when it does not match role with null role' do
211
+ @variant.volume_prices.first.update(role_id: @role.id)
212
+ expect(@variant.volume_price(10).to_f).to be(10.00)
213
+ end
214
+
215
+ it 'uses the variants price when it does not match roles' do
216
+ other_role = create(:role)
217
+ @user.spree_roles << other_role
218
+ @variant.volume_prices.first.update(role_id: @role.id)
219
+ expect(@variant.volume_price(10, @user).to_f).to be(10.00)
220
+ end
221
+
222
+ it 'uses the volume price when it does match a range' do
223
+ expect(@variant.volume_price(10).to_f).to be(9.00)
224
+ end
225
+
226
+ it 'uses the volume price when it does match a range and role' do
227
+ @user.spree_roles << @role
228
+ Spree::Config.volume_pricing_role = @role.name
229
+ @variant.volume_prices.first.update(role_id: @role.id)
230
+ expect(@variant.volume_price(10, @user).to_f).to be(9.00)
231
+ end
232
+
233
+ it 'gives percent of earning without roles' do
234
+ expect(@variant.volume_price_earning_percent(10)).to be(10)
235
+ @variant_five = create :variant, price: 10
236
+ @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
237
+ expect(@variant_five.volume_price_earning_percent(1)).to be(50)
238
+ end
239
+
240
+ it 'gives amount earning if role matches' do
241
+ @user.spree_roles << @role
242
+ Spree::Config.volume_pricing_role = @role.name
243
+ expect(@variant.volume_price_earning_percent(10)).to be(10)
244
+ @variant_five = create :variant, price: 10
245
+ @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
246
+ @variant_five.volume_prices.first.update(role_id: @role.id)
247
+ expect(@variant_five.volume_price_earning_percent(1, @user)).to be(50)
248
+ end
249
+
250
+ it 'gives zero percent earning if doesnt match' do
251
+ expect(@variant.volume_price_earning_percent(1)).to be(0)
252
+ end
253
+
254
+ it 'gives zero percent earning if role doesnt match with null' do
255
+ @variant.volume_prices.first.update(role_id: @role.id)
256
+ expect(@variant.volume_price_earning_percent(10)).to be(0)
257
+ end
258
+
259
+ it 'gives zero percent earning if role doesnt match' do
260
+ other_role = create(:role)
261
+ @user.spree_roles << other_role
262
+ @variant.volume_prices.first.update(role_id: @role.id)
263
+ expect(@variant.volume_price_earning_percent(10, @user)).to be(0)
264
+ end
265
+
266
+ it 'gives amount earning without roles' do
267
+ expect(@variant.volume_price_earning_amount(10)).to eq(1)
268
+ @variant_five = create :variant, price: 10
269
+ @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
270
+ expect(@variant_five.volume_price_earning_amount(1)).to eq(5)
271
+ end
272
+
273
+ it 'gives amount earning if role matches' do
274
+ @user.spree_roles << @role
275
+ Spree::Config.volume_pricing_role = @role.name
276
+ expect(@variant.volume_price_earning_amount(10)).to eq(1)
277
+ @variant_five = create :variant, price: 10
278
+ @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
279
+ @variant_five.volume_prices.first.update(role_id: @role.id)
280
+ expect(@variant_five.volume_price_earning_amount(1, @user)).to eq(5)
281
+ end
282
+
283
+ it 'uses the volume price when it does match from a volume price model' do
284
+ @variant.volume_price_models << create(:volume_price_model)
285
+ @variant.volume_price_models.first.volume_prices.create!(amount: 0.5, discount_type: 'percent', range: '(5+)')
286
+ expect(@variant.volume_price(6).to_f).to be(5.00)
287
+ end
288
+
289
+ it 'gives zero earning amount if doesnt match' do
290
+ expect(@variant.volume_price_earning_amount(1)).to eq(0)
291
+ end
292
+
293
+ it 'gives zero earning amount if role doesnt match with null' do
294
+ @variant.volume_prices.first.update(role_id: @role.id)
295
+ expect(@variant.volume_price_earning_amount(10)).to be(0)
296
+ end
297
+
298
+ it 'gives zero earning amount if role doesnt match' do
299
+ other_role = create(:role)
300
+ @user.spree_roles << other_role
301
+ @variant.volume_prices.first.update(role_id: @role.id)
302
+ expect(@variant.volume_price_earning_amount(10, @user)).to be(0)
303
+ end
304
+ end
305
+ end
306
+ end
@@ -0,0 +1,121 @@
1
+ RSpec.describe Spree::VolumePrice, type: :model do
2
+ it { is_expected.to belong_to(:variant).touch(true) }
3
+ it { is_expected.to belong_to(:volume_price_model).touch(true) }
4
+ it { is_expected.to belong_to(:spree_role).class_name('Spree::Role').with_foreign_key('role_id') }
5
+ it { is_expected.to validate_presence_of(:discount_type) }
6
+ it { is_expected.to validate_inclusion_of(:discount_type).in_array(%w(price dollar percent)) }
7
+ it { is_expected.to validate_presence_of(:amount) }
8
+
9
+ before do
10
+ @volume_price = Spree::VolumePrice.new(variant: Spree::Variant.new, amount: 10, discount_type: 'price')
11
+ end
12
+
13
+ ['1..2', '(1..2)'].each do |range|
14
+ it "does not interepret a Ruby range of #{range} as being opend ended" do
15
+ @volume_price.range = range
16
+ expect(@volume_price).not_to be_open_ended
17
+ end
18
+ end
19
+
20
+ ['50+', '(50+)'].each do |range|
21
+ it "properly interpret an open ended range of #{range}" do
22
+ @volume_price.range = range
23
+ expect(@volume_price).to be_open_ended
24
+ end
25
+ end
26
+
27
+ describe 'valid range format' do
28
+ it 'requires the presence of a variant' do
29
+ @volume_price.variant = nil
30
+ expect(@volume_price).not_to be_valid
31
+ end
32
+
33
+ it 'consider a range of (1..2) to be valid' do
34
+ @volume_price.range = '(1..2)'
35
+ expect(@volume_price).to be_valid
36
+ end
37
+
38
+ it 'consider a range of (1...2) to be valid' do
39
+ @volume_price.range = '(1...2)'
40
+ expect(@volume_price).to be_valid
41
+ end
42
+
43
+ it 'consider a range of 1..2 to be valid' do
44
+ @volume_price.range = '1..2'
45
+ expect(@volume_price).to be_valid
46
+ end
47
+
48
+ it 'consider a range of 1...2 to be valid' do
49
+ @volume_price.range = '1...2'
50
+ expect(@volume_price).to be_valid
51
+ end
52
+
53
+ it 'consider a range of (10+) to be valid' do
54
+ @volume_price.range = '(10+)'
55
+ expect(@volume_price).to be_valid
56
+ end
57
+
58
+ it 'consider a range of 10+ to be valid' do
59
+ @volume_price.range = '10+'
60
+ expect(@volume_price).to be_valid
61
+ end
62
+
63
+ it 'does not consider a range of 1-2 to valid' do
64
+ @volume_price.range = '1-2'
65
+ expect(@volume_price).not_to be_valid
66
+ end
67
+
68
+ it 'does not consider a range of 1 to valid' do
69
+ @volume_price.range = '1'
70
+ expect(@volume_price).not_to be_valid
71
+ end
72
+
73
+ it 'does not consider a range of foo to valid' do
74
+ @volume_price.range = 'foo'
75
+ expect(@volume_price).not_to be_valid
76
+ end
77
+ end
78
+
79
+ describe 'include?' do
80
+ ['10..20', '(10..20)'].each do |range|
81
+ it "does not match a quantity that fails to fall within the specified range of #{range}" do
82
+ @volume_price.range = range
83
+ expect(@volume_price).not_to include(21)
84
+ end
85
+
86
+ it "matches a quantity that is within the specified range of #{range}" do
87
+ @volume_price.range = range
88
+ expect(@volume_price).to include(12)
89
+ end
90
+
91
+ it 'matches the upper bound of ranges that include the upper bound' do
92
+ @volume_price.range = range
93
+ expect(@volume_price).to include(20)
94
+ end
95
+ end
96
+
97
+ ['10...20', '(10...20)'].each do |range|
98
+ it 'does not match the upper bound for ranges that exclude the upper bound' do
99
+ @volume_price.range = range
100
+ expect(@volume_price).not_to include(20)
101
+ end
102
+ end
103
+
104
+ ['50+', '(50+)'].each do |range|
105
+ it "matches a quantity that exceeds the value of an open ended range of #{range}" do
106
+ @volume_price.range = range
107
+ expect(@volume_price).to include(51)
108
+ end
109
+
110
+ it "matches a quantity that equals the value of an open ended range of #{range}" do
111
+ @volume_price.range = range
112
+ expect(@volume_price).to include(50)
113
+ end
114
+
115
+ it "does not match a quantity that is less then the value of an open ended range of #{range}" do
116
+ @volume_price.range = range
117
+ expect(@volume_price).not_to include(40)
118
+ end
119
+ end
120
+ end
121
+ end