bigbluebutton_rails 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/Gemfile.lock +5 -5
  4. data/app/controllers/bigbluebutton/rooms_controller.rb +0 -5
  5. data/app/controllers/bigbluebutton/servers_controller.rb +1 -1
  6. data/app/models/bigbluebutton_meeting.rb +2 -2
  7. data/app/models/bigbluebutton_recording.rb +16 -12
  8. data/app/models/bigbluebutton_room.rb +109 -42
  9. data/app/models/bigbluebutton_server.rb +10 -9
  10. data/app/views/bigbluebutton/servers/_form.html.erb +2 -2
  11. data/app/views/bigbluebutton/servers/index.html.erb +1 -1
  12. data/app/views/bigbluebutton/servers/show.html.erb +2 -2
  13. data/app/workers/bigbluebutton_meeting_updater.rb +7 -14
  14. data/bigbluebutton_rails.gemspec +1 -1
  15. data/config/locales/en.yml +1 -1
  16. data/config/locales/pt-br.yml +1 -1
  17. data/lib/bigbluebutton_rails.rb +17 -10
  18. data/lib/bigbluebutton_rails/background_tasks.rb +9 -5
  19. data/lib/bigbluebutton_rails/version.rb +1 -1
  20. data/lib/generators/bigbluebutton_rails/templates/migration.rb +6 -2
  21. data/lib/generators/bigbluebutton_rails/templates/migration_2_1_0.rb +21 -0
  22. data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +1 -13
  23. data/spec/controllers/bigbluebutton/servers_controller_spec.rb +2 -2
  24. data/spec/factories/bigbluebutton_meeting.rb +2 -0
  25. data/spec/factories/bigbluebutton_metadata.rb +1 -1
  26. data/spec/factories/bigbluebutton_room.rb +1 -0
  27. data/spec/factories/bigbluebutton_server.rb +1 -1
  28. data/spec/lib/bigbluebutton_rails/background_tasks_spec.rb +106 -15
  29. data/spec/models/bigbluebutton_meeting_db_spec.rb +9 -4
  30. data/spec/models/bigbluebutton_meeting_spec.rb +2 -2
  31. data/spec/models/bigbluebutton_recording_spec.rb +19 -4
  32. data/spec/models/bigbluebutton_room_options_spec.rb +1 -1
  33. data/spec/models/bigbluebutton_room_spec.rb +396 -97
  34. data/spec/models/bigbluebutton_server_db_spec.rb +1 -1
  35. data/spec/models/bigbluebutton_server_spec.rb +38 -16
  36. data/spec/rails_app/db/seeds.rb +0 -1
  37. data/spec/rails_app/features/config.yml.example +2 -4
  38. data/spec/rails_app/features/step_definitions/activity_monitor_servers_step.rb +2 -4
  39. data/spec/rails_app/features/step_definitions/common_steps.rb +1 -2
  40. data/spec/rails_app/features/step_definitions/create_servers_steps.rb +2 -2
  41. data/spec/rails_app/features/step_definitions/destroy_servers_steps.rb +1 -2
  42. data/spec/rails_app/features/support/factories/bigbluebutton_server_integration.rb +1 -1
  43. data/spec/rails_app/features/support/templates.rb +5 -5
  44. data/spec/rails_app/lib/tasks/db/populate.rake +1 -1
  45. data/spec/workers/bigbluebutton_meeting_updater_spec.rb +86 -5
  46. metadata +5 -4
@@ -13,11 +13,16 @@ describe BigbluebuttonMeeting do
13
13
  it { should have_db_column(:recorded).of_type(:boolean) }
14
14
  it { should have_db_column(:creator_id).of_type(:integer) }
15
15
  it { should have_db_column(:creator_name).of_type(:string) }
16
- it { should have_db_index([:meetingid, :start_time]).unique(true) }
16
+ it { should have_db_column(:create_time).of_type(:integer) }
17
+ it { should have_db_index([:meetingid, :create_time]).unique(true) }
18
+ it { should have_db_column(:ended).of_type(:boolean) }
19
+ it { should have_db_column(:server_url).of_type(:string) }
20
+ it { should have_db_column(:server_secret).of_type(:string) }
17
21
  it "default values" do
18
- room = BigbluebuttonRoom.new
19
- room.running.should be_falsey
20
- room.record_meeting.should be_falsey
22
+ room = BigbluebuttonMeeting.new
23
+ room.running.should be(false)
24
+ room.ended.should be(false)
25
+ room.recorded.should be(false)
21
26
  end
22
27
  end
23
28
 
@@ -19,8 +19,8 @@ describe BigbluebuttonMeeting do
19
19
  it { should validate_presence_of(:meetingid) }
20
20
  it { should ensure_length_of(:meetingid).is_at_least(1).is_at_most(100) }
21
21
 
22
- it { should validate_presence_of(:start_time) }
23
- it { should validate_uniqueness_of(:start_time).scoped_to(:room_id) }
22
+ it { should validate_presence_of(:create_time) }
23
+ it { should validate_uniqueness_of(:create_time).scoped_to(:room_id) }
24
24
 
