acts_as_bookable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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