bigbluebutton_rails 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +10 -1
  4. data/CHANGELOG.md +259 -0
  5. data/Gemfile +14 -19
  6. data/Gemfile.lock +194 -188
  7. data/README.md +416 -0
  8. data/Rakefile +12 -12
  9. data/TODO.md +13 -0
  10. data/app/controllers/bigbluebutton/playback_types_controller.rb +44 -0
  11. data/app/controllers/bigbluebutton/recordings_controller.rb +17 -10
  12. data/app/controllers/bigbluebutton/rooms_controller.rb +65 -36
  13. data/app/controllers/bigbluebutton/servers_controller.rb +12 -8
  14. data/app/models/bigbluebutton_metadata.rb +1 -1
  15. data/app/models/bigbluebutton_playback_format.rb +22 -1
  16. data/app/models/bigbluebutton_playback_type.rb +29 -0
  17. data/app/models/bigbluebutton_recording.rb +38 -19
  18. data/app/models/bigbluebutton_room.rb +150 -73
  19. data/app/models/bigbluebutton_room_options.rb +10 -7
  20. data/app/models/bigbluebutton_server.rb +69 -13
  21. data/app/models/bigbluebutton_server_config.rb +49 -0
  22. data/app/views/bigbluebutton/recordings/_form.html.erb +4 -0
  23. data/app/views/bigbluebutton/recordings/_recordings.html.erb +10 -3
  24. data/app/views/bigbluebutton/rooms/_form.html.erb +18 -6
  25. data/app/views/bigbluebutton/rooms/_rooms.html.erb +6 -3
  26. data/app/views/bigbluebutton/rooms/invite.html.erb +5 -5
  27. data/app/views/bigbluebutton/rooms/show.html.erb +18 -6
  28. data/app/views/bigbluebutton/servers/_form.html.erb +1 -1
  29. data/app/views/bigbluebutton/servers/show.html.erb +5 -0
  30. data/app/workers/bigbluebutton_finish_meetings.rb +11 -0
  31. data/app/workers/bigbluebutton_update_recordings.rb +11 -0
  32. data/app/workers/bigbluebutton_update_server_configs.rb +18 -0
  33. data/bigbluebutton_rails.gemspec +8 -7
  34. data/config/locales/en.yml +52 -7
  35. data/config/locales/pt-br.yml +162 -0
  36. data/config/resque/resque.rake +27 -0
  37. data/config/resque/workers_schedule.yml +17 -0
  38. data/lib/bigbluebutton_rails.rb +30 -2
  39. data/lib/bigbluebutton_rails/background_tasks.rb +31 -0
  40. data/lib/bigbluebutton_rails/controller_methods.rb +12 -8
  41. data/lib/bigbluebutton_rails/dial_number.rb +48 -0
  42. data/lib/bigbluebutton_rails/rails/routes.rb +9 -2
  43. data/lib/bigbluebutton_rails/utils.rb +9 -2
  44. data/lib/bigbluebutton_rails/version.rb +1 -1
  45. data/lib/generators/bigbluebutton_rails/install_generator.rb +0 -8
  46. data/lib/generators/bigbluebutton_rails/templates/migration.rb +28 -6
  47. data/lib/generators/bigbluebutton_rails/templates/migration_2_0_0.rb +56 -0
  48. data/lib/tasks/bigbluebutton_rails/meetings.rake +1 -13
  49. data/lib/tasks/bigbluebutton_rails/recordings.rake +1 -12
  50. data/lib/tasks/bigbluebutton_rails/server_configs.rake +10 -0
  51. data/spec/bigbluebutton_rails_spec.rb +0 -13
  52. data/spec/controllers/bigbluebutton/playback_types_controller_spec.rb +76 -0
  53. data/spec/controllers/bigbluebutton/recordings_controller_spec.rb +109 -37
  54. data/spec/controllers/bigbluebutton/rooms_controller_exception_handling_spec.rb +1 -0
  55. data/spec/controllers/bigbluebutton/rooms_controller_json_responses_spec.rb +27 -3
  56. data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +338 -77
  57. data/spec/controllers/bigbluebutton/servers_controller_json_responses_spec.rb +8 -0
  58. data/spec/controllers/bigbluebutton/servers_controller_spec.rb +182 -47
  59. data/spec/factories/bigbluebutton_meeting.rb +2 -2
  60. data/spec/factories/bigbluebutton_playback_format.rb +2 -2
  61. data/spec/factories/bigbluebutton_playback_type.rb +7 -0
  62. data/spec/factories/bigbluebutton_recording.rb +8 -0
  63. data/spec/factories/bigbluebutton_room.rb +10 -3
  64. data/spec/factories/bigbluebutton_server.rb +6 -1
  65. data/spec/factories/bigbluebutton_server_config.rb +6 -0
  66. data/spec/generators/install_generator_spec.rb +0 -16
  67. data/spec/lib/bigbluebutton_rails/background_tasks_spec.rb +61 -0
  68. data/spec/lib/bigbluebutton_rails/dial_number_spec.rb +78 -0
  69. data/spec/lib/bigbluebutton_rails/utils_spec.rb +56 -0
  70. data/spec/lib/tasks/meetings_rake_spec.rb +14 -1
  71. data/spec/lib/tasks/recordings_rake_spec.rb +14 -1
  72. data/spec/models/bigbluebutton_meeting_db_spec.rb +3 -3
  73. data/spec/models/bigbluebutton_meeting_spec.rb +4 -4
  74. data/spec/models/bigbluebutton_playback_format_db_spec.rb +0 -1
  75. data/spec/models/bigbluebutton_playback_format_spec.rb +75 -4
  76. data/spec/models/bigbluebutton_playback_type_db_spec.rb +14 -0
  77. data/spec/models/bigbluebutton_playback_type_spec.rb +76 -0
  78. data/spec/models/bigbluebutton_recording_db_spec.rb +3 -1
  79. data/spec/models/bigbluebutton_recording_spec.rb +234 -58
  80. data/spec/models/bigbluebutton_room_db_spec.rb +8 -6
  81. data/spec/models/bigbluebutton_room_options_db_spec.rb +1 -0
  82. data/spec/models/bigbluebutton_room_options_spec.rb +137 -38
  83. data/spec/models/bigbluebutton_room_spec.rb +540 -153
  84. data/spec/models/bigbluebutton_server_config_spec.rb +115 -0
  85. data/spec/models/bigbluebutton_server_spec.rb +180 -23
  86. data/spec/rails_app/app/controllers/my_playback_types_controller.rb +7 -0
  87. data/spec/rails_app/app/views/frontpage/show.html.erb +1 -0
  88. data/spec/rails_app/app/views/my_playback_types/index.html.erb +33 -0
  89. data/spec/rails_app/config/application.rb +0 -3
  90. data/spec/rails_app/config/database.yml.travis +10 -0
  91. data/spec/rails_app/config/environments/development.rb +1 -6
  92. data/spec/rails_app/config/environments/production.rb +2 -0
  93. data/spec/rails_app/config/environments/test.rb +2 -0
  94. data/spec/rails_app/config/routes.rb +5 -2
  95. data/spec/rails_app/db/seeds.rb +1 -1
  96. data/spec/rails_app/features/config.yml.example +3 -4
  97. data/spec/rails_app/features/join_rooms.feature +14 -14
  98. data/spec/rails_app/features/step_definitions/activity_monitor_servers_step.rb +2 -2
  99. data/spec/rails_app/features/step_definitions/create_rooms_steps.rb +4 -4
  100. data/spec/rails_app/features/step_definitions/destroy_rooms_steps.rb +2 -2
  101. data/spec/rails_app/features/step_definitions/join_rooms_steps.rb +10 -10
  102. data/spec/rails_app/features/step_definitions/web_steps.rb +2 -2
  103. data/spec/rails_app/features/support/configurations.rb +1 -1
  104. data/spec/rails_app/features/support/templates.rb +12 -12
  105. data/spec/rails_app/lib/tasks/db/populate.rake +19 -6
  106. data/spec/routing/bigbluebutton/custom_controllers_routing_spec.rb +1 -1
  107. data/spec/routing/bigbluebutton/recordings_only_routing_spec.rb +2 -2
  108. data/spec/routing/bigbluebutton/recordings_routing_spec.rb +2 -2
  109. data/spec/routing/bigbluebutton/rooms_only_routing_spec.rb +1 -1
  110. data/spec/routing/bigbluebutton/rooms_routing_spec.rb +15 -1
  111. data/spec/routing/bigbluebutton/servers_only_routing_spec.rb +1 -1
  112. data/spec/routing/bigbluebutton/servers_routing_spec.rb +1 -1
  113. data/spec/spec_helper.rb +23 -31
  114. data/spec/support/matchers/delegate_matcher.rb +8 -1
  115. data/spec/support/matchers/shoulda/respond_with_json_matcher.rb +2 -2
  116. data/spec/support/mocked_server.rb +2 -0
  117. data/spec/support/shared_contexts/rake.rb +23 -0
  118. data/spec/workers/bigbluebutton_finish_meetings_spec.rb +14 -0
  119. data/spec/workers/bigbluebutton_update_recordings_spec.rb +14 -0
  120. data/spec/workers/bigbluebutton_update_server_configs_spec.rb +47 -0
  121. metadata +70 -59
  122. data/CHANGELOG.rdoc +0 -111
  123. data/README.rdoc +0 -319
  124. data/TODO.rdoc +0 -16
  125. data/config/schedule.rb +0 -7
