acts_as_bookable 0.1.0

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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +43 -0
  6. data/Appraisals +21 -0
  7. data/Gemfile +21 -0
  8. data/Gemfile.lock +168 -0
  9. data/Guardfile +5 -0
  10. data/MIT-LICENSE +20 -0
  11. data/README.md +473 -0
  12. data/Rakefile +19 -0
  13. data/acts_as_bookable.gemspec +41 -0
  14. data/app/assets/images/acts_as_bookable/.keep +0 -0
  15. data/app/assets/javascripts/acts_as_bookable/application.js +13 -0
  16. data/app/assets/stylesheets/acts_as_bookable/application.css +15 -0
  17. data/app/controllers/acts_as_bookable/application_controller.rb +4 -0
  18. data/app/helpers/acts_as_bookable/application_helper.rb +4 -0
  19. data/app/views/layouts/acts_as_bookable/application.html.erb +14 -0
  20. data/bin/rails +12 -0
  21. data/config/locales/en.yml +12 -0
  22. data/config/routes.rb +2 -0
  23. data/db/migrate/20160217085200_create_acts_as_bookable_bookings.rb +14 -0
  24. data/gemfiles/activerecord_3.2.gemfile +16 -0
  25. data/gemfiles/activerecord_4.0.gemfile +16 -0
  26. data/gemfiles/activerecord_4.1.gemfile +16 -0
  27. data/gemfiles/activerecord_4.2.gemfile +17 -0
  28. data/gemfiles/activerecord_5.0.gemfile +17 -0
  29. data/lib/acts_as_bookable/bookable/core.rb +285 -0
  30. data/lib/acts_as_bookable/bookable.rb +56 -0
  31. data/lib/acts_as_bookable/booker.rb +70 -0
  32. data/lib/acts_as_bookable/booking.rb +54 -0
  33. data/lib/acts_as_bookable/db_utils.rb +39 -0
  34. data/lib/acts_as_bookable/engine.rb +5 -0
  35. data/lib/acts_as_bookable/t.rb +11 -0
  36. data/lib/acts_as_bookable/time_utils.rb +135 -0
  37. data/lib/acts_as_bookable/version.rb +3 -0
  38. data/lib/acts_as_bookable.rb +42 -0
  39. data/lib/tasks/acts_as_bookable_tasks.rake +4 -0
  40. data/spec/acts_as_bookable/acts_as_bookable_spec.rb +52 -0
  41. data/spec/acts_as_bookable/acts_as_booker_spec.rb +57 -0
  42. data/spec/acts_as_bookable/bookable/core_spec.rb +593 -0
  43. data/spec/acts_as_bookable/bookable_spec.rb +124 -0
  44. data/spec/acts_as_bookable/booker_spec.rb +140 -0
  45. data/spec/acts_as_bookable/booking_spec.rb +241 -0
  46. data/spec/acts_as_bookable/schedule_spec.rb +137 -0
  47. data/spec/acts_as_bookable/time_utils_spec.rb +525 -0
  48. data/spec/factories/bookable.rb +7 -0
  49. data/spec/factories/booker.rb +5 -0
  50. data/spec/factories/room.rb +11 -0
  51. data/spec/internal/app/models/Bookable.rb +3 -0
  52. data/spec/internal/app/models/Booker.rb +3 -0
  53. data/spec/internal/app/models/Event.rb +3 -0
  54. data/spec/internal/app/models/Generic.rb +2 -0
  55. data/spec/internal/app/models/NotBooker.rb +2 -0
  56. data/spec/internal/app/models/Room.rb +3 -0
  57. data/spec/internal/app/models/Show.rb +3 -0
  58. data/spec/internal/app/models/Unbookable.rb +2 -0
  59. data/spec/internal/config/database.yml.sample +17 -0
  60. data/spec/internal/db/schema.rb +51 -0
  61. data/spec/spec_helper.rb +26 -0
  62. data/spec/support/0-helpers.rb +32 -0
  63. data/spec/support/1-database.rb +42 -0
  64. data/spec/support/2-database_cleaner.rb +21 -0
  65. data/spec/support/3-factory_girl.rb +12 -0
  66. metadata +296 -0