25
25
  describe "#created_by?" do
26
26
  let(:target) { FactoryGirl.create(:bigbluebutton_meeting) }
@@ -173,7 +173,7 @@ describe BigbluebuttonRecording do
173
173
  it { BigbluebuttonRecording.count.should == 2 }
174
174
  end
175
175
 
176
- context "sets recording that are not in the parameters as unavailable" do
176
+ context "sets recording that are not in the parameters as unavailable in a full sync" do
177
177
 
178
178
  context "for recordings in multiple servers" do
179
179
  before {
@@ -182,7 +182,7 @@ describe BigbluebuttonRecording do
182
182
  @r2 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => new_server)
183
183
  @r3 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => FactoryGirl.create(:bigbluebutton_server))
184
184
  @r4 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => FactoryGirl.create(:bigbluebutton_server))
185
- BigbluebuttonRecording.sync(new_server, data)
185
+ BigbluebuttonRecording.sync(new_server, data, true)
186
186
  }
187
187
  it { BigbluebuttonRecording.count.should == 5 }
188
188
  it ("recording from the target server") { @r1.reload.available.should == false }
@@ -196,7 +196,7 @@ describe BigbluebuttonRecording do
196
196
  new_server.recordings.delete_all
197
197
  @r1 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => FactoryGirl.create(:bigbluebutton_server))
198
198
  @r2 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => FactoryGirl.create(:bigbluebutton_server))
199
- BigbluebuttonRecording.sync(new_server, data)
199
+ BigbluebuttonRecording.sync(new_server, data, true)
200
200
  }
201
201
  it { new_server.recordings.should be_empty }
202
202
  it ("recording from another server") { @r1.reload.available.should == true }
@@ -208,7 +208,7 @@ describe BigbluebuttonRecording do
208
208
  BigbluebuttonRecording.delete_all
209
209
  @r1 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => new_server)
210
210
  @r2 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => new_server)
211
- BigbluebuttonRecording.sync(new_server, data)
211
+ BigbluebuttonRecording.sync(new_server, data, true)
212
212
  }
213
213
  it { BigbluebuttonRecording.count.should == 3 }
214
214
  it ("recording from another server") { @r1.reload.available.should == false }
@@ -216,6 +216,21 @@ describe BigbluebuttonRecording do
216
216
  end
217
217
  end
218
218
 
219
+ context "doesn't set recordings that are not in the parameters as unavailable if not in a full sync" do
220
+ before {
221
+ BigbluebuttonRecording.delete_all
222
+ @r1 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => new_server)
223
+ @r2 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => new_server)
224
+ @r3 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => FactoryGirl.create(:bigbluebutton_server))
225
+ @r4 = FactoryGirl.create(:bigbluebutton_recording, :available => true, :server => FactoryGirl.create(:bigbluebutton_server))
226
+ BigbluebuttonRecording.sync(new_server, data)
227
+ }
228
+ it { @r1.reload.available.should == true }
229
+ it { @r2.reload.available.should == true }
230
+ it { @r3.reload.available.should == true }
231
+ it { @r4.reload.available.should == true }
232
+ end
233
+
219
234
  context "works for multiple recordings" do
220
235
  before {
221
236
  # adds 2 more recordings to the input data
@@ -47,7 +47,7 @@ describe BigbluebuttonRoomOptions do
47
47
  BigBlueButton::BigBlueButtonConfigXml.any_instance
48
48
  .should_receive(:is_modified?).and_return(true)
49
49
  BigBlueButton::BigBlueButtonConfigXml.any_instance
50
- .should_receive(:as_string).and_return('new xml as string')
50
+ .stub(:as_string).and_return('new xml as string')
51
51
  }
52
52
  subject { room_options.set_on_config_xml(config_xml) }
53
53
  it("returns the new xml") { should eql('new xml as string') }
@@ -274,7 +274,7 @@ describe BigbluebuttonRoom do
274
274
  # these hashes should be exactly as returned by bigbluebutton-api-ruby to be sure we are testing it right
275
275
  let(:hash_info) {
276
276
  { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
277
- :running=>false, :hasBeenForciblyEnded=>false, :startTime=>nil, :endTime=>nil,
277
+ :running=>false, :hasBeenForciblyEnded=>false, :startTime=>nil, :createTime=>nil, :endTime=>nil,
278
278
  :participantCount=>0, :moderatorCount=>0, :attendees=>[], :messageKey=>"", :message=>""
279
279
  }
280
280
  }
@@ -296,7 +296,7 @@ describe BigbluebuttonRoom do
296
296
  { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
297
297
  :running=>true, :hasBeenForciblyEnded=>false, :startTime=>DateTime.parse("Wed Apr 06 17:09:57 UTC 2011"),
298
298
  :endTime=>nil, :participantCount=>4, :moderatorCount=>2, :metadata=>metadata,
299
- :attendees=>users, :messageKey=>{ }, :message=>{ }
299
+ :createTime=>1466876909, :attendees=>users, :messageKey=>{ }, :message=>{ }
300
300
  }