@@ -9,8 +9,10 @@ describe BigbluebuttonRoom do
9
9
  it { should have_db_column(:owner_type).of_type(:string) }
10
10
  it { should have_db_column(:meetingid).of_type(:string) }
11
11
  it { should have_db_column(:name).of_type(:string) }
12
- it { should have_db_column(:attendee_password).of_type(:string) }
13
- it { should have_db_column(:moderator_password).of_type(:string) }
12
+ it { should have_db_column(:attendee_key).of_type(:string) }
13
+ it { should have_db_column(:moderator_key).of_type(:string) }
14
+ it { should have_db_column(:attendee_api_password).of_type(:string) }
15
+ it { should have_db_column(:moderator_api_password).of_type(:string) }
14
16
  it { should have_db_column(:welcome_msg).of_type(:string) }
15
17
  it { should have_db_column(:dial_number).of_type(:string) }
16
18
  it { should have_db_column(:logout_url).of_type(:string) }
@@ -19,17 +21,17 @@ describe BigbluebuttonRoom do
19
21
  it { should have_db_column(:private).of_type(:boolean) }
20
22
  it { should have_db_column(:external).of_type(:boolean) }
21
23
  it { should have_db_column(:param).of_type(:string) }
22
- it { should have_db_column(:record).of_type(:boolean) }
24
+ it { should have_db_column(:record_meeting).of_type(:boolean) }
23
25
  it { should have_db_column(:duration).of_type(:integer) }
24
26
  it { should have_db_column(:created_at).of_type(:datetime) }
25
27
  it { should have_db_column(:updated_at).of_type(:datetime) }
28
+ it { should have_db_column(:create_time).of_type(:integer) }
26
29
  it { should have_db_index(:server_id) }
27
30
  it { should have_db_index(:meetingid).unique(true) }
28
- it { should have_db_index(:voice_bridge).unique(true) }
29
31
  it "default values" do
30
32
  room = BigbluebuttonRoom.new
31
- room.private.should be_false
32
- room.external.should be_false
33
+ room.private.should be_falsey
34
+ room.external.should be_falsey
33
35
  room.meetingid.should_not be_nil
34
36
  end
35
37
  end
@@ -11,6 +11,7 @@ describe BigbluebuttonRoomOptions do
11
11
  it { should have_db_column(:presenter_share_only).of_type(:boolean)}
12
12
  it { should have_db_column(:auto_start_video).of_type(:boolean) }
13
13
  it { should have_db_column(:auto_start_audio).of_type(:boolean) }
14
+ it { should have_db_column(:background).of_type(:string) }
14
15
  end
15
16
 
16
17
  end
@@ -15,13 +15,6 @@ describe BigbluebuttonRoomOptions do
15
15
  .room.should be_a_kind_of(BigbluebuttonRoom) }
16
16
  it { should validate_presence_of(:room_id) }
17
17
 
18
- describe "#get_available_layouts" do
19
- it "returns the layouts available" do
20
- expected = ["Default", "Video Chat", "Meeting", "Webinar", "Lecture assistant", "Lecture"]
21
- room_options.get_available_layouts.should eql(expected)
22
- end
23
- end
24
-
25
18
  describe "#set_on_config_xml" do
26
19
  let(:config_xml) { '<config></config>' }
27
20
 
@@ -31,7 +24,8 @@ describe BigbluebuttonRoomOptions do
31
24
  room_options.update_attributes(:default_layout => "AnyLayout",
32
25
  :presenter_share_only => true,
33
26
  :auto_start_video => false,
34
- :auto_start_audio => false)
27
+ :auto_start_audio => false,
28
+ :background => "http://mconf.org/anything")
35
29
  BigBlueButton::BigBlueButtonConfigXml.any_instance
36
30
  .should_receive(:set_attribute)
37
31
  .with('layout', 'defaultLayout', "AnyLayout", false)
@@ -47,6 +41,9 @@ describe BigbluebuttonRoomOptions do
47
41
  BigBlueButton::BigBlueButtonConfigXml.any_instance
48
42
  .should_receive(:set_attribute)
49
43
  .with('PhoneModule', 'autoJoin', false, true)
44
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
45
+ .should_receive(:set_attribute)
46
+ .with('branding', 'background', "http://mconf.org/anything", false)
50
47
  BigBlueButton::BigBlueButtonConfigXml.any_instance
51
48
  .should_receive(:is_modified?).and_return(true)
52
49
  BigBlueButton::BigBlueButtonConfigXml.any_instance
@@ -58,33 +55,26 @@ describe BigbluebuttonRoomOptions do
58
55
 
59
56
  context "if the xml did not change" do
60
57
  before {
61
- room_options.update_attributes(:default_layout => "AnyLayout",
62
- :presenter_share_only => false,
63
- :auto_start_video => false,
64
- :auto_start_audio => false)
65
- BigBlueButton::BigBlueButtonConfigXml.any_instance
66
- .should_receive(:set_attribute)
67
- .with('layout', 'defaultLayout', "AnyLayout", false)
68
- BigBlueButton::BigBlueButtonConfigXml.any_instance
69
- .should_receive(:set_attribute)
70
- .with('VideoconfModule', 'presenterShareOnly', false, true)
71
- BigBlueButton::BigBlueButtonConfigXml.any_instance
72
- .should_receive(:set_attribute)
73
- .with('PhoneModule', 'presenterShareOnly', false, true)
74
- BigBlueButton::BigBlueButtonConfigXml.any_instance
75
- .should_receive(:set_attribute)
76
- .with('VideoconfModule', 'autoStart', false, true)
77
- BigBlueButton::BigBlueButtonConfigXml.any_instance
78
- .should_receive(:set_attribute)
79
- .with('PhoneModule', 'autoJoin', false, true)
80
- BigBlueButton::BigBlueButtonConfigXml.any_instance
58
+ BigBlueButton::BigBlueButtonConfigXml.stub(:set_attribute)
59
+
60
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
81
61
  .should_receive(:is_modified?).and_return(false)
82
62
  }
83
63
  subject { room_options.set_on_config_xml(config_xml) }
84
- it("returns false") { should be_false }
64
+ it("returns false") { should be(false) }
85
65
  end
86
66
 
87
67
  context "if #default_layout is" do
68
+ context "a valid string" do
69
+ before {
70
+ room_options.update_attributes(:default_layout => "my layout")
71
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
72
+ .should_receive(:set_attribute)
73
+ .with('layout', 'defaultLayout', "my layout", anything)
74
+ }
75
+ it("sets the property in the xml") { room_options.set_on_config_xml(config_xml) }
76
+ end
77
+
88
78
  context "nil" do
89
79
  before {
90
80
  room_options.update_attributes(:default_layout => nil)
@@ -119,6 +109,32 @@ describe BigbluebuttonRoomOptions do
119
109
  }
120
110
  it("doesn't set the property in the xml") { room_options.set_on_config_xml(config_xml) }
121
111
  end
112
+
113
+ context "true" do
114
+ before {
115
+ room_options.update_attributes(:presenter_share_only => true)
116
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
117
+ .should_receive(:set_attribute)
118
+ .with('VideoconfModule', 'presenterShareOnly', true, anything)
119
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
120
+ .should_receive(:set_attribute)
121
+ .with('PhoneModule', 'presenterShareOnly', true, anything)
122
+ }
123
+ it("sets the property in the xml") { room_options.set_on_config_xml(config_xml) }
124
+ end
125
+
126
+ context "false" do
127
+ before {
128
+ room_options.update_attributes(:presenter_share_only => false)
129
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
130
+ .should_receive(:set_attribute)
131
+ .with('VideoconfModule', 'presenterShareOnly', false, anything)
132
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
133
+ .should_receive(:set_attribute)
134
+ .with('PhoneModule', 'presenterShareOnly', false, anything)
135
+ }
136
+ it("sets the property in the xml") { room_options.set_on_config_xml(config_xml) }
137
+ end
122
138
  end
123
139
 
124
140
  context "if #auto_start_video is" do
@@ -131,6 +147,26 @@ describe BigbluebuttonRoomOptions do
131
147
  }
132
148
  it("doesn't set the property in the xml") { room_options.set_on_config_xml(config_xml) }
133
149
  end