@@ -0,0 +1,593 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Bookable model' do
4
+ describe 'InstanceMethods' do
5
+ it 'should add a method #check_availability! in instance-side' do
6
+ @bookable = Bookable.new
7
+ expect(@bookable).to respond_to :check_availability!
8
+ end
9
+
10
+ it 'should add a method #check_availability in instance-side' do
11
+ @bookable = Bookable.new
12
+ expect(@bookable).to respond_to :check_availability
13
+ end
14
+
15
+ it 'should add a method #validate_booking_options! in instance-side' do
16
+ @bookable = Bookable.new
17
+ expect(@bookable).to respond_to :validate_booking_options!
18
+ end
19
+
20
+ describe '#check_availability! and check_availability' do
21
+ after(:each) do
22
+ Bookable.booking_opts = {}
23
+ Bookable.initialize_acts_as_bookable_core
24
+ end
25
+
26
+ describe 'whithout any constraint' do
27
+ before(:each) do
28
+ Bookable.booking_opts = {
29
+ time_type: :none,
30
+ capacity_type: :none
31
+ }
32
+ Bookable.initialize_acts_as_bookable_core
33
+ @bookable = Bookable.create!(name: 'bookable')
34
+ end
35
+
36
+ it 'should be always available' do
37
+ expect(@bookable.check_availability({})).to be_truthy
38
+ expect(@bookable.check_availability!({})).to be_truthy
39
+ end
40
+ end
41
+ end
42
+
43
+ describe 'with time_type: :range' do
44
+ before(:each) do
45
+ Bookable.booking_opts = {
46
+ time_type: :range,
47
+ capacity_type: :none
48
+ }
49
+ Bookable.initialize_acts_as_bookable_core
50
+ @bookable = Bookable.create!(name: 'bookable', schedule: IceCube::Schedule.new('2016-01-01'.to_date, duration: 1.day))
51
+ ## bookable the first and third day of the month
52
+ @bookable.schedule.add_recurrence_rule IceCube::Rule.monthly.day_of_month([1,3])
53
+ @bookable.save!
54
+ end
55
+
56
+ it 'should be available in bookable times' do
57
+ time = '2016-01-01'.to_date
58
+ endtime = time + 10.minutes
59
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
60
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
61
+ end
62
+
63
+ it 'should not be available in not bookable times' do
64
+ time = '2016-01-02'.to_date
65
+ endtime = '2016-01-04'.to_date
66
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_falsy
67
+ expect{ @bookable.check_availability!({time_start: time, time_end: endtime}) }.to raise_error ActsAsBookable::AvailabilityError
68
+ begin
69
+ @bookable.check_availability!({time_start: time, time_end: endtime})
70
+ rescue ActsAsBookable::AvailabilityError => e
71
+ expect(e.message).to include "the Bookable is not available from #{time} to #{endtime}"
72
+ end
73
+ end
74
+
75
+ it 'should be bookable within a bookable time' do
76
+ time = '2016-01-01'.to_date + 1.minute
77
+ endtime = '2016-01-02'.to_date - 1.minute
78
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
79
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
80
+ end
81
+
82
+ it 'should be bookable within a bookable time' do
83
+ time = '2016-01-01'.to_date + 1.minute
84
+ endtime = '2016-01-02'.to_date - 1.minute
85
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
86
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
87
+ end
88
+
89
+ it 'should not be available when time_start is available, time_end is available but the availability is splitted in between' do
90
+ time = '2016-01-01'.to_date + 1.minute
91
+ endtime = '2016-01-03'.to_date + 1.minute
92
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_falsy
93
+ expect{ @bookable.check_availability!({time_start: time, time_end: endtime}) }.to raise_error ActsAsBookable::AvailabilityError
94
+ begin
95
+ @bookable.check_availability!({time_start: time, time_end: endtime})
96
+ rescue ActsAsBookable::AvailabilityError => e
97
+ expect(e.message).to include "the Bookable is not available from #{time} to #{endtime}"
98
+ end
99
+ end
100
+ end
101
+
102
+ describe 'with time_type: :range and with bookable_across_occurrences: true' do
103
+ before(:each) do
104
+ Bookable.booking_opts = {
105
+ time_type: :range,
106
+ capacity_type: :none,
107
+ bookable_across_occurrences: true
108
+ }
109
+ Bookable.initialize_acts_as_bookable_core
110
+ @bookable = Bookable.create!(name: 'bookable', schedule: IceCube::Schedule.new('2016-01-01'.to_date, duration: 1.day))
111
+ ## bookable the first and third day of the month
112
+ @bookable.schedule.add_recurrence_rule IceCube::Rule.monthly.day_of_month([1,3])
113
+ @bookable.save!
114
+ end
115
+
116
+ it 'should be available in bookable times' do
117
+ time = '2016-01-01'.to_date
118
+ endtime = time + 10.minutes
119
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
120
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
121
+ end
122
+
123
+ it 'should not be available in not bookable times' do
124
+ time = '2016-01-02'.to_date
125
+ endtime = '2016-01-04'.to_date
126
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_falsy
127
+ expect{ @bookable.check_availability!({time_start: time, time_end: endtime}) }.to raise_error ActsAsBookable::AvailabilityError
128
+ begin
129
+ @bookable.check_availability!({time_start: time, time_end: endtime})
130
+ rescue ActsAsBookable::AvailabilityError => e
131
+ expect(e.message).to include "the Bookable is not available from #{time} to #{endtime}"
132
+ end
133
+ end
134
+
135
+ it 'should be bookable within a bookable time' do
136
+ time = '2016-01-01'.to_date + 1.minute
137
+ endtime = '2016-01-02'.to_date - 1.minute
138
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
139
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
140
+ end
141
+
142
+ it 'should be bookable within a bookable time' do
143
+ time = '2016-01-01'.to_date + 1.minute
144
+ endtime = '2016-01-02'.to_date - 1.minute
145
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
146
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
147
+ end
148
+
149
+ it 'should be available when time_start is available, time_end is available and the availability is splitted in between' do
150
+ time = '2016-01-01'.to_date + 1.minute
151
+ endtime = '2016-01-03'.to_date + 1.minute
152
+ expect(@bookable.check_availability({time_start: time, time_end: endtime})).to be_truthy
153
+ expect(@bookable.check_availability!({time_start: time, time_end: endtime})).to be_truthy
154
+ end
155
+ end
156
+
157
+ describe 'with time_type: :fixed' do
158
+ before(:each) do
159
+ Bookable.booking_opts = {
160
+ time_type: :fixed,
161
+ capacity_type: :none
162
+ }
163
+ Bookable.initialize_acts_as_bookable_core
164
+ @bookable = Bookable.create!(name: 'bookable', schedule: IceCube::Schedule.new('2016-01-01'.to_date))
165
+ ## bookable the first and third day of the month, at 9AM
166
+ @bookable.schedule.add_recurrence_rule IceCube::Rule.monthly.day_of_month([1,3]).hour_of_day(9)
167
+ @bookable.save!
168
+ end
169
+
170
+ it 'should be available in available times' do
171
+ time = '2016-01-01'.to_date + 9.hours
172
+ expect(@bookable.check_availability(time: time)).to be_truthy
173
+ expect(@bookable.check_availability!(time: time)).to be_truthy
174
+ time = '2016-01-03'.to_date + 9.hours
175
+ expect(@bookable.check_availability(time: time)).to be_truthy
176
+ expect(@bookable.check_availability!(time: time)).to be_truthy
177
+ end
178
+
179
+ it 'should not be available in not bookable day' do
180
+ time = '2016-01-02'.to_date
181
+ expect(@bookable.check_availability(time: time)).to be_falsy
182
+ expect{ @bookable.check_availability!(time: time) }.to raise_error ActsAsBookable::AvailabilityError
183
+ begin
184
+ @bookable.check_availability!(time: time)
185
+ rescue ActsAsBookable::AvailabilityError => e
186
+ expect(e.message).to include "the Bookable is not available at #{time}"
187
+ end
188
+ end
189
+
190
+
191
+ it 'should not be available in bookable day but not bookable time' do
192
+ time = '2016-01-02'.to_date + 10.hours
193
+ expect(@bookable.check_availability(time: time)).to be_falsy
194
+ expect{ @bookable.check_availability!(time: time) }.to raise_error ActsAsBookable::AvailabilityError
195
+ begin
196
+ @bookable.check_availability!(time: time)
197
+ rescue ActsAsBookable::AvailabilityError => e
198
+ expect(e.message).to include "the Bookable is not available at #{time}"
199
+ end
200
+ end
201
+
202
+ it 'should not be available very close to a bookable time but not the exact second' do
203
+ time = '2016-01-02'.to_date + 9.hours + 1.second
204
+ expect(@bookable.check_availability(time: time)).to be_falsy
205
+ expect{ @bookable.check_availability!(time: time) }.to raise_error ActsAsBookable::AvailabilityError
206
+ begin
207
+ @bookable.check_availability!(time: time)
208
+ rescue ActsAsBookable::AvailabilityError => e
209
+ expect(e.message).to include "the Bookable is not available at #{time}"
210
+ end
211
+ end
212
+ end
213
+
214
+ describe 'with capacity_type: :open' do
215
+ before(:each) do
216
+ Bookable.booking_opts = {
217
+ time_type: :none,
218
+ capacity_type: :open
219
+ }
220
+ Bookable.initialize_acts_as_bookable_core
221
+ @bookable = Bookable.create!(name: 'bookable', capacity: 4)
222
+ end
223
+
224
+ it 'should be available if amount <= capacity' do
225
+ (1..@bookable.capacity).each do |amount|
226
+ expect(@bookable.check_availability(amount: amount)).to be_truthy
227
+ expect(@bookable.check_availability!(amount: amount)).to be_truthy
228
+ end
229
+ end
230
+
231
+ it 'should not be available if amount > capacity' do
232
+ expect(@bookable.check_availability(amount: @bookable.capacity + 1)).to be_falsy
233
+ expect { @bookable.check_availability!(amount: @bookable.capacity + 1) }.to raise_error ActsAsBookable::AvailabilityError
234
+ begin
235
+ @bookable.check_availability!(amount: @bookable.capacity + 1)
236
+ rescue ActsAsBookable::AvailabilityError => e
237
+ expect(e.message).to include 'cannot be greater'
238
+ end
239
+ end
240
+
241
+ it 'should be available if already booked but amount <= conditional capacity' do
242
+ booker = create(:booker)
243
+ @bookable.be_booked!(booker, amount: 2)
244
+ (1..(@bookable.capacity - 2)).each do |amount|
245
+ expect(@bookable.check_availability(amount: amount)).to be_truthy
246
+ expect(@bookable.check_availability!(amount: amount)).to be_truthy
247
+ end
248
+ end
249
+
250
+ it 'should not be available if amount <= capacity but already booked and amount > conditional capacity' do
251
+ booker = create(:booker)
252
+ @bookable.be_booked!(booker, amount: 2)
253
+ amount = @bookable.capacity - 2 + 1
254
+ expect(@bookable.check_availability(amount: amount)).to be_falsy
255
+ expect { @bookable.check_availability!(amount: amount) }.to raise_error ActsAsBookable::AvailabilityError
256
+ begin
257
+ @bookable.check_availability!(amount: amount)
258
+ rescue ActsAsBookable::AvailabilityError => e
259
+ expect(e.message).to include 'is fully booked'
260
+ end
261
+ end
262
+
263
+ it 'should be available if amount <= capacity and already booked and amount > conditional capacity but overlappings are separated in time and space' do
264
+ Bookable.booking_opts = {
265
+ time_type: :range,
266
+ capacity_type: :open,
267
+ bookable_across_occurrences: true
268
+ }
269
+ Bookable.initialize_acts_as_bookable_core
270
+ @bookable = Bookable.create!(name: 'bookable', capacity: 4, schedule: IceCube::Schedule.new(Date.today, duration: 1.day))
271
+ @bookable.schedule.add_recurrence_rule IceCube::Rule.daily
272
+ @bookable.save!
273
+ booker = create(:booker)
274
+ @bookable.be_booked!(booker, amount: 3, time_start: Date.today, time_end: Date.today + 8.hours)
275
+ @bookable.be_booked!(booker, amount: 3, time_start: Date.today + 8.hours, time_end: Date.today + 16.hours)
276
+ @bookable.be_booked!(booker, amount: 3, time_start: Date.today + 16.hours, time_end: Date.today + 24.hours)
277
+ amount = 1
278
+ expect(@bookable.check_availability(amount: amount, time_start: Date.today, time_end: Date.today + 24.hours)).to be_truthy
279
+ end
280
+
281
+ it 'should not be available if amount <= capacity and already booked and amount > conditional capacity' do
282
+ Bookable.booking_opts = {
283
+ time_type: :range,
284
+ capacity_type: :open,
285
+ bookable_across_occurrences: true
286
+ }
287
+ Bookable.initialize_acts_as_bookable_core
288
+ @bookable = Bookable.create!(name: 'bookable', capacity: 4, schedule: IceCube::Schedule.new(Date.today, duration: 1.day))
289
+ @bookable.schedule.add_recurrence_rule IceCube::Rule.daily
290
+ @bookable.save!
291
+ booker = create(:booker)
292
+ @bookable.be_booked!(booker, amount: 3, time_start: Date.today, time_end: Date.today + 8.hours)
293
+ @bookable.be_booked!(booker, amount: 3, time_start: Date.today + 8.hours, time_end: Date.today + 16.hours)
294
+ @bookable.be_booked!(booker, amount: 1, time_start: Date.today + 8.hours, time_end: Date.today + 24.hours)
295
+ amount = 2
296
+ expect(@bookable.check_availability(amount: amount, time_start: Date.today, time_end: Date.today + 8.hours)).to be_truthy
297
+ expect(@bookable.check_availability(amount: amount, time_start: Date.today + 8.hours, time_end: Date.today + 16.hours)).to be_truthy
298
+ expect(@bookable.check_availability(amount: amount, time_start: Date.today + 16.hours, time_end: Date.today + 24.hours)).to be_truthy
299
+ expect(@bookable.check_availability(amount: amount, time_start: Date.today, time_end: Date.today + 24.hours)).to be_truthy
300
+ end
301
+ end
302
+
303
+ describe 'with capacity_type: :closed' do
304
+ before(:each) do
305
+ Bookable.booking_opts = {
306
+ time_type: :none,
307
+ capacity_type: :closed
308
+ }
309
+ Bookable.initialize_acts_as_bookable_core
310
+ @bookable = Bookable.create!(name: 'bookable', capacity: 4)
311
+ end
312
+
313
+ it 'should be available if amount <= capacity' do
314
+ (1..@bookable.capacity).each do |amount|
315
+ expect(@bookable.check_availability(amount: amount)).to be_truthy
316
+ expect(@bookable.check_availability!(amount: amount)).to be_truthy
317
+ end
318
+ end
319
+
320
+ it 'should not be available if amount > capacity' do
321
+ expect(@bookable.check_availability(amount: @bookable.capacity + 1)).to be_falsy
322
+ expect { @bookable.check_availability!(amount: @bookable.capacity + 1) }.to raise_error ActsAsBookable::AvailabilityError
323
+ begin
324
+ @bookable.check_availability!(amount: @bookable.capacity + 1)
325
+ rescue ActsAsBookable::AvailabilityError => e
326
+ expect(e.message).to include 'cannot be greater'
327
+ end
328
+ end
329
+
330
+ it 'should not be available if already booked (even though amount < capacity - overlapped amounts)' do
331
+ booker = create(:booker)
332
+ @bookable.be_booked!(booker, amount: 1)
333
+ (1..(@bookable.capacity + 1)).each do |amount|
334
+ expect(@bookable.check_availability(amount: amount)).to be_falsy
335
+ expect { @bookable.check_availability!(amount: amount) }.to raise_error ActsAsBookable::AvailabilityError
336
+ begin
337
+ @bookable.check_availability!(amount: amount)
338
+ rescue ActsAsBookable::AvailabilityError => e
339
+ if(amount <= @bookable.capacity)
340
+ expect(e.message).to include('is fully booked')
341
+ else
342
+ expect(e.message).to include('cannot be greater')
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ describe 'classMethods' do
351
+ before(:each) do
352
+ Bookable.booking_opts = {}
353
+ Bookable.initialize_acts_as_bookable_core
354
+ end
355
+ after(:each) do
356
+ Bookable.booking_opts = {}
357
+ Bookable.initialize_acts_as_bookable_core
358
+ end
359
+
360
+ describe 'self.initialize_acts_as_bookable_core' do
361
+ describe '#set_options' do
362
+ it 'preset options for room' do
363
+ [:room,:event,:show].each do |p|
364
+ Bookable.booking_opts = {preset: p}
365
+ Bookable.initialize_acts_as_bookable_core
366
+ expect(Bookable.booking_opts[:preset]).to eq p
367
+ expect(Bookable.booking_opts[:time_type]).to be(:range).or be(:fixed).or be(:none)
368
+ expect(Bookable.booking_opts[:capacity_type]).to be(:open).or be(:closed)
369
+ expect(Bookable.booking_opts[:bookable_across_occurrences]).to be(true).or be(false)
370
+ end
371
+ end
372
+
373
+ it 'fails when using an unknown preset' do
374
+ Bookable.booking_opts = {preset: 'unknown'}
375
+ expect{ Bookable.initialize_acts_as_bookable_core }.to raise_error ActsAsBookable::InitializationError
376
+ end
377
+
378
+ it 'correctly set undefined options' do
379
+ Bookable.booking_opts = {}
380
+ Bookable.initialize_acts_as_bookable_core
381
+ expect(Bookable.booking_opts[:preset]).not_to be_present
382
+ expect(Bookable.booking_opts[:date_type]).not_to be_present
383
+ expect(Bookable.booking_opts[:time_type]).to be_present
384
+ expect(Bookable.booking_opts[:location_type]).not_to be_present
385
+ expect(Bookable.booking_opts[:capacity_type]).to be_present
386
+ expect(Bookable.booking_opts[:bookable_across_occurrences]).not_to be_nil
387
+ end
388
+
389
+ it 'correctly merges options' do
390
+ Bookable.booking_opts = {
391
+ time_type: :range,
392
+ capacity_type: :closed,
393
+ bookable_across_occurrences: false
394
+ }
395
+ Bookable.initialize_acts_as_bookable_core
396
+ expect(Bookable.booking_opts[:preset]).not_to be_present
397
+ expect(Bookable.booking_opts[:date_type]).not_to be_present
398
+ expect(Bookable.booking_opts[:time_type]).to be :range
399
+ expect(Bookable.booking_opts[:location_type]).not_to be_present
400
+ expect(Bookable.booking_opts[:capacity_type]).to be :closed
401
+ expect(Bookable.booking_opts[:bookable_across_occurrences]).to be false
402
+ end
403
+
404
+ it 'should not allow unknown keys' do
405
+ Bookable.booking_opts = {unknown: 'lol'}
406
+ expect { Bookable.initialize_acts_as_bookable_core }.to raise_error ActsAsBookable::InitializationError
407
+ begin
408
+ Bookable.initialize_acts_as_bookable_core
409
+ rescue ActsAsBookable::InitializationError => e
410
+ expect(e.message).to include 'is not a valid option'
411
+ end
412
+ end
413
+
414
+ it 'should not allow unknown values on :time_type' do
415
+ Bookable.booking_opts = {time_type: :unknown}
416
+ expect { Bookable.initialize_acts_as_bookable_core }.to raise_error ActsAsBookable::InitializationError
417
+ begin
418
+ Bookable.initialize_acts_as_bookable_core
419
+ rescue ActsAsBookable::InitializationError => e
420
+ expect(e.message).to include 'is not a valid value for time_type'
421
+ end
422
+ end
423
+
424
+ it 'should not allow unknown values on :capacity_type' do
425
+ Bookable.booking_opts = {capacity_type: :unknown}
426
+ expect { Bookable.initialize_acts_as_bookable_core }.to raise_error ActsAsBookable::InitializationError
427
+ begin
428
+ Bookable.initialize_acts_as_bookable_core
429
+ rescue ActsAsBookable::InitializationError => e
430
+ expect(e.message).to include 'is not a valid value for capacity_type'
431
+ end
432
+ end
433
+
434
+ it 'should not allow unknown values on bookable_across_occurrences' do
435
+ Bookable.booking_opts = {bookable_across_occurrences: :unknown}
436
+ expect { Bookable.initialize_acts_as_bookable_core }.to raise_error ActsAsBookable::InitializationError
437
+ begin
438
+ Bookable.initialize_acts_as_bookable_core
439
+ rescue ActsAsBookable::InitializationError => e
440
+ expect(e.message).to include 'is not a valid value for bookable_across_occurrences'
441
+ end
442
+ end
443
+ end
444
+ end
445
+
446
+ describe 'self.validate_booking_options!' do
447
+ before(:each) do
448
+ Bookable.booking_opts = {
449
+ time_type: :none,
450
+ capacity_type: :none
451
+ }
452
+ @opts = {}
453
+ end
454
+
455
+ describe 'with capacity_type: :none and time_type: :none' do
456
+ it 'validates with default options' do
457
+ expect(Bookable.validate_booking_options!(@opts)).to be_truthy
458
+ end
459
+ end
460
+
461
+ describe 'with time_type = ' do
462
+ describe ':range' do
463
+ before(:each) do
464
+ Bookable.booking_opts[:time_type] = :range
465
+ Bookable.initialize_acts_as_bookable_core
466
+ @opts[:time_start] = Time.now + 1.hour
467
+ @opts[:time_end] = Time.now + 4.hours
468
+ end
469
+
470
+ it 'validates with all options fields set' do
471
+ expect(Bookable.validate_booking_options!(@opts)).to be_truthy
472
+ end
473
+
474
+ it 'requires time_start as Time' do
475
+ @opts[:time_start] = nil
476
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
477
+ @opts[:time_start] = 'String'
478
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
479
+ end
480
+
481
+ it 'requires time_end as Time' do
482
+ @opts[:time_end] = nil
483
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
484
+ @opts[:time_end] = 'String'
485
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
486
+ end
487
+
488
+ it 'doesn\'t accept a fixed time' do
489
+ @opts[:time] = Time.now
490
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
491
+ end
492
+ end
493
+
494
+ describe ':fixed' do
495
+ before(:each) do
496
+ Bookable.booking_opts[:time_type] = :fixed
497
+ Bookable.initialize_acts_as_bookable_core
498
+ @opts[:time] = Time.now + 1.hour
499
+ end
500
+
501
+ it 'validates with the right fields set' do
502
+ expect(Bookable.validate_booking_options!(@opts)).to be_truthy
503
+ end
504
+
505
+ it 'requires date as Time' do
506
+ @opts[:time] = nil
507
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
508
+ @opts[:time] = 'String'
509
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
510
+ end
511
+
512
+ it 'doesn\'t accept time_start' do
513
+ @opts[:time_start] = Time.now + 13
514
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
515
+ end
516
+
517
+ it 'doesn\'t accept time_end' do
518
+ @opts[:time_end] = Time.now + 15
519
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
520
+ end
521
+ end
522
+
523
+ describe ':none' do
524
+ before(:each) do
525
+ Bookable.initialize_acts_as_bookable_core
526
+ end
527
+
528
+ it 'doesn\'t accept time' do
529
+ @opts[:time] = Time.now + 13
530
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
531
+ end
532
+
533
+ it 'doesn\'t accept time_start' do
534
+ @opts[:time_start] = Time.now + 13
535
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
536
+ end
537
+
538
+ it 'doesn\'t accept time_end' do
539
+ @opts[:time_end] = Time.now + 15
540
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
541
+ end
542
+ end
543
+ end
544
+
545
+ describe 'with capacity_type = ' do
546
+ describe ':open' do
547
+ before(:each) do
548
+ Bookable.booking_opts[:capacity_type] = :open
549
+ Bookable.initialize_acts_as_bookable_core
550
+ @opts[:amount] = 2
551
+ end
552
+
553
+ it 'validates with all options fields set' do
554
+ expect(Bookable.validate_booking_options!(@opts)).to be_truthy
555
+ end
556
+
557
+ it 'requires :amount as integer' do
558
+ @opts[:amount] = nil
559
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
560
+ end
561
+ end
562
+
563
+ describe ':closed' do
564
+ before(:each) do
565
+ Bookable.booking_opts[:capacity_type] = :closed
566
+ Bookable.initialize_acts_as_bookable_core
567
+ @opts[:amount] = 2
568
+ end
569
+
570
+ it 'validates with all options fields set' do
571
+ expect(Bookable.validate_booking_options!(@opts)).to be_truthy
572
+ end
573
+
574
+ it 'requires :amount as integer' do
575
+ @opts[:amount] = nil
576
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
577
+ end
578
+ end
579
+
580
+ describe ':none' do
581
+ before(:each) do
582
+ Bookable.initialize_acts_as_bookable_core
583
+ end
584
+
585
+ it 'doesn\'t accept amount' do
586
+ @opts[:amount] = 2.3
587
+ expect{ Bookable.validate_booking_options!(@opts) }.to raise_error ActsAsBookable::OptionsInvalid
588
+ end
589
+ end
590
+ end
591
+ end
592
+ end
593
+ end