301
301
  }
302
302
 
@@ -315,6 +315,7 @@ describe BigbluebuttonRoom do
315
315
  it { room.participant_count.should == 0 }
316
316
  it { room.moderator_count.should == 0 }
317
317
  it { room.start_time.should == nil }
318
+ it { room.reload.create_time.should == nil }
318
319
  it { room.end_time.should == nil }
319
320
  it { room.attendees.should == [] }
320
321
  end
@@ -332,6 +333,7 @@ describe BigbluebuttonRoom do
332
333
  it { room.participant_count.should == 4 }
333
334
  it { room.moderator_count.should == 2 }
334
335
  it { room.start_time.should == DateTime.parse("Wed Apr 06 17:09:57 UTC 2011") }
336
+ it { room.reload.create_time.should == 1466876909 }
335
337
  it { room.end_time.should == nil }
336
338
  it {
337
339
  users.each do |att|
@@ -342,7 +344,7 @@ describe BigbluebuttonRoom do
342
344
  }
343
345
  end
344
346
 
345
- context "calls #update_current_meeting after the information is fetched" do
347
+ context "calls #update_current_meeting_record after the information is fetched" do
346
348
  before {
347
349
  mocked_api.should_receive(:get_meeting_info).
348
350
  with(room.meetingid, room.moderator_api_password).and_return(hash_info2)
@@ -350,10 +352,77 @@ describe BigbluebuttonRoom do
350
352
  room.server = mocked_server
351
353
 
352
354
  # here's the validation
353
- room.should_receive(:update_current_meeting).with(metadata)
355
+ room.should_receive(:update_current_meeting_record).with(metadata, true)
354
356
  }
355
357
  it { room.fetch_meeting_info }
356
358
  end
359
+
360
+ context "if an exception 'notFound' is raised" do
361
+ let!(:exception) {
362
+ e = BigBlueButton::BigBlueButtonException.new('Test error')
363
+ e.key = 'notFound'
364
+ e
365
+ }
366
+ before {
367
+ expect(mocked_api).to receive(:get_meeting_info) { raise exception }
368
+ expect(room).not_to receive(:update_current_meeting_record)
369
+ expect(room).to receive(:finish_meetings)
370
+ }
371
+ it { expect { room.fetch_meeting_info }.not_to raise_exception }
372
+ it {
373
+ room.fetch_meeting_info
374
+ room.reload.create_time.should be_nil
375
+ }
376
+ end
377
+
378
+ context "if an exception other than 'notFound' is raised" do
379
+ let!(:exception) {
380
+ e = BigBlueButton::BigBlueButtonException.new('Test error')
381
+ e.key = 'anythingElse'
382
+ e
383
+ }
384
+ before {
385
+ expect(mocked_api).to receive(:get_meeting_info) { raise exception }
386
+ expect(room).not_to receive(:update_current_meeting_record)
387
+ expect(room).to receive(:finish_meetings)
388
+ }
389
+ it { expect { room.fetch_meeting_info }.not_to raise_exception }
390
+ it {
391
+ room.fetch_meeting_info
392
+ room.reload.create_time.should be_nil
393
+ }
394
+ end
395
+
396
+ context "if an exception with a blank key is raised" do
397
+ let!(:exception) {
398
+ e = BigBlueButton::BigBlueButtonException.new('Test error')
399
+ e.key = ''
400
+ e
401
+ }
402
+ before {
403
+ expect(mocked_api).to receive(:get_meeting_info) { raise exception }
404
+ expect(room).not_to receive(:update_current_meeting_record)
405
+ expect(room).to receive(:finish_meetings)
406
+ }
407
+ it { expect { room.fetch_meeting_info }.not_to raise_exception }
408
+ it {
409
+ room.fetch_meeting_info
410
+ room.reload.create_time.should be_nil
411
+ }
412
+ end
413
+
414
+ context "raises any exception other than a BigBlueButtonException" do
415
+ let!(:exception) { NoMethodError.new('Test error') }
416
+ before {
417
+ expect(mocked_api).to receive(:get_meeting_info) { raise exception }
418
+ expect(room).not_to receive(:update_current_meeting_record)
419
+ expect(room).not_to receive(:finish_meetings)
420
+ }
421
+ it {
422
+ expect { room.fetch_meeting_info }.to raise_exception
423
+ room.reload.create_time.should_not be_nil
424
+ }
425
+ end
357
426
  end
358
427
 
359
428
  describe "#send_end" do
@@ -378,7 +447,7 @@ describe BigbluebuttonRoom do
378
447
  subject { Resque.peek(:bigbluebutton_rails) }
379
448
  it("should have a job schedule") { subject.should_not be_nil }
380
449
  it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdater') }