150
+
151
+ context "true" do
152
+ before {
153
+ room_options.update_attributes(:auto_start_video => true)
154
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
155
+ .should_receive(:set_attribute)
156
+ .with('VideoconfModule', 'autoStart', true, anything)
157
+ }
158
+ it("sets the property in the xml") { room_options.set_on_config_xml(config_xml) }
159
+ end
160
+
161
+ context "false" do
162
+ before {
163
+ room_options.update_attributes(:auto_start_video => false)
164
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
165
+ .should_receive(:set_attribute)
166
+ .with('VideoconfModule', 'autoStart', false, anything)
167
+ }
168
+ it("sets the property in the xml") { room_options.set_on_config_xml(config_xml) }
169
+ end
134
170
  end
135
171
 
136
172
  context "if #auto_start_audio is" do
@@ -143,63 +179,126 @@ describe BigbluebuttonRoomOptions do
143
179
  }
144
180
  it("doesn't set the property in the xml") {room_options.set_on_config_xml(config_xml) }
145
181
  end
182
+
183
+ context "true" do
184
+ before {
185
+ room_options.update_attributes(:auto_start_audio => true)
186
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
187
+ .should_receive(:set_attribute)
188
+ .with('PhoneModule', 'autoJoin', true, anything)
189
+ }
190
+ it("sets the property in the xml") {room_options.set_on_config_xml(config_xml) }
191
+ end
192
+
193
+ context "false" do
194
+ before {
195
+ room_options.update_attributes(:auto_start_audio => false)
196
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
197
+ .should_receive(:set_attribute)
198
+ .with('PhoneModule', 'autoJoin', false, anything)
199
+ }
200
+ it("sets the property in the xml") {room_options.set_on_config_xml(config_xml) }
201
+ end
146
202
  end
147
203
 
204
+ context "if #background is" do
205
+ context "a valid string" do
206
+ before {
207
+ room_options.update_attributes(:background => "my background")
208
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
209
+ .should_receive(:set_attribute)
210
+ .with('branding', 'background', 'my background', anything)
211
+ }
212
+ it("sets the property in the xml") { room_options.set_on_config_xml(config_xml) }
213
+ end
214
+
215
+ context "nil" do
216
+ before {
217
+ room_options.update_attributes(:background => nil)
218
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
219
+ .should_not_receive(:set_attribute)
220
+ .with('branding', 'background', anything, anything)
221
+ }
222
+ it("doesn't set the property in the xml") {room_options.set_on_config_xml(config_xml) }
223
+ end
224
+
225
+ context "empty string" do
226
+ before {
227
+ room_options.update_attributes(:background => "")
228
+ BigBlueButton::BigBlueButtonConfigXml.any_instance
229
+ .should_not_receive(:set_attribute)
230
+ .with('branding', 'background', anything, anything)
231
+ }
232
+ it("doesn't set the property in the xml") { room_options.set_on_config_xml(config_xml) }
233
+ end
234
+ end
148
235
  end
149
236
 
150
237
  describe "#is_modified?" do
151
238
  context "if default_layout is set" do
152
239
  before { room_options.update_attributes(:default_layout => 'Any') }
153
240
  subject { room_options.is_modified? }
154
- it("returns true") { should be_true }
241
+ it { should be(true) }
155
242
  end
156
243
 
157
244
  context "if default_layout is not set" do
158
245
  before { room_options.update_attributes(:default_layout => nil) }
159
246
  subject { room_options.is_modified? }
160
- it("returns false") { should be_false }
247
+ it { should be(false) }
161
248
  end
162
249
 
163
250
  context "if default_layout is empty" do
164
251
  before { room_options.update_attributes(:default_layout => "") }
165
252
  subject { room_options.is_modified? }
166
- it("returns true") { should be_true }
253
+ it { should be(false) }
167
254
  end
168
255
 
169
256
  context "if presenter_share_only is set" do
170
257
  before { room_options.update_attributes(:presenter_share_only => true) }
171
258
  subject { room_options.is_modified? }
172
- it("returns true") { should be_true}
259
+ it { should be(true) }
173
260
  end
174
261
 
175
262
  context "if presenter_share_only is not set" do
176
263
  before { room_options.update_attributes(:presenter_share_only => nil) }
177
264
  subject { room_options.is_modified? }
178
- it("returns false") { should be_false }
265
+ it { should be(false) }
179
266
  end
180
267
 
181
268
  context "if auto_start_video is set" do
182
269
  before { room_options.update_attributes(:auto_start_video => true) }
183
270
  subject { room_options.is_modified? }
184
- it("returns true") { should be_true}
271
+ it { should be(true) }
185
272
  end
186
273
 
187
274
  context "if auto_start_video is not set" do
188
275
  before { room_options.update_attributes(:auto_start_video => nil) }
189
276
  subject { room_options.is_modified? }
190
- it("returns false" ) { should be_false }
277
+ it { should be(false) }
191
278
  end
192
279
 
193
280
  context "if auto_start_audio is set" do
194
281
  before { room_options.update_attributes(:auto_start_audio => true) }
195
282
  subject { room_options.is_modified? }
196
- it("returns true") { should be_true}
283
+ it { should be(true) }
197
284
  end
198
285
 
199
286
  context "if auto_start_audio is not set" do
200
287
  before { room_options.update_attributes(:auto_start_audio => nil) }
201
288
  subject { room_options.is_modified? }
202
- it("returns false" ) { should be_false }
289
+ it { should be(false) }
290
+ end
291
+
292
+ context "if background is set" do
293
+ before { room_options.update_attributes(:background => true) }
294
+ subject { room_options.is_modified? }
295
+ it { should be(true) }
296
+ end
297
+
298
+ context "if background is not set" do
299
+ before { room_options.update_attributes(:background => nil) }
300
+ subject { room_options.is_modified? }
301
+ it { should be(false) }
203
302
  end
204
303
  end
205
304
 
@@ -33,17 +33,14 @@ describe BigbluebuttonRoom do
33
33
  it { should delegate(:auto_start_audio).to(:room_options) }
34
34
  it { should delegate(:"auto_start_audio=").to(:room_options) }
35
35
 
36
- it { should delegate(:get_available_layouts).to(:room_options) }
36
+ it { should delegate(:background).to(:room_options) }
37
+ it { should delegate(:"background=").to(:room_options) }
37
38
 
38
39
  it { should validate_presence_of(:meetingid) }
39
40
  it { should validate_uniqueness_of(:meetingid) }
40
41
  it { should ensure_length_of(:meetingid).is_at_least(1).is_at_most(100) }
41
42
 
42
- it { should validate_presence_of(:voice_bridge) }
43
- it { should validate_uniqueness_of(:voice_bridge) }
44
-
45
43
  it { should validate_presence_of(:name) }
46
- it { should validate_uniqueness_of(:name) }
47
44
  it { should ensure_length_of(:name).is_at_least(1).is_at_most(150) }
48
45
 
49
46
  it { should validate_presence_of(:param) }
@@ -52,7 +49,7 @@ describe BigbluebuttonRoom do
52
49
 
53
50
  it { should be_boolean(:private) }
54
51
 
55
- it { should be_boolean(:record) }
52
+ it { should be_boolean(:record_meeting) }
56
53
 
57
54
  it { should validate_presence_of(:duration) }
58
55
  it { should validate_numericality_of(:duration).only_integer }
@@ -60,9 +57,9 @@ describe BigbluebuttonRoom do
60
57
  it { should allow_value(0).for(:duration) }
61
58
  it { should allow_value(1).for(:duration) }
62
59
 
63
- it { should ensure_length_of(:attendee_password).is_at_most(16) }
60
+ it { should ensure_length_of(:attendee_key).is_at_most(16) }
64
61
 
65
- it { should ensure_length_of(:moderator_password).is_at_most(16) }
62
+ it { should ensure_length_of(:moderator_key).is_at_most(16) }
66
63
 
67
64
  it { should ensure_length_of(:welcome_msg).is_at_most(250) }
68
65
 
@@ -71,7 +68,7 @@ describe BigbluebuttonRoom do
71
68
  # attr_accessors
72
69
  [:running, :participant_count, :moderator_count, :attendees,
73
70
  :has_been_forcibly_ended, :start_time, :end_time, :external,
74
- :server, :request_headers, :record, :duration].each do |attr|
71
+ :server, :request_headers, :record_meeting, :duration].each do |attr|
75
72
  it { should respond_to(attr) }
76
73
  it { should respond_to("#{attr}=") }
77
74
  end
@@ -87,13 +84,13 @@ describe BigbluebuttonRoom do
87
84
  it { should respond_to(:is_running?) }
88
85
 
89
86
  describe "#user_role" do
90
- let(:room) { FactoryGirl.build(:bigbluebutton_room, :moderator_password => "mod", :attendee_password => "att") }
87
+ let(:room) { FactoryGirl.build(:bigbluebutton_room, :moderator_key => "mod", :attendee_key => "att") }
91
88
  it { should respond_to(:user_role) }
