bigbluebutton_rails 2.2.0 → 2.3.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 +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +34 -0
- data/Dockerfile +23 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +14 -5
- data/README.md +42 -59
- data/Rakefile +6 -3
- data/app/controllers/bigbluebutton/api/rooms_controller.rb +117 -0
- data/app/controllers/bigbluebutton/playback_types_controller.rb +0 -3
- data/app/controllers/bigbluebutton/recordings_controller.rb +37 -23
- data/app/controllers/bigbluebutton/rooms_controller.rb +6 -31
- data/app/controllers/bigbluebutton/servers_controller.rb +0 -14
- data/app/helpers/bigbluebutton_rails_helper.rb +4 -0
- data/app/models/bigbluebutton_attendee.rb +21 -0
- data/app/models/bigbluebutton_meeting.rb +5 -0
- data/app/models/bigbluebutton_playback_format.rb +3 -2
- data/app/models/bigbluebutton_recording.rb +164 -68
- data/app/models/bigbluebutton_room.rb +148 -59
- data/app/models/bigbluebutton_server.rb +1 -1
- data/app/views/bigbluebutton/api/error.rabl +10 -0
- data/app/views/bigbluebutton/api/rooms/index.rabl +45 -0
- data/app/views/bigbluebutton/api/rooms/join.rabl +6 -0
- data/app/views/bigbluebutton/api/rooms/running.rabl +10 -0
- data/app/views/bigbluebutton/recordings/play.html.erb +1 -0
- data/app/views/bigbluebutton/servers/_activity_list.html.erb +5 -5
- data/app/workers/{bigbluebutton_finish_meetings.rb → bigbluebutton_finish_meetings_worker.rb} +2 -2
- data/app/workers/{bigbluebutton_meeting_updater.rb → bigbluebutton_meeting_updater_worker.rb} +3 -3
- data/app/workers/bigbluebutton_recordings_for_room_worker.rb +27 -0
- data/app/workers/{bigbluebutton_update_recordings.rb → bigbluebutton_update_recordings_worker.rb} +2 -2
- data/app/workers/{bigbluebutton_update_server_configs.rb → bigbluebutton_update_server_configs_worker.rb} +3 -3
- data/bigbluebutton_rails.gemspec +1 -0
- data/config/locales/en.yml +21 -0
- data/config/locales/pt-br.yml +1 -0
- data/config/resque/resque.rake +7 -1
- data/config/resque/workers_schedule.yml +3 -3
- data/docker-compose.yml +68 -0
- data/dumb-init_1.2.0 +0 -0
- data/lib/bigbluebutton_rails.rb +1 -2
- data/lib/bigbluebutton_rails/api_controller_methods.rb +138 -0
- data/lib/bigbluebutton_rails/configuration.rb +33 -4
- data/lib/bigbluebutton_rails/controller_methods.rb +0 -31
- data/lib/bigbluebutton_rails/exceptions.rb +17 -0
- data/lib/bigbluebutton_rails/rails/routes.rb +14 -0
- data/lib/bigbluebutton_rails/version.rb +1 -1
- data/lib/generators/bigbluebutton_rails/templates/migration.rb +17 -3
- data/lib/generators/bigbluebutton_rails/templates/migration_2_2_0.rb +1 -1
- data/lib/generators/bigbluebutton_rails/templates/migration_2_2_0_b.rb +106 -0
- data/lib/generators/bigbluebutton_rails/templates/migration_2_3_0.rb +22 -0
- data/lib/tasks/bigbluebutton_rails/meetings.rake +1 -1
- data/spec/controllers/bigbluebutton/api/rooms_controller_spec.rb +498 -0
- data/spec/controllers/bigbluebutton/recordings_controller_spec.rb +84 -0
- data/spec/controllers/bigbluebutton/rooms_controller_exception_handling_spec.rb +2 -2
- data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +24 -22
- data/spec/controllers/bigbluebutton/servers_controller_spec.rb +9 -0
- data/spec/factories/bigbluebutton_attendee.rb +7 -0
- data/spec/factories/bigbluebutton_meeting.rb +0 -1
- data/spec/factories/bigbluebutton_playback_type.rb +1 -0
- data/spec/factories/bigbluebutton_recording.rb +2 -4
- data/spec/helpers/bigbluebutton_rails_helper_spec.rb +10 -2
- data/spec/lib/bigbluebutton_rails/background_tasks_spec.rb +1 -0
- data/spec/lib/tasks/meetings_rake_spec.rb +1 -1
- data/spec/models/bigbluebutton_attendee_spec.rb +44 -0
- data/spec/models/bigbluebutton_meeting_db_spec.rb +0 -1
- data/spec/models/bigbluebutton_meeting_spec.rb +1 -0
- data/spec/models/bigbluebutton_playback_format_spec.rb +2 -0
- data/spec/models/bigbluebutton_playback_type_db_spec.rb +1 -0
- data/spec/models/bigbluebutton_recording_db_spec.rb +2 -2
- data/spec/models/bigbluebutton_recording_spec.rb +404 -72
- data/spec/models/bigbluebutton_room_spec.rb +435 -148
- data/spec/rails_app/config/database.yml.example +10 -11
- data/spec/rails_app/config/initializers/resque.rb +33 -0
- data/spec/rails_app/config/routes.rb +2 -0
- data/spec/rails_app/lib/tasks/db/populate.rake +73 -55
- data/spec/support/mocked_server.rb +1 -1
- data/spec/workers/{bigbluebutton_finish_meetings_spec.rb → bigbluebutton_finish_meetings_worker_spec.rb} +3 -3
- data/spec/workers/{bigbluebutton_meeting_updater_spec.rb → bigbluebutton_meeting_updater_worker_spec.rb} +8 -7
- data/spec/workers/bigbluebutton_recordings_for_room_worker_spec.rb +49 -0
- data/spec/workers/{bigbluebutton_update_recordings_spec.rb → bigbluebutton_update_recordings_worker_spec.rb} +3 -3
- data/spec/workers/{bigbluebutton_update_server_configs_spec.rb → bigbluebutton_update_server_configs_worker_spec.rb} +4 -4
- metadata +42 -14
- data/lib/classes/bigbluebutton_attendee.rb +0 -21
- data/spec/classes/bigbluebutton_attendee_spec.rb +0 -76
- data/spec/controllers/bigbluebutton/recordings_controller_json_responses_spec.rb +0 -111
- data/spec/controllers/bigbluebutton/rooms_controller_json_responses_spec.rb +0 -203
- data/spec/controllers/bigbluebutton/servers_controller_json_responses_spec.rb +0 -162
|
@@ -273,6 +273,90 @@ describe Bigbluebutton::RecordingsController do
|
|
|
273
273
|
before(:each) { get :play, :id => recording.to_param, :type => format.format_type }
|
|
274
274
|
it { should assign_to(:recording).with(other_recording) }
|
|
275
275
|
end
|
|
276
|
+
|
|
277
|
+
context "authenticates" do
|
|
278
|
+
let!(:format) { FactoryGirl.create(:bigbluebutton_playback_format, :recording => recording) }
|
|
279
|
+
|
|
280
|
+
before { @previous = BigbluebuttonRails.configuration.playback_url_authentication }
|
|
281
|
+
after { BigbluebuttonRails.configuration.playback_url_authentication = @previous }
|
|
282
|
+
|
|
283
|
+
context "if authentication is enabled" do
|
|
284
|
+
before {
|
|
285
|
+
BigbluebuttonRails.configuration.playback_url_authentication = true
|
|
286
|
+
controller.should_receive(:bigbluebutton_user).and_return('fake-user')
|
|
287
|
+
BigbluebuttonRecording.any_instance.should_receive(:token_url)
|
|
288
|
+
.with('fake-user', request.remote_ip, format)
|
|
289
|
+
.and_return('tokenized-url')
|
|
290
|
+
}
|
|
291
|
+
before(:each) { get :play, :id => recording.to_param, :type => format.format_type }
|
|
292
|
+
it { should respond_with(:redirect) }
|
|
293
|
+
it { should redirect_to 'tokenized-url' }
|
|
294
|
+
it { should assign_to(:playback_url).with('tokenized-url') }
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
context "if authentication is not enabled" do
|
|
298
|
+
before {
|
|
299
|
+
BigbluebuttonRails.configuration.playback_url_authentication = false
|
|
300
|
+
BigbluebuttonRecording.any_instance.should_not_receive(:token_url)
|
|
301
|
+
}
|
|
302
|
+
before(:each) { get :play, :id => recording.to_param, :type => format.format_type }
|
|
303
|
+
it { should respond_with(:redirect) }
|
|
304
|
+
it { should redirect_to format.url }
|
|
305
|
+
it { should assign_to(:playback_url).with(format.url) }
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
context "uses an iframe" do
|
|
310
|
+
let!(:format) { FactoryGirl.create(:bigbluebutton_playback_format, :recording => recording) }
|
|
311
|
+
|
|
312
|
+
before { @previous = BigbluebuttonRails.configuration.playback_iframe }
|
|
313
|
+
after { BigbluebuttonRails.configuration.playback_iframe = @previous }
|
|
314
|
+
|
|
315
|
+
context "if the iframe option is on" do
|
|
316
|
+
before { BigbluebuttonRails.configuration.playback_iframe = true }
|
|
317
|
+
|
|
318
|
+
context "and it is downloadable" do
|
|
319
|
+
before {
|
|
320
|
+
format.playback_type.update_attributes(downloadable: true)
|
|
321
|
+
get :play, :id => recording.to_param, :type => format.format_type
|
|
322
|
+
}
|
|
323
|
+
it { should respond_with(:redirect) }
|
|
324
|
+
it { should redirect_to format.url }
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
context "and it is not downloadable" do
|
|
328
|
+
before {
|
|
329
|
+
format.playback_type.update_attributes(downloadable: false)
|
|
330
|
+
get :play, :id => recording.to_param, :type => format.format_type
|
|
331
|
+
}
|
|
332
|
+
it { should respond_with(:success) }
|
|
333
|
+
it { should render_template(:play) }
|
|
334
|
+
it { should_not render_with_layout }
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
context "if the iframe option is off" do
|
|
339
|
+
before { BigbluebuttonRails.configuration.playback_iframe = false }
|
|
340
|
+
|
|
341
|
+
context "and it is downloadable" do
|
|
342
|
+
before {
|
|
343
|
+
format.playback_type.update_attributes(downloadable: true)
|
|
344
|
+
get :play, :id => recording.to_param, :type => format.format_type
|
|
345
|
+
}
|
|
346
|
+
it { should respond_with(:redirect) }
|
|
347
|
+
it { should redirect_to format.url }
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
context "and it is not downloadable" do
|
|
351
|
+
before {
|
|
352
|
+
format.playback_type.update_attributes(downloadable: false)
|
|
353
|
+
get :play, :id => recording.to_param, :type => format.format_type
|
|
354
|
+
}
|
|
355
|
+
it { should respond_with(:redirect) }
|
|
356
|
+
it { should redirect_to format.url }
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
276
360
|
end
|
|
277
361
|
|
|
278
362
|
# these actions are essentially the same
|
|
@@ -10,7 +10,7 @@ describe Bigbluebutton::RoomsController do
|
|
|
10
10
|
let(:http_referer) { bigbluebutton_server_path(mocked_server) }
|
|
11
11
|
let(:room) { FactoryGirl.create(:bigbluebutton_room) }
|
|
12
12
|
before {
|
|
13
|
-
BigbluebuttonRoom.stub(:
|
|
13
|
+
BigbluebuttonRoom.stub(:find_by) { room }
|
|
14
14
|
BigbluebuttonRoom.stub(:find) { room }
|
|
15
15
|
mock_server_and_api
|
|
16
16
|
request.env["HTTP_REFERER"] = http_referer
|
|
@@ -69,7 +69,7 @@ describe Bigbluebutton::RoomsController do
|
|
|
69
69
|
before {
|
|
70
70
|
controller.should_receive(:bigbluebutton_role).with(room).and_return(:moderator)
|
|
71
71
|
room.stub(:select_server).and_return(mocked_server)
|
|
72
|
-
BigbluebuttonRoom.stub(:
|
|
72
|
+
BigbluebuttonRoom.stub(:find_by).and_return(room)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
it "catches exception on the first is_meeting_running" do
|
|
@@ -307,7 +307,7 @@ describe Bigbluebutton::RoomsController do
|
|
|
307
307
|
it {
|
|
308
308
|
# we just check that the rails method 'permit' is being called on the hash with the
|
|
309
309
|
# correct parameters
|
|
310
|
-
BigbluebuttonRoom.stub(:
|
|
310
|
+
BigbluebuttonRoom.stub(:find_by).and_return(room)
|
|
311
311
|
room.stub(:update_attributes).and_return(true)
|
|
312
312
|
attrs.stub(:permit).and_return(attrs)
|
|
313
313
|
controller.stub(:params).and_return(params)
|
|
@@ -476,7 +476,7 @@ describe Bigbluebutton::RoomsController do
|
|
|
476
476
|
context "if params[:id] doesn't exists" do
|
|
477
477
|
let(:message) { I18n.t('bigbluebutton_rails.rooms.errors.join.wrong_params') }
|
|
478
478
|
before(:each) {
|
|
479
|
-
BigbluebuttonRoom.stub(:
|
|
479
|
+
BigbluebuttonRoom.stub(:find_by).and_return(nil)
|
|
480
480
|
send(method, :join, :id => "inexistent-room-id", :user => user_hash)
|
|
481
481
|
}
|
|
482
482
|
it { should assign_to(:room).with(nil) }
|
|
@@ -801,6 +801,15 @@ describe Bigbluebutton::RoomsController do
|
|
|
801
801
|
it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.notice.fetch_recordings.success')) }
|
|
802
802
|
end
|
|
803
803
|
|
|
804
|
+
context "responds to :json" do
|
|
805
|
+
before(:each) {
|
|
806
|
+
mocked_server.should_receive(:fetch_recordings).with(filter)
|
|
807
|
+
post :fetch_recordings, :id => room.to_param, :format => :json
|
|
808
|
+
}
|
|
809
|
+
it { should respond_with(:success) }
|
|
810
|
+
it { should respond_with_content_type('application/json') }
|
|
811
|
+
end
|
|
812
|
+
|
|
804
813
|
context "on BigBlueButtonException" do
|
|
805
814
|
let(:bbb_error_msg) { SecureRandom.hex(250) }
|
|
806
815
|
let(:bbb_error) { BigBlueButton::BigBlueButtonException.new(bbb_error_msg) }
|
|
@@ -930,7 +939,7 @@ describe Bigbluebutton::RoomsController do
|
|
|
930
939
|
# uses any action that triggers this before filter
|
|
931
940
|
context "when @room is valid" do
|
|
932
941
|
before {
|
|
933
|
-
BigbluebuttonRoom.stub(:
|
|
942
|
+
BigbluebuttonRoom.stub(:find_by).and_return(room)
|
|
934
943
|
room.should_receive(:fetch_is_running?).and_return(false)
|
|
935
944
|
}
|
|
936
945
|
it {
|
|
@@ -969,28 +978,22 @@ describe Bigbluebutton::RoomsController do
|
|
|
969
978
|
request.env["HTTP_REFERER"] = http_referer
|
|
970
979
|
controller.stub(:bigbluebutton_user).and_return(user)
|
|
971
980
|
controller.stub(:bigbluebutton_role).and_return(:attendee)
|
|
972
|
-
BigbluebuttonRoom.stub(:
|
|
981
|
+
BigbluebuttonRoom.stub(:find_by).and_return(room)
|
|
973
982
|
controller.send(:find_room)
|
|
974
983
|
}
|
|
975
984
|
|
|
976
985
|
context "when the user has permission to create the meeting" do
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
room.should_receive(:join_url).and_return("http://test.com/join/url/")
|
|
989
|
-
}
|
|
990
|
-
before(:each) { get :join, :id => room.to_param }
|
|
991
|
-
it { should respond_with(:redirect) }
|
|
992
|
-
it { should redirect_to("http://test.com/join/url/") }
|
|
993
|
-
end
|
|
986
|
+
before {
|
|
987
|
+
room.should_receive(:fetch_is_running?).at_least(:once).and_return(false)
|
|
988
|
+
controller.stub(:bigbluebutton_can_create?).with(room, :attendee).and_return(true)
|
|
989
|
+
room.should_receive(:create_meeting)
|
|
990
|
+
.with(user, controller.request).and_return(true)
|
|
991
|
+
room.should_receive(:fetch_new_token).and_return(nil)
|
|
992
|
+
room.should_receive(:join_url).and_return("http://test.com/join/url/")
|
|
993
|
+
}
|
|
994
|
+
before(:each) { get :join, :id => room.to_param }
|
|
995
|
+
it { should respond_with(:redirect) }
|
|
996
|
+
it { should redirect_to("http://test.com/join/url/") }
|
|
994
997
|
end
|
|
995
998
|
|
|
996
999
|
context "when the user doesn't have permission to create the meeting" do
|
|
@@ -1194,7 +1197,6 @@ describe Bigbluebutton::RoomsController do
|
|
|
1194
1197
|
context "doesn't break if a guest user has permission to create a meeting" do
|
|
1195
1198
|
before {
|
|
1196
1199
|
room.stub(:fetch_is_running?).and_return(false)
|
|
1197
|
-
controller.stub(:bigbluebutton_create_options).and_return({ custom: true })
|
|
1198
1200
|
controller.stub(:bigbluebutton_can_create?).and_return(true)
|
|
1199
1201
|
room.stub(:create_meeting).and_return(true)
|
|
1200
1202
|
controller.stub(:bigbluebutton_user).and_return(nil)
|
|
@@ -469,6 +469,15 @@ describe Bigbluebutton::ServersController do
|
|
|
469
469
|
it { should set_the_flash.to(I18n.t('bigbluebutton_rails.servers.notice.fetch_recordings.success')) }
|
|
470
470
|
end
|
|
471
471
|
|
|
472
|
+
context "responds to :json" do
|
|
473
|
+
before(:each) {
|
|
474
|
+
server.should_receive(:fetch_recordings).with({})
|
|
475
|
+
post :fetch_recordings, :id => server.to_param, :format => :json
|
|
476
|
+
}
|
|
477
|
+
it { should respond_with(:success) }
|
|
478
|
+
it { should respond_with_content_type('application/json') }
|
|
479
|
+
end
|
|
480
|
+
|
|
472
481
|
context "on failure" do
|
|
473
482
|
let(:bbb_error_msg) { SecureRandom.hex(250) }
|
|
474
483
|
let(:bbb_error) { BigBlueButton::BigBlueButtonException.new(bbb_error_msg) }
|
|
@@ -6,8 +6,8 @@ FactoryGirl.define do
|
|
|
6
6
|
r.meetingid { "meeting" + SecureRandom.hex(8) }
|
|
7
7
|
r.sequence(:name) { |n| "Rec #{n}" }
|
|
8
8
|
r.published true
|
|
9
|
-
r.start_time { Time.now - rand(5).hours }
|
|
10
|
-
r.end_time { Time.now + rand(5).hours }
|
|
9
|
+
r.start_time { Time.now.to_i - rand(5).hours }
|
|
10
|
+
r.end_time { Time.now.to_i + rand(5).hours }
|
|
11
11
|
# TODO: should contain the meeting's start_time at the end
|
|
12
12
|
r.sequence(:recordid) { |n| "rec#{n}-#{SecureRandom.uuid}-#{DateTime.now.to_i}" }
|
|
13
13
|
r.size { rand((20*1024**2)..(500*1024**2)) } # size ranging from 20Mb to 500Mb
|
|
@@ -17,8 +17,6 @@ FactoryGirl.define do
|
|
|
17
17
|
after(:create) do |r|
|
|
18
18
|
r.updated_at = r.updated_at.change(:usec => 0)
|
|
19
19
|
r.created_at = r.created_at.change(:usec => 0)
|
|
20
|
-
r.start_time = r.start_time.change(:usec => 0)
|
|
21
|
-
r.end_time = r.end_time.change(:usec => 0)
|
|
22
20
|
end
|
|
23
21
|
end
|
|
24
22
|
end
|
|
@@ -14,6 +14,14 @@ describe BigbluebuttonRailsHelper do
|
|
|
14
14
|
it("uses UTF-8") { should match /choe=UTF-8/ }
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
describe "#api_typeof" do
|
|
18
|
+
it { api_type_of(FactoryGirl.create(:bigbluebutton_room)).should eql('room') }
|
|
19
|
+
it { api_type_of(FactoryGirl.create(:bigbluebutton_server)).should eql('server') }
|
|
20
|
+
it { api_type_of(FactoryGirl.create(:bigbluebutton_recording)).should eql('recording') }
|
|
19
21
|
|
|
22
|
+
context "for a new class" do
|
|
23
|
+
class MyUserClass; end
|
|
24
|
+
it { api_type_of(MyUserClass.new).should eql('my-user-class') }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -4,6 +4,7 @@ describe BigbluebuttonRails::BackgroundTasks do
|
|
|
4
4
|
|
|
5
5
|
describe ".finish_meetings" do
|
|
6
6
|
let!(:api) { double(BigBlueButton::BigBlueButtonApi) }
|
|
7
|
+
let!(:server) { FactoryGirl.create(:bigbluebutton_server) }
|
|
7
8
|
|
|
8
9
|
context "set meetings that ended as not running and ended" do
|
|
9
10
|
let(:room) { FactoryGirl.create(:bigbluebutton_room) }
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
describe BigbluebuttonAttendee do
|
|
5
|
+
it "loaded correctly" do
|
|
6
|
+
BigbluebuttonAttendee.new.should be_a_kind_of(ActiveRecord::Base)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
before { FactoryGirl.create(:bigbluebutton_attendee) }
|
|
10
|
+
|
|
11
|
+
context "gets params from hash" do
|
|
12
|
+
let(:hash) { {:userID=>"user_id", :fullName=>"House M.D.", :role=>"MODERATOR"} }
|
|
13
|
+
let(:attendee) { BigbluebuttonAttendee.new }
|
|
14
|
+
|
|
15
|
+
it "standard case" do
|
|
16
|
+
attendee.from_hash(hash)
|
|
17
|
+
attendee.user_id.should == "user_id"
|
|
18
|
+
attendee.user_name.should == "House M.D."
|
|
19
|
+
attendee.role.should == :moderator
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "converts user_id to string" do
|
|
23
|
+
hash[:userID] = 123
|
|
24
|
+
attendee.from_hash(hash)
|
|
25
|
+
attendee.user_id.should == "123"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "role is not case sensitive" do
|
|
29
|
+
hash[:role] = "mODErAtOR"
|
|
30
|
+
attendee.from_hash(hash)
|
|
31
|
+
attendee.role.should == :moderator
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "any role other than 'moderator' is attendee" do
|
|
35
|
+
hash[:role] = "VIEWER"
|
|
36
|
+
attendee.from_hash(hash)
|
|
37
|
+
attendee.role.should == :attendee
|
|
38
|
+
|
|
39
|
+
hash[:role] = "whatever"
|
|
40
|
+
attendee.from_hash(hash)
|
|
41
|
+
attendee.role.should == :attendee
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -7,7 +7,6 @@ describe BigbluebuttonMeeting do
|
|
|
7
7
|
it { should have_db_column(:room_id).of_type(:integer) }
|
|
8
8
|
it { should have_db_column(:meetingid).of_type(:string) }
|
|
9
9
|
it { should have_db_column(:name).of_type(:string) }
|
|
10
|
-
it { should have_db_column(:start_time).of_type(:datetime) }
|
|
11
10
|
it { should have_db_column(:running).of_type(:boolean) }
|
|
12
11
|
it { should have_db_column(:recorded).of_type(:boolean) }
|
|
13
12
|
it { should have_db_column(:creator_id).of_type(:integer) }
|
|
@@ -22,6 +22,8 @@ describe BigbluebuttonPlaybackFormat do
|
|
|
22
22
|
it { should delegate_method(:default).to(:playback_type) }
|
|
23
23
|
it { should delegate_method(:default?).to(:playback_type) }
|
|
24
24
|
it { should delegate_method(:description).to(:playback_type) }
|
|
25
|
+
it { should delegate_method(:downloadable).to(:playback_type) }
|
|
26
|
+
it { should delegate_method(:downloadable?).to(:playback_type) }
|
|
25
27
|
|
|
26
28
|
context "allows nil for delegates to playback_type" do
|
|
27
29
|
let(:target) { FactoryGirl.create(:bigbluebutton_playback_format, playback_type: nil) }
|
|
@@ -9,6 +9,7 @@ describe BigbluebuttonPlaybackType do
|
|
|
9
9
|
it { should have_db_column(:default).of_type(:boolean) }
|
|
10
10
|
it { should have_db_column(:created_at).of_type(:datetime) }
|
|
11
11
|
it { should have_db_column(:updated_at).of_type(:datetime) }
|
|
12
|
+
it { should have_db_column(:downloadable).of_type(:boolean) }
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
end
|
|
@@ -10,8 +10,8 @@ describe BigbluebuttonRecording do
|
|
|
10
10
|
it { should have_db_column(:meetingid).of_type(:string) }
|
|
11
11
|
it { should have_db_column(:name).of_type(:string) }
|
|
12
12
|
it { should have_db_column(:published).of_type(:boolean) }
|
|
13
|
-
it { should have_db_column(:start_time).of_type(:
|
|
14
|
-
it { should have_db_column(:end_time).of_type(:
|
|
13
|
+
it { should have_db_column(:start_time).of_type(:integer) }
|
|
14
|
+
it { should have_db_column(:end_time).of_type(:integer) }
|
|
15
15
|
it { should have_db_column(:available).of_type(:boolean) }
|
|
16
16
|
it { should have_db_column(:description).of_type(:string) }
|
|
17
17
|
it { should have_db_column(:created_at).of_type(:datetime) }
|
|
@@ -48,6 +48,43 @@ describe BigbluebuttonRecording do
|
|
|
48
48
|
}
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
describe "#get_token" do
|
|
52
|
+
it { should respond_to(:get_token) }
|
|
53
|
+
|
|
54
|
+
let!(:recording) { FactoryGirl.create(:bigbluebutton_recording) }
|
|
55
|
+
let!(:type_default) { FactoryGirl.create(:bigbluebutton_playback_type, default: true) }
|
|
56
|
+
let!(:server) { FactoryGirl.create(:bigbluebutton_server) }
|
|
57
|
+
let(:user) { FactoryGirl.build(:user) }
|
|
58
|
+
let(:user_ip) { "10.0.0.1" }
|
|
59
|
+
let(:api) { double(BigBlueButton::BigBlueButtonApi) }
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
BigbluebuttonServer.any_instance.stub(:api).and_return(api)
|
|
63
|
+
api.stub(:send_api_request).and_return({:returncode=>true, :token=>"RECORDING_TOKEN", :messageKey=>"", :message=>""})
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it { recording.get_token(user, user_ip).should include("RECORDING_TOKEN") }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "#token_url" do
|
|
70
|
+
it { should respond_to(:token_url) }
|
|
71
|
+
|
|
72
|
+
let!(:recording) { FactoryGirl.create(:bigbluebutton_recording) }
|
|
73
|
+
let!(:type_default) { FactoryGirl.create(:bigbluebutton_playback_type, default: true) }
|
|
74
|
+
let!(:server) { FactoryGirl.create(:bigbluebutton_server) }
|
|
75
|
+
let(:user) { FactoryGirl.build(:user) }
|
|
76
|
+
let(:user_ip) { "10.0.0.1" }
|
|
77
|
+
let!(:format) { FactoryGirl.create(:bigbluebutton_playback_format, recording: recording, playback_type: type_default) }
|
|
78
|
+
let(:api) { double(BigBlueButton::BigBlueButtonApi) }
|
|
79
|
+
|
|
80
|
+
before do
|
|
81
|
+
BigbluebuttonServer.any_instance.stub(:api).and_return(api)
|
|
82
|
+
api.stub(:send_api_request).and_return({:returncode=>true, :token=>"RECORDING_TOKEN", :messageKey=>"", :message=>""})
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it { recording.token_url(user, user_ip, format).should include("?token=RECORDING_TOKEN") }
|
|
86
|
+
end
|
|
87
|
+
|
|
51
88
|
describe "#default_playback_format" do
|
|
52
89
|
let!(:recording) { FactoryGirl.create(:bigbluebutton_recording) }
|
|
53
90
|
let!(:type_default) { FactoryGirl.create(:bigbluebutton_playback_type, default: true) }
|
|
@@ -66,6 +103,26 @@ describe BigbluebuttonRecording do
|
|
|
66
103
|
end
|
|
67
104
|
end
|
|
68
105
|
|
|
106
|
+
describe "#delete_from_server" do
|
|
107
|
+
let!(:recording) { FactoryGirl.create(:bigbluebutton_recording) }
|
|
108
|
+
|
|
109
|
+
context "when there's a server associated" do
|
|
110
|
+
let!(:server) { FactoryGirl.create(:bigbluebutton_server) }
|
|
111
|
+
before {
|
|
112
|
+
recording.update_attributes(server: server)
|
|
113
|
+
server.should_receive(:send_delete_recordings).with(recording.recordid).and_return('response')
|
|
114
|
+
}
|
|
115
|
+
it { recording.delete_from_server!.should eql('response') }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context "when there's no server associated" do
|
|
119
|
+
before {
|
|
120
|
+
recording.update_attributes(server: nil)
|
|
121
|
+
}
|
|
122
|
+
it { recording.delete_from_server!.should be(false) }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
69
126
|
describe ".overall_average_length" do
|
|
70
127
|
context "when there's no recording" do
|
|
71
128
|
it { BigbluebuttonRecording.overall_average_length.should eql(0) }
|
|
@@ -98,36 +155,221 @@ describe BigbluebuttonRecording do
|
|
|
98
155
|
end
|
|
99
156
|
end
|
|
100
157
|
|
|
158
|
+
describe ".recording_changed?" do
|
|
159
|
+
let!(:data) {
|
|
160
|
+
{
|
|
161
|
+
recordid: "recording-1",
|
|
162
|
+
meetingid: "meetingid-1",
|
|
163
|
+
name: "Evening Class1",
|
|
164
|
+
published: true,
|
|
165
|
+
start_time: DateTime.now,
|
|
166
|
+
end_time: DateTime.now + 2.hours,
|
|
167
|
+
size: "100",
|
|
168
|
+
metadata: {
|
|
169
|
+
course: "Fundamentals of JAVA",
|
|
170
|
+
description: "List of recordings",
|
|
171
|
+
activity: "Evening Class1"
|
|
172
|
+
},
|
|
173
|
+
playback: { format:
|
|
174
|
+
[
|
|
175
|
+
{ type: "slides",
|
|
176
|
+
url: "http://test-install.blindsidenetworks.com/playback/slides/playback.html?meetingId=125468758b24fa27551e7a065849dda3ce65dd32-1329872486268",
|
|
177
|
+
length: 64
|
|
178
|
+
},
|
|
179
|
+
{ type: "presentation",
|
|
180
|
+
url: "http://test-install.blindsidenetworks.com/presentation/slides/playback.html?meetingId=125468758b24fa27551e7a065849dda3ce65dd32-1329872486268",
|
|
181
|
+
length: 64
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
let!(:recording) {
|
|
188
|
+
attrs = {
|
|
189
|
+
recordid: data[:recordid],
|
|
190
|
+
meetingid: data[:meetingid],
|
|
191
|
+
name: data[:name],
|
|
192
|
+
published: data[:published],
|
|
193
|
+
start_time: data[:start_time],
|
|
194
|
+
end_time: data[:end_time],
|
|
195
|
+
size: data[:size]
|
|
196
|
+
}
|
|
197
|
+
r = FactoryGirl.create(:bigbluebutton_recording, attrs)
|
|
198
|
+
data[:metadata].each do |k, v|
|
|
199
|
+
BigbluebuttonMetadata.create(owner: r, name: k, content: v)
|
|
200
|
+
end
|
|
201
|
+
data[:playback][:format].each do |format|
|
|
202
|
+
type = BigbluebuttonPlaybackType.create(visible: true, identifier: format[:type])
|
|
203
|
+
BigbluebuttonPlaybackFormat.create(recording: r, url: format[:url], length: format[:length], playback_type: type)
|
|
204
|
+
end
|
|
205
|
+
r
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
it "returns false when they didn't changed" do
|
|
209
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(false)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
context "returns true when an attribute changed" do
|
|
213
|
+
it "in the data" do
|
|
214
|
+
data[:published] = !data[:published]
|
|
215
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it "in the database" do
|
|
219
|
+
recording.update(published: !recording.published)
|
|
220
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context "returns true when a metadata" do
|
|
225
|
+
context "changed" do
|
|
226
|
+
it "in the data" do
|
|
227
|
+
data[:metadata][:course] = data[:metadata][:course] + "-changed"
|
|
228
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "in the database" do
|
|
232
|
+
recording.metadata.first.update(content: recording.metadata.first.content + "-changed")
|
|
233
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
context "was added" do
|
|
238
|
+
it "in the data" do
|
|
239
|
+
data[:metadata][:new_one] = "anything"
|
|
240
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "in the database" do
|
|
244
|
+
BigbluebuttonMetadata.create(owner: recording, name: "new", content: "anything")
|
|
245
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
context "was removed" do
|
|
250
|
+
it "in the data" do
|
|
251
|
+
data[:metadata].delete(:course)
|
|
252
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "in the database" do
|
|
256
|
+
recording.metadata.first.destroy
|
|
257
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
context "returns true when a playback format" do
|
|
263
|
+
context "changed" do
|
|
264
|
+
it "in the data" do
|
|
265
|
+
data[:playback][:format][0][:url] = data[:playback][:format][0][:url] + "/changed"
|
|
266
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "in the database" do
|
|
270
|
+
recording.playback_formats.first.update(url: recording.playback_formats.first.url + "/changed")
|
|
271
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
context "was added" do
|
|
276
|
+
it "in the data" do
|
|
277
|
+
data[:playback][:format] << {
|
|
278
|
+
type: "new-format",
|
|
279
|
+
url: "http://anything.here",
|
|
280
|
+
length: 64
|
|
281
|
+
}
|
|
282
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
it "in the database" do
|
|
286
|
+
type = BigbluebuttonPlaybackType.create(visible: true, identifier: "new-format-db")
|
|
287
|
+
BigbluebuttonPlaybackFormat.create(recording: recording, url: "anything", length: 12, playback_type: type)
|
|
288
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
context "was removed" do
|
|
293
|
+
it "in the data" do
|
|
294
|
+
data[:playback][:format] = data[:playback][:format].drop(1)
|
|
295
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
it "in the database" do
|
|
299
|
+
recording.playback_formats.first.destroy
|
|
300
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
context "ignores ignored keys" do
|
|
306
|
+
it "in the data" do
|
|
307
|
+
data[:random] = "anything"
|
|
308
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(false)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it "in the database" do
|
|
312
|
+
recording.available = !recording.available
|
|
313
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(false)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "ignores the ordering of the elements in the inputs" do
|
|
318
|
+
data[:playback][:format] = data[:playback][:format].reverse
|
|
319
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(false)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context "works when there are no formats" do
|
|
323
|
+
it "in the data" do
|
|
324
|
+
data[:playback].delete(:format)
|
|
325
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it "in the database" do
|
|
329
|
+
BigbluebuttonPlaybackFormat.delete_all
|
|
330
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
context "works when there is no metadata" do
|
|
335
|
+
it "in the data" do
|
|
336
|
+
data.delete(:metadata)
|
|
337
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
it "in the database" do
|
|
341
|
+
BigbluebuttonMetadata.delete_all
|
|
342
|
+
BigbluebuttonRecording.recording_changed?(recording, data).should be(true)
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
101
347
|
describe ".sync" do
|
|
102
348
|
let(:data) {
|
|
103
|
-
[
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
]
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
]
|
|
349
|
+
[{
|
|
350
|
+
recordID: "recording-1",
|
|
351
|
+
meetingID: "meetingid-1",
|
|
352
|
+
name: "Evening Class1",
|
|
353
|
+
published: true,
|
|
354
|
+
startTime: DateTime.now,
|
|
355
|
+
endTime: DateTime.now + 2.hours,
|
|
356
|
+
size: 100,
|
|
357
|
+
metadata: {
|
|
358
|
+
course: "Fundamentals of JAVA",
|
|
359
|
+
description: "List of recordings",
|
|
360
|
+
activity: "Evening Class1"
|
|
361
|
+
},
|
|
362
|
+
playback: { format:
|
|
363
|
+
[{ type: "slides",
|
|
364
|
+
url: "http://test-install.blindsidenetworks.com/playback/slides/playback.html?meetingId=125468758b24fa27551e7a065849dda3ce65dd32-1329872486268",
|
|
365
|
+
length: 64
|
|
366
|
+
},
|
|
367
|
+
{ type: "presentation",
|
|
368
|
+
url: "http://test-install.blindsidenetworks.com/presentation/slides/playback.html?meetingId=125468758b24fa27551e7a065849dda3ce65dd32-1329872486268",
|
|
369
|
+
length: 64
|
|
370
|
+
}]
|
|
371
|
+
}
|
|
372
|
+
}]
|
|
131
373
|
}
|
|
132
374
|
let(:new_server) { FactoryGirl.create(:bigbluebutton_server) }
|
|
133
375
|
before {
|
|
@@ -144,8 +386,8 @@ describe BigbluebuttonRecording do
|
|
|
144
386
|
it { @recording.meetingid.should == data[0][:meetingID] }
|
|
145
387
|
it { @recording.name.should == data[0][:name] }
|
|
146
388
|
it { @recording.published.should == data[0][:published] }
|
|
147
|
-
it { @recording.end_time.
|
|
148
|
-
it { @recording.start_time.
|
|
389
|
+
it { @recording.end_time.to_i.should == data[0][:endTime].to_i }
|
|
390
|
+
it { @recording.start_time.to_i.should == data[0][:startTime].to_i }
|
|
149
391
|
it { @recording.server.should == new_server }
|
|
150
392
|
it { @recording.room.should == @room }
|
|
151
393
|
it { @recording.available.should == true }
|
|
@@ -176,8 +418,8 @@ describe BigbluebuttonRecording do
|
|
|
176
418
|
it { @recording.meetingid.should == data[0][:meetingID] }
|
|
177
419
|
it { @recording.name.should == data[0][:name] }
|
|
178
420
|
it { @recording.published.should == data[0][:published] }
|
|
179
|
-
it { @recording.end_time.
|
|
180
|
-
it { @recording.start_time.
|
|
421
|
+
it { @recording.end_time.to_i.should == data[0][:endTime].to_i }
|
|
422
|
+
it { @recording.start_time.to_i.should == data[0][:startTime].to_i }
|
|
181
423
|
it { @recording.server.should == new_server }
|
|
182
424
|
it { @recording.room.should == @room }
|
|
183
425
|
it { @recording.available.should == true }
|
|
@@ -293,6 +535,40 @@ describe BigbluebuttonRecording do
|
|
|
293
535
|
it { BigbluebuttonMetadata.count.should == 3 }
|
|
294
536
|
it { BigbluebuttonPlaybackFormat.count.should == 2 }
|
|
295
537
|
end
|
|
538
|
+
|
|
539
|
+
context "when there are unused playback types on the database" do
|
|
540
|
+
before {
|
|
541
|
+
FactoryGirl.create(:bigbluebutton_playback_type, :identifier => "to-be-removed")
|
|
542
|
+
FactoryGirl.create(:bigbluebutton_playback_type, :identifier => "another")
|
|
543
|
+
BigbluebuttonRecording.sync(new_server, data)
|
|
544
|
+
}
|
|
545
|
+
it { BigbluebuttonPlaybackType.count.should == 2 }
|
|
546
|
+
it { BigbluebuttonPlaybackType.find_by(identifier: "slides").should_not be_nil }
|
|
547
|
+
it { BigbluebuttonPlaybackType.find_by(identifier: "presentation").should_not be_nil }
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
it "doesn't update if the recording didn't change" do
|
|
551
|
+
# once to create the recording
|
|
552
|
+
now = DateTime.now
|
|
553
|
+
expected = now - 1.month
|
|
554
|
+
Timecop.freeze(expected)
|
|
555
|
+
rec_data = data.clone
|
|
556
|
+
|
|
557
|
+
BigbluebuttonRecording.sync(new_server, rec_data)
|
|
558
|
+
|
|
559
|
+
# set an expected updated_at
|
|
560
|
+
rec = BigbluebuttonRecording.first
|
|
561
|
+
puts "before #{rec.updated_at} (#{DateTime.now})"
|
|
562
|
+
# rec.send(:write_attribute, :updated_at, expected)
|
|
563
|
+
|
|
564
|
+
# shouldn't change it
|
|
565
|
+
Timecop.freeze(now)
|
|
566
|
+
BigbluebuttonRecording.sync(new_server, rec_data)
|
|
567
|
+
puts "after #{rec.reload.updated_at} (#{DateTime.now})"
|
|
568
|
+
rec.reload.updated_at.to_i.should eql(expected.to_i)
|
|
569
|
+
|
|
570
|
+
Timecop.return
|
|
571
|
+
end
|
|
296
572
|
end
|
|
297
573
|
|
|
298
574
|
describe ".update_recording" do
|
|
@@ -309,6 +585,7 @@ describe BigbluebuttonRecording do
|
|
|
309
585
|
:end_time => attrs[:end_time],
|
|
310
586
|
:size => attrs[:size],
|
|
311
587
|
:metadata => { :any => "any" },
|
|
588
|
+
:recordingUsers => { :user => [{ :externalUserID => 1 }, { :externalUserID => 2 }] },
|
|
312
589
|
:playback => { :format => [ { :type => "any1" }, { :type => "any2" } ] }
|
|
313
590
|
}
|
|
314
591
|
}
|
|
@@ -325,11 +602,12 @@ describe BigbluebuttonRecording do
|
|
|
325
602
|
it { recording.meetingid.should == attrs[:meetingid] }
|
|
326
603
|
it { recording.name.should == attrs[:name] }
|
|
327
604
|
it { recording.published.should == !old_attrs[:published] }
|
|
328
|
-
it { recording.end_time.
|
|
329
|
-
it { recording.start_time.
|
|
605
|
+
it { recording.end_time.to_i.should == attrs[:end_time].to_i }
|
|
606
|
+
it { recording.start_time.to_i.should == attrs[:start_time].to_i }
|
|
330
607
|
it { recording.size.should == attrs[:size] }
|
|
331
608
|
it { recording.server.should == new_server }
|
|
332
609
|
it { recording.room.should == @room }
|
|
610
|
+
it { recording.recording_users.should eql([1, 2]) }
|
|
333
611
|
end
|
|
334
612
|
|
|
335
613
|
context "works if the recording returned has no :size attribute" do
|
|
@@ -340,11 +618,19 @@ describe BigbluebuttonRecording do
|
|
|
340
618
|
}
|
|
341
619
|
it { recording.size.should == 0 }
|
|
342
620
|
end
|
|
621
|
+
|
|
622
|
+
context "works if the recording returned has no :recordingUsers attribute" do
|
|
623
|
+
before {
|
|
624
|
+
data.delete(:recordingUsers)
|
|
625
|
+
BigbluebuttonRecording.send(:update_recording, new_server, recording, data)
|
|
626
|
+
}
|
|
627
|
+
it { recording.recording_users.should == [] }
|
|
628
|
+
end
|
|
343
629
|
end
|
|
344
630
|
|
|
345
631
|
describe ".create_recording" do
|
|
346
|
-
let(:
|
|
347
|
-
let(:recordid) { "#{SecureRandom.uuid}-#{
|
|
632
|
+
let(:meeting_create_time) { DateTime.now.utc.to_i }
|
|
633
|
+
let(:recordid) { "#{SecureRandom.uuid}-#{meeting_create_time.to_i}" }
|
|
348
634
|
let(:attrs) { FactoryGirl.attributes_for(:bigbluebutton_recording) }
|
|
349
635
|
let(:data) {
|
|
350
636
|
{
|
|
@@ -352,9 +638,10 @@ describe BigbluebuttonRecording do
|
|
|
352
638
|
:meetingid => attrs[:meetingid],
|
|
353
639
|
:name => attrs[:name],
|
|
354
640
|
:published => attrs[:published],
|
|
355
|
-
:start_time =>
|
|
641
|
+
:start_time => meeting_create_time,
|
|
356
642
|
:end_time => attrs[:end_time],
|
|
357
643
|
:metadata => { :any => "any" },
|
|
644
|
+
:recordingUsers => { :user => [{ :externalUserID => 3 }, { :externalUserID => 4 }] },
|
|
358
645
|
:playback => { :format => [ { :type => "any1" }, { :type => "any2" } ] }
|
|
359
646
|
}
|
|
360
647
|
}
|
|
@@ -362,7 +649,7 @@ describe BigbluebuttonRecording do
|
|
|
362
649
|
|
|
363
650
|
before {
|
|
364
651
|
@room = FactoryGirl.create(:bigbluebutton_room, :meetingid => attrs[:meetingid])
|
|
365
|
-
@meeting = FactoryGirl.create(:bigbluebutton_meeting, :room => @room, :
|
|
652
|
+
@meeting = FactoryGirl.create(:bigbluebutton_meeting, :room => @room, :create_time => meeting_create_time, :meetingid => attrs[:meetingid])
|
|
366
653
|
|
|
367
654
|
BigbluebuttonRecording.should_receive(:sync_additional_data)
|
|
368
655
|
.with(anything, data)
|
|
@@ -373,15 +660,16 @@ describe BigbluebuttonRecording do
|
|
|
373
660
|
it("sets meetingid") { @recording.meetingid.should == attrs[:meetingid] }
|
|
374
661
|
it("sets name") { @recording.name.should == attrs[:name] }
|
|
375
662
|
it("sets published") { @recording.published.should == attrs[:published] }
|
|
376
|
-
it("sets end_time") { @recording.end_time.
|
|
377
|
-
it("sets start_time") { @recording.start_time.
|
|
663
|
+
it("sets end_time") { @recording.end_time.to_i.should == attrs[:end_time].to_i }
|
|
664
|
+
it("sets start_time") { @recording.start_time.to_i.should == meeting_create_time }
|
|
378
665
|
it("sets server") { @recording.server.should == new_server }
|
|
379
666
|
it("sets room") { @recording.room.should == @room }
|
|
380
667
|
it("sets meeting") { @recording.meeting.should == @meeting }
|
|
381
668
|
it("sets description") {
|
|
382
|
-
time = data[:start_time].utc.to_formatted_s(:long)
|
|
669
|
+
time = Time.at(data[:start_time]).utc.to_formatted_s(:long)
|
|
383
670
|
@recording.description.should == I18n.t('bigbluebutton_rails.recordings.default.description', :time => time)
|
|
384
671
|
}
|
|
672
|
+
it("sets recording_users") { @recording.recording_users.should eql([3, 4]) }
|
|
385
673
|
end
|
|
386
674
|
|
|
387
675
|
describe ".adapt_recording_hash" do
|
|
@@ -407,6 +695,30 @@ describe BigbluebuttonRecording do
|
|
|
407
695
|
it { should eq(after) }
|
|
408
696
|
end
|
|
409
697
|
|
|
698
|
+
describe ".adapt_recording_users" do
|
|
699
|
+
context "with one user" do
|
|
700
|
+
let(:original) {
|
|
701
|
+
{ :user => { :externalUserID => 1 } }
|
|
702
|
+
}
|
|
703
|
+
let(:expected) { [1] }
|
|
704
|
+
it { BigbluebuttonRecording.send(:adapt_recording_users, original).should eql(expected) }
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
context "with several users" do
|
|
708
|
+
let(:original) {
|
|
709
|
+
{ :user => [{ :externalUserID => 2 }, { :externalUserID => 1 }, { :externalUserID => 15 }] }
|
|
710
|
+
}
|
|
711
|
+
let(:expected) { [2, 1, 15] }
|
|
712
|
+
it { BigbluebuttonRecording.send(:adapt_recording_users, original).should eql(expected) }
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
[nil, []].each do |arg|
|
|
716
|
+
context "returns nil if the argument is #{arg.inspect}" do
|
|
717
|
+
it { BigbluebuttonRecording.send(:adapt_recording_users, arg).should be_nil }
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
|
|
410
722
|
describe ".sync_additional_data" do
|
|
411
723
|
let(:attrs) { FactoryGirl.attributes_for(:bigbluebutton_recording) }
|
|
412
724
|
let(:recording) { FactoryGirl.create(:bigbluebutton_recording) }
|
|
@@ -520,14 +832,29 @@ describe BigbluebuttonRecording do
|
|
|
520
832
|
}
|
|
521
833
|
|
|
522
834
|
context "and it's not in the database yet" do
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
835
|
+
context "if it is not a downloadable format" do
|
|
836
|
+
before {
|
|
837
|
+
BigbluebuttonRecording.send(:sync_playback_formats, recording, data)
|
|
838
|
+
}
|
|
839
|
+
it { BigbluebuttonPlaybackFormat.count.should == 1 }
|
|
840
|
+
it { BigbluebuttonPlaybackFormat.where(:recording_id => recording.id).count.should == 1 }
|
|
841
|
+
it { BigbluebuttonPlaybackFormat.where(:recording_id => recording.id).last.url.should == "url1" }
|
|
842
|
+
it { BigbluebuttonPlaybackFormat.where(:recording_id => recording.id).last.length.should == 1 }
|
|
843
|
+
it { BigbluebuttonPlaybackFormat.where(:recording_id => recording.id).last.visible.should be(true) }
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
context "if it is a downloadable format" do
|
|
847
|
+
after {
|
|
848
|
+
@previous = BigbluebuttonRails.configuration.downloadable_playback_types
|
|
849
|
+
}
|
|
850
|
+
before {
|
|
851
|
+
BigbluebuttonRails.configuration.downloadable_playback_types = ['any1']
|
|
852
|
+
BigbluebuttonRecording.send(:sync_playback_formats, recording, data)
|
|
853
|
+
BigbluebuttonRails.configuration.downloadable_playback_types = @previous
|
|
854
|
+
}
|
|
855
|
+
it { BigbluebuttonPlaybackFormat.count.should == 1 }
|
|
856
|
+
it { BigbluebuttonPlaybackFormat.where(:recording_id => recording.id).last.downloadable.should be(true) }
|
|
857
|
+
end
|
|
531
858
|
end
|
|
532
859
|
|
|
533
860
|
context "and it's already in the database" do
|
|
@@ -584,17 +911,31 @@ describe BigbluebuttonRecording do
|
|
|
584
911
|
|
|
585
912
|
BigbluebuttonRecording.send(:sync_playback_formats, recording, data)
|
|
586
913
|
}
|
|
587
|
-
it { BigbluebuttonPlaybackType.count.should == 3 }
|
|
588
914
|
it { BigbluebuttonPlaybackFormat.count.should == 3 }
|
|
589
|
-
it { BigbluebuttonPlaybackFormat.where(:
|
|
590
|
-
it {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
915
|
+
it { BigbluebuttonPlaybackFormat.where(recording_id: recording.id).count.should == 3 }
|
|
916
|
+
it {
|
|
917
|
+
q = BigbluebuttonPlaybackFormat.where(recording_id: recording.id, playback_type_id: playback_type.id, url: "url1")
|
|
918
|
+
q.size.should == 1
|
|
919
|
+
f = q.first
|
|
920
|
+
f.should_not be_nil
|
|
921
|
+
f.length.should == 1
|
|
922
|
+
f.visible.should be(true)
|
|
923
|
+
}
|
|
924
|
+
it {
|
|
925
|
+
q = BigbluebuttonPlaybackFormat.where(recording_id: recording.id, playback_type_id: playback_type_hidden.id, url: "url2")
|
|
926
|
+
q.size.should == 1
|
|
927
|
+
f = q.first
|
|
928
|
+
f.should_not be_nil
|
|
929
|
+
f.length.should == 2
|
|
930
|
+
f.visible.should be(false)
|
|
931
|
+
}
|
|
932
|
+
it {
|
|
933
|
+
q = BigbluebuttonPlaybackFormat.where(recording_id: recording.id, playback_type_id: BigbluebuttonPlaybackType.last.id, url: "url3")
|
|
934
|
+
q.size.should == 1
|
|
935
|
+
f = q.first
|
|
936
|
+
f.should_not be_nil
|
|
937
|
+
f.length.should == 3
|
|
938
|
+
}
|
|
598
939
|
end
|
|
599
940
|
|
|
600
941
|
context "ignores formats with blank type" do
|
|
@@ -637,16 +978,6 @@ describe BigbluebuttonRecording do
|
|
|
637
978
|
it { BigbluebuttonPlaybackType.last.identifier.should == "any1" }
|
|
638
979
|
it { BigbluebuttonPlaybackType.last.playback_formats.should include(BigbluebuttonPlaybackFormat.last) }
|
|
639
980
|
end
|
|
640
|
-
|
|
641
|
-
context "when there are unused playback types on the database" do
|
|
642
|
-
before {
|
|
643
|
-
FactoryGirl.create(:bigbluebutton_playback_type, :identifier => "any2")
|
|
644
|
-
FactoryGirl.create(:bigbluebutton_playback_type, :identifier => "any3")
|
|
645
|
-
BigbluebuttonRecording.send(:sync_playback_formats, recording, data)
|
|
646
|
-
}
|
|
647
|
-
it { BigbluebuttonPlaybackType.count.should == 1 }
|
|
648
|
-
it { BigbluebuttonPlaybackType.last.identifier.should == "any1" }
|
|
649
|
-
end
|
|
650
981
|
end
|
|
651
982
|
end
|
|
652
983
|
|
|
@@ -702,9 +1033,10 @@ describe BigbluebuttonRecording do
|
|
|
702
1033
|
end
|
|
703
1034
|
|
|
704
1035
|
context "if found a start time in recordid" do
|
|
705
|
-
let(:
|
|
1036
|
+
let(:meeting_create_time) { DateTime.now.to_i }
|
|
1037
|
+
let(:meetingid_rand) { SecureRandom.uuid }
|
|
706
1038
|
let(:recording) {
|
|
707
|
-
FactoryGirl.create(:bigbluebutton_recording, :recordid => "#{SecureRandom.uuid}-#{
|
|
1039
|
+
FactoryGirl.create(:bigbluebutton_recording, :recordid => "#{SecureRandom.uuid}-#{meeting_create_time}", :start_time => meeting_create_time, :meetingid => "#{meetingid_rand}-#{meeting_create_time}")
|
|
708
1040
|
}
|
|
709
1041
|
|
|
710
1042
|
context "when there's no associated meeting" do
|
|
@@ -714,7 +1046,7 @@ describe BigbluebuttonRecording do
|
|
|
714
1046
|
|
|
715
1047
|
context "when there's one associated meeting" do
|
|
716
1048
|
before {
|
|
717
|
-
@meeting = FactoryGirl.create(:bigbluebutton_meeting, :room => recording.room, :
|
|
1049
|
+
@meeting = FactoryGirl.create(:bigbluebutton_meeting, :room => recording.room, :create_time => meeting_create_time, :meetingid => "#{meetingid_rand}-#{meeting_create_time}")
|
|
718
1050
|
}
|
|
719
1051
|
subject { BigbluebuttonRecording.send(:find_matching_meeting, recording) }
|
|
720
1052
|
it { subject.should eq(@meeting) }
|