381
- it("the job should have the correct parameters") { subject['args'].should eq([room.id, 15]) }
450
+ it("the job should have the correct parameters") { subject['args'].should eq([room.id]) }
382
451
  end
383
452
  end
384
453
 
@@ -469,7 +538,11 @@ describe BigbluebuttonRoom do
469
538
  it { new_room.attendee_api_password.should be(new_attendee_api_password) }
470
539
  it { new_room.moderator_api_password.should be(new_moderator_api_password) }
471
540
  it { new_room.voice_bridge.should be(voice_bridge) }
472
- it("and do not save the record") { new_room.new_record?.should be_truthy }
541
+ it("doesn't save the record") { new_room.new_record?.should be(true) }
542
+ it("doesn't create a meeting") { BigbluebuttonMeeting.where(room: new_room).should be_empty }
543
+ it("doesn't schedule a meeting updater") {
544
+ Resque.peek(:bigbluebutton_rails).should be_nil
545
+ }
473
546
  end
474
547
 
475
548
  context "passing the user" do
@@ -562,6 +635,50 @@ describe BigbluebuttonRoom do
562
635
  it { room.changed?.should be(false) }
563
636
  end
564
637
  end
638
+
639
+ context "creates a meeting record" do
640
+ before do
641
+ mocked_api.should_receive(:create_meeting)
642
+ .with(room.name, room.meetingid, expected_params)
643
+ .and_return(hash_create)
644
+ room.stub(:select_server).and_return(mocked_server)
645
+
646
+ room.server = mocked_server
647
+ expect {
648
+ room.send_create
649
+ }.to change{ BigbluebuttonMeeting.count }.by(1)
650
+ end
651
+ subject { BigbluebuttonMeeting.last }
652
+ it { subject.room.should eql(room) }
653
+ it { subject.server_id.should eql(room.server.id) }
654
+ it { subject.server_url.should eql(room.server.url) }
655
+ it { subject.server_secret.should eql(room.server.secret) }
656
+ it { subject.meetingid.should eql(room.meetingid) }
657
+ it { subject.name.should eql(room.name) }
658
+ it { subject.recorded.should eql(room.record_meeting) }
659
+ it { subject.create_time.should eql(room.create_time) }
660
+ it { subject.create_time.should eql(room.create_time) }
661
+ it { subject.start_time.should eql(room.start_time) }
662
+ it { subject.ended.should eql(false) }
663
+ end
664
+
665
+ context "enqueues a BigbluebuttonMeetingUpdater" do
666
+ before do
667
+ mocked_api.should_receive(:create_meeting)
668
+ .with(room.name, room.meetingid, expected_params)
669
+ .and_return(hash_create)
670
+ room.stub(:select_server).and_return(mocked_server)
671
+
672
+ room.server = mocked_server
673
+ expect {
674
+ room.send_create
675
+ }.to change{ Resque.info[:pending] }.by(1)
676
+ end
677
+ subject { Resque.peek(:bigbluebutton_rails) }
678
+ it("should have a job schedule") { subject.should_not be_nil }
679
+ it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdater') }
680
+ it("the job should have the correct parameters") { subject['args'].should eq([room.id, 10]) }
681
+ end
565
682
  end
566
683
 
567
684
  context "generating a meeting id" do
@@ -693,7 +810,6 @@ describe BigbluebuttonRoom do
693
810
  end
694
811
  it { room.send_create }
695
812
  end
696
-
697
813
  end # #send_create
698
814
 
699
815
  describe "#join_url" do
@@ -1142,14 +1258,66 @@ describe BigbluebuttonRoom do
1142
1258
 
1143
1259
  describe "#get_metadata_for_create" do
1144
1260
  let(:room) { FactoryGirl.create(:bigbluebutton_room, :server => nil) }