92
- it { room.user_role({ :password => room.moderator_password }).should == :moderator }
93
- it { room.user_role({ :password => room.attendee_password }).should == :attendee }
94
- it { room.user_role({ :password => "wrong" }).should == nil }
95
- it { room.user_role({ :password => nil }).should == nil }
96
- it { room.user_role({ :not_password => "any" }).should == nil }
89
+ it { room.user_role({ :key => room.moderator_key }).should == :moderator }
90
+ it { room.user_role({ :key => room.attendee_key }).should == :attendee }
91
+ it { room.user_role({ :key => "wrong" }).should == nil }
92
+ it { room.user_role({ :key => nil }).should == nil }
93
+ it { room.user_role({ :not_key => "any" }).should == nil }
97
94
  it { room.user_role({ }).should == nil }
98
95
  it { room.user_role(nil).should == nil }
99
96
  end
@@ -119,18 +116,18 @@ describe BigbluebuttonRoom do
119
116
  let(:room) { BigbluebuttonRoom.last }
120
117
  let(:room2) { BigbluebuttonRoom.last }
121
118
  it { should respond_to(:attr_equal?) }
122
- it { room.attr_equal?(room2).should be_true }
119
+ it { room.attr_equal?(room2).should be_truthy }
123
120
  it "differentiates instance variables" do
124
121
  room2.running = !room.running
125
- room.attr_equal?(room2).should be_false
122
+ room.attr_equal?(room2).should be(false)
126
123
  end
127
124
  it "differentiates attributes" do
128
125
  room2.private = !room.private
129
- room.attr_equal?(room2).should be_false
126
+ room.attr_equal?(room2).should be(false)
130
127
  end
131
128
  it "differentiates objects" do
132
129
  room2 = room.dup
133
- room.attr_equal?(room2).should be_false
130
+ room.attr_equal?(room2).should be(false)
134
131
  end
135
132
  end
136
133
 
@@ -140,8 +137,8 @@ describe BigbluebuttonRoom do
140
137
  it "fetched attributes before they are fetched" do
141
138
  room.participant_count.should be(0)
142
139
  room.moderator_count.should be(0)
143
- room.running.should be_false
144
- room.has_been_forcibly_ended.should be_false
140
+ room.running.should be(false)
141
+ room.has_been_forcibly_ended.should be(false)
145
142
  room.start_time.should be_nil
146
143
  room.end_time.should be_nil
147
144
  room.attendees.should eql([])
@@ -155,25 +152,7 @@ describe BigbluebuttonRoom do
155
152
  b.meetingid.should == "user defined"
156
153
  }
157
154
  end
158
-
159
- context "voice_bridge" do
160
- it {
161
- b = BigbluebuttonRoom.new(:voice_bridge => "user defined")
162
- b.voice_bridge.should == "user defined"
163
- }
164
- context "with a random value" do
165
- it { room.voice_bridge.should_not be_nil }
166
- it { room.voice_bridge.should =~ /7[0-9]{4}/ }
167
- it "tries to randomize 10 times if voice_bridge already exists" do
168
- room = FactoryGirl.create(:bigbluebutton_room, :voice_bridge => "70000")
169
- BigbluebuttonRoom.stub(:find_by_voice_bridge).and_return(room)
170
- SecureRandom.should_receive(:random_number).exactly(10).and_return(0000)
171
- room2 = BigbluebuttonRoom.new # triggers the random_number calls
172
- room2.voice_bridge.should == "70000"
173
- end
174
- end
175
- end
176
- end
155
+ end
177
156
 
178
157
  describe "#room_options" do
179
158
  it "is created when the room is created" do
@@ -192,12 +171,12 @@ describe BigbluebuttonRoom do
192
171
  }
193
172
  it { @room.room_options.should_not be_nil }
194
173
  it("is not promptly saved") {
195
- @room.room_options.new_record?.should be_true
174
+ @room.room_options.new_record?.should be(true)
196
175
  }
197
176
  it("is saved when the room is saved") {
198
177
  @room.save!
199
178
  @room.reload
200
- @room.room_options.new_record?.should be_false
179
+ @room.room_options.new_record?.should be(false)
201
180
  }
202
181
  end
203
182
  end
@@ -226,7 +205,7 @@ describe BigbluebuttonRoom do
226
205
 
227
206
  context "sets param as the downcased parameterized name if param is" do
228
207
  after :each do
229
- @room.save.should be_true
208
+ @room.save.should be_truthy
230
209
  @room.param.should == @room.name.downcase.parameterize
231
210
  end
232
211
  it "nil" do
@@ -240,18 +219,18 @@ describe BigbluebuttonRoom do
240
219
  end
241
220
 
242
221
  context "when room set to private" do
243
- context "sets passwords that are not yet defined" do
244
- let(:room) { FactoryGirl.create(:bigbluebutton_room, :private => false, :moderator_password => nil, :attendee_password => nil) }
222
+ context "sets keys that are not yet defined" do
223
+ let(:room) { FactoryGirl.create(:bigbluebutton_room, :private => false, :moderator_key => nil, :attendee_key => nil) }
245
224
  before(:each) { room.update_attributes(:private => true) }
246
- it { room.moderator_password.should_not be_nil }
247
- it { room.attendee_password.should_not be_nil }
225
+ it { room.moderator_key.should_not be_nil }
226
+ it { room.attendee_key.should_not be_nil }
248
227
  end
249
228
 
250
- context "only sets the passwords if the room was public before" do
251
- let(:room) { FactoryGirl.create(:bigbluebutton_room, :private => true, :moderator_password => "123", :attendee_password => "321") }
229
+ context "only sets the keys if the room was public before" do
230
+ let(:room) { FactoryGirl.create(:bigbluebutton_room, :private => true, :moderator_key => "123", :attendee_key => "321") }
252
231
  before(:each) { room.update_attributes(:private => true) }
253
- it { room.moderator_password.should == "123" }
254
- it { room.attendee_password.should == "321" }
232
+ it { room.moderator_key.should == "123" }
233
+ it { room.attendee_key.should == "321" }
255
234
  end
256
235
  end
257
236
 
@@ -270,9 +249,9 @@ describe BigbluebuttonRoom do
270
249
  room.server = mocked_server
271
250
  }
272
251
  before(:each) { @response = room.fetch_is_running? }
273
- it { room.running.should be_false }
274
- it { room.is_running?.should be_false }
275
- it { @response.should be_false }
252
+ it { room.running.should be(false) }
253
+ it { room.is_running?.should be(false) }
254
+ it { @response.should be(false) }
276
255
  end
277
256
 
278
257
  context "fetches 'running' when running" do
@@ -282,9 +261,9 @@ describe BigbluebuttonRoom do
282
261
  room.server = mocked_server
283
262
  }
284
263
  before(:each) { @response = room.fetch_is_running? }
285
- it { room.running.should be_true }
286
- it { room.is_running?.should be_true }
287
- it { @response.should be_true }
264
+ it { room.running.should be_truthy }
265
+ it { room.is_running?.should be_truthy }
266
+ it { @response.should be_truthy }
288
267
  end
289
268
 
290
269
  end
@@ -326,7 +305,7 @@ describe BigbluebuttonRoom do
326
305
  context "fetches meeting info when the meeting is not running" do
327
306
  before {
328
307
  mocked_api.should_receive(:get_meeting_info).
329
- with(room.meetingid, room.moderator_password).and_return(hash_info)
308
+ with(room.meetingid, room.moderator_api_password).and_return(hash_info)
330
309
  room.should_receive(:require_server)
331
310
  room.server = mocked_server
332
311
  }
@@ -343,7 +322,7 @@ describe BigbluebuttonRoom do
343
322
  context "fetches meeting info when the meeting is running" do
344
323
  before {
345
324
  mocked_api.should_receive(:get_meeting_info).
346
- with(room.meetingid, room.moderator_password).and_return(hash_info2)
325
+ with(room.meetingid, room.moderator_api_password).and_return(hash_info2)
347
326
  room.should_receive(:require_server)
348
327
  room.server = mocked_server
349
328
  }
@@ -366,7 +345,7 @@ describe BigbluebuttonRoom do
366
345
  context "calls #update_current_meeting after the information is fetched" do
