bigbluebutton_rails 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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