1145
- before {
1146
- @m1 = FactoryGirl.create(:bigbluebutton_room_metadata, :owner => room)
1147
- @m2 = FactoryGirl.create(:bigbluebutton_room_metadata, :owner => room)
1148
- }
1149
- it {
1150
- result = { "meta_#{@m1.name}" => @m1.content, "meta_#{@m2.name}" => @m2.content }
1151
- room.send(:get_metadata_for_create).should == result
1152
- }
1261
+
1262
+ context "returns the metadata from the database" do
1263
+ before {
1264
+ @m1 = FactoryGirl.create(:bigbluebutton_room_metadata, :owner => room)
1265
+ @m2 = FactoryGirl.create(:bigbluebutton_room_metadata, :owner => room)
1266
+ }
1267
+ it {
1268
+ result = { "meta_#{@m1.name}" => @m1.content, "meta_#{@m2.name}" => @m2.content }
1269
+ room.send(:get_metadata_for_create).should == result
1270
+ }
1271
+ end
1272
+
1273
+ context "returns the dynamic metadata, if any" do
1274
+ before {
1275
+ BigbluebuttonRoom.class_eval do
1276
+ def dynamic_metadata
1277
+ {
1278
+ "test1" => "value1",
1279
+ "test2" => "value2"
1280
+ }
1281
+ end
1282
+ end
1283
+ }
1284
+ after {
1285
+ BigbluebuttonRoom.class_eval do
1286
+ undef_method :dynamic_metadata
1287
+ end
1288
+ }
1289
+
1290
+ it {
1291
+ result = { "meta_test1" => "value1", "meta_test2" => "value2" }
1292
+ room.send(:get_metadata_for_create).should eql(result)
1293
+ }
1294
+ end
1295
+
1296
+ context "gives priority to the dynamic metadata" do
1297
+ before {
1298
+ BigbluebuttonRoom.class_eval do
1299
+ def dynamic_metadata
1300
+ {
1301
+ "test1" => "value1",
1302
+ "test2" => "value2"
1303
+ }
1304
+ end
1305
+ end
1306
+
1307
+ @m1 = FactoryGirl.create(:bigbluebutton_room_metadata, owner: room, name: "test1", content: "content overwritten")
1308
+ @m2 = FactoryGirl.create(:bigbluebutton_room_metadata, owner: room, name: "other", content: "other content")
1309
+ }
1310
+ after {
1311
+ BigbluebuttonRoom.class_eval do
1312
+ undef_method :dynamic_metadata
1313
+ end
1314
+ }
1315
+
1316
+ it {
1317
+ result = { "meta_test1" => "value1", "meta_test2" => "value2", "meta_other" => "other content" }
1318
+ room.send(:get_metadata_for_create).should eql(result)
1319
+ }
1320
+ end
1153
1321
  end
1154
1322
 
1155
1323
  describe "#get_current_meeting" do
@@ -1160,28 +1328,28 @@ describe BigbluebuttonRoom do
1160
1328
  it { room.get_current_meeting.should be_nil }
1161
1329
  end
1162
1330
 
1163
- context "if the room has a start_time set" do
1331
+ context "if the room has a create_time set" do
1164
1332
  before {
1165
- @m1 = FactoryGirl.create(:bigbluebutton_meeting, :room => room, :start_time => Time.now.utc - 2.minutes)
1166
- @m2 = FactoryGirl.create(:bigbluebutton_meeting, :room => room, :start_time => Time.now.utc)
1167
- room.start_time = @m1.start_time
1333
+ @m1 = FactoryGirl.create(:bigbluebutton_meeting, :room => room, :create_time => Time.now.utc - 2.minutes)
1334
+ @m2 = FactoryGirl.create(:bigbluebutton_meeting, :room => room, :create_time => Time.now.utc)
1335
+ room.update_attributes(create_time: @m1.create_time)
1168
1336
  }
1169
1337
  it("returns the correct BigbluebuttonMeeting") { room.get_current_meeting.should eql(@m1) }
1170
1338
  end
1171
1339
  end
1172
1340
 
1173
- describe "#update_current_meeting" do
1341
+ describe "#update_current_meeting_record" do
1174
1342
  let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1175
1343
 