367
346
  before {
368
347
  mocked_api.should_receive(:get_meeting_info).
369
- with(room.meetingid, room.moderator_password).and_return(hash_info2)
348
+ with(room.meetingid, room.moderator_api_password).and_return(hash_info2)
370
349
  room.should_receive(:require_server)
371
350
  room.server = mocked_server
372
351
 
@@ -382,7 +361,7 @@ describe BigbluebuttonRoom do
382
361
 
383
362
  context "calls end_meeting" do
384
363
  before {
385
- mocked_api.should_receive(:end_meeting).with(room.meetingid, room.moderator_password)
364
+ mocked_api.should_receive(:end_meeting).with(room.meetingid, room.moderator_api_password)
386
365
  room.should_receive(:require_server)
387
366
  room.server = mocked_server
388
367
  }
@@ -404,15 +383,19 @@ describe BigbluebuttonRoom do
404
383
  end
405
384
 
406
385
  describe "#send_create" do
407
- let(:attendee_password) { Forgery(:basic).password }
408
- let(:moderator_password) { Forgery(:basic).password }
386
+ let(:time) { 1409531761442 }
387
+ let(:new_moderator_api_password) { Forgery(:basic).password }
388
+ let(:new_attendee_api_password) { Forgery(:basic).password }
389
+ let(:voice_bridge) { SecureRandom.random_number(99999) }
409
390
  let(:hash_create) {
410
391
  {
411
392
  :returncode => "SUCCESS", :meetingID => "test_id",
412
- :attendeePW => attendee_password, :moderatorPW => moderator_password,
393
+ :attendeePW => new_attendee_api_password, :moderatorPW => new_moderator_api_password,
394
+ :voiceBridge => voice_bridge, :createTime => time,
413
395
  :hasBeenForciblyEnded => "false", :messageKey => {}, :message => {}
414
396
  }
415
397
  }
398
+ let(:expected_params) { get_create_params(room) }
416
399
  before {
417
400
  room.update_attributes(:welcome_msg => "Anything")
418
401
  FactoryGirl.create(:bigbluebutton_room_metadata, :owner => room)
@@ -441,80 +424,223 @@ describe BigbluebuttonRoom do
441
424
  end
442
425
  end
443
426
 
427
+ context "sets the room's create_time" do
428
+ before do
429
+ mocked_api.should_receive(:create_meeting)
430
+ .with(room.name, room.meetingid, get_create_params(room))
431
+ .and_return(hash_create)
432
+ room.stub(:select_server).and_return(mocked_server)
433
+ room.server = mocked_server
434
+ room.send_create
435
+ end
436
+
437
+ it { expect(room.create_time).to eq(time) }
438
+ end
439
+
444
440
  context "sends create_meeting" do
445
441
 
446
442
  context "for a stored room" do
447
443
  before do
448
444
  mocked_api.should_receive(:create_meeting)
449
- .with(room.name, room.meetingid, get_create_params(room))
445
+ .with(room.name, room.meetingid, expected_params)
450
446
  .and_return(hash_create)
451
447
  room.stub(:select_server).and_return(mocked_server)
448
+
452
449
  room.server = mocked_server
453
450
  room.send_create
454
451
  end
455
- it { room.attendee_password.should be(attendee_password) }
456
- it { room.moderator_password.should be(moderator_password) }
457
- it { room.changed?.should be_false }
452
+ it { room.attendee_api_password.should be(new_attendee_api_password) }
453
+ it { room.moderator_api_password.should be(new_moderator_api_password) }
454
+ it { room.voice_bridge.should be(voice_bridge) }
455
+ it { room.changed?.should be(false) }
458
456
  end
459
457
 
460
458
  context "for a new record" do
461
459
  let(:new_room) { FactoryGirl.build(:bigbluebutton_room) }
462
460
  before do
461
+ params = get_create_params(new_room)
463
462
  mocked_api.should_receive(:create_meeting)
464
- .with(new_room.name, new_room.meetingid, get_create_params(new_room))
463
+ .with(new_room.name, new_room.meetingid, params)
465
464
  .and_return(hash_create)
466
465
  new_room.stub(:select_server).and_return(mocked_server)
467
466
  new_room.server = mocked_server
468
467
  new_room.send_create
469
468
  end
470
- it { new_room.attendee_password.should be(attendee_password) }
471
- it { new_room.moderator_password.should be(moderator_password) }
472
- it("and do not save the record") { new_room.new_record?.should be_true }
469
+ it { new_room.attendee_api_password.should be(new_attendee_api_password) }
470
+ it { new_room.moderator_api_password.should be(new_moderator_api_password) }
471
+ it { new_room.voice_bridge.should be(voice_bridge) }
472
+ it("and do not save the record") { new_room.new_record?.should be_truthy }
473
473
  end
474
474
 
475
475
  context "passing the user" do
476
476
  let(:user) { FactoryGirl.build(:user) }
477
477
  before do
478
+ params = get_create_params(room, user)
478
479
  mocked_api.should_receive(:create_meeting)
479
- .with(room.name, room.meetingid, get_create_params(room, user))
480
+ .with(room.name, room.meetingid, params)
480
481
  .and_return(hash_create)
481
482
  room.stub(:select_server).and_return(mocked_server)
482
483
  room.server = mocked_server
483
484
  room.send_create(user)
484
485
  end
485
- it { room.attendee_password.should be(attendee_password) }
486
- it { room.moderator_password.should be(moderator_password) }
487
- it { room.changed?.should be_false }
486
+ it { room.attendee_api_password.should be(new_attendee_api_password) }
487
+ it { room.moderator_api_password.should be(new_moderator_api_password) }
488
+ it { room.changed?.should be(false) }
488
489
  end
489
490
 
490
491
  context "passing additional options" do
491
492
  let(:user) { FactoryGirl.build(:user) }
492
- let(:user_opts) { { :record => false, :other => true } }
493
+ let(:user_opts) { { :record_meeting => false, :other => true } }
493
494
  before do
495
+ params = get_create_params(room, user).merge(user_opts)
494
496
  mocked_api.should_receive(:create_meeting)
495
- .with(room.name, room.meetingid, get_create_params(room, user).merge(user_opts))
497
+ .with(room.name, room.meetingid, params)
496
498
  .and_return(hash_create)
497
499
  room.stub(:select_server).and_return(mocked_server)
498
500
  room.server = mocked_server
499
501
  room.send_create(user, user_opts)
500
502
  end
501
- it { room.attendee_password.should be(attendee_password) }
502
- it { room.moderator_password.should be(moderator_password) }
503
- it { room.changed?.should be_false }
503
+ it { room.attendee_api_password.should be(new_attendee_api_password) }
504
+ it { room.moderator_api_password.should be(new_moderator_api_password) }
505
+ it { room.changed?.should be(false) }
506
+ end
507
+
508
+ context "when the call to create doesn't return a voice bridge" do
509
+ before do
510
+ room.update_attributes(:voice_bridge => nil)
511
+ hash_create.delete(:voiceBridge)
512
+
513
+ mocked_api.should_receive(:create_meeting)
514
+ .with(room.name, room.meetingid, get_create_params(room))
515
+ .and_return(hash_create)
516
+ room.stub(:select_server).and_return(mocked_server)
517
+ room.server = mocked_server
518
+ room.send_create
519
+ end
520
+ it { room.voice_bridge.should be_nil }
521
+ it { room.changed?.should be(false) }
522
+ end
523
+
524
+ context "when it's set to use local voice bridges" do
525
+ before {
526
+ @use_local_voice_bridges = BigbluebuttonRails.use_local_voice_bridges
527
+ BigbluebuttonRails.use_local_voice_bridges = true
528
+ }
529
+ after {
530
+ BigbluebuttonRails.use_local_voice_bridges = @use_local_voice_bridges
531
+ }
532
+
533
+ context "sets the voice bridge in the params if there's a voice bridge" do
534
+ let(:voice_bridge) { SecureRandom.random_number(99999) }
535
+ before do
536
+ room.update_attributes(:voice_bridge => voice_bridge)
537
+ create_params = get_create_params(room)
538
+ create_params.merge!({ :voiceBridge => voice_bridge })
539
+
540
+ mocked_api.should_receive(:create_meeting)
541
+ .with(room.name, room.meetingid, create_params)
542
+ .and_return(hash_create)
543
+ room.stub(:select_server).and_return(mocked_server)
544
+ room.server = mocked_server
545
+ room.send_create
546
+ end
547
+ it { room.changed?.should be(false) }
548
+ end
549
+
550
+ context "doesn't set the voice bridge if it's blank" do
551
+ let(:voice_bridge) { SecureRandom.random_number(99999) }
552
+ before do
553
+ room.update_attributes(:voice_bridge => "")
554
+
555
+ mocked_api.should_receive(:create_meeting)
556
+ .with(room.name, room.meetingid, get_create_params(room))
557
+ .and_return(hash_create)
558
+ room.stub(:select_server).and_return(mocked_server)
559
+ room.server = mocked_server
560
+ room.send_create
561
+ end
562
+ it { room.changed?.should be(false) }
563
+ end
504
564
  end
505
565
  end
506
566
 
507
- context "generates a meetingid if nil" do
567
+ context "generating a meeting id" do
508
568
  let(:new_id) { "new id" }
509
- before {
510
- room.meetingid = nil
569
+
570
+ ['', nil].each do |value|
571
+ it "generates a new one if it's empty or nil" do
572
+ room.meetingid = value
573
+ room.stub(:select_server).and_return(mocked_server)
574
+ room.server = mocked_server
575
+ room.should_receive(:unique_meetingid).and_return(new_id)
576
+ mocked_api.should_receive(:create_meeting)
577
+ .with(room.name, new_id, anything)
578
+ room.send_create
579
+ end
580
+ end
581
+
582
+ it "doesn't generate a new meetingid if already set" do
583
+ old_id = "old id"
584
+ room.meetingid = old_id
511
585
  room.stub(:select_server).and_return(mocked_server)
512
586
  room.server = mocked_server
513
- }
514
- it "before calling create" do
515
- room.should_receive(:unique_meetingid).and_return(new_id)
587
+ room.should_not_receive(:unique_meetingid)
588
+ mocked_api.should_receive(:create_meeting)
589
+ .with(room.name, old_id, anything)
590
+ room.send_create
591
+ end
592
+ end
593
+
594
+ context "generating a moderator password" do
595
+ let(:new_pass) { "new pass" }
596
+
597
+ ['', nil].each do |value|
598
+ it "generates a new one if it's empty or nil" do
599
+ room.moderator_api_password = value
600
+ room.stub(:select_server).and_return(mocked_server)
601
+ room.server = mocked_server
602
+ room.should_receive(:internal_password).and_return(new_pass)
603
+ mocked_api.should_receive(:create_meeting)
604
+ .with(room.name, anything, hash_including(moderatorPW: new_pass))
605
+ room.send_create
606
+ end
607
+ end
608
+
609
+ it "doesn't generate a new moderator password if already set" do
610
+ old_pass = "old pass"
611
+ room.moderator_api_password = old_pass
612
+ room.stub(:select_server).and_return(mocked_server)
613
+ room.server = mocked_server
614
+ room.should_not_receive(:internal_password)
615
+ mocked_api.should_receive(:create_meeting)
616
+ .with(room.name, anything, hash_including(moderatorPW: old_pass))
617
+ room.send_create
618
+ end
619
+ end
620
+
621
+ context "generating a attendee password" do
622
+ let(:new_pass) { "new pass" }
623
+
624
+ ['', nil].each do |value|
625
+ it "generates a new one if it's empty or nil" do
626
+ room.attendee_api_password = value
627
+ room.stub(:select_server).and_return(mocked_server)
628
+ room.server = mocked_server
629
+ room.should_receive(:internal_password).and_return(new_pass)
630
+ mocked_api.should_receive(:create_meeting)
631
+ .with(room.name, anything, hash_including(attendeePW: new_pass))
632
+ room.send_create
633
+ end
634
+ end
635
+
636
+ it "doesn't generate a new attendee password if already set" do
637
+ old_pass = "old pass"
638
+ room.attendee_api_password = old_pass
639
+ room.stub(:select_server).and_return(mocked_server)
640
+ room.server = mocked_server
641
+ room.should_not_receive(:internal_password)
516
642
  mocked_api.should_receive(:create_meeting)
517
- .with(room.name, new_id, get_create_params(room))
643
+ .with(room.name, anything, hash_including(attendeePW: old_pass))
518
644
  room.send_create
519
645
  end
520
646
  end
@@ -533,29 +659,27 @@ describe BigbluebuttonRoom do
533
659
 
534
660
  context "selects and requires a server" do
535
661
  let(:another_server) { FactoryGirl.create(:bigbluebutton_server) }
536
-
662
+ let(:room2) { FactoryGirl.create(:bigbluebutton_room, :server => nil) }
537
663
  context "and saves the result" do
538
664
  before do
539
- room.should_receive(:select_server).and_return(another_server)
540
- room.should_receive(:require_server)
541
- room.should_receive(:internal_create_meeting)
542
- room.server = mocked_server
543
- room.send_create
665
+ room2.should_receive(:internal_create_meeting)
666
+ room2.send_create
544
667
  end
545
- it { BigbluebuttonRoom.find(room.id).server_id.should == another_server.id }
668
+ # send_create will call require_server, so a server will be assigned
669
+ # to this room
670
+ it { BigbluebuttonRoom.find(room2.id).server_id.should_not be_nil }
546
671
  end
547
672
 
548
673
  context "and does not save when is a new record" do
549
674
  let(:new_room) { FactoryGirl.build(:bigbluebutton_room) }
550
675
  before do
551
- new_room.should_receive(:select_server).and_return(another_server)
552
676
  new_room.should_receive(:require_server)
553
677
  new_room.should_receive(:internal_create_meeting).and_return(nil)
554
678
  new_room.should_not_receive(:save)
555
679
  new_room.server = mocked_server
556
680
  new_room.send_create
557
681
  end
558
- it { new_room.new_record?.should be_true }
682
+ it { new_room.new_record?.should be_truthy }
559
683
  end
560
684
  end
561
685
 
@@ -583,7 +707,7 @@ describe BigbluebuttonRoom do
583
707
  before {
584
708
  room.should_receive(:require_server)
585
709
  mocked_api.should_receive(:join_meeting_url)
586
- .with(room.meetingid, username, room.moderator_password, join_options)
710
+ .with(room.meetingid, username, room.moderator_api_password, join_options)
587
711
  .and_return(expected)
588
712
  room.server = mocked_server
589
713
  }
@@ -596,7 +720,7 @@ describe BigbluebuttonRoom do
596
720
  before {
597
721
  room.should_receive(:require_server)
598
722
  mocked_api.should_receive(:join_meeting_url)
599
- .with(room.meetingid, username, room.attendee_password, join_options)
723
+ .with(room.meetingid, username, room.attendee_api_password, join_options)
600
724
  .and_return(expected)
601
725
  room.server = mocked_server
602
726
  }
@@ -605,16 +729,44 @@ describe BigbluebuttonRoom do
605
729
  end
606
730
 
607
731
  context "without a role" do
608
- let(:expected) { 'expected-url' }
609
- before {
610
- room.should_receive(:require_server)
611
- mocked_api.should_receive(:join_meeting_url)
612
- .with(room.meetingid, username, 'pass', join_options)
613
- .and_return(expected)
614
- room.server = mocked_server
615
- }
616
- subject { room.join_url(username, nil, 'pass', join_options) }
617
- it("returns the correct url") { subject.should eq(expected) }
732
+ context "passing the moderator key" do
733
+ let(:expected) { 'expected-url' }
734
+ before {
735
+ room.should_receive(:require_server)
736
+ mocked_api.should_receive(:join_meeting_url)
737
+ .with(room.meetingid, username, room.moderator_api_password, join_options)
738
+ .and_return(expected)
739
+ room.server = mocked_server
740
+ }
741
+ subject { room.join_url(username, nil, room.moderator_key, join_options) }
742
+ it("returns the correct url") { subject.should eq(expected) }
743
+ end
744
+
745
+ context "passing the attendee key" do
746
+ let(:expected) { 'expected-url' }
747
+ before {
748
+ room.should_receive(:require_server)
749
+ mocked_api.should_receive(:join_meeting_url)
750
+ .with(room.meetingid, username, room.attendee_api_password, join_options)
751
+ .and_return(expected)
752
+ room.server = mocked_server
753
+ }
754
+ subject { room.join_url(username, nil, room.attendee_key, join_options) }
755
+ it("returns the correct url") { subject.should eq(expected) }
756
+ end
757
+
758
+ context "passing an unmatching key" do
759
+ let(:expected) { 'expected-url' }
760
+ before {
761
+ room.should_receive(:require_server)
762
+ mocked_api.should_receive(:join_meeting_url)
763
+ .with(room.meetingid, username, nil, join_options)
764
+ .and_return(expected)
765
+ room.server = mocked_server
766
+ }
767
+ subject { room.join_url(username, nil, "wrong key", join_options) }
768
+ it("returns the correct url") { subject.should eq(expected) }
769
+ end
618
770
  end
619
771
 
620
772
  context "strips the url before returning it" do
@@ -632,8 +784,8 @@ describe BigbluebuttonRoom do
632
784
  describe "#fetch_new_token" do
633
785
  let(:config_xml) {
634
786
  '<config>
635
- <localeversion suppressWarning="false">0.8</localeversion>
636
- <version>0.8</version>
787
+ <localeversion suppressWarning="false">0.9.0</localeversion>
788
+ <version>264</version>
637
789
  <layout showLogButton="false" showVideoLayout="false" showResetLayout="false" defaultLayout="Webinar" showToolbar="true" showFooter="true" showMeetingName="true" showHelpButton="true" showLogoutWindow="true" showLayoutTools="true" showNetworkMonitor="true" confirmLogout="true"/>
638
790
  <modules>
639
791
  <module name="LayoutModule" url="http://server.test/client/LayoutModule.swf?v=15" uri="rtmp://server.test/bigbluebutton" layoutConfig="http://server.test/client/conf/layout.xml" enableEdit="true"/>
@@ -655,6 +807,7 @@ describe BigbluebuttonRoom do
655
807
  mocked_api.should_receive(:set_config_xml)
656
808
  .with(room.meetingid, 'fake-config-xml')
657
809
  .and_return('fake-token')
810
+ mocked_server.should_receive(:update_config).with('fake-config-xml')
658
811
  }
659
812
  it("returns the token generated") { room.fetch_new_token.should eql('fake-token') }
660
813
  end
@@ -682,17 +835,118 @@ describe BigbluebuttonRoom do
682
835
 
683
836
  end
684
837
 
685
- context "validates passwords" do
838
+ context "#available_layouts" do
839
+ context "delegates to server" do
840
+ let(:room) { FactoryGirl.build(:bigbluebutton_room) }
841
+ let(:layouts) { [ 'layout-1', 'another layout' ] }
842
+ before {
843
+ room.server.should_receive(:available_layouts)
844
+ .and_return(layouts)
845
+ }
846
+ it { room.available_layouts.should eql(layouts) }
847
+ end
848
+
849
+ context "returns and empty array if the server is nil" do
850
+ let(:room) { FactoryGirl.build(:bigbluebutton_room, server: nil) }
851
+ it { room.available_layouts.should eql([]) }
852
+ end
853
+ end
854
+
855
+ context "#available_layouts_names" do
856
+ context "delegates to server" do
857
+ let(:room) { FactoryGirl.build(:bigbluebutton_room) }
858
+ let(:layouts) { [ 'layout-1', 'another layout' ] }
859
+ before {
860
+ room.server.should_receive(:available_layouts_names)
861
+ .and_return(layouts)
862
+ }
863
+ it { room.available_layouts_names.should eql(layouts) }
864
+ end
865
+
866
+ context "returns and empty array if the server is nil" do
867
+ let(:room) { FactoryGirl.build(:bigbluebutton_room, server: nil) }
868
+ it { room.available_layouts_names.should eql([]) }
869
+ end
870
+ end
871
+
872
+ context "#available_layouts_for_select" do
873
+ context "delegates to server" do
874
+ let(:room) { FactoryGirl.build(:bigbluebutton_room) }
875
+ let(:layouts) { [ 'layout-1', 'another layout' ] }
876
+ before {
877
+ room.server.should_receive(:available_layouts_for_select)
878
+ .and_return(layouts)
879
+ }
880
+ it { room.available_layouts_for_select.should eql(layouts) }
881
+ end
882
+
883
+ context "returns and empty array if the server is nil" do
884
+ let(:room) { FactoryGirl.build(:bigbluebutton_room, server: nil) }
885
+ it { room.available_layouts_for_select.should eql([]) }
886
+ end
887
+ end
888
+
889
+ context "#generate_dial_number!" do
890
+ let(:room) { FactoryGirl.create(:bigbluebutton_room) }
891
+
892
+ context "generates the dial number and saves in the room" do
893
+ before {
894
+ BigbluebuttonRails::DialNumber.stub(:randomize).and_return("(99) 1234-5678")
895
+ }
896
+ it { room.generate_dial_number!.should be(true) }
897
+ it {
898
+ room.generate_dial_number!
899
+ room.reload.dial_number.should eql("(99) 1234-5678")
900
+ }
901
+ end
902
+
903
+ context "uses the pattern informed" do
904
+ before {
905
+ BigbluebuttonRails::DialNumber.should_receive(:randomize).with("(99) 12xx-xxxx")
906
+ }
907
+ it { room.generate_dial_number!("(99) 12xx-xxxx").should be(true) }
908
+ end
909
+
910
+ # tries several times
911
+
912
+ context "tries to generate a unique number multiple times" do
913
+ let!(:another_room) { FactoryGirl.create(:bigbluebutton_room, dial_number: "(99) 1234-5678") }
914
+ before {
915
+ expect(BigbluebuttonRails::DialNumber).to receive(:randomize).exactly(19).times.and_return("(99) 1234-5678")
916
+ expect(BigbluebuttonRails::DialNumber).to receive(:randomize).and_return("(99) 1234-5679") # unique
917
+ }
918
+ it { room.generate_dial_number!.should be(true) }
919
+ it {
920
+ room.generate_dial_number!
921
+ room.reload.dial_number.should eql("(99) 1234-5679")
922
+ }
923
+ end
924
+
925
+ context "returns nil if can't generate a unique number" do
926
+ before { @previous_dn = room.dial_number }
927
+ let!(:another_room) { FactoryGirl.create(:bigbluebutton_room, dial_number: "(99) 1234-5678") }
928
+ before {
929
+ expect(BigbluebuttonRails::DialNumber).to receive(:randomize).exactly(20).times.and_return("(99) 1234-5678")
930
+ }
931
+ it { room.generate_dial_number!.should be_nil }
932
+ it {
933
+ room.generate_dial_number!
934
+ room.reload.dial_number.should eql(@previous_dn)
935
+ }
936
+ end
937
+ end
938
+
939
+ context "validates keys" do
686
940
  context "for private rooms" do
687
941
  let(:room) { FactoryGirl.create(:bigbluebutton_room, :private => true) }
688
- it { room.should_not allow_value('').for(:moderator_password) }
689
- it { room.should_not allow_value('').for(:attendee_password) }
942
+ it { room.should_not allow_value('').for(:moderator_key) }
943
+ it { room.should_not allow_value('').for(:attendee_key) }
690
944
  end
691
945
 
692
946
  context "for public rooms" do
693
947
  let(:room) { FactoryGirl.create(:bigbluebutton_room, :private => false) }
694
- it { room.should allow_value('').for(:moderator_password) }
695
- it { room.should allow_value('').for(:attendee_password) }
948
+ it { room.should allow_value('').for(:moderator_key) }
949
+ it { room.should allow_value('').for(:attendee_key) }
696
950
  end
697
951
  end
698
952
 
@@ -740,16 +994,17 @@ describe BigbluebuttonRoom do
740
994
  room.should_receive(:is_running?).and_return(true)
741
995
  }
742
996
  subject { room.create_meeting(user) }
743
- it { should be_false }
997
+ it { should be(false) }
744
998
  end
745
999
 
746
1000
  context "when the conference is not running" do
747
1001
  before {
748
1002
  room.should_receive(:is_running?).and_return(false)
749
1003
  room.should_receive(:send_create).with(user, {})
1004
+ room.should_receive(:send_end)
750
1005
  }
751
1006
  subject { room.create_meeting(user) }
752
- it { should be_true }
1007
+ it { should be(true) }
753
1008
  end
754
1009
 
755
1010
  context "when the parameter 'request' is informed" do
@@ -760,23 +1015,24 @@ describe BigbluebuttonRoom do
760
1015
  room.should_receive(:add_domain_to_logout_url).with("HTTP://", "test.com:80")
761
1016
  room.should_receive(:is_running?).and_return(false)
762
1017
  room.should_receive(:send_create)
1018
+ room.should_receive(:send_end)
763
1019
  }
