bigbluebutton_rails 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +1 -1
  2. data/CHANGELOG.rdoc +8 -0
  3. data/Gemfile +13 -7
  4. data/Gemfile.lock +112 -86
  5. data/README.rdoc +26 -80
  6. data/Rakefile +2 -1
  7. data/TODO_08 +13 -0
  8. data/app/controllers/bigbluebutton/rooms_controller.rb +9 -9
  9. data/app/controllers/bigbluebutton/servers_controller.rb +1 -1
  10. data/app/models/bigbluebutton_room.rb +16 -14
  11. data/app/models/bigbluebutton_server.rb +1 -1
  12. data/app/views/bigbluebutton/rooms/_form.html.erb +1 -1
  13. data/app/views/bigbluebutton/rooms/external.html.erb +3 -3
  14. data/app/views/bigbluebutton/rooms/invite.html.erb +3 -3
  15. data/app/views/bigbluebutton/servers/_form.html.erb +1 -1
  16. data/bigbluebutton_rails.gemspec +2 -2
  17. data/lib/bigbluebutton_rails/version.rb +1 -1
  18. data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +42 -37
  19. data/spec/factories/bigbluebutton_room.rb +3 -1
  20. data/spec/models/bigbluebutton_room_db_spec.rb +34 -0
  21. data/spec/models/bigbluebutton_room_spec.rb +452 -457
  22. data/spec/models/bigbluebutton_server_db_spec.rb +14 -0
  23. data/spec/models/bigbluebutton_server_spec.rb +162 -176
  24. data/spec/rails_app/.gitignore +2 -1
  25. data/spec/rails_app/db/seeds.rb +16 -4
  26. data/spec/rails_app/features/activity_monitor_servers.feature +53 -0
  27. data/spec/rails_app/features/config.yml.example +13 -0
  28. data/spec/rails_app/features/create_rooms.feature +17 -0
  29. data/spec/rails_app/features/create_servers.feature +17 -0
  30. data/spec/rails_app/features/destroy_rooms.feature +12 -0
  31. data/spec/rails_app/features/destroy_servers.feature +11 -0
  32. data/spec/rails_app/features/edit_rooms.feature +26 -0
  33. data/spec/rails_app/features/edit_servers.feature +24 -0
  34. data/spec/rails_app/features/join_external_rooms.feature +61 -0
  35. data/spec/rails_app/features/join_mobile.feature +10 -0
  36. data/spec/rails_app/features/join_rooms.feature +117 -0
  37. data/spec/rails_app/features/list_and_show_rooms.feature +18 -0
  38. data/spec/rails_app/features/list_and_show_servers.feature +16 -0
  39. data/spec/rails_app/features/step_definitions/activity_monitor_servers_step.rb +102 -0
  40. data/spec/rails_app/features/step_definitions/common_steps.rb +99 -3
  41. data/spec/rails_app/features/step_definitions/create_rooms_steps.rb +38 -0
  42. data/spec/rails_app/features/step_definitions/{bigbluebutton_server_steps.rb → create_servers_steps.rb} +11 -6
  43. data/spec/rails_app/features/step_definitions/destroy_rooms_steps.rb +17 -0
  44. data/spec/rails_app/features/step_definitions/destroy_servers_steps.rb +15 -0
  45. data/spec/rails_app/features/step_definitions/edit_rooms_steps.rb +15 -0
  46. data/spec/rails_app/features/step_definitions/edit_servers_steps.rb +15 -0
  47. data/spec/rails_app/features/step_definitions/join_mobile_steps.rb +5 -0
  48. data/spec/rails_app/features/step_definitions/join_rooms_steps.rb +49 -0
  49. data/spec/rails_app/features/step_definitions/list_and_show_rooms_steps.rb +11 -0
  50. data/spec/rails_app/features/step_definitions/list_and_show_servers_steps.rb +11 -0
  51. data/spec/rails_app/features/support/configurations.rb +34 -0
  52. data/spec/rails_app/features/support/content.rb +27 -7
  53. data/spec/rails_app/features/support/env_custom.rb +21 -0
  54. data/spec/rails_app/features/support/factories/bigbluebutton_server_integration.rb +5 -0
  55. data/spec/rails_app/features/support/hooks.rb +14 -0
  56. data/spec/rails_app/features/support/locales.rb +18 -0
  57. data/spec/rails_app/features/support/paths.rb +25 -10
  58. data/spec/rails_app/features/support/selectors.rb +26 -0
  59. data/spec/rails_app/features/support/templates.rb +241 -0
  60. metadata +43 -20
  61. data/spec/factories/integration/bigbluebutton_server_integration.rb +0 -8
  62. data/spec/integration_conf.yml.example +0 -5
  63. data/spec/rails_app/features/join_external_bigbluebutton_rooms.feature +0 -19
  64. data/spec/rails_app/features/manage_bigbluebutton_rooms.feature +0 -9
  65. data/spec/rails_app/features/manage_bigbluebutton_servers.feature +0 -9
  66. data/spec/rails_app/features/step_definitions/bigbluebutton_room_steps.rb +0 -64
  67. data/spec/rails_app/features/support/env_gem.rb +0 -10
  68. data/spec/rails_app/features/support/forms.rb +0 -12
  69. data/spec/support/integration/integration_conf.rb +0 -16
data/Rakefile CHANGED
@@ -56,8 +56,9 @@ end
56
56
  task :cucumber do
57
57
  if File.exists? "features/"
58
58
  puts "* Gem features"
59
- sh %{ cucumber features/ }
59
+ sh "cucumber features/"
60
60
  end
61
+
61
62
  puts "* Dummy app features"
62
63
  cd File.join(File.dirname(__FILE__), "spec", "rails_app")
63
64
  sh "cucumber features/"
data/TODO_08 ADDED
@@ -0,0 +1,13 @@
1
+ TODO for BigBlueButton 0.8:
2
+
3
+ See:
4
+ * http://code.google.com/p/bigbluebutton/wiki/API#Version_0.8
5
+ * http://groups.google.com/group/bigbluebutton-dev/browse_thread/thread/c214cbe9bdb2268a?pli=1
6
+
7
+ TODO:
8
+ * Support for recordings
9
+ * Keep track of older meetings?
10
+ * Pre-upload of slides
11
+ * New arguments in some methods (e.g. userID, record, duration, meta_*)
12
+ * New return values (e.g createTime).
13
+ * We don't need to randomize the meeting_id anymore (to confirm)
@@ -165,7 +165,7 @@ class Bigbluebutton::RoomsController < ApplicationController
165
165
  role = @room.user_role(params[:user])
166
166
  end
167
167
 
168
- unless role.nil? or name.nil?
168
+ unless role.nil? or name.nil? or name.empty?
169
169
  join_internal(name, role, :invite)
170
170
  else
171
171
  flash[:error] = t('bigbluebutton_rails.rooms.errors.auth.failure')
@@ -185,11 +185,11 @@ class Bigbluebutton::RoomsController < ApplicationController
185
185
  # Authenticates an user using name and password passed in the params from #external
186
186
  # Uses params[:meeting] to get the meetingID of the target room
187
187
  def external_auth
188
- @room = nil
189
188
  if !params[:meeting].blank? && !params[:user].blank?
190
189
  @server.fetch_meetings
191
190
  @room = @server.meetings.select{ |r| r.meetingid == params[:meeting] }.first
192
191
  else
192
+ @room = nil
193
193
  message = t('bigbluebutton_rails.rooms.errors.auth.wrong_params')
194
194
  redirect_to request.referer, :notice => message
195
195
  return
@@ -202,11 +202,11 @@ class Bigbluebutton::RoomsController < ApplicationController
202
202
  name = bigbluebutton_user.nil? ? params[:user][:name] : bigbluebutton_user.name
203
203
  role = @room.user_role(params[:user])
204
204
 
205
- unless role.nil? or name.nil?
206
- @room.fetch_meeting_info
207
- if @room.is_running?
208
- join_url = @room.join_url(name, role)
209
- redirect_to(join_url)
205
+ # FIXME: use internal_join ?
206
+ unless role.nil? or name.nil? or name.empty?
207
+ url = @room.perform_join(name, role, request)
208
+ unless url.nil?
209
+ redirect_to(url)
210
210
  else
211
211
  flash[:error] = t('bigbluebutton_rails.rooms.errors.auth.not_running')
212
212
  render :external
@@ -264,13 +264,13 @@ class Bigbluebutton::RoomsController < ApplicationController
264
264
  end
265
265
 
266
266
  def join_mobile