1176
- context "if @start_time is not set in the room" do
1177
- before { room.start_time = nil }
1178
- subject { room.update_current_meeting }
1179
- it("doesn't create a meeting") {
1344
+ context "if #create_time is not set in the room" do
1345
+ before { room.update_attributes(create_time: nil) }
1346
+ subject { room.update_current_meeting_record }
1347
+ it("doesn't do anything") {
1180
1348
  BigbluebuttonMeeting.find_by_room_id(room.id).should be_nil
1181
1349
  }
1182
1350
  end
1183
1351
 
1184
- context "if @start_time is set" do
1352
+ context "if #create_time is set" do
1185
1353
  let(:user) { FactoryGirl.build(:user) }
1186
1354
  let(:metadata) {
1187
1355
  m = {}
@@ -1190,67 +1358,109 @@ describe BigbluebuttonRoom do
1190
1358
  m
1191
1359
  }
1192
1360
  before {
1193
- room.start_time = Time.now.utc
1361
+ room.create_time = Time.now.utc
1194
1362
  room.running = !room.running # to change its default value
1195
- room.record_meeting = !room.record_meeting # to change its default value
1363
+ room.start_time = Time.at(Time.now.to_i - 123) # to change its default value
1196
1364
  }
1197
1365
 
1198
- context "if there's no meeting associated yet creates one" do
1199
- context "and no metadata was passed" do
1200
- before { room.running = true }
1201
- before(:each) {
1202
- expect {
1203
- room.update_current_meeting
1204
- }.to change{ BigbluebuttonMeeting.count }.by(1)
1205
- }
1206
- subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1207
- it("sets server") { subject.server.should eq(room.server) }
1208
- it("sets room") { subject.room.should eq(room) }
1209
- it("sets meetingid") { subject.meetingid.should eq(room.meetingid) }
1210
- it("sets name") { subject.name.should eq(room.name) }
1211
- it("sets recorded") { subject.recorded.should eq(room.record_meeting) }
1212
- it("sets running") { subject.running.should eq(room.running) }
1213
- it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1214
- it("doesn't set creator_id") { subject.creator_id.should be_nil }
1215
- it("doesn't set creator_name") { subject.creator_name.should be_nil }
1216
- end
1366
+ context "and no metadata was passed" do
1367
+ before {
1368
+ FactoryGirl.create(:bigbluebutton_meeting, :room => room, :create_time => room.create_time)
1369
+ }
1370
+ before(:each) {
1371
+ expect {
1372
+ room.update_current_meeting_record
1373
+ }.not_to change{ BigbluebuttonMeeting.count }
1374
+ }
1375
+ subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1376
+ it("sets running") { subject.running.should eq(room.running) }
1377
+ it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1378
+ it("doesn't set creator_id") { subject.creator_id.should be_nil }
1379
+ it("doesn't set creator_name") { subject.creator_name.should be_nil }
1380
+ end
1217
1381
 
1218
- context "and metadata was passed" do
1219
- before { room.running = true }
1220
- before(:each) {
1221
- expect {
1222
- room.update_current_meeting(metadata)
1223
- }.to change{ BigbluebuttonMeeting.count }.by(1)
1224
- }
1225
- subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1226
- it("sets creator_id") { subject.creator_id.should eq(user.id) }
1227
- it("sets creator_name") { subject.creator_name.should eq(user.name) }
1228
- end
1382
+ context "and metadata was passed" do
1383
+ before {
1384
+ FactoryGirl.create(:bigbluebutton_meeting, :room => room, :create_time => room.create_time)
1385
+ }
1386
+ before(:each) {
1387
+ expect {
1388
+ room.update_current_meeting_record(metadata)
1389
+ }.not_to change{ BigbluebuttonMeeting.count }
1390
+ }
1391
+ subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1392
+ it("sets running") { subject.running.should eq(room.running) }
1393
+ it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1394
+ it("sets creator_id") { subject.creator_id.should eq(user.id) }
1395
+ it("sets creator_name") { subject.creator_name.should eq(user.name) }
1229
1396
  end
1230
1397
 
1231
- context "if there's no meeting associated yet but the meeting is not running" do
1232
- before { room.running = false }
1398
+ context "if force_not_ended is set" do
1399
+ before {
1400
+ FactoryGirl.create(:bigbluebutton_meeting, :room => room, :create_time => room.create_time, :ended => true)
1401
+ }
1233
1402
  before(:each) {
1234
1403
  expect {
1235
- room.update_current_meeting
1404
+ room.update_current_meeting_record(nil, true)
1236
1405
  }.not_to change{ BigbluebuttonMeeting.count }
1237
1406
  }
1238
1407
  subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1239
- it("shouldn't create a meeting") { subject.should be_nil }
1408
+ it("sets running") { subject.running.should eq(room.running) }
1409
+ it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
1410
+ it("sets ended") { subject.ended.should be(false) }
1240
1411
  end
1412
+ end
1413
+ end
1414
+
1415
+ describe "#create_meeting_record" do
1416
+ let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1417
+
1418
+ context "if there is already a current meeting" do
1419
+ let!(:meeting) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true, create_time: room.create_time) }
1420
+ subject {
1421
+ expect {
1422
+ room.create_meeting_record
1423
+ }.not_to change{ BigbluebuttonMeeting.count }
1424
+ }
1425
+ it { BigbluebuttonMeeting.where(room: room).count.should be(1) }
1426
+ it { meeting.reload.running.should be(true) }
1427
+ it { meeting.reload.ended.should be(false) }
1428
+ end
1429
+
1430
+ context "if #create_time is not set in the room" do
1431
+ before { room.update_attributes(create_time: nil) }
1432
+ subject { room.create_meeting_record }
1433
+ it("doesn't create a meeting") {
1434
+ BigbluebuttonMeeting.find_by(room_id: room.id).should be_nil
1435
+ }
1436
+ end
1437
+
1438
+ context "if #create_time is set" do
1439
+ let(:user) { FactoryGirl.build(:user) }
1440
+ let(:metadata) {
1441
+ m = {}
1442
+ m[BigbluebuttonRails.metadata_user_id] = user.id
1443
+ m[BigbluebuttonRails.metadata_user_name] = user.name
1444
+ m
1445
+ }
1446
+ before {
1447
+ room.create_time = Time.now.utc
1448
+ room.running = !room.running # to change its default value
1449
+ room.record_meeting = !room.record_meeting # to change its default value
1450
+ room.start_time = Time.at(Time.now.to_i - 123) # to change its default value
1451
+ }
1241
1452
 
1242
- context "if there's already a meeting associated updates it" do
1453
+ context "if there's no meeting associated yet creates one" do
1243
1454
  context "and no metadata was passed" do