764
1020
  subject { room.create_meeting(user, request) }
765
- it { should be_true }
1021
+ it { should be(true) }
766
1022
  end
767
1023
 
768
- # context "when the parameter 'request' is informed" do
769
- # let(:request) { double(ActionDispatch::Request) }
770
- # before {
771
- # request.stub(:protocol).and_return("HTTP://")
772
- # request.stub(:host_with_port).and_return("test.com:80")
773
- # room.should_receive(:add_domain_to_logout_url).with("HTTP://", "test.com:80")
774
- # room.should_receive(:is_running?).and_return(false)
775
- # room.should_receive(:send_create)
776
- # }
777
- # subject { room.create_meeting(user.name, user.id, request) }
778
- # it { should be_true }
779
- # end
1024
+ context "ignores exceptions raised by send_end (for when there's no meeting created)" do
1025
+ before {
1026
+ room.should_receive(:is_running?).and_return(false)
1027
+ room.should_receive(:send_create).with(user, {})
1028
+ room.should_receive(:send_end) { raise BigBlueButton::BigBlueButtonException.new('test') }
1029
+ }
1030
+ it {
1031
+ expect {
1032
+ room.create_meeting(user)
1033
+ }.not_to raise_error
1034
+ }
1035
+ end
780
1036
  end