267
- @join_url = join_bigbluebutton_server_room_path(@server, @room, :mobile => '1')
267
+ @join_url = join_bigbluebutton_server_room_url(@server, @room, :mobile => '1')
268
268
  @join_url.gsub!(/http:\/\//i, "bigbluebutton://")
269
269
 
270
270
  # TODO: we can't use the mconf url because the mobile client scanning the qrcode is not
271
271
  # logged. so we are using the full BBB url for now.
272
272
  @qrcode_url = @room.join_url(bigbluebutton_user.name, bigbluebutton_role(@room))
273
- @qrcode_url.gsub!("http://", "bigbluebutton://")
273
+ @qrcode_url.gsub!(/http:\/\//i, "bigbluebutton://")
274
274
  end
275
275
 
276
276
  protected
@@ -34,7 +34,7 @@ class Bigbluebutton::ServersController < ApplicationController
34
34
 
35
35
  # update_list works only for html
36
36
  if params[:update_list] && (params[:format].nil? || params[:format].to_s == "html")
37
- render :html => 'activity_list', :server => @server
37
+ render :partial => 'activity_list', :locals => { :server => @server }
38
38
  return
39
39
  end
40
40
 
@@ -1,5 +1,3 @@
1
- require 'active_support/secure_random'
2
-
3
1
  class BigbluebuttonRoom < ActiveRecord::Base
4
2
  belongs_to :server, :class_name => 'BigbluebuttonServer'
5
3
  belongs_to :owner, :polymorphic => true
@@ -41,6 +39,9 @@ class BigbluebuttonRoom < ActiveRecord::Base
41
39
  after_initialize :init
42
40
  before_validation :set_param
43
41
 
42
+ # the full logout_url used when logout_url is a relative path
43
+ attr_accessor :full_logout_url
44
+
44
45
  # Convenience method to access the attribute <tt>running</tt>
45
46
  def is_running?
46
47
  @running
@@ -201,10 +202,9 @@ class BigbluebuttonRoom < ActiveRecord::Base
201
202
  def perform_join(username, role, request=nil)
202
203
  fetch_is_running?
203
204
 
204
- # if the current user is a moderator, create the room (if needed)
205
- # and join it
205
+ # if the user is a moderator, create the room (if needed) and join it
206
206
  if role == :moderator
207
- add_domain_to_logout_url(request.protocol, request.host) unless request.nil?
207
+ add_domain_to_logout_url(request.protocol, request.host_with_port) unless request.nil?
208
208
  send_create unless is_running?
209
209
  ret = join_url(username, role)
210
210
 
@@ -218,6 +218,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
218
218
  end
219
219
 
220
220
  # add a domain name and/or protocol to the logout_url if needed
221
+ # it doesn't save in the db, just updates the instance
221
222
  def add_domain_to_logout_url(protocol, host)
222
223
  unless logout_url.nil?
223
224
  url = logout_url.downcase
@@ -227,7 +228,7 @@ class BigbluebuttonRoom < ActiveRecord::Base
227
228
  end
228
229
  url = protocol + url
229
230
  end
230
- update_attributes(:logout_url => url.downcase)
231
+ self.full_logout_url = url.downcase
231
232
  end
232
233
  end
233
234
 
@@ -248,29 +249,30 @@ class BigbluebuttonRoom < ActiveRecord::Base
248
249
  end
249
250
 
250
251
  def random_meetingid
251
- #ActiveSupport::SecureRandom.hex(16)
252
252
  # TODO temporarily using the name to get a friendlier meetingid
253
253
  if self[:name].blank?
254
- ActiveSupport::SecureRandom.hex(8)
254
+ SecureRandom.hex(8)
255
255
  else
256
- self[:name] + '-' + ActiveSupport::SecureRandom.random_number(9999).to_s
256
+ self[:name] + '-' + SecureRandom.random_number(9999).to_s
257
257
  end
258
258
  end
259
259
 
260
260
  def random_voice_bridge
261
- value = (70000 + ActiveSupport::SecureRandom.random_number(9999)).to_s
261
+ value = (70000 + SecureRandom.random_number(9999)).to_s
262
262
  count = 1
263
263
  while not BigbluebuttonRoom.find_by_voice_bridge(value).nil? and count < 10
264
264
  count += 1
265
- value = (70000 + ActiveSupport::SecureRandom.random_number(9999)).to_s
265
+ value = (70000 + SecureRandom.random_number(9999)).to_s
266
266
  end
267
267
  value
268
268
  end
269
269
 
270
270
  def do_create_meeting
271
- self.server.api.create_meeting(self.name, self.meetingid, self.moderator_password,
272
- self.attendee_password, self.welcome_msg, self.dial_number,
273
- self.logout_url, self.max_participants, self.voice_bridge)
271
+ opts = { :moderatorPW => self.moderator_password, :attendeePW => self.attendee_password,
272
+ :welcome => self.welcome_msg, :dialNumber => self.dial_number,
273
+ :logoutURL => self.full_logout_url || self.logout_url,
274
+ :maxParticipants => self.max_participants, :voiceBridge => self.voice_bridge }
275
+ self.server.api.create_meeting(self.name, self.meetingid, opts)
274
276
  end
275
277
 
276
278
  # if :param wasn't set, sets it as :name downcase and parameterized
@@ -31,7 +31,7 @@ class BigbluebuttonServer < ActiveRecord::Base
31
31
 
32
32
  validates :version,
33
33
  :presence => true,
34
- :inclusion => { :in => ['0.64', '0.7'] }
34
+ :inclusion => { :in => ['0.7', '0.8'] }
35
35
 
36
36
  attr_accessible :name, :url, :version, :salt, :param
37
37
 
@@ -7,7 +7,7 @@
7
7
  <%= form_for [@server, @room], :url => url do |f| %>
8
8
  <% if @room.errors.any? %>
9
9
  <div id="error_explanation">
10
- <h2><%= pluralize(@room.errors.count, "error") %> prohibited this bigbluebutton_room from being saved:</h2>
10
+ <h2><%= pluralize(@room.errors.count, "error") %>:</h2>
11
11
  <ul>
12
12
  <% @room.errors.full_messages.each do |msg| %>
13
13
  <li><%= msg %></li>
@@ -1,6 +1,6 @@
1
1
  <h1>Join the meeting <%= @room.name %></h1>
2
2
 
3
- <p id="error"><%= flash[:error] %></p>
3
+ <div id="error_explanation"><%= flash[:error] %></div>
4
4
 
5
5
  <p>This meeting was created from another application.<br/>You must provide a name and a password to join:</p>
6
6
 
@@ -8,7 +8,7 @@
8
8
  <%= hidden_field_tag "meeting", params[:meeting] %>
9
9
 
10
10
  <div class="field">
11
- Name:<br />
11
+ <label for="user_name">Name:</label><br />
12
12
  <% if bigbluebutton_user.nil? %>
13
13
  <%= text_field_tag "user[name]", "" %>
14
14
  <% else %>
@@ -16,7 +16,7 @@
16
16
  <% end %>
17
17
  </div>
18
18
  <div class="field">
19
- Password:<br />
19
+ <label for="user_password">Password:</label><br />
20
20
  <%= password_field_tag "user[password]", "" %>
21
21
  </div>
22
22
 
@@ -28,7 +28,7 @@ $(document).ready(function(){
28
28
 
29
29
  <h1>Invite to the meeting <%= @room.name %></h1>
30
30
 
31
- <p id="error"><%= flash[:error] %></p>
31
+ <div id="error_explanation"><%= flash[:error] %></div>
32
32
 
33
33
  <p>Meeting status: <span id="meeting_status">-</span> (<a href="javascript:ajax_request();">refresh</a>)</p>
34
34
  <p><%= @room.name %> requires a name and/or password to join:</p>
@@ -36,7 +36,7 @@ $(document).ready(function(){
36
36
  <%= form_tag join_bigbluebutton_server_room_path(@server, @room) do %>
37
37
 
38
38
  <div class="field">
39
- Name:<br />
39
+ <label for="user_name">Name:</label><br />
40
40
  <% if bigbluebutton_user.nil? %>
41
41
  <%= text_field_tag "user[name]", "" %>
42
42
  <% else %>
@@ -44,7 +44,7 @@ $(document).ready(function(){
44
44
  <% end %>
45
45
  </div>
46
46
  <div class="field">
47
- Password:<br />
47
+ <label for="user_password">Password:</label><br />
48
48
  <% if @room.private %>
49
49
  <%= password_field_tag "user[password]", "" %>
50
50
  <% else %>
@@ -1,7 +1,7 @@
1
1
  <%= form_for(@server) do |f| %>
2
2
  <% if @server.errors.any? %>
3
3
  <div id="error_explanation">
4
- <h2><%= pluralize(@server.errors.count, "error") %> prohibited this bigbluebutton_server from being saved:</h2>
4
+ <h2><%= pluralize(@server.errors.count, "error") %>:</h2>
5
5
  <ul>
6
6
  <% @server.errors.full_messages.each do |msg| %>
7
7
  <li><%= msg %></li>
@@ -15,6 +15,6 @@ Gem::Specification.new do |s|
15
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
16
  s.require_paths = ["lib"]
17
17
 
18
- s.add_dependency("rails", ">= 3.0.3")
19
- s.add_dependency("bigbluebutton-api-ruby", "~> 0.0.11")
18
+ s.add_dependency("rails", ">= 3.0.0")
19
+ s.add_dependency("bigbluebutton-api-ruby", "~> 0.1.0")
20
20
  end
@@ -1,3 +1,3 @@
1
1
  module BigbluebuttonRails
2
- VERSION = "0.0.6".freeze
2
+ VERSION = "0.1.0".freeze
3
3
  end
@@ -49,7 +49,7 @@ describe Bigbluebutton::RoomsController do
49
49
  mock_server_and_api
50
50
  controller.stub(:bigbluebutton_user) { user }
51
51
  controller.should_receive(:bigbluebutton_role).and_return(:moderator)
52
- controller.should_receive(:join_bigbluebutton_server_room_path).
52
+ controller.should_receive(:join_bigbluebutton_server_room_url).
53
53
  with(mocked_server, room, :mobile => '1').
54
54
  and_return("http://test.com/join/url?mobile=1")
55
55
  mocked_api.should_receive(:join_meeting_url).
@@ -482,6 +482,14 @@ describe Bigbluebutton::RoomsController do
482
482
  it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.errors.auth.failure')) }
483
483
  end
484
484
 
485
+ context "when name is set but empty" do
486
+ let(:user_hash) { { :password => room.moderator_password, :name => "" } }
487
+ it { should respond_with(:unauthorized) }
488
+ it { should assign_to(:room).with(room) }
489
+ it { should render_template(:invite) }
490
+ it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.errors.auth.failure')) }
491
+ end
492
+
485
493
  context "when the password is wrong" do
486
494
  let(:user_hash) { { :name => "Elftor", :password => nil } }
487
495
  it { should respond_with(:unauthorized) }
@@ -534,8 +542,7 @@ describe Bigbluebutton::RoomsController do
534
542
  end # #external
535
543
 
536
544
  describe "#external_auth" do
537
- let(:user) { Factory.build(:user) }
538
- let(:user_hash) { { :name => "Elftor", :password => new_room.attendee_password } }
545
+ let(:user_hash) { { :name => "Any Name", :password => new_room.attendee_password } }
539
546
  let(:meetingid) { "my-meeting-id" }
540
547
  let(:new_room) { BigbluebuttonRoom.new(:meetingid => meetingid,
541
548
  :attendee_password => Forgery(:basic).password,
@@ -554,7 +561,7 @@ describe Bigbluebutton::RoomsController do
554
561
  before { # TODO: this block is being repeated several times, put it in a method or something
555
562
  mocked_server.should_receive(:fetch_meetings)
556
563
  mocked_server.should_receive(:meetings).and_return(meetings)
557
- new_room.should_receive(:fetch_meeting_info)
564
+ new_room.should_receive(:perform_join)
558
565
  }
559
566
  before(:each) { post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash }
560
567
  it { should assign_to(:room).with(new_room) }
@@ -592,11 +599,6 @@ describe Bigbluebutton::RoomsController do
592
599
  }.should raise_error(BigbluebuttonRails::RoomAccessDenied)
593
600
  end
594
601
 
595
- it "fetches meeting info" do
596
- new_room.should_receive(:fetch_meeting_info)
597
- post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash
598
- end
599
-
600
602
  context "validates user input and shows error" do
601
603
  before(:each) { post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash }
602
604
 
@@ -608,6 +610,14 @@ describe Bigbluebutton::RoomsController do
608
610
  it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.errors.auth.failure')) }
609
611
  end
610
612
 
613
+ context "when name is empty not set" do
614
+ let(:user_hash) { { :password => room.moderator_password, :name => "" } }
615
+ it { should respond_with(:unauthorized) }
616
+ it { should assign_to(:room).with(new_room) }
617
+ it { should render_template(:external) }
618
+ it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.errors.auth.failure')) }
619
+ end
620
+
611
621
  context "when the password is wrong" do
612
622
  let(:user_hash) { { :name => "Elftor", :password => nil } }
613
623
  it { should respond_with(:unauthorized) }
@@ -617,39 +627,34 @@ describe Bigbluebutton::RoomsController do
617
627
  end
618
628
  end
619
629
 
620
- context "and the meeting is running" do
621
- before {
622
- new_room.should_receive(:fetch_meeting_info)
623
- new_room.running = true
624
- }
625
-
626
- it "if there's a user logged, should use his name" do
627
- controller.stub(:bigbluebutton_user).and_return(user)
628
- mocked_api.should_receive(:join_meeting_url).
629
- with(new_room.meetingid, user.name, new_room.attendee_password). # here's the validation
630
- and_return("http://test.com/attendee/join")
631
- post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash
630
+ context "calls room#perform_join" do
631
+ context "and redirects to the url received" do
632
+ before {
633
+ new_room.should_receive(:perform_join).with(anything, :attendee, request).
634
+ and_return("http://test.com/attendee/join")
635
+ }
636
+ before(:each) { post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash }
637
+ it { should respond_with(:redirect) }
638
+ it { should redirect_to("http://test.com/attendee/join") }
632
639
  end
633
640
 
634
- it "redirects to the correct join_url" do
635
- controller.stub(:bigbluebutton_user).and_return(user)
636
- mocked_api.should_receive(:join_meeting_url).
637
- and_return("http://test.com/attendee/join")
638
- post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash
639
- should respond_with(:redirect)
640
- should redirect_to("http://test.com/attendee/join")
641
+ context "and shows error if it returns nil" do
642
+ before {
643
+ new_room.should_receive(:perform_join).with(user_hash[:name], :attendee, request).and_return(nil)
644
+ }
645
+ before(:each) { post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash }
646
+ it { should respond_with(:success) }
647
+ it { should render_template(:external) }
648
+ it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.errors.auth.not_running')) }
641
649
  end
642
650
  end
643
651
 
644
- context "and the meeting is not running" do
645
- before {
646
- new_room.should_receive(:fetch_meeting_info)
647
- new_room.running = false
648
- }
649
- before(:each) { post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash }
650
- it { should respond_with(:success) }
651
- it { should render_template(:external) }
652
- it { should set_the_flash.to(I18n.t('bigbluebutton_rails.rooms.errors.auth.not_running')) }
652
+ it "if there's a user logged, should use his name" do
653
+ user = Factory.build(:user)
654
+ controller.stub(:bigbluebutton_user).and_return(user)
655
+ new_room.should_receive(:perform_join).with(user.name, anything, anything). # here's the validation
656
+ and_return("http://test.com/attendee/join")
657
+ post :external_auth, :server_id => mocked_server.to_param, :meeting => new_room.meetingid, :user => user_hash
653
658
  end
654
659
 
655
660
  end
@@ -1,6 +1,8 @@
1
1
  Factory.define :bigbluebutton_room do |r|
2
+ # meetingid with a random factor to avoid duplicated ids in consecutive test runs
3
+ r.sequence(:meetingid) { |n| "meeting-#{n}-" + SecureRandom.hex(4) }
4
+
2
5
  r.association :server, :factory => :bigbluebutton_server
3
- r.sequence(:meetingid) { |n| "MeetingID#{n}" }
4
6
  r.sequence(:name) { |n| "Name#{n}" }
5
7
  r.attendee_password { Forgery(:basic).password :at_least => 10, :at_most => 16 }
6
8
  r.moderator_password { Forgery(:basic).password :at_least => 10, :at_most => 16 }
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe BigbluebuttonRoom do
4
+
5
+ # to ensure that the migration is correct
6
+ context "db" do
7
+ it { should have_db_column(:server_id).of_type(:integer) }
8
+ it { should have_db_column(:owner_id).of_type(:integer) }
9
+ it { should have_db_column(:owner_type).of_type(:string) }
10
+ it { should have_db_column(:meetingid).of_type(:string) }
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) }
14
+ it { should have_db_column(:welcome_msg).of_type(:string) }
15
+ it { should have_db_column(:dial_number).of_type(:string) }
16
+ it { should have_db_column(:logout_url).of_type(:string) }
17
+ it { should have_db_column(:voice_bridge).of_type(:string) }
18
+ it { should have_db_column(:max_participants).of_type(:integer) }
19
+ it { should have_db_column(:private).of_type(:boolean) }
20
+ it { should have_db_column(:randomize_meetingid).of_type(:boolean) }
21
+ it { should have_db_column(:external).of_type(:boolean) }
22
+ it { should have_db_column(:param).of_type(:string) }
23
+ it { should have_db_index(:server_id) }
24
+ it { should have_db_index(:meetingid).unique(true) }
25
+ it { should have_db_index(:voice_bridge).unique(true) }
26
+ it "default values" do
27
+ room = BigbluebuttonRoom.new
28
+ room.private.should be_false
29
+ room.randomize_meetingid.should be_true
30
+ room.external.should be_false
31
+ end
32
+ end
33
+
34
+ end
@@ -6,551 +6,546 @@ describe BigbluebuttonRoom do
6
6
  BigbluebuttonRoom.new.should be_a_kind_of(ActiveRecord::Base)
7
7
  end
8
8
 
9
- # to ensure that the migration is correct
10
- context "db" do
11
- it { should have_db_column(:server_id).of_type(:integer) }
12
- it { should have_db_column(:owner_id).of_type(:integer) }
13
- it { should have_db_column(:owner_type).of_type(:string) }
14
- it { should have_db_column(:meetingid).of_type(:string) }
15
- it { should have_db_column(:name).of_type(:string) }
16
- it { should have_db_column(:attendee_password).of_type(:string) }
17
- it { should have_db_column(:moderator_password).of_type(:string) }
18
- it { should have_db_column(:welcome_msg).of_type(:string) }
19
- it { should have_db_column(:dial_number).of_type(:string) }
20
- it { should have_db_column(:logout_url).of_type(:string) }
21
- it { should have_db_column(:voice_bridge).of_type(:string) }
22
- it { should have_db_column(:max_participants).of_type(:integer) }
23
- it { should have_db_column(:private).of_type(:boolean) }
24
- it { should have_db_column(:randomize_meetingid).of_type(:boolean) }
25
- it { should have_db_column(:external).of_type(:boolean) }
26
- it { should have_db_column(:param).of_type(:string) }
27
- it { should have_db_index(:server_id) }
28
- it { should have_db_index(:meetingid).unique(true) }
29
- it { should have_db_index(:voice_bridge).unique(true) }
30
- it "default values" do
31
- room = BigbluebuttonRoom.new
32
- room.private.should be_false
33
- room.randomize_meetingid.should be_true
34
- room.external.should be_false
35
- end
9
+ before { Factory.create(:bigbluebutton_room) }
10
+
11
+ it { should belong_to(:server) }
12
+ it { should belong_to(:owner) }
13
+ it { should_not validate_presence_of(:owner_id) }
14
+ it { should_not validate_presence_of(:owner_type) }
15
+
16
+ it { should validate_presence_of(:server_id) }
17
+ it { should validate_presence_of(:meetingid) }
18
+ it { should validate_presence_of(:voice_bridge) }
19
+ it { should validate_presence_of(:name) }
20
+ it { should validate_presence_of(:param) }
21
+
22
+ it { should be_boolean(:private) }
23
+ it { should be_boolean(:randomize_meetingid) }
24
+
25
+ [:name, :server_id, :meetingid, :attendee_password, :moderator_password,
26
+ :welcome_msg, :owner, :server, :private, :logout_url, :dial_number,
27
+ :voice_bridge, :max_participants, :owner_id, :owner_type,
28
+ :randomize_meetingid, :param].
29
+ each do |attribute|
30
+ it { should allow_mass_assignment_of(attribute) }
31
+ end
32
+ it { should_not allow_mass_assignment_of(:id) }
33
+
34
+ it { should validate_uniqueness_of(:meetingid) }
35
+ it { should validate_uniqueness_of(:name) }
36
+ it { should validate_uniqueness_of(:voice_bridge) }
37
+ it { should validate_uniqueness_of(:param) }
38
+
39
+ it {
40
+ room = Factory.create(:bigbluebutton_room)
41
+ room.server.should_not be_nil
42
+ }
43
+
44
+ it { should ensure_length_of(:meetingid).is_at_least(1).is_at_most(100) }
45
+ it { should ensure_length_of(:name).is_at_least(1).is_at_most(150) }
46
+ it { should ensure_length_of(:attendee_password).is_at_most(16) }
47
+ it { should ensure_length_of(:moderator_password).is_at_most(16) }
48
+ it { should ensure_length_of(:welcome_msg).is_at_most(250) }
49
+ it { should ensure_length_of(:param).is_at_least(3) }
50
+
51
+ # attr_accessors
52
+ [:running, :participant_count, :moderator_count, :attendees,
53
+ :has_been_forcibly_ended, :start_time, :end_time, :external].each do |attr|
54
+ it { should respond_to(attr) }
55
+ it { should respond_to("#{attr}=") }
36
56
  end
37
57
 
38
- context do
39
- before { Factory.create(:bigbluebutton_room) }
40
-
41
- it { should belong_to(:server) }
42
- it { should belong_to(:owner) }
43
- it { should_not validate_presence_of(:owner_id) }
44
- it { should_not validate_presence_of(:owner_type) }
45
-
46
- it { should validate_presence_of(:server_id) }
47
- it { should validate_presence_of(:meetingid) }
48
- it { should validate_presence_of(:voice_bridge) }
49
- it { should validate_presence_of(:name) }
50
- it { should validate_presence_of(:param) }
51
-
52
- it { should be_boolean(:private) }
53
- it { should be_boolean(:randomize_meetingid) }
54
-
55
- [:name, :server_id, :meetingid, :attendee_password, :moderator_password,
56
- :welcome_msg, :owner, :server, :private, :logout_url, :dial_number,
57
- :voice_bridge, :max_participants, :owner_id, :owner_type,
58
- :randomize_meetingid, :param].
59
- each do |attribute|
60
- it { should allow_mass_assignment_of(attribute) }
61
- end
62
- it { should_not allow_mass_assignment_of(:id) }
63
-
64
- it { should validate_uniqueness_of(:meetingid) }
65
- it { should validate_uniqueness_of(:name) }
66
- it { should validate_uniqueness_of(:voice_bridge) }
67
- it { should validate_uniqueness_of(:param) }
68
-
58
+ context ".to_param" do
59
+ it { should respond_to(:to_param) }
69
60
  it {
70
- room = Factory.create(:bigbluebutton_room)
71
- room.server.should_not be_nil
61
+ r = Factory.create(:bigbluebutton_room)
62
+ r.to_param.should be(r.param)
72
63
  }
64
+ end
73
65
 
74
- it { should ensure_length_of(:meetingid).is_at_least(1).is_at_most(100) }
75
- it { should ensure_length_of(:name).is_at_least(1).is_at_most(150) }
76
- it { should ensure_length_of(:attendee_password).is_at_most(16) }
77
- it { should ensure_length_of(:moderator_password).is_at_most(16) }
78
- it { should ensure_length_of(:welcome_msg).is_at_most(250) }
79
- it { should ensure_length_of(:param).is_at_least(3) }
80
-
81
- # attr_accessors
82
- [:running, :participant_count, :moderator_count, :attendees,
83
- :has_been_forcibly_ended, :start_time, :end_time, :external].each do |attr|
84
- it { should respond_to(attr) }
85
- it { should respond_to("#{attr}=") }
86
- end
87
-
88
- context ".to_param" do
89
- it { should respond_to(:to_param) }
90
- it {
91
- r = Factory.create(:bigbluebutton_room)
92
- r.to_param.should be(r.param)
93
- }
94
- end
66
+ it { should respond_to(:is_running?) }
95
67
 
96
- it { should respond_to(:is_running?) }
68
+ describe "#user_role" do
69
+ let(:room) { Factory.build(:bigbluebutton_room, :moderator_password => "mod", :attendee_password => "att") }
70
+ it { should respond_to(:user_role) }
71
+ it { room.user_role({ :password => room.moderator_password }).should == :moderator }
72
+ it { room.user_role({ :password => room.attendee_password }).should == :attendee }
73
+ it { room.user_role({ :password => "wrong" }).should == nil }
74
+ it { room.user_role({ :password => nil }).should == nil }
75
+ it { room.user_role({ :not_password => "any" }).should == nil }
76
+ end
97
77
 
98
- describe "#user_role" do
99
- let(:room) { Factory.build(:bigbluebutton_room, :moderator_password => "mod", :attendee_password => "att") }
100
- it { should respond_to(:user_role) }
101
- it { room.user_role({ :password => room.moderator_password }).should == :moderator }
102
- it { room.user_role({ :password => room.attendee_password }).should == :attendee }
103
- it { room.user_role({ :password => "wrong" }).should == nil }
104
- it { room.user_role({ :password => nil }).should == nil }
105
- it { room.user_role({ :not_password => "any" }).should == nil }
78
+ describe "#instance_variables_compare" do
79
+ let(:room) { Factory.create(:bigbluebutton_room) }
80
+ let(:room2) { BigbluebuttonRoom.last }
81
+ it { should respond_to(:instance_variables_compare) }
82
+ it { room.instance_variables_compare(room2).should be_empty }
83
+ it "compares instance variables" do
84
+ room2.running = !room.running
85
+ room.instance_variables_compare(room2).should_not be_empty
86
+ room.instance_variables_compare(room2).should include(:@running)
106
87
  end
107
-
108
- describe "#instance_variables_compare" do
109
- let(:room) { Factory.create(:bigbluebutton_room) }
110
- let(:room2) { BigbluebuttonRoom.last }
111
- it { should respond_to(:instance_variables_compare) }
112
- it { room.instance_variables_compare(room2).should be_empty }
113
- it "compares instance variables" do
114
- room2.running = !room.running
115
- room.instance_variables_compare(room2).should_not be_empty
116
- room.instance_variables_compare(room2).should include(:@running)
117
- end
118
- it "ignores attributes" do
119
- room2.private = !room.private
120
- room.instance_variables_compare(room2).should be_empty
121
- end
88
+ it "ignores attributes" do
89
+ room2.private = !room.private
90
+ room.instance_variables_compare(room2).should be_empty
122
91
  end
92
+ end
123
93
 
124
- describe "#attr_equal?" do
125
- before { Factory.create(:bigbluebutton_room) }
126
- let(:room) { BigbluebuttonRoom.last }
127
- let(:room2) { BigbluebuttonRoom.last }
128
- it { should respond_to(:attr_equal?) }
129
- it { room.attr_equal?(room2).should be_true }
130
- it "compares instance variables" do
131
- room2.running = !room.running
132
- room.attr_equal?(room2).should be_false
133
- end
134
- it "compares attributes" do
135
- room2.private = !room.private
136
- room.attr_equal?(room2).should be_false
137
- end
138
- it "compares objects" do
139
- room2 = room.clone
140
- room.attr_equal?(room2).should be_false
141
- end
94
+ describe "#attr_equal?" do
95
+ before { Factory.create(:bigbluebutton_room) }
96
+ let(:room) { BigbluebuttonRoom.last }
97
+ let(:room2) { BigbluebuttonRoom.last }
98
+ it { should respond_to(:attr_equal?) }
99
+ it { room.attr_equal?(room2).should be_true }
100
+ it "compares instance variables" do
101
+ room2.running = !room.running
102
+ room.attr_equal?(room2).should be_false
142
103
  end
104
+ it "compares attributes" do
105
+ room2.private = !room.private
106
+ room.attr_equal?(room2).should be_false
107
+ end
108
+ it "compares objects" do
109
+ room2 = room.clone
110
+ room.attr_equal?(room2).should be_false
111
+ end
112
+ end
143
113
 
144
- context "initializes" do
145
- let(:room) { BigbluebuttonRoom.new }
146
-
147
- it "fetched attributes before they are fetched" do
148
- room.participant_count.should == 0
149
- room.moderator_count.should == 0
150
- room.running.should be_false
151
- room.has_been_forcibly_ended.should be_false
152
- room.start_time.should be_nil
153
- room.end_time.should be_nil
154
- room.attendees.should == []
155
- end
114
+ context "initializes" do
115
+ let(:room) { BigbluebuttonRoom.new }
116
+
117
+ it "fetched attributes before they are fetched" do
118
+ room.participant_count.should == 0
119
+ room.moderator_count.should == 0
120
+ room.running.should be_false
121
+ room.has_been_forcibly_ended.should be_false
122
+ room.start_time.should be_nil
123
+ room.end_time.should be_nil
124
+ room.attendees.should == []
125
+ end
156
126
 
157
- context "meetingid" do
158
- it { room.meetingid.should_not be_nil }
159
- it {
160
- b = BigbluebuttonRoom.new(:meetingid => "user defined")
161
- b.meetingid.should == "user defined"
162
- }
163
- end
127
+ context "meetingid" do
128
+ it { room.meetingid.should_not be_nil }
129
+ it {
130
+ b = BigbluebuttonRoom.new(:meetingid => "user defined")
131
+ b.meetingid.should == "user defined"
132
+ }
133
+ end
164
134
 
165
- context "voice_bridge" do
166
- it {
167
- b = BigbluebuttonRoom.new(:voice_bridge => "user defined")
168
- b.voice_bridge.should == "user defined"
169
- }
170
- context "with a random value" do
171
- it { room.voice_bridge.should_not be_nil }
172
- it { room.voice_bridge.should =~ /7[0-9]{4}/ }
173
- it "tries to randomize 10 times if voice_bridge already exists" do
174
- room = Factory.create(:bigbluebutton_room, :voice_bridge => "70000")
175
- BigbluebuttonRoom.stub!(:find_by_voice_bridge).and_return(room)
176
- ActiveSupport::SecureRandom.should_receive(:random_number).exactly(10).and_return(0000)
177
- room2 = BigbluebuttonRoom.new # triggers the random_number calls
178
- room2.voice_bridge.should == "70000"
179
- end
135
+ context "voice_bridge" do
136
+ it {
137
+ b = BigbluebuttonRoom.new(:voice_bridge => "user defined")
138
+ b.voice_bridge.should == "user defined"
139
+ }
140
+ context "with a random value" do
141
+ it { room.voice_bridge.should_not be_nil }
142
+ it { room.voice_bridge.should =~ /7[0-9]{4}/ }
143
+ it "tries to randomize 10 times if voice_bridge already exists" do
144
+ room = Factory.create(:bigbluebutton_room, :voice_bridge => "70000")
145
+ BigbluebuttonRoom.stub!(:find_by_voice_bridge).and_return(room)
146
+ SecureRandom.should_receive(:random_number).exactly(10).and_return(0000)
147
+ room2 = BigbluebuttonRoom.new # triggers the random_number calls
148
+ room2.voice_bridge.should == "70000"
180
149
  end
181
150
  end
182
151
  end
152
+ end
183
153
 
184
- context "param format" do
185
- let(:msg) { I18n.t('bigbluebutton_rails.rooms.errors.param_format') }
186
- it { should validate_format_of(:param).not_with("123 321").with_message(msg) }
187
- it { should validate_format_of(:param).not_with("").with_message(msg) }
188
- it { should validate_format_of(:param).not_with("ab@c").with_message(msg) }
189
- it { should validate_format_of(:param).not_with("ab#c").with_message(msg) }
190
- it { should validate_format_of(:param).not_with("ab$c").with_message(msg) }
191
- it { should validate_format_of(:param).not_with("ab%c").with_message(msg) }
192
- it { should validate_format_of(:param).not_with("ábcd").with_message(msg) }
193
- it { should validate_format_of(:param).not_with("-abc").with_message(msg) }
194
- it { should validate_format_of(:param).not_with("abc-").with_message(msg) }
195
- it { should validate_format_of(:param).with("_abc").with_message(msg) }
196
- it { should validate_format_of(:param).with("abc_").with_message(msg) }
197
- it { should validate_format_of(:param).with("abc") }
198
- it { should validate_format_of(:param).with("123") }
199
- it { should validate_format_of(:param).with("abc-123_d5") }
200
- end
154
+ context "param format" do
155
+ let(:msg) { I18n.t('bigbluebutton_rails.rooms.errors.param_format') }
156
+ it { should validate_format_of(:param).not_with("123 321").with_message(msg) }
157
+ it { should validate_format_of(:param).not_with("").with_message(msg) }
158
+ it { should validate_format_of(:param).not_with("ab@c").with_message(msg) }
159
+ it { should validate_format_of(:param).not_with("ab#c").with_message(msg) }
160
+ it { should validate_format_of(:param).not_with("ab$c").with_message(msg) }
161
+ it { should validate_format_of(:param).not_with("ab%c").with_message(msg) }
162
+ it { should validate_format_of(:param).not_with("ábcd").with_message(msg) }
163
+ it { should validate_format_of(:param).not_with("-abc").with_message(msg) }
164
+ it { should validate_format_of(:param).not_with("abc-").with_message(msg) }
165
+ it { should validate_format_of(:param).with("_abc").with_message(msg) }
166
+ it { should validate_format_of(:param).with("abc_").with_message(msg) }
167
+ it { should validate_format_of(:param).with("abc") }
168
+ it { should validate_format_of(:param).with("123") }
169
+ it { should validate_format_of(:param).with("abc-123_d5") }
170
+ end
201
171
 
202
- context "sets param as the downcased parameterized name if param is" do
203
- after :each do
204
- @room.save.should be_true
205
- @room.param.should == @room.name.downcase.parameterize
206
- end
207
- it "nil" do
208
- @room = Factory.build(:bigbluebutton_room, :param => nil,
209
- :name => "-My Name@ _Is Odd_-")
210
- end
211
- it "empty" do
212
- @room = Factory.build(:bigbluebutton_room, :param => "",
213
- :name => "-My Name@ _Is Odd_-")
214
- end
172
+ context "sets param as the downcased parameterized name if param is" do
173
+ after :each do
174
+ @room.save.should be_true
175
+ @room.param.should == @room.name.downcase.parameterize
176
+ end
177
+ it "nil" do
178
+ @room = Factory.build(:bigbluebutton_room, :param => nil,
179
+ :name => "-My Name@ _Is Odd_-")
215
180
  end
181
+ it "empty" do
182
+ @room = Factory.build(:bigbluebutton_room, :param => "",
183
+ :name => "-My Name@ _Is Odd_-")
184
+ end
185
+ end
216
186
 
217
- context "using the api" do
218
- before { mock_server_and_api }
219
- let(:room) { Factory.create(:bigbluebutton_room) }
187
+ context "using the api" do
188
+ before { mock_server_and_api }
189
+ let(:room) { Factory.create(:bigbluebutton_room) }
220
190
 
221
- describe "#fetch_is_running?" do
191
+ describe "#fetch_is_running?" do
222
192
 
223
- it { should respond_to(:fetch_is_running?) }
193
+ it { should respond_to(:fetch_is_running?) }
224
194
 
225
- it "fetches is_running? when not running" do
226
- mocked_api.should_receive(:is_meeting_running?).with(room.meetingid).and_return(false)
227
- room.server = mocked_server
228
- room.fetch_is_running?
229
- room.running.should == false
230
- room.is_running?.should == false
231
- end
232
-
233
- it "fetches is_running? when running" do
234
- mocked_api.should_receive(:is_meeting_running?).with(room.meetingid).and_return(true)
235
- room.server = mocked_server
236
- room.fetch_is_running?
237
- room.running.should == true
238
- room.is_running?.should == true
239
- end
195
+ it "fetches is_running? when not running" do
196
+ mocked_api.should_receive(:is_meeting_running?).with(room.meetingid).and_return(false)
197
+ room.server = mocked_server
198
+ room.fetch_is_running?
199
+ room.running.should == false
200
+ room.is_running?.should == false
201
+ end
240
202
 
203
+ it "fetches is_running? when running" do
204
+ mocked_api.should_receive(:is_meeting_running?).with(room.meetingid).and_return(true)
205
+ room.server = mocked_server
206
+ room.fetch_is_running?
207
+ room.running.should == true
208
+ room.is_running?.should == true
241
209
  end
242
210
 
243
- describe "#fetch_meeting_info" do
211
+ end
244
212
 
245
- # these hashes should be exactly as returned by bigbluebutton-api-ruby to be sure we are testing it right
246
- let(:hash_info) {
247
- { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
248
- :running=>false, :hasBeenForciblyEnded=>false, :startTime=>nil, :endTime=>nil,
249
- :participantCount=>0, :moderatorCount=>0, :attendees=>[], :messageKey=>"", :message=>""
250
- }
251
- }
252
- let(:users) {
253
- [
254
- {:userID=>"ndw1fnaev0rj", :fullName=>"House M.D.", :role=>:moderator},
255
- {:userID=>"gn9e22b7ynna", :fullName=>"Dexter Morgan", :role=>:moderator},
256
- {:userID=>"llzihbndryc3", :fullName=>"Cameron Palmer", :role=>:viewer},
257
- {:userID=>"rbepbovolsxt", :fullName=>"Trinity", :role=>:viewer}
258
- ]
213
+ describe "#fetch_meeting_info" do
214
+
215
+ # these hashes should be exactly as returned by bigbluebutton-api-ruby to be sure we are testing it right
216
+ let(:hash_info) {
217
+ { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
218
+ :running=>false, :hasBeenForciblyEnded=>false, :startTime=>nil, :endTime=>nil,
219
+ :participantCount=>0, :moderatorCount=>0, :attendees=>[], :messageKey=>"", :message=>""
259
220
  }
260
- let(:hash_info2) {
261
- { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
262
- :running=>true, :hasBeenForciblyEnded=>false, :startTime=>DateTime.parse("Wed Apr 06 17:09:57 UTC 2011"),
263
- :endTime=>nil, :participantCount=>4, :moderatorCount=>2,
264
- :attendees=>users, :messageKey=>{ }, :message=>{ }
265
- }
221
+ }
222
+ let(:users) {
223
+ [
224
+ {:userID=>"ndw1fnaev0rj", :fullName=>"House M.D.", :role=>:moderator},
225
+ {:userID=>"gn9e22b7ynna", :fullName=>"Dexter Morgan", :role=>:moderator},
226
+ {:userID=>"llzihbndryc3", :fullName=>"Cameron Palmer", :role=>:viewer},
227
+ {:userID=>"rbepbovolsxt", :fullName=>"Trinity", :role=>:viewer}
228
+ ]
229
+ }
230
+ let(:hash_info2) {
231
+ { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
232
+ :running=>true, :hasBeenForciblyEnded=>false, :startTime=>DateTime.parse("Wed Apr 06 17:09:57 UTC 2011"),
233
+ :endTime=>nil, :participantCount=>4, :moderatorCount=>2,
234
+ :attendees=>users, :messageKey=>{ }, :message=>{ }
266
235
  }
236
+ }
267
237
 
268
- it { should respond_to(:fetch_meeting_info) }
269
-
270
- it "fetches meeting info when the meeting is not running" do
271
- mocked_api.should_receive(:get_meeting_info).
272
- with(room.meetingid, room.moderator_password).and_return(hash_info)
273
- room.server = mocked_server
238
+ it { should respond_to(:fetch_meeting_info) }
274
239
 
275
- room.fetch_meeting_info
276
- room.running.should == false
277
- room.has_been_forcibly_ended.should == false
278
- room.participant_count.should == 0
279
- room.moderator_count.should == 0
280
- room.start_time.should == nil
281
- room.end_time.should == nil
282
- room.attendees.should == []
283
- end
240
+ it "fetches meeting info when the meeting is not running" do
241
+ mocked_api.should_receive(:get_meeting_info).
242
+ with(room.meetingid, room.moderator_password).and_return(hash_info)
243
+ room.server = mocked_server
284
244
 
285
- it "fetches meeting info when the meeting is running" do
286
- mocked_api.should_receive(:get_meeting_info).
287
- with(room.meetingid, room.moderator_password).and_return(hash_info2)
288
- room.server = mocked_server
245
+ room.fetch_meeting_info
246
+ room.running.should == false
247
+ room.has_been_forcibly_ended.should == false
248
+ room.participant_count.should == 0
249
+ room.moderator_count.should == 0
250
+ room.start_time.should == nil
251
+ room.end_time.should == nil
252
+ room.attendees.should == []
253
+ end
289
254
 
290
- room.fetch_meeting_info
291
- room.running.should == true
292
- room.has_been_forcibly_ended.should == false
293
- room.participant_count.should == 4
294
- room.moderator_count.should == 2
295
- room.start_time.should == DateTime.parse("Wed Apr 06 17:09:57 UTC 2011")
296
- room.end_time.should == nil
297
-
298
- users.each do |att|
299
- attendee = BigbluebuttonAttendee.new
300
- attendee.from_hash(att)
301
- room.attendees.should include(attendee)
302
- end
255
+ it "fetches meeting info when the meeting is running" do
256
+ mocked_api.should_receive(:get_meeting_info).
257
+ with(room.meetingid, room.moderator_password).and_return(hash_info2)
258
+ room.server = mocked_server
259
+
260
+ room.fetch_meeting_info
261
+ room.running.should == true
262
+ room.has_been_forcibly_ended.should == false
263
+ room.participant_count.should == 4
264
+ room.moderator_count.should == 2
265
+ room.start_time.should == DateTime.parse("Wed Apr 06 17:09:57 UTC 2011")
266
+ room.end_time.should == nil
267
+
268
+ users.each do |att|
269
+ attendee = BigbluebuttonAttendee.new
270
+ attendee.from_hash(att)
271
+ room.attendees.should include(attendee)
303
272
  end
304
-
305
273
  end
306
274
 
307
- describe "#send_end" do
275
+ end
308
276
 
309
- it { should respond_to(:send_end) }
277
+ describe "#send_end" do
310
278
 
311
- it "send end_meeting" do
312
- mocked_api.should_receive(:end_meeting).with(room.meetingid, room.moderator_password)
313
- room.server = mocked_server
314
- room.send_end
315
- end
279
+ it { should respond_to(:send_end) }
316
280
 
281
+ it "send end_meeting" do
282
+ mocked_api.should_receive(:end_meeting).with(room.meetingid, room.moderator_password)
283
+ room.server = mocked_server
284
+ room.send_end
317
285
  end
318
286
 
319
- describe "#send_create" do
320
- let(:attendee_password) { Forgery(:basic).password }
321
- let(:moderator_password) { Forgery(:basic).password }
322
- let(:hash_create) {
323
- {
324
- :returncode => "SUCCESS", :meetingID => "test_id",
325
- :attendeePW => attendee_password, :moderatorPW => moderator_password,
326
- :hasBeenForciblyEnded => "false", :messageKey => {}, :message => {}
327
- }
328
- }
329
-
330
- it { should respond_to(:send_create) }
331
-
332
- context "send create_meeting" do
333
-
334
- context "for a stored room" do
335
- before do
336
- mocked_api.should_receive(:create_meeting).
337
- with(room.name, room.meetingid, room.moderator_password,
338
- room.attendee_password, room.welcome_msg, room.dial_number,
339
- room.logout_url, room.max_participants, room.voice_bridge).
340
- and_return(hash_create)
341
- room.server = mocked_server
342
- room.send_create
343
- end
344
- it { room.attendee_password.should be(attendee_password) }
345
- it { room.moderator_password.should be(moderator_password) }
346
- it { room.changed?.should be_false }
347
- end
287
+ end
348
288
 
349
- context "for a new_record" do
350
- let(:new_room) { Factory.build(:bigbluebutton_room) }
351
- before do
352
- mocked_api.should_receive(:create_meeting).
353
- with(new_room.name, new_room.meetingid, new_room.moderator_password,
354
- new_room.attendee_password, new_room.welcome_msg, new_room.dial_number,
355
- new_room.logout_url, new_room.max_participants, new_room.voice_bridge).
356
- and_return(hash_create)
357
- new_room.server = mocked_server
358
- new_room.send_create
359
- end
360
- it { new_room.attendee_password.should be(attendee_password) }
361
- it { new_room.moderator_password.should be(moderator_password) }
362
- it("do not save the record") { new_room.new_record?.should be_true }
363
- end
289
+ describe "#send_create" do
290
+ let(:attendee_password) { Forgery(:basic).password }
291
+ let(:moderator_password) { Forgery(:basic).password }
292
+ let(:hash_create) {
293
+ {
294
+ :returncode => "SUCCESS", :meetingID => "test_id",
295
+ :attendeePW => attendee_password, :moderatorPW => moderator_password,
296
+ :hasBeenForciblyEnded => "false", :messageKey => {}, :message => {}
297
+ }
298
+ }
364
299
 
365
- end
300
+ it { should respond_to(:send_create) }
366
301
 
367
- context "randomizes meetingid" do
368
- let(:fail_hash) { { :returncode => true, :meetingID => "new id",
369
- :messageKey => "duplicateWarning" } }
370
- let(:success_hash) { { :returncode => true, :meetingID => "new id",
371
- :messageKey => "" } }
372
- let(:new_id) { "new id" }
373
- before {
374
- room.randomize_meetingid = true
375
- room.server = mocked_server
376
- }
302
+ context "send create_meeting" do
377
303
 
378
- it "before calling create" do
379
- room.should_receive(:random_meetingid).and_return(new_id)
304
+ context "for a stored room" do
305
+ before do
306
+ hash = hash_including(:moderatorPW => room.moderator_password, :attendeePW => room.attendee_password,
307
+ :welcome => room.welcome_msg, :dialNumber => room.dial_number,
308
+ :logoutURL => room.logout_url, :maxParticipants => room.max_participants,
309
+ :voiceBridge => room.voice_bridge)
380
310
  mocked_api.should_receive(:create_meeting).
381
- with(room.name, new_id, room.moderator_password,
382
- room.attendee_password, room.welcome_msg, room.dial_number,
383
- room.logout_url, room.max_participants, room.voice_bridge)
384
- room.send_create
385
- end
386
-
387
- it "and tries again on error" do
388
- # fails twice and them succeds
389
- room.should_receive(:random_meetingid).exactly(3).times.and_return(new_id)
390
- mocked_api.should_receive(:create_meeting).
391
- with(room.name, new_id, room.moderator_password,
392
- room.attendee_password, room.welcome_msg, room.dial_number,
393
- room.logout_url, room.max_participants, room.voice_bridge).
394
- twice.
395
- and_return(fail_hash)
396
- mocked_api.should_receive(:create_meeting).
397
- with(room.name, new_id, room.moderator_password,
398
- room.attendee_password, room.welcome_msg, room.dial_number,
399
- room.logout_url, room.max_participants, room.voice_bridge).
400
- once.
401
- and_return(success_hash)
311
+ with(room.name, room.meetingid, hash).and_return(hash_create)
312
+ room.server = mocked_server
402
313
  room.send_create
403
314
  end
315
+ it { room.attendee_password.should be(attendee_password) }
316
+ it { room.moderator_password.should be(moderator_password) }
317
+ it { room.changed?.should be_false }
318
+ end
404
319
 
405
- it "and limits to 10 tries" do
406
- room.should_receive(:random_meetingid).exactly(11).times.and_return(new_id)
320
+ context "for a new record" do
321
+ let(:new_room) { Factory.build(:bigbluebutton_room) }
322
+ before do
323
+ hash = hash_including(:moderatorPW => new_room.moderator_password, :attendeePW => new_room.attendee_password,
324
+ :welcome => new_room.welcome_msg, :dialNumber => new_room.dial_number,
325
+ :logoutURL => new_room.logout_url, :maxParticipants => new_room.max_participants,
326
+ :voiceBridge => new_room.voice_bridge)
407
327
  mocked_api.should_receive(:create_meeting).
408
- with(room.name, new_id, room.moderator_password,
409
- room.attendee_password, room.welcome_msg, room.dial_number,
410
- room.logout_url, room.max_participants, room.voice_bridge).
411
- exactly(10).times.
412
- and_return(fail_hash)
413
- room.send_create
328
+ with(new_room.name, new_room.meetingid, hash).and_return(hash_create)
329
+ new_room.server = mocked_server
330
+ new_room.send_create
414
331
  end
332
+ it { new_room.attendee_password.should be(attendee_password) }
333
+ it { new_room.moderator_password.should be(moderator_password) }
334
+ it("and do not save the record") { new_room.new_record?.should be_true }
415
335
  end
416
336
 
417
337
  end
418
338
 
419
- describe "#join_url" do
420
- let(:username) { Forgery(:name).full_name }
339
+ context "randomizes meetingid" do
340
+ let(:fail_hash) { { :returncode => true, :meetingID => "new id",
341
+ :messageKey => "duplicateWarning" } }
342
+ let(:success_hash) { { :returncode => true, :meetingID => "new id",
343
+ :messageKey => "" } }
344
+ let(:new_id) { "new id" }
345
+ before {
346
+ room.randomize_meetingid = true
347
+ room.server = mocked_server
348
+ }
421
349
 
422
- it { should respond_to(:join_url) }
350
+ it "before calling create" do
351
+ room.should_receive(:random_meetingid).and_return(new_id)
352
+ hash = hash_including(:moderatorPW => room.moderator_password, :attendeePW => room.attendee_password,
353
+ :welcome => room.welcome_msg, :dialNumber => room.dial_number,
354
+ :logoutURL => room.logout_url, :maxParticipants => room.max_participants,
355
+ :voiceBridge => room.voice_bridge)
356
+ mocked_api.should_receive(:create_meeting).with(room.name, new_id, hash)
357
+ room.send_create
358
+ end
423
359
 
424
- it "with moderator role" do
425
- mocked_api.should_receive(:join_meeting_url).
426
- with(room.meetingid, username, room.moderator_password)
427
- room.server = mocked_server
428
- room.join_url(username, :moderator)
360
+ it "and tries again on error" do
361
+ # fails twice and them succeds
362
+ room.should_receive(:random_meetingid).exactly(3).times.and_return(new_id)
363
+ hash = hash_including(:moderatorPW => room.moderator_password, :attendeePW => room.attendee_password,
364
+ :welcome => room.welcome_msg, :dialNumber => room.dial_number,
365
+ :logoutURL => room.logout_url, :maxParticipants => room.max_participants,
366
+ :voiceBridge => room.voice_bridge)
367
+ mocked_api.should_receive(:create_meeting).
368
+ with(room.name, new_id, hash).twice.and_return(fail_hash)
369
+ mocked_api.should_receive(:create_meeting).
370
+ with(room.name, new_id, hash).once.and_return(success_hash)
371
+ room.send_create
429
372
  end
430
373
 
431
- it "with attendee role" do
432
- mocked_api.should_receive(:join_meeting_url).
433
- with(room.meetingid, username, room.attendee_password)
434
- room.server = mocked_server
435
- room.join_url(username, :attendee)
374
+ it "and limits to 10 tries" do
375
+ room.should_receive(:random_meetingid).exactly(11).times.and_return(new_id)
376
+ hash = hash_including(:moderatorPW => room.moderator_password, :attendeePW => room.attendee_password,
377
+ :welcome => room.welcome_msg, :dialNumber => room.dial_number,
378
+ :logoutURL => room.logout_url, :maxParticipants => room.max_participants,
379
+ :voiceBridge => room.voice_bridge)
380
+ mocked_api.should_receive(:create_meeting).
381
+ with(room.name, new_id, hash).exactly(10).times.and_return(fail_hash)
382
+ room.send_create
436
383
  end
384
+ end
437
385
 
438
- it "without a role" do
439
- mocked_api.should_receive(:join_meeting_url).
440
- with(room.meetingid, username, 'pass')
386
+ context "uses #full_logout_url when set" do
387
+ before do
388
+ room.full_logout_url = "full-version-of-logout-url"
389
+ hash = hash_including(:moderatorPW => room.moderator_password, :attendeePW => room.attendee_password,
390
+ :welcome => room.welcome_msg, :dialNumber => room.dial_number,
391
+ :logoutURL => "full-version-of-logout-url", :maxParticipants => room.max_participants,
392
+ :voiceBridge => room.voice_bridge)
393
+ mocked_api.should_receive(:create_meeting).
394
+ with(room.name, room.meetingid, hash).and_return(hash_create)
441
395
  room.server = mocked_server
442
- room.join_url(username, nil, 'pass')
443
396
  end
397
+ it { room.send_create }
444
398
  end
445
399
 
446
400
  end
447
401
 
448
- context "validates passwords" do
449
- context "for private rooms" do
450
- let (:room) { Factory.build(:bigbluebutton_room, :private => true) }
451
- it { room.should_not allow_value('').for(:moderator_password) }
452
- it { room.should_not allow_value('').for(:attendee_password) }
453
- end
402
+ describe "#join_url" do
403
+ let(:username) { Forgery(:name).full_name }
454
404
 
455
- context "for public rooms" do
456
- let (:room) { Factory.build(:bigbluebutton_room, :private => false) }
457
- it { room.should allow_value('').for(:moderator_password) }
458
- it { room.should allow_value('').for(:attendee_password) }
459
- end
460
- end
405
+ it { should respond_to(:join_url) }
461
406
 
462
- describe "#add_domain_to_logout_url" do
463
- context "when logout_url has a path only" do
464
- let(:room) { Factory.create(:bigbluebutton_room, :logout_url => '/only/path') }
465
- before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com") }
466
- it { room.logout_url.should == "http://test.com/only/path" }
407
+ it "with moderator role" do
408
+ mocked_api.should_receive(:join_meeting_url).
409
+ with(room.meetingid, username, room.moderator_password)
410
+ room.server = mocked_server
411
+ room.join_url(username, :moderator)
467
412
  end
468
413
 
469
- context "when logout_url has a path and domain" do
470
- let(:room) { Factory.create(:bigbluebutton_room, :logout_url => 'other.com/only/path') }
471
- before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com") }
472
- it { room.logout_url.should == "http://other.com/only/path" }
414
+ it "with attendee role" do
415
+ mocked_api.should_receive(:join_meeting_url).
416
+ with(room.meetingid, username, room.attendee_password)
417
+ room.server = mocked_server
418
+ room.join_url(username, :attendee)
473
419
  end
474
420
 
475
- context "when logout_url has a path, domain and protocol" do
476
- let(:room) { Factory.create(:bigbluebutton_room, :logout_url => 'HTTPS://other.com/only/path') }
477
- before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com") }
478
- it { room.logout_url.should == "https://other.com/only/path" }
421
+ it "without a role" do
422
+ mocked_api.should_receive(:join_meeting_url).
423
+ with(room.meetingid, username, 'pass')
424
+ room.server = mocked_server
425
+ room.join_url(username, nil, 'pass')
479
426
  end
427
+ end
480
428
 
481
- context "does nothing if logout_url is nil" do
482
- let(:room) { Factory.create(:bigbluebutton_room, :logout_url => nil) }
483
- before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com") }
484
- it { room.logout_url.should == nil }
485
- end
429
+ end
430
+
431
+ context "validates passwords" do
432
+ context "for private rooms" do
433
+ let (:room) { Factory.build(:bigbluebutton_room, :private => true) }
434
+ it { room.should_not allow_value('').for(:moderator_password) }
435
+ it { room.should_not allow_value('').for(:attendee_password) }
486
436
  end
487
437
 
488
- describe "#perform_join" do
489
- let(:room) { Factory.create(:bigbluebutton_room) }
490
- let(:user) { Factory.build(:user) }
491
-
492
- context "for an attendee" do
493
- before { room.should_receive(:fetch_is_running?) }
494
-
495
- context "when the conference is running" do
496
- before {
497
- room.should_receive(:is_running?).and_return(true)
498
- room.should_receive(:join_url).with(user.name, :attendee).
499
- and_return("http://test.com/attendee/join")
500
- }
501
- subject { room.perform_join(user.name, :attendee) }
502
- it { should == "http://test.com/attendee/join" }
503
- end
438
+ context "for public rooms" do
439
+ let (:room) { Factory.build(:bigbluebutton_room, :private => false) }
440
+ it { room.should allow_value('').for(:moderator_password) }
441
+ it { room.should allow_value('').for(:attendee_password) }
442
+ end
443
+ end
504
444
 
505
- context "when the conference is not running" do
506
- before { room.should_receive(:is_running?).and_return(false) }
507
- subject { room.perform_join(user.name, :attendee) }
508
- it { should be_nil }
509
- end
445
+ describe "#add_domain_to_logout_url" do
446
+ context "when logout_url has a path only" do
447
+ let(:room) { Factory.create(:bigbluebutton_room, :logout_url => '/only/path') }
448
+ before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com:80") }
449
+ it { room.full_logout_url.should == "http://test.com:80/only/path" }
450
+ it { room.logout_url.should == "/only/path" }
451
+ it { BigbluebuttonRoom.find(room.id).logout_url.should == "/only/path" }
452
+ end
453
+
454
+ context "when logout_url has a path and domain" do
455
+ let(:room) { Factory.create(:bigbluebutton_room, :logout_url => 'other.com/only/path') }
456
+ before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com:80") }
457
+ it { room.full_logout_url.should == "http://other.com/only/path" }
458
+ it { room.logout_url.should == "other.com/only/path" }
459
+ it { BigbluebuttonRoom.find(room.id).logout_url.should == "other.com/only/path" }
460
+ end
461
+
462
+ context "when logout_url has a path, domain and protocol" do
463
+ let(:room) { Factory.create(:bigbluebutton_room, :logout_url => 'HTTPS://other.com/only/path') }
464
+ before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com:80") }
465
+ it { room.full_logout_url.should == "https://other.com/only/path" }
466
+ it { room.logout_url.should == "HTTPS://other.com/only/path" }
467
+ it { BigbluebuttonRoom.find(room.id).logout_url.should == "HTTPS://other.com/only/path" }
468
+ end
469
+
470
+ context "does nothing if logout_url is nil" do
471
+ let(:room) { Factory.create(:bigbluebutton_room, :logout_url => nil) }
472
+ before(:each) { room.add_domain_to_logout_url("HTTP://", "test.com:80") }
473
+ it { room.full_logout_url.should be_nil }
474
+ it { room.logout_url.should be_nil }
475
+ it { BigbluebuttonRoom.find(room.id).logout_url.should be_nil }
476
+ end
477
+ end
478
+
479
+ describe "#perform_join" do
480
+ let(:room) { Factory.create(:bigbluebutton_room) }
481
+ let(:user) { Factory.build(:user) }
482
+
483
+ context "for an attendee" do
484
+ before { room.should_receive(:fetch_is_running?) }
485
+
486
+ context "when the conference is running" do
487
+ before {
488
+ room.should_receive(:is_running?).and_return(true)
489
+ room.should_receive(:join_url).with(user.name, :attendee).
490
+ and_return("http://test.com/attendee/join")
491
+ }
492
+ subject { room.perform_join(user.name, :attendee) }
493
+ it { should == "http://test.com/attendee/join" }
510
494
  end
511
495
 
512
- context "for a moderator" do
513
- before { room.should_receive(:fetch_is_running?) }
514
-
515
- context "when the conference is running" do
516
- before {
517
- room.should_receive(:is_running?).and_return(true)
518
- room.should_receive(:join_url).with(user.name, :moderator).
519
- and_return("http://test.com/moderator/join")
520
- }
521
- subject { room.perform_join(user.name, :moderator) }
522
- it { should == "http://test.com/moderator/join" }
523
- end
496
+ context "when the conference is not running" do
497
+ before { room.should_receive(:is_running?).and_return(false) }
498
+ subject { room.perform_join(user.name, :attendee) }
499
+ it { should be_nil }
500
+ end
501
+ end
524
502
 
525
- context "when the conference is not running" do
526
- before {
527
- room.should_receive(:is_running?).and_return(false)
528
- room.should_receive(:send_create)
529
- room.should_receive(:join_url).with(user.name, :moderator).
530
- and_return("http://test.com/moderator/join")
531
- }
532
- subject { room.perform_join(user.name, :moderator) }
533
- it { should == "http://test.com/moderator/join" }
534
- end
503
+ context "for a moderator" do
504
+ before { room.should_receive(:fetch_is_running?) }
535
505
 
536
- context "when the arg 'request' is informed" do
537
- let(:request) { stub(ActionController::Request) }
538
- before {
539
- request.stub!(:protocol).and_return("HTTP://")
540
- request.stub!(:host).and_return("test.com")
541
- room.should_receive(:add_domain_to_logout_url).with("HTTP://", "test.com")
542
- room.should_receive(:is_running?).and_return(true)
543
- room.should_receive(:join_url).with(user.name, :moderator).
544
- and_return("http://test.com/moderator/join")
545
- }
546
- subject { room.perform_join(user.name, :moderator, request) }
547
- it { should == "http://test.com/moderator/join" }
548
- end
506
+ context "when the conference is running" do
507
+ before {
508
+ room.should_receive(:is_running?).and_return(true)
509
+ room.should_receive(:join_url).with(user.name, :moderator).
510
+ and_return("http://test.com/moderator/join")
511
+ }
512
+ subject { room.perform_join(user.name, :moderator) }
513
+ it { should == "http://test.com/moderator/join" }
514
+ end
515
+
516
+ context "when the conference is not running" do
517
+ before {
518
+ room.should_receive(:is_running?).and_return(false)
519
+ room.should_receive(:send_create)
520
+ room.should_receive(:join_url).with(user.name, :moderator).
521
+ and_return("http://test.com/moderator/join")
522
+ }
523
+ subject { room.perform_join(user.name, :moderator) }
524
+ it { should == "http://test.com/moderator/join" }
525
+ end
549
526
 
527
+ context "when the arg 'request' is informed" do
528
+ let(:request) { stub(ActionController::Request) }
529
+ before {
530
+ request.stub!(:protocol).and_return("HTTP://")
531
+ request.stub!(:host_with_port).and_return("test.com:80")
532
+ room.should_receive(:add_domain_to_logout_url).with("HTTP://", "test.com:80")
533
+ room.should_receive(:is_running?).and_return(true)
534
+ room.should_receive(:join_url).with(user.name, :moderator).
535
+ and_return("http://test.com/moderator/join")
536
+ }
537
+ subject { room.perform_join(user.name, :moderator, request) }
538
+ it { should == "http://test.com/moderator/join" }
550
539
  end
551
540
 
552
541
  end
553
542
 
554
543
  end
555
544
 
545
+ describe "#full_logout_url" do
546
+ subject { BigbluebuttonRoom.new }
547
+ it { should respond_to(:full_logout_url) }
548
+ it { should respond_to(:"full_logout_url=") }
549
+ end
550
+
556
551
  end