1244
- before {
1245
- FactoryGirl.create(:bigbluebutton_meeting, :room => room, :start_time => room.start_time)
1246
- }
1247
1455
  before(:each) {
1248
1456
  expect {
1249
- room.update_current_meeting
1250
- }.not_to change{ BigbluebuttonMeeting.count }
1457
+ room.create_meeting_record
1458
+ }.to change{ BigbluebuttonMeeting.count }.by(1)
1251
1459
  }
1252
- subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1460
+ subject { BigbluebuttonMeeting.last }
1253
1461
  it("sets server") { subject.server.should eq(room.server) }
1462
+ it("sets server_url") { subject.server_url.should eq(room.server.url) }
1463
+ it("sets server_secret") { subject.server_secret.should eq(room.server.secret) }
1254
1464
  it("sets room") { subject.room.should eq(room) }
1255
1465
  it("sets meetingid") { subject.meetingid.should eq(room.meetingid) }
1256
1466
  it("sets name") { subject.name.should eq(room.name) }
@@ -1262,43 +1472,67 @@ describe BigbluebuttonRoom do
1262
1472
  end
1263
1473
 
1264
1474
  context "and metadata was passed" do
1265
- before {
1266
- FactoryGirl.create(:bigbluebutton_meeting, :room => room, :start_time => room.start_time)
1267
- }
1268
1475
  before(:each) {
1269
1476
  expect {
1270
- room.update_current_meeting(metadata)
1271
- }.not_to change{ BigbluebuttonMeeting.count }
1477
+ room.create_meeting_record(metadata)
1478
+ }.to change{ BigbluebuttonMeeting.count }.by(1)
1272
1479
  }
1273
- subject { BigbluebuttonMeeting.find_by_room_id(room.id) }
1480
+ subject { BigbluebuttonMeeting.last }
1274
1481
  it("sets creator_id") { subject.creator_id.should eq(user.id) }
1275
1482
  it("sets creator_name") { subject.creator_name.should eq(user.name) }
1276
1483
  end
1277
1484
  end
1485
+
1486
+ context "if there were already old meetings associated with the room, finishes them" do
1487
+ let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true) }
1488
+ let!(:meeting2) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: false) }
1489
+
1490
+ before(:each) {
1491
+ BigbluebuttonMeeting.where(room: room, ended: false).count.should be(2)
1492
+ expect {
1493
+ room.create_meeting_record(metadata)
1494
+ }.to change{ BigbluebuttonMeeting.count }.by(1)
1495
+ }
1496
+ it { BigbluebuttonMeeting.where(room: room).count.should be(3) }
1497
+ it { BigbluebuttonMeeting.where(room: room, ended: false).count.should be(1) }
1498
+ it { BigbluebuttonMeeting.where(room: room, ended: true).count.should be(2) }
1499
+ it { BigbluebuttonMeeting.where(room: room, ended: true, running: false).count.should be(2) }
1500
+ end
1278
1501
  end
1279
1502
  end
1280
1503
 
1281
1504
  describe "#finish_meetings" do
1282
1505
  let!(:room) { FactoryGirl.create(:bigbluebutton_room) }
1283
1506
 
1284
- context "finishes all meetings related to this room that are still running" do
1285
- let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, room: room, running: true) }
1286
- let!(:meeting2) { FactoryGirl.create(:bigbluebutton_meeting, room: room, running: true) }
1507
+ context "finishes all meetings related to this room that are still not ended" do
1508
+ let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true) }
1509
+ let!(:meeting2) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: true) }
1510
+ let!(:meeting3) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: false) }
1287
1511
  before(:each) { room.finish_meetings }
1288
1512
  it { meeting1.reload.running.should be(false) }
1513
+ it { meeting1.reload.ended.should be(true) }
1289
1514
  it { meeting2.reload.running.should be(false) }
1515
+ it { meeting2.reload.ended.should be(true) }
1516
+ it { meeting3.reload.running.should be(false) }
1517
+ it { meeting3.reload.ended.should be(true) }
1290
1518
  end
1291
1519
 
1292
1520
  context "works if the room has no meetings" do
1293
1521
  it { room.finish_meetings }
1294
1522
  end
1295
1523
 
1296
- context "works if the room has no meetings running" do
1297
- let!(:meeting1) { FactoryGirl.create(:bigbluebutton_meeting, room: room, running: false) }
1298
- let!(:meeting2) { FactoryGirl.create(:bigbluebutton_meeting, room: room, running: false) }
1299
- it { room.finish_meetings }
1300
- it { meeting1.reload.running.should be(false) }
1301
- it { meeting2.reload.running.should be(false) }
1524
+ context "if there's a current meeting not running, ends it" do
1525
+ let!(:meeting) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: false, running: false, create_time: room.create_time) }
1526
+ before(:each) { room.finish_meetings }
1527
+ it { meeting.reload.running.should be(false) }
1528
+ it { meeting.reload.ended.should be(true) }
1529
+ end
1530
+
1531
+ context "ends meetings are already ended but still set as running" do
1532
+ let!(:meeting) { FactoryGirl.create(:bigbluebutton_meeting, room: room, ended: true, running: true) }
1533
+ before(:each) { room.finish_meetings }
1534
+ it { meeting.reload.running.should be(false) }
1535
+ it { meeting.reload.ended.should be(true) }
1302
1536
  end