781
1037
 
782
1038
  describe "#full_logout_url" do
@@ -787,30 +1043,77 @@ describe BigbluebuttonRoom do
787
1043
 
788
1044
  describe "#require_server" do
789
1045
  let(:room) { FactoryGirl.create(:bigbluebutton_room) }
790
- it { should respond_to(:require_server) }
1046
+ it { room.respond_to?(:require_server, true).should be(true) }
791
1047
 
792
- context "throws exception when the room has no server associated" do
793
- before { room.server = nil }
794
- it {
795
- expect {
796
- room.send(:require_server)
797
- }.to raise_error(BigbluebuttonRails::ServerRequired)
1048
+ context "if the room has no server associated" do
1049
+ let(:server) { FactoryGirl.create(:bigbluebutton_server) }
1050
+ before {
1051
+ room.server = nil
798
1052
  }
1053
+
1054
+ context "assigns server to room if there is one" do
1055
+ before {
1056
+ room.send(:require_server)
1057
+ }
1058
+ it { room.reload.server.should_not be_nil }
1059
+ end
1060
+
1061
+ context "raises exception if there are no servers to assign" do
1062
+ before {
1063
+ room.should_receive(:select_server).and_return(nil)
1064
+ }
1065
+ it {
1066
+ expect {
1067
+ room.send(:require_server)
1068
+ }.to raise_error(BigbluebuttonRails::ServerRequired)
1069
+ }
1070
+ end
1071
+
1072
+ context "doesn't save the room if no server is selected" do
1073
+ before {
1074
+ @updated_at = room.updated_at
1075
+ room.should_receive(:select_server).and_return(nil)
1076
+ expect {
1077
+ room.send(:require_server)
1078
+ }.to raise_error(BigbluebuttonRails::ServerRequired)
1079
+ }
1080
+ it { room.updated_at.should eql(@updated_at) }
1081
+ end
1082
+
1083
+ context "doesn't save the room if it's a new record" do
1084
+ let(:room) { FactoryGirl.build(:bigbluebutton_room) }
1085
+ before {
1086
+ room.should_receive(:select_server).and_return(server)
1087
+ room.send(:require_server)
1088
+ }
1089
+ it { room.new_record?.should be(true) }
1090
+ it { room.server.should eql(server) }
1091
+ end
1092
+
1093
+ context "passes the api_method parameter to #select_server" do
1094
+ let(:method) { :my_api_method }
1095
+ before {
1096
+ room.should_receive(:select_server).with(method).and_return(server)
1097
+ }
1098
+ it { room.send(:require_server, method) }
1099
+ end
799
1100
  end
800
1101
 
801
1102
  context "does nothing if the room has a server associated" do
802
- before { room.server = FactoryGirl.create(:bigbluebutton_server) }
803
- it {
1103
+ let(:server) { FactoryGirl.create(:bigbluebutton_server) }
1104
+ before {
1105
+ room.server = server
804
1106
  expect {
805
1107
  room.send(:require_server)
806
- }.not_to raise_error()
1108
+ }.not_to raise_error
807
1109
  }
1110
+ it { room.server.should eql(server) }
808
1111
  end
809
1112
  end
810
1113
 
811
1114
  describe "#select_server" do
812
1115
  let(:room) { FactoryGirl.create(:bigbluebutton_room, :server => nil) }
813
- it { should respond_to(:select_server) }
1116
+ it { room.respond_to?(:select_server, true).should be(true) }
814
1117
 
815
1118
  context "selects the server with less rooms" do
816
1119
  before {
@@ -824,7 +1127,15 @@ describe BigbluebuttonRoom do
824
1127
  end
825
1128
 
826
1129
  context "returns nil of there are no servers" do
827
- before(:each) { BigbluebuttonServer.destroy_all }
1130
+ before { BigbluebuttonServer.destroy_all }
1131
+ it { room.send(:select_server).should == nil }
1132
+ end
1133
+
1134
+ context "returns nil if the room already has a server" do
1135
+ before {
1136
+ 2.times{ FactoryGirl.create(:bigbluebutton_server) }
1137
+ room.update_attributes(server: FactoryGirl.create(:bigbluebutton_server))
1138
+ }
828
1139
  it { room.send(:select_server).should == nil }
829
1140
  end
830
1141
  end
@@ -881,7 +1192,7 @@ describe BigbluebuttonRoom do
881
1192
  before {
882
1193
  room.start_time = Time.now.utc
883
1194
  room.running = !room.running # to change its default value
884
- room.record = !room.record # to change its default value
1195
+ room.record_meeting = !room.record_meeting # to change its default value
885
1196
  }
886
1197
 
887
1198
  context "if there's no meeting associated yet creates one" do
@@ -897,7 +1208,7 @@ describe BigbluebuttonRoom do
897
1208
  it("sets room") { subject.room.should eq(room) }
898
1209
  it("sets meetingid") { subject.meetingid.should eq(room.meetingid) }
899
1210
  it("sets name") { subject.name.should eq(room.name) }
900
- it("sets record") { subject.record.should eq(room.record) }
1211
+ it("sets recorded") { subject.recorded.should eq(room.record_meeting) }
901
1212
  it("sets running") { subject.running.should eq(room.running) }
902
1213
  it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
903
1214
  it("doesn't set creator_id") { subject.creator_id.should be_nil }
@@ -943,7 +1254,7 @@ describe BigbluebuttonRoom do
943
1254
  it("sets room") { subject.room.should eq(room) }
944
1255
  it("sets meetingid") { subject.meetingid.should eq(room.meetingid) }
945
1256
  it("sets name") { subject.name.should eq(room.name) }
946
- it("sets record") { subject.record.should eq(room.record) }
1257
+ it("sets recorded") { subject.recorded.should eq(room.record_meeting) }
947
1258
  it("sets running") { subject.running.should eq(room.running) }
948
1259
  it("sets start_time") { subject.start_time.utc.to_i.should eq(room.start_time.utc.to_i) }
949
1260
  it("doesn't set creator_id") { subject.creator_id.should be_nil }
@@ -968,7 +1279,27 @@ describe BigbluebuttonRoom do
968
1279
  end
969
1280
 
970
1281
  describe "#finish_meetings" do
971
- it "finishes all meetings related to this room that are still running"
1282
+ let!(:room) { FactoryGirl.create(:bigbluebutton_room) }
1283
+
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) }
1287
+ before(:each) { room.finish_meetings }
1288
+ it { meeting1.reload.running.should be(false) }
1289
+ it { meeting2.reload.running.should be(false) }
1290
+ end
1291
+
1292
+ context "works if the room has no meetings" do
1293
+ it { room.finish_meetings }
1294
+ end
1295
+
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) }
1302
+ end
972
1303
  end
