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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +43 -0
- data/Appraisals +21 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +168 -0
- data/Guardfile +5 -0
- data/MIT-LICENSE +20 -0
- data/README.md +473 -0
- data/Rakefile +19 -0
- data/acts_as_bookable.gemspec +41 -0
- data/app/assets/images/acts_as_bookable/.keep +0 -0
- data/app/assets/javascripts/acts_as_bookable/application.js +13 -0
- data/app/assets/stylesheets/acts_as_bookable/application.css +15 -0
- data/app/controllers/acts_as_bookable/application_controller.rb +4 -0
- data/app/helpers/acts_as_bookable/application_helper.rb +4 -0
- data/app/views/layouts/acts_as_bookable/application.html.erb +14 -0
- data/bin/rails +12 -0
- data/config/locales/en.yml +12 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20160217085200_create_acts_as_bookable_bookings.rb +14 -0
- data/gemfiles/activerecord_3.2.gemfile +16 -0
- data/gemfiles/activerecord_4.0.gemfile +16 -0
- data/gemfiles/activerecord_4.1.gemfile +16 -0
- data/gemfiles/activerecord_4.2.gemfile +17 -0
- data/gemfiles/activerecord_5.0.gemfile +17 -0
- data/lib/acts_as_bookable/bookable/core.rb +285 -0
- data/lib/acts_as_bookable/bookable.rb +56 -0
- data/lib/acts_as_bookable/booker.rb +70 -0
- data/lib/acts_as_bookable/booking.rb +54 -0
- data/lib/acts_as_bookable/db_utils.rb +39 -0
- data/lib/acts_as_bookable/engine.rb +5 -0
- data/lib/acts_as_bookable/t.rb +11 -0
- data/lib/acts_as_bookable/time_utils.rb +135 -0
- data/lib/acts_as_bookable/version.rb +3 -0
- data/lib/acts_as_bookable.rb +42 -0
- data/lib/tasks/acts_as_bookable_tasks.rake +4 -0
- data/spec/acts_as_bookable/acts_as_bookable_spec.rb +52 -0
- data/spec/acts_as_bookable/acts_as_booker_spec.rb +57 -0
- data/spec/acts_as_bookable/bookable/core_spec.rb +593 -0
- data/spec/acts_as_bookable/bookable_spec.rb +124 -0
- data/spec/acts_as_bookable/booker_spec.rb +140 -0
- data/spec/acts_as_bookable/booking_spec.rb +241 -0
- data/spec/acts_as_bookable/schedule_spec.rb +137 -0
- data/spec/acts_as_bookable/time_utils_spec.rb +525 -0
- data/spec/factories/bookable.rb +7 -0
- data/spec/factories/booker.rb +5 -0
- data/spec/factories/room.rb +11 -0
- data/spec/internal/app/models/Bookable.rb +3 -0
- data/spec/internal/app/models/Booker.rb +3 -0
- data/spec/internal/app/models/Event.rb +3 -0
- data/spec/internal/app/models/Generic.rb +2 -0
- data/spec/internal/app/models/NotBooker.rb +2 -0
- data/spec/internal/app/models/Room.rb +3 -0
- data/spec/internal/app/models/Show.rb +3 -0
- data/spec/internal/app/models/Unbookable.rb +2 -0
- data/spec/internal/config/database.yml.sample +17 -0
- data/spec/internal/db/schema.rb +51 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/0-helpers.rb +32 -0
- data/spec/support/1-database.rb +42 -0
- data/spec/support/2-database_cleaner.rb +21 -0
- data/spec/support/3-factory_girl.rb +12 -0
- metadata +296 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Bookable model' do
|
4
|
+
before(:each) do
|
5
|
+
@bookable = build(:bookable)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'conditional validations' do
|
9
|
+
it 'should be valid with all required fields set' do
|
10
|
+
expect(@bookable).to be_valid
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should save a bookable' do
|
14
|
+
expect(@bookable.save).to be_truthy
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'when capacity is required' do
|
18
|
+
before(:each) do
|
19
|
+
Bookable.booking_opts[:capacity_type] = :closed
|
20
|
+
Bookable.initialize_acts_as_bookable_core
|
21
|
+
end
|
22
|
+
after(:all) do
|
23
|
+
Bookable.booking_opts = {}
|
24
|
+
Bookable.initialize_acts_as_bookable_core
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should not validate with capacity < 0 if capacity is required' do
|
28
|
+
@bookable.capacity = -1
|
29
|
+
expect(@bookable.valid?).to be_falsy
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should not validate without capacity' do
|
33
|
+
@bookable.capacity = nil
|
34
|
+
expect(@bookable.valid?).to be_falsy
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'when capacity is not required' do
|
39
|
+
before(:each) do
|
40
|
+
Bookable.booking_opts[:capacity_type] = :none
|
41
|
+
Bookable.initialize_acts_as_bookable_core
|
42
|
+
end
|
43
|
+
after(:all) do
|
44
|
+
Bookable.booking_opts = {}
|
45
|
+
Bookable.initialize_acts_as_bookable_core
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should validate with capacity < 0' do
|
49
|
+
@bookable.capacity = -1
|
50
|
+
expect(@bookable.valid?).to be_truthy
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should validate without capacity if it\'s not required' do
|
54
|
+
@bookable.capacity = nil
|
55
|
+
expect(@bookable.valid?).to be_truthy
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'when schedule is required' do
|
60
|
+
before(:each) do
|
61
|
+
Bookable.booking_opts[:time_type] = :range
|
62
|
+
Bookable.initialize_acts_as_bookable_core
|
63
|
+
end
|
64
|
+
after(:all) do
|
65
|
+
Bookable.booking_opts = {}
|
66
|
+
Bookable.initialize_acts_as_bookable_core
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should not validate without schedule' do
|
70
|
+
@bookable.schedule = nil
|
71
|
+
expect(@bookable.valid?).to be_falsy
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'when schedule is not required' do
|
76
|
+
before(:each) do
|
77
|
+
Bookable.booking_opts[:time_type] = :none
|
78
|
+
Bookable.initialize_acts_as_bookable_core
|
79
|
+
end
|
80
|
+
after(:all) do
|
81
|
+
Bookable.booking_opts = {}
|
82
|
+
Bookable.initialize_acts_as_bookable_core
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should validate without schedule if it\'s not required' do
|
86
|
+
@bookable.schedule = nil
|
87
|
+
expect(@bookable.valid?).to be_truthy
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
describe 'has_many :bookings' do
|
94
|
+
before(:each) do
|
95
|
+
@bookable.save!
|
96
|
+
booker1 = create(:booker, name: 'Booker 1')
|
97
|
+
booker2 = create(:booker, name: 'Booker 2')
|
98
|
+
booking1 = ActsAsBookable::Booking.create!(booker: booker1, bookable: @bookable)
|
99
|
+
booking2 = ActsAsBookable::Booking.create!(booker: booker1, bookable: @bookable)
|
100
|
+
@bookable.reload
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should have many bookings' do
|
104
|
+
expect(@bookable.bookings).to be_present
|
105
|
+
expect(@bookable.bookings.count).to eq 2
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'dependent: :destroy' do
|
109
|
+
count = ActsAsBookable::Booking.count
|
110
|
+
@bookable.destroy
|
111
|
+
expect(ActsAsBookable::Booking.count).to eq count -2
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#schedule' do
|
116
|
+
it 'allows for creation of a bookable with a IceCube schedule' do
|
117
|
+
schedule = IceCube::Schedule.new
|
118
|
+
# Every Monday,Tuesday and Friday
|
119
|
+
schedule.add_recurrence_rule IceCube::Rule.weekly.day(:monday, :tuesday, :friday)
|
120
|
+
@bookable.schedule = schedule
|
121
|
+
expect(@bookable.save).to be_truthy
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Booker model' do
|
4
|
+
before(:each) do
|
5
|
+
@booker = build(:booker)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should be valid with all required fields set' do
|
9
|
+
expect(@booker).to be_valid
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should save a booker' do
|
13
|
+
expect(@booker.save).to be_truthy
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'has_many :bookings' do
|
17
|
+
before(:each) do
|
18
|
+
@booker.save!
|
19
|
+
bookable1 = create(:bookable)
|
20
|
+
bookable2 = create(:bookable)
|
21
|
+
booking1 = ActsAsBookable::Booking.create(bookable: bookable1, booker: @booker)
|
22
|
+
booking2 = ActsAsBookable::Booking.create(bookable: bookable2, booker: @booker)
|
23
|
+
@booker.reload
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should have many bookings' do
|
27
|
+
expect(@booker.bookings).to be_present
|
28
|
+
expect(@booker.bookings.count).to eq 2
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'dependent: :destroy' do
|
32
|
+
count = ActsAsBookable::Booking.count
|
33
|
+
@booker.destroy
|
34
|
+
expect(ActsAsBookable::Booking.count).to eq count -2
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#book!' do
|
39
|
+
before(:each) do
|
40
|
+
@bookable = create(:room)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should respond to #book!' do
|
45
|
+
expect(@booker).to respond_to :book!
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should create a new booking' do
|
49
|
+
count = @booker.bookings.count
|
50
|
+
new_booking = @booker.book!(@bookable, time_start: Date.today, time_end: Date.today + 1.day, amount: 2)
|
51
|
+
expect(@booker.bookings.count).to eq count+1
|
52
|
+
expect(new_booking.class.to_s).to eq "ActsAsBookable::Booking"
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'new booking should have all fields set' do
|
56
|
+
new_booking = @booker.book!(@bookable, time_start: Date.today, time_end: Date.today + 1.day, amount: 2)
|
57
|
+
new_booking.reload
|
58
|
+
expect(new_booking.time_start).to be_present
|
59
|
+
expect(new_booking.time_end).to be_present
|
60
|
+
expect(new_booking.amount).to be_present
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should raise ActiveRecord::RecordInvalid if new booking is not valid' do
|
64
|
+
expect{ @booker.book!(Generic.new) }.to raise_error ActiveRecord::RecordInvalid
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should not create a new booking if it\'s not valid' do
|
68
|
+
count = @booker.bookings.count
|
69
|
+
begin
|
70
|
+
@booker.book!(Generic.new)
|
71
|
+
rescue ActiveRecord::RecordInvalid => er
|
72
|
+
end
|
73
|
+
expect(@booker.bookings.count).to eq count
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should raise ActsAsBookable::AvailabilityError if the bookable is not available' do
|
77
|
+
@booker.book!(@bookable, time_start: Date.today, time_end: Date.today + 1.day, amount: 2)
|
78
|
+
expect{ @booker.book!(@bookable, time_start: Date.today, time_end: Date.today + 1.day, amount: 2)}.to raise_error ActsAsBookable::AvailabilityError
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
# describe 'Booker Method Generation' do
|
85
|
+
# before :each do
|
86
|
+
# Generic.acts_as_booker
|
87
|
+
# @booker = Generic.new()
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# it "should responde 'true' to booker?" do
|
91
|
+
# expect(@booker.class).to be_booker
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# describe 'class configured as Booker' do
|
96
|
+
# before(:each) do
|
97
|
+
# @booker = Booker.new
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# it 'should add #booker? query method to the class-side' do
|
101
|
+
# expect(Booker).to respond_to(:booker?)
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# it 'should return true from the class-side #booker?' do
|
105
|
+
# expect(Booker.booker?).to be_truthy
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# it 'should return false from the base #booker?' do
|
109
|
+
# expect(ActiveRecord::Base.booker?).to be_falsy
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
# it 'should add #booker? query method to the singleton' do
|
113
|
+
# expect(@booker).to respond_to(:booker?)
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# it 'should add #booker? query method to the instance-side' do
|
117
|
+
# expect(@booker).to respond_to(:booker?)
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# it 'should add #booker? query method to the instance-side' do
|
121
|
+
# expect(@booker.booker?).to be_truthy
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# # it 'should add #tag method on the instance-side' do
|
125
|
+
# # expect(@booker).to respond_to(:tag)
|
126
|
+
# # end
|
127
|
+
#
|
128
|
+
# # it 'should generate an association for #owned_taggings and #owned_tags' do
|
129
|
+
# # expect(@booker).to respond_to(:owned_taggings, :owned_tags)
|
130
|
+
# # end
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# describe 'Reloading' do
|
134
|
+
# it 'should save a model instantiated by Model.find' do
|
135
|
+
# booker = Generic.create!(name: 'Booker')
|
136
|
+
# found_booker = Generic.find(booker.id)
|
137
|
+
# expect(found_booker.save).to eq true
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Booking model' do
|
4
|
+
before(:each) do
|
5
|
+
@booking = ActsAsBookable::Booking.new(amount: 2)
|
6
|
+
@booker = create(:booker)
|
7
|
+
@bookable = create(:bookable)
|
8
|
+
@booking.booker = @booker
|
9
|
+
@booking.bookable = @bookable
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should be valid with all required fields set' do
|
13
|
+
expect(@booking).to be_valid
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should save a booking' do
|
17
|
+
expect(@booking.save).to be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should not be valid without a booker' do
|
21
|
+
@booking.booker = nil
|
22
|
+
expect(@booking).not_to be_valid
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should not be valid without a bookable' do
|
26
|
+
@booking.bookable = nil
|
27
|
+
expect(@booking).not_to be_valid
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should not be valid if booking.booker.booker? is false' do
|
31
|
+
not_booker = Generic.create(name: 'New generic model')
|
32
|
+
@booking.booker = not_booker
|
33
|
+
expect(@booking).not_to be_valid
|
34
|
+
expect(@booking.errors.messages[:booker]).to be_present
|
35
|
+
expect(@booking.errors.messages[:booker][0]).to include "Generic"
|
36
|
+
expect(@booking.errors.messages).not_to include "missing translation"
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not be valid if booking.bookable.bookable? is false' do
|
40
|
+
bookable = Generic.create(name: 'New generic model')
|
41
|
+
@booking.bookable = bookable
|
42
|
+
expect(@booking).not_to be_valid
|
43
|
+
expect(@booking.errors.messages[:bookable]).to be_present
|
44
|
+
expect(@booking.errors.messages[:bookable][0]).to include "Generic"
|
45
|
+
expect(@booking.errors.messages).not_to include "missing translation"
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should belong to booker' do
|
49
|
+
expect(@booking.booker.id).to eq @booker.id
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should belong to bookable' do
|
53
|
+
expect(@booking.bookable.id).to eq @bookable.id
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "overlapped scope" do
|
57
|
+
|
58
|
+
describe "without time" do
|
59
|
+
it "returns a booking without checking the time" do
|
60
|
+
time = Date.today.to_time
|
61
|
+
booking = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: time, bookable: @bookable, booker: @booker)
|
62
|
+
opts = {}
|
63
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 1
|
64
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking.id
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns all the bookings without checking the time" do
|
68
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: Time.now, bookable: @bookable, booker: @booker)
|
69
|
+
booking2 = ActsAsBookable::Booking.create!(time_start: Time.now, time_end: Time.now + 3.hours, time: nil, bookable: @bookable, booker: @booker)
|
70
|
+
booking3 = ActsAsBookable::Booking.create!(time_start: Time.now - 10.days, time_end: Time.now - 9.days, time: nil, bookable: @bookable, booker: @booker)
|
71
|
+
opts = {}
|
72
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 3
|
73
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking1.id
|
74
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[1].id).to eq booking2.id
|
75
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[2].id).to eq booking3.id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "with fixed time" do
|
80
|
+
it "returns overlapped booking" do
|
81
|
+
time = Date.today.to_time
|
82
|
+
booking = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: time, bookable: @bookable, booker: @booker)
|
83
|
+
opts = {time: time}
|
84
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 1
|
85
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking.id
|
86
|
+
end
|
87
|
+
|
88
|
+
it "returns all the overlapped bookings" do
|
89
|
+
time = Date.today.to_time
|
90
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: time, bookable: @bookable, booker: @booker)
|
91
|
+
booking2 = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: time, bookable: @bookable, booker: @booker)
|
92
|
+
booking3 = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: time + 1.hour, bookable: @bookable, booker: @booker)
|
93
|
+
opts = {time: time}
|
94
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 2
|
95
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking1.id
|
96
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[1].id).to eq booking2.id
|
97
|
+
end
|
98
|
+
|
99
|
+
it "returns no overlapped booking if time is wrong" do
|
100
|
+
time = Date.today.to_time
|
101
|
+
booking = ActsAsBookable::Booking.create!(time_start: nil, time_end: nil, time: time, bookable: @bookable, booker: @booker)
|
102
|
+
opts = {time: (time + 1.hour)}
|
103
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 0
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "with time range" do
|
108
|
+
it "returns overlapped booking" do
|
109
|
+
time_start = Date.today.to_time
|
110
|
+
time_end = Date.today.to_time + 10.hours
|
111
|
+
booking = ActsAsBookable::Booking.create!(time_start: time_start, time_end: time_end, time: nil, bookable: @bookable, booker: @booker)
|
112
|
+
opts = { time_start: time_start, time_end: time_end }
|
113
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 1
|
114
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking.id
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns more overlapped bookings" do
|
118
|
+
time_start = Date.today.to_time
|
119
|
+
time_end = Date.today.to_time + 10.hours
|
120
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: time_start, time_end: time_end, time: nil, bookable: @bookable, booker: @booker)
|
121
|
+
booking2 = ActsAsBookable::Booking.create!(time_start: time_start, time_end: time_end, time: nil, bookable: @bookable, booker: @booker)
|
122
|
+
booking3 = ActsAsBookable::Booking.create!(time_start: time_start-10.days, time_end: time_end-10.days, time: nil, bookable: @bookable, booker: @booker)
|
123
|
+
opts = { time_start: time_start, time_end: time_end }
|
124
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 2
|
125
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking1.id
|
126
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[1].id).to eq booking2.id
|
127
|
+
end
|
128
|
+
|
129
|
+
it "doesn't return any booking if time is wrong" do
|
130
|
+
time_start = Date.today.to_time
|
131
|
+
time_end = Date.today.to_time + 10.hours
|
132
|
+
booking = ActsAsBookable::Booking.create!(time_start: time_start - 10.days, time_end: time_end - 10.days, time: nil, bookable: @bookable, booker: @booker)
|
133
|
+
opts = { time_start: time_start, time_end: time_end }
|
134
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 0
|
135
|
+
end
|
136
|
+
|
137
|
+
it "returns also a booking overlapping but with time_start outside interval" do
|
138
|
+
time_start = Date.today.to_time
|
139
|
+
time_end = Date.tomorrow.to_time
|
140
|
+
booking = ActsAsBookable::Booking.create!(time_start: time_start - 10.hours, time_end: time_end, bookable: @bookable, booker: @booker)
|
141
|
+
opts = { time_start: time_start, time_end: time_end }
|
142
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 1
|
143
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking.id
|
144
|
+
end
|
145
|
+
|
146
|
+
it "returns also a booking overlapping but with time_end outside interval" do
|
147
|
+
time_start = Date.today.to_time
|
148
|
+
time_end = Date.tomorrow.to_time
|
149
|
+
booking = ActsAsBookable::Booking.create!(time_start: time_start, time_end: time_end + 10.hours, bookable: @bookable, booker: @booker)
|
150
|
+
opts = { time_start: time_start, time_end: time_end }
|
151
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 1
|
152
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking.id
|
153
|
+
end
|
154
|
+
|
155
|
+
it "returns more overlapped bookings, some of them not completely overlapping" do
|
156
|
+
time_start = Date.today.to_time
|
157
|
+
time_end = Date.today.to_time + 10.hours
|
158
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: time_start - 5.hours, time_end: time_end - 5.hours, time: nil, bookable: @bookable, booker: @booker)
|
159
|
+
booking2 = ActsAsBookable::Booking.create!(time_start: time_start + 5.hours, time_end: time_end + 5.hours, time: nil, bookable: @bookable, booker: @booker)
|
160
|
+
booking3 = ActsAsBookable::Booking.create!(time_start: time_start + 2.hours, time_end: time_end - 2.hours, time: nil, bookable: @bookable, booker: @booker)
|
161
|
+
booking4 = ActsAsBookable::Booking.create!(time_start: time_start-10.days, time_end: time_end-10.days, time: nil, bookable: @bookable, booker: @booker)
|
162
|
+
booking4 = ActsAsBookable::Booking.create!(time_start: time_start+10.days, time_end: time_end+10.days, time: nil, bookable: @bookable, booker: @booker)
|
163
|
+
opts = { time_start: time_start, time_end: time_end }
|
164
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts).count).to eq 3
|
165
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[0].id).to eq booking1.id
|
166
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[1].id).to eq booking2.id
|
167
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,opts)[2].id).to eq booking3.id
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "should handle limit cases" do
|
171
|
+
before :each do
|
172
|
+
@time_start = Date.today.to_time
|
173
|
+
@time_end = Date.today.to_time + 10.hours
|
174
|
+
|
175
|
+
@time_before_start = @time_start - 1.second
|
176
|
+
@time_after_start = @time_start + 1.second
|
177
|
+
@time_before_end = @time_end - 1.second
|
178
|
+
@time_after_end = @time_end + 1.second
|
179
|
+
|
180
|
+
@opts = { time_start: @time_start, time_end: @time_end }
|
181
|
+
end
|
182
|
+
|
183
|
+
it "excludes intervals with end before time_start and start after time_end" do
|
184
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_start - 5.hours, time_end: @time_before_start, time: nil, bookable: @bookable, booker: @booker)
|
185
|
+
booking2 = ActsAsBookable::Booking.create!(time_start: @time_after_end, time_end: @time_end + 5.hours, time: nil, bookable: @bookable, booker: @booker)
|
186
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 0
|
187
|
+
end
|
188
|
+
|
189
|
+
it "excludes intervals with start matching exactly with time_end" do
|
190
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_end, time_end: @time_end + 2.hours, time: nil, bookable: @bookable, booker: @booker)
|
191
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 0
|
192
|
+
end
|
193
|
+
|
194
|
+
it "includes intervals with end after time_start" do
|
195
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_start - 5.hours, time_end: @time_after_start, time: nil, bookable: @bookable, booker: @booker)
|
196
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 1
|
197
|
+
end
|
198
|
+
|
199
|
+
it "includes intervals with end exactly at time_start" do
|
200
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_start - 5.hours, time_end: @time_start, time: nil, bookable: @bookable, booker: @booker)
|
201
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 1
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "should convert dates to times" do
|
206
|
+
before :each do
|
207
|
+
@time_start = Date.today
|
208
|
+
@time_end = Date.tomorrow
|
209
|
+
|
210
|
+
@time_before_start = @time_start - 1.second
|
211
|
+
@time_after_start = @time_start + 1.second
|
212
|
+
@time_before_end = @time_end - 1.second
|
213
|
+
@time_after_end = @time_end + 1.second
|
214
|
+
|
215
|
+
@opts = { time_start: @time_start, time_end: @time_end }
|
216
|
+
end
|
217
|
+
|
218
|
+
it "excludes intervals with end before time_start and start after time_end" do
|
219
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_start - 5.hours, time_end: @time_before_start, time: nil, bookable: @bookable, booker: @booker)
|
220
|
+
booking2 = ActsAsBookable::Booking.create!(time_start: @time_after_end, time_end: @time_end + 5.hours, time: nil, bookable: @bookable, booker: @booker)
|
221
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 0
|
222
|
+
end
|
223
|
+
|
224
|
+
it "excludes intervals with start matching exactly with time_end" do
|
225
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_end, time_end: @time_end + 2.hours, time: nil, bookable: @bookable, booker: @booker)
|
226
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 0
|
227
|
+
end
|
228
|
+
|
229
|
+
it "includes intervals with end after time_start" do
|
230
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_start - 5.hours, time_end: @time_after_start, time: nil, bookable: @bookable, booker: @booker)
|
231
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 1
|
232
|
+
end
|
233
|
+
|
234
|
+
it "includes intervals with end exactly at time_start" do
|
235
|
+
booking1 = ActsAsBookable::Booking.create!(time_start: @time_start - 5.hours, time_end: @time_start, time: nil, bookable: @bookable, booker: @booker)
|
236
|
+
expect(ActsAsBookable::Booking.overlapped(@bookable,@opts).count).to eq 1
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Schedules' do
|
4
|
+
describe "Room schedules" do
|
5
|
+
before :each do
|
6
|
+
@test_from = '2016-02-01'.to_date # it's a monday
|
7
|
+
@schedule = IceCube::Schedule.new @test_from
|
8
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:monday,:tuesday,:wednesday,:thursday,:friday)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "Weekly, From monday to friday" do
|
12
|
+
# Weekly, From monday to friday
|
13
|
+
expect(@schedule.occurring_at?(@test_from)).to be true
|
14
|
+
expect(@schedule.occurring_at?(@test_from + 1.day)).to be true
|
15
|
+
expect(@schedule.occurring_at?(@test_from + 2.day)).to be true
|
16
|
+
expect(@schedule.occurring_at?(@test_from + 3.day)).to be true
|
17
|
+
expect(@schedule.occurring_at?(@test_from + 4.day)).to be true
|
18
|
+
expect(@schedule.occurring_at?(@test_from + 5.day)).to be false
|
19
|
+
expect(@schedule.occurring_at?(@test_from + 6.day)).to be false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "doesn't match if not at exact minute" do
|
23
|
+
expect(@schedule.occurring_at?(@test_from + 1.minute)).to be false
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "with daily duration" do
|
27
|
+
before :each do
|
28
|
+
@test_from = '2016-02-01'.to_date # it's a monday
|
29
|
+
@schedule = IceCube::Schedule.new @test_from
|
30
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:monday,:tuesday,:wednesday,:thursday,:friday)
|
31
|
+
@schedule.duration = 1.day
|
32
|
+
end
|
33
|
+
|
34
|
+
it "match with the exact minute" do
|
35
|
+
# Weekly, From monday to friday
|
36
|
+
expect(@schedule.occurring_at?(@test_from)).to be true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "matches if not at exact minute" do
|
40
|
+
expect(@schedule.occurring_at?(@test_from + 1.minute)).to be true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "matches if at end of day" do
|
44
|
+
expect(@schedule.occurring_at?(@test_from + 1.day - 1.minute)).to be true
|
45
|
+
expect(@schedule.occurring_at?(@test_from + 1.day - 1.minute)).to be true
|
46
|
+
expect(@schedule.occurring_at?(@test_from + 4.day - 1.second)).to be true
|
47
|
+
expect(@schedule.occurring_at?(@test_from + 4.day - 1.second)).to be true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "doesn't match at the first second of the first day not included" do
|
51
|
+
expect(@schedule.occurring_at?(@test_from + 5.days)).to be false
|
52
|
+
expect(@schedule.occurring_at?(@test_from + 5.days + 1.second)).to be false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "except the first and the last day of the month" do
|
57
|
+
before :each do
|
58
|
+
@test_from = '2016-02-01'.to_date # it's a monday
|
59
|
+
@schedule = IceCube::Schedule.new @test_from
|
60
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:monday,:tuesday,:wednesday,:thursday,:friday)
|
61
|
+
@schedule.add_exception_rule IceCube::Rule.monthly.day_of_month(1, -1)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "doesn't match on the first of the month" do
|
65
|
+
expect(@schedule.occurring_at?(@test_from)).to be false
|
66
|
+
expect(@schedule.occurring_at?(@test_from.end_of_month)).to be false
|
67
|
+
expect(@schedule.occurring_at?(@test_from + 1.month)).to be false
|
68
|
+
expect(@schedule.occurring_at?((@test_from + 1.month).end_of_month)).to be false
|
69
|
+
expect(@schedule.occurring_at?('2017-01-01'.to_date)).to be false # sunday
|
70
|
+
expect(@schedule.occurring_at?('2017-01-01'.to_date + 1.second)).to be false # sunday
|
71
|
+
expect(@schedule.occurring_at?('2017-01-01'.to_date + 1.day)).to be true # monday
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "Gym schedules" do
|
77
|
+
before :each do
|
78
|
+
# Mon | Tue | Wed | Thu | Fri | Sat |Sun
|
79
|
+
# 9-10 | 10-11 | 9-10 | 10-11 | | 14-15 |
|
80
|
+
# 18:10-19:10 | 20-21 | 18:10-19:10 | 20-21 | | |
|
81
|
+
# Except for the third saturday of the month
|
82
|
+
@test_from = '2016-02-01'.to_date # it's a monday
|
83
|
+
@schedule = IceCube::Schedule.new(@test_from, duration: 1.hour)
|
84
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:monday,:wednesday).hour_of_day(9)
|
85
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:monday,:wednesday).hour_of_day(18).minute_of_hour(10)
|
86
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:tuesday,:thursday).hour_of_day(10,20)
|
87
|
+
@schedule.add_recurrence_rule IceCube::Rule.weekly.day(:saturday).hour_of_day(14)
|
88
|
+
@schedule.add_exception_rule IceCube::Rule.monthly.day_of_week(saturday: [3]).hour_of_day(14)
|
89
|
+
@schedule.add_exception_rule IceCube::Rule.monthly.day_of_week(wednesday: [3]).hour_of_day(9)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "matches at the occurrences" do
|
93
|
+
(0...12).each do |i|
|
94
|
+
minute = (i * 5).minutes
|
95
|
+
expect(@schedule.occurring_at?(@test_from + 9.hours + minute)).to be true # monday
|
96
|
+
expect(@schedule.occurring_at?(@test_from + 18.hours + 10.minutes + minute)).to be true # monday
|
97
|
+
expect(@schedule.occurring_at?(@test_from + 5.days + 14.hours + minute)).to be true # tuesday
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "doesn't match close to the occurrences" do
|
102
|
+
expect(@schedule.occurring_at?(@test_from + 9.hours - 1.minute)).to be false # monday
|
103
|
+
expect(@schedule.occurring_at?(@test_from + 10.hours)).to be false # monday
|
104
|
+
expect(@schedule.occurring_at?(@test_from + 18.hours + 9.minutes)).to be false # monday
|
105
|
+
expect(@schedule.occurring_at?(@test_from + 19.hours + 9.minutes)).to be true # monday
|
106
|
+
expect(@schedule.occurring_at?(@test_from + 19.hours + 10.minutes)).to be false # monday
|
107
|
+
end
|
108
|
+
|
109
|
+
it "doesn't match the saturday of the third week of the month" do
|
110
|
+
(0...12).each do |i|
|
111
|
+
minute = (i * 5).minutes
|
112
|
+
expect(@schedule.occurring_at?('2016-02-20'.to_date + 14.hours + minute)).to be false # monday
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "borderline matchings" do
|
117
|
+
before :each do
|
118
|
+
# Except the third wednesday of the month
|
119
|
+
@test_from = '2016-02-01'.to_date # it's a monday
|
120
|
+
@schedule = IceCube::Schedule.new(@test_from)
|
121
|
+
@schedule.add_recurrence_rule IceCube::Rule.monthly.day_of_week(wednesday: [3])
|
122
|
+
end
|
123
|
+
|
124
|
+
it "matches the third wednesday of the month, in normal conditions" do
|
125
|
+
expect(@schedule.occurring_at?('2016-02-17'.to_date)).to be true
|
126
|
+
end
|
127
|
+
|
128
|
+
it "matches the third wednesday of the month, if the month starts on friday" do
|
129
|
+
expect(@schedule.occurring_at?('2016-04-20'.to_date)).to be true
|
130
|
+
end
|
131
|
+
|
132
|
+
it "doesn't match the wednesday of the third week of the month, if the month starts on friday" do
|
133
|
+
expect(@schedule.occurring_at?('2016-04-13'.to_date)).to be false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|