1303
1537
  end
1304
1538
 
@@ -1323,7 +1557,7 @@ describe BigbluebuttonRoom do
1323
1557
 
1324
1558
  context "doesn't add the invitation URL by default" do
1325
1559
  before {
1326
- mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1560
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1327
1561
  opts.should_not have_key('meta_invitation-url')
1328
1562
  opts.should_not have_key(:'meta_invitation-url')
1329
1563
  end
@@ -1340,11 +1574,17 @@ describe BigbluebuttonRoom do
1340
1574
  end
1341
1575
 
1342
1576
  room.should respond_to(:invitation_url)
1343
- mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1577
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1344
1578
  opts.should_not have_key('meta_invitation-url')
1345
1579
  opts.should_not have_key(:'meta_invitation-url')
1346
1580
  end
1347
1581
  }
1582
+ after {
1583
+ BigbluebuttonRoom.class_eval do
1584
+ undef_method :invitation_url
1585
+ end
1586
+ }
1587
+
1348
1588
  it { room.send(:internal_create_meeting) }
1349
1589
  end
1350
1590
 
@@ -1357,32 +1597,91 @@ describe BigbluebuttonRoom do
1357
1597
  end
1358
1598
 
1359
1599
  room.should respond_to(:invitation_url)
1360
- mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1600
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1361
1601
  opts.should include('meta_invitation-url' => 'http://my-invitation.url')
1362
1602
  end
1363
1603
  }
1604
+ after {
1605
+ BigbluebuttonRoom.class_eval do
1606
+ undef_method :invitation_url
1607
+ end
1608
+ }
1609
+
1364
1610
  it { room.send(:internal_create_meeting) }
1365
1611
  end
1366
1612
  end
1367
1613
 
1368
- context "schedules a BigbluebuttonMeetingUpdater" do
1614
+ context "adds the dynamic metadata, if any" do
1369
1615
  before { mock_server_and_api }
1370
1616
  let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1371
1617
 
1372
1618
  before {
1373
- mocked_api.stub(:create_meeting)
1374
1619
  mocked_api.stub(:"request_headers=")
1375
1620
  room.server = mocked_server
1376
1621
  }
1377
- before(:each) {
1378
- expect {
1379
- room.send(:internal_create_meeting)
1380
- }.to change{ Resque.info[:pending] }.by(1)
1381
- }
1382
- subject { Resque.peek(:bigbluebutton_rails) }
1383
- it("should have a job schedule") { subject.should_not be_nil }
1384
- it("the job should be the right one") { subject['class'].should eq('BigbluebuttonMeetingUpdater') }
1385
- it("the job should have the correct parameters") { subject['args'].should eq([room.id]) }
1622
+
1623
+ it { room.should_not respond_to(:dynamic_metadata) }
1624
+
1625
+ context "doesn't havedefault dynamic metadata" do
1626
+ before {
1627
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1628
+ opts.each do |key, value|
1629
+ key.should_not match(/meta_/)
1630
+ end
1631
+ end
1632
+ }
1633
+ it { room.send(:internal_create_meeting) }
1634
+ end
1635
+
1636
+ context "doesn't add the dynamic metadata if it returns nil" do
1637
+ before {
1638
+ BigbluebuttonRoom.class_eval do
1639
+ def dynamic_metadata
1640
+ nil
1641
+ end
1642
+ end
1643
+
1644
+ room.should respond_to(:dynamic_metadata)
1645
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1646
+ opts.each do |key, value|
1647
+ key.should_not match(/meta_/)
1648
+ end
1649
+ end
1650
+ }
1651
+ after {
1652
+ BigbluebuttonRoom.class_eval do
1653
+ undef_method :dynamic_metadata
1654
+ end
1655
+ }
1656
+
1657
+ it { room.send(:internal_create_meeting) }
1658
+ end
1659
+
1660
+ context "adds the value returned by BigbluebuttonRoom#invitation_url" do
1661
+ before {
1662
+ BigbluebuttonRoom.class_eval do
1663
+ def dynamic_metadata
1664
+ {
1665
+ "test1" => "value1",
1666
+ "test2" => "value2"
1667
+ }
1668
+ end
1669
+ end
1670
+
1671
+ room.should respond_to(:dynamic_metadata)
1672
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1673
+ opts.should include('meta_test1' => 'value1')
1674
+ opts.should include('meta_test2' => 'value2')
1675
+ end
1676
+ }
1677
+ after {
1678
+ BigbluebuttonRoom.class_eval do
1679
+ undef_method :dynamic_metadata
1680
+ end
1681
+ }
1682
+
1683
+ it { room.send(:internal_create_meeting) }
1684
+ end
1386
1685
  end
1387
1686
  end
1388
1687
  end