973
1304
 
974
1305
  describe "#internal_create_meeting" do
@@ -979,6 +1310,61 @@ describe BigbluebuttonRoom do
979
1310
  it "calls api.create_meeting"
980
1311
  it "accepts additional user options to override the options in the database"
981
1312
 
1313
+ context "adds the invitation URL, if any" do
1314
+ before { mock_server_and_api }
1315
+ let(:room) { FactoryGirl.create(:bigbluebutton_room) }
1316
+
1317
+ before {
1318
+ mocked_api.stub(:"request_headers=")
1319
+ room.server = mocked_server
1320
+ }
1321
+
1322
+ it { room.should_not respond_to(:invitation_url) }
1323
+
1324
+ context "doesn't add the invitation URL by default" do
1325
+ before {
1326
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1327
+ opts.should_not have_key('meta_invitation-url')
1328
+ opts.should_not have_key(:'meta_invitation-url')
1329
+ end
1330
+ }
1331
+ it { room.send(:internal_create_meeting) }
1332
+ end
1333
+
1334
+ context "doesn't add the invitation URL if BigbluebuttonRoom#invitation_url returns nil" do
1335
+ before {
1336
+ BigbluebuttonRoom.class_eval do
1337
+ def invitation_url
1338
+ nil
1339
+ end
1340
+ end
1341
+
1342
+ room.should respond_to(:invitation_url)
1343
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1344
+ opts.should_not have_key('meta_invitation-url')
1345
+ opts.should_not have_key(:'meta_invitation-url')
1346
+ end
1347
+ }
1348
+ it { room.send(:internal_create_meeting) }
1349
+ end
1350
+
1351
+ context "adds the value returned by BigbluebuttonRoom#invitation_url" do
1352
+ before {
1353
+ BigbluebuttonRoom.class_eval do
1354
+ def invitation_url
1355
+ 'http://my-invitation.url'
1356
+ end
1357
+ end
1358
+
1359
+ room.should respond_to(:invitation_url)
1360
+ mocked_api.should_receive(:create_meeting) do |name, meetingid, opts|
1361
+ opts.should include('meta_invitation-url' => 'http://my-invitation.url')
1362
+ end
1363
+ }
1364
+ it { room.send(:internal_create_meeting) }
1365
+ end
1366
+ end
1367
+
982
1368
  context "schedules a BigbluebuttonMeetingUpdater" do
983
1369
  before { mock_server_and_api }
984
1370
  let(:room) { FactoryGirl.create(:bigbluebutton_room) }
@@ -999,20 +1385,21 @@ describe BigbluebuttonRoom do
999
1385
  it("the job should have the correct parameters") { subject['args'].should eq([room.id]) }
1000
1386
  end
1001
1387
  end
1002
-
1003
1388
  end
1004
1389
 
1005
1390
  def get_create_params(room, user=nil)
1006
1391
  params = {
1007
- :moderatorPW => room.moderator_password,
1008
- :attendeePW => room.attendee_password,
1392
+ :record => room.record_meeting,
1393
+ :duration => room.duration,
1394
+ :moderatorPW => room.moderator_api_password,
1395
+ :attendeePW => room.attendee_api_password,
1009
1396
  :welcome => room.welcome_msg,
1010
1397
  :dialNumber => room.dial_number,
1011
1398
  :logoutURL => room.logout_url,
1012
1399
  :maxParticipants => room.max_participants,
1013
- :voiceBridge => room.voice_bridge,
1014
- :record => room.record,
1015
- :duration => room.duration
1400
+ :moderatorOnlyMessage => room.moderator_only_message,
1401
+ :autoStartRecording => room.auto_start_recording,
1402
+ :allowStartStopRecording => room.allow_start_stop_recording
1016
1403
  }
1017
1404
  room.metadata.each { |meta| params["meta_#{meta.name}"] = meta.content }
1018
1405
  unless user.nil?