bigbluebutton_rails 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/CHANGELOG.rdoc +9 -1
  2. data/Gemfile.lock +3 -3
  3. data/README.rdoc +56 -21
  4. data/Rakefile +1 -0
  5. data/app/controllers/bigbluebutton/rooms_controller.rb +92 -35
  6. data/app/models/bigbluebutton_room.rb +136 -27
  7. data/app/models/bigbluebutton_server.rb +22 -6
  8. data/app/views/bigbluebutton/rooms/_form.html.erb +31 -6
  9. data/app/views/bigbluebutton/rooms/edit.html.erb +1 -1
  10. data/app/views/bigbluebutton/rooms/index.html.erb +20 -8
  11. data/app/views/bigbluebutton/rooms/invite.html.erb +56 -0
  12. data/app/views/bigbluebutton/rooms/{join_wait.html.erb → join.html.erb} +16 -12
  13. data/app/views/bigbluebutton/rooms/new.html.erb +1 -1
  14. data/app/views/bigbluebutton/rooms/show.html.erb +33 -9
  15. data/app/views/bigbluebutton/servers/edit.html.erb +1 -1
  16. data/app/views/bigbluebutton/servers/index.html.erb +6 -4
  17. data/app/views/bigbluebutton/servers/new.html.erb +1 -1
  18. data/app/views/bigbluebutton/servers/show.html.erb +5 -5
  19. data/bigbluebutton_rails.gemspec +1 -1
  20. data/config/locales/en.yml +31 -0
  21. data/lib/bigbluebutton_rails/controller_methods.rb +7 -1
  22. data/lib/bigbluebutton_rails/rails/routes.rb +10 -1
  23. data/lib/bigbluebutton_rails/version.rb +1 -1
  24. data/lib/bigbluebutton_rails.rb +0 -1
  25. data/lib/classes/bigbluebutton_attendee.rb +2 -0
  26. data/lib/generators/bigbluebutton_rails/install_generator.rb +2 -1
  27. data/lib/generators/bigbluebutton_rails/public_generator.rb +0 -1
  28. data/lib/generators/bigbluebutton_rails/templates/migration.rb +8 -2
  29. data/spec/controllers/bigbluebutton/rooms_controller_spec.rb +339 -88
  30. data/spec/factories/bigbluebutton_room.rb +5 -3
  31. data/spec/factories/user.rb +3 -0
  32. data/spec/generators/public_generator_spec.rb +0 -1
  33. data/spec/generators/views_generator_spec.rb +1 -1
  34. data/spec/models/bigbluebutton_room_spec.rb +276 -177
  35. data/spec/models/bigbluebutton_server_spec.rb +117 -96
  36. data/spec/routing/bigbluebutton/rooms_routing_spec.rb +24 -0
  37. data/spec/support/matchers/shoulda/be_boolean.rb +38 -0
  38. data/spec/support/mocked_server.rb +14 -0
  39. metadata +26 -26
  40. data/config/routes.rb +0 -2
  41. data/lib/classes/bigbluebutton_meeting.rb +0 -18
  42. data/lib/generators/bigbluebutton_rails/templates/public/javascripts/heartbeat.js +0 -54
  43. data/spec/classes/bigbluebutton_meeting_spec.rb +0 -62
@@ -1,227 +1,326 @@
1
1
  require 'spec_helper'
2
2
 
3
- def mock_server_and_api
4
- @api_mock = mock(BigBlueButton::BigBlueButtonApi)
5
- @server_mock = mock_model(BigbluebuttonServer)
6
- @server_mock.stub(:api).and_return(@api_mock)
7
- BigbluebuttonServer.stub(:find).with(@server_mock.id.to_s).and_return(@server_mock)
8
- end
9
-
10
- def mocked_server
11
- @server_mock
12
- end
13
-
14
- def mocked_api
15
- @api_mock
16
- end
17
-
18
3
  describe BigbluebuttonRoom do
19
4
  it "loaded correctly" do
20
5
  BigbluebuttonRoom.new.should be_a_kind_of(ActiveRecord::Base)
21
6
  end
22
7
 
23
- before { Factory.create(:bigbluebutton_room) }
24
-
25
- it { should belong_to(:server) }
26
-
27
- it { should belong_to(:owner) }
28
- it { should have_db_column(:owner_id).of_type(:integer) }
29
- it { should have_db_column(:owner_type).of_type(:string) }
30
- it { should_not validate_presence_of(:owner_id) }
31
- it { should_not validate_presence_of(:owner_type) }
32
-
33
- it { should validate_presence_of(:server_id) }
34
- it { should validate_presence_of(:meeting_id) }
35
- it { should validate_presence_of(:name) }
36
-
37
- it { should allow_mass_assignment_of(:name) }
38
- it { should allow_mass_assignment_of(:attendee_password) }
39
- it { should allow_mass_assignment_of(:moderator_password) }
40
- it { should allow_mass_assignment_of(:welcome_msg) }
41
- it { should allow_mass_assignment_of(:server_id) }
42
- it { should allow_mass_assignment_of(:meeting_id) }
43
- it { should_not allow_mass_assignment_of(:id) }
44
-
45
- it { should validate_uniqueness_of(:meeting_id) }
46
- it { should validate_uniqueness_of(:name) }
47
-
48
- it {
49
- room = Factory.create(:bigbluebutton_room)
50
- room.server.should_not be_nil
51
- }
52
-
53
- it { should ensure_length_of(:meeting_id).is_at_least(1).is_at_most(100) }
54
- it { should ensure_length_of(:name).is_at_least(1).is_at_most(150) }
55
- it { should ensure_length_of(:attendee_password).is_at_most(50) }
56
- it { should ensure_length_of(:moderator_password).is_at_most(50) }
57
- it { should ensure_length_of(:welcome_msg).is_at_most(250) }
58
-
59
- # attr_readers
60
- [:running, :participant_count, :moderator_count, :attendees,
61
- :has_been_forcibly_ended, :start_time, :end_time].each do |attr|
62
- it { should respond_to(attr) }
8
+ # to ensure that the migration is correct
9
+ context "db" do
10
+ it { should have_db_column(:server_id).of_type(:integer) }
11
+ it { should have_db_column(:owner_id).of_type(:integer) }
12
+ it { should have_db_column(:owner_type).of_type(:string) }
13
+ it { should have_db_column(:meetingid).of_type(:string) }
14
+ it { should have_db_column(:name).of_type(:string) }
15
+ it { should have_db_column(:attendee_password).of_type(:string) }
16
+ it { should have_db_column(:moderator_password).of_type(:string) }
17
+ it { should have_db_column(:welcome_msg).of_type(:string) }
18
+ it { should have_db_column(:dial_number).of_type(:string) }
19
+ it { should have_db_column(:logout_url).of_type(:string) }
20
+ it { should have_db_column(:voice_bridge).of_type(:string) }
21
+ it { should have_db_column(:max_participants).of_type(:integer) }
22
+ it { should have_db_column(:private).of_type(:boolean) }
23
+ it { should have_db_column(:randomize_meetingid).of_type(:boolean) }
24
+ it { should have_db_index(:server_id) }
25
+ it { should have_db_index(:meetingid).unique(true) }
26
+ it {
27
+ room = BigbluebuttonRoom.new
28
+ room.private.should be_false
29
+ }
30
+ it {
31
+ room = BigbluebuttonRoom.new
32
+ room.randomize_meetingid.should be_true
33
+ }
63
34
  end
64
35
 
65
- it { should respond_to(:is_running?) }
66
-
67
- context "using the api" do
68
- before { mock_server_and_api }
69
- let(:room) { Factory.create(:bigbluebutton_room) }
36
+ context do
70
37
 
71
- describe "#fetch_is_running?" do
38
+ before { Factory.create(:bigbluebutton_room) }
72
39
 
73
- it { should respond_to(:fetch_is_running?) }
40
+ it { should belong_to(:server) }
41
+ it { should belong_to(:owner) }
42
+ it { should_not validate_presence_of(:owner_id) }
43
+ it { should_not validate_presence_of(:owner_type) }
74
44
 
75
- it "fetches is_running? when not running" do
76
- mocked_api.should_receive(:is_meeting_running?).with(room.meeting_id).and_return(false)
77
- room.server = mocked_server
78
- room.fetch_is_running?
79
- room.running.should == false
80
- room.is_running?.should == false
81
- end
45
+ it { should validate_presence_of(:server_id) }
46
+ it { should validate_presence_of(:meetingid) }
47
+ it { should validate_presence_of(:name) }
82
48
 
83
- it "fetches is_running? when running" do
84
- mocked_api.should_receive(:is_meeting_running?).with(room.meeting_id).and_return(true)
85
- room.server = mocked_server
86
- room.fetch_is_running?
87
- room.running.should == true
88
- room.is_running?.should == true
89
- end
49
+ it { should be_boolean(:private) }
50
+ it { should be_boolean(:randomize_meetingid) }
90
51
 
52
+ [:name, :server_id, :meetingid, :attendee_password, :moderator_password,
53
+ :welcome_msg, :owner, :server, :private, :logout_url, :dial_number,
54
+ :voice_bridge, :max_participants, :owner_id, :owner_type, :randomize_meetingid].
55
+ each do |attribute|
56
+ it { should allow_mass_assignment_of(attribute) }
91
57
  end
58
+ it { should_not allow_mass_assignment_of(:id) }
92
59
 
93
- describe "#fetch_meeting_info" do
60
+ it { should validate_uniqueness_of(:meetingid) }
61
+ it { should validate_uniqueness_of(:name) }
94
62
 
95
- # these hashes should be exactly as returned by bigbluebutton-api-ruby to be sure we are testing it right
96
- let(:hash_info) {
97
- { :returncode=>"SUCCESS", :meetingID=>"test_id", :attendeePW=>1234, :moderatorPW=>4321,
98
- :running=>"false", :hasBeenForciblyEnded=>"false", :startTime=>"null", :endTime=>"null",
99
- :participantCount=>0, :moderatorCount=>0, :attendees=>[], :messageKey=>{ }, :message=>{ }
100
- }
101
- }
102
- let(:users) {
103
- [
104
- {:userID=>"ndw1fnaev0rj", :fullName=>"House M.D.", :role=>"MODERATOR"},
105
- {:userID=>"gn9e22b7ynna", :fullName=>"Dexter Morgan", :role=>"MODERATOR"},
106
- {:userID=>"llzihbndryc3", :fullName=>"Cameron Palmer", :role=>"VIEWER"},
107
- {:userID=>"rbepbovolsxt", :fullName=>"Trinity", :role=>"VIEWER"}
108
- ]
109
- }
110
- let(:hash_info2) {
111
- { :returncode=>"SUCCESS", :meetingID=>"test_id", :attendeePW=>1234, :moderatorPW=>4321,
112
- :running=>"true", :hasBeenForciblyEnded=>"false", :startTime=>"Wed Apr 06 17:09:57 UTC 2011",
113
- :endTime=>"null", :participantCount=>4, :moderatorCount=>2,
114
- :attendees => users, :messageKey=>{ }, :message=>{ }
115
- }
116
- }
63
+ it {
64
+ room = Factory.create(:bigbluebutton_room)
65
+ room.server.should_not be_nil
66
+ }
117
67
 
118
- it { should respond_to(:fetch_meeting_info) }
68
+ it { should ensure_length_of(:meetingid).is_at_least(1).is_at_most(100) }
69
+ it { should ensure_length_of(:name).is_at_least(1).is_at_most(150) }
70
+ it { should ensure_length_of(:attendee_password).is_at_most(16) }
71
+ it { should ensure_length_of(:moderator_password).is_at_most(16) }
72
+ it { should ensure_length_of(:welcome_msg).is_at_most(250) }
119
73
 
120
- it "fetches meeting info when the meeting is not running" do
121
- mocked_api.should_receive(:get_meeting_info).
122
- with(room.meeting_id, room.moderator_password).and_return(hash_info)
123
- room.server = mocked_server
74
+ # attr_accessors
75
+ [:running, :participant_count, :moderator_count, :attendees,
76
+ :has_been_forcibly_ended, :start_time, :end_time].each do |attr|
77
+ it { should respond_to(attr) }
78
+ it { should respond_to("#{attr}=") }
79
+ end
80
+
81
+ it { should respond_to(:is_running?) }
82
+
83
+ describe "#user_role" do
84
+ let(:room) { Factory.build(:bigbluebutton_room, :moderator_password => "mod", :attendee_password => "att") }
85
+ it { should respond_to(:user_role) }
86
+ it { room.user_role({ :password => room.moderator_password }).should == :moderator }
87
+ it { room.user_role({ :password => room.attendee_password }).should == :attendee }
88
+ it { room.user_role({ :password => "wrong" }).should == nil }
89
+ it { room.user_role({ :password => nil }).should == nil }
90
+ it { room.user_role({ :not_password => "any" }).should == nil }
91
+ end
92
+
93
+ context "initializes" do
94
+ let(:room) { BigbluebuttonRoom.new }
124
95
 
125
- room.fetch_meeting_info
126
- room.running.should == false
127
- room.has_been_forcibly_ended.should == false
96
+ it "fetched attributes before they are fetched" do
128
97
  room.participant_count.should == 0
129
98
  room.moderator_count.should == 0
130
- room.start_time.should == nil
131
- room.end_time.should == nil
99
+ room.running.should be_false
100
+ room.has_been_forcibly_ended.should be_false
101
+ room.start_time.should be_nil
102
+ room.end_time.should be_nil
132
103
  room.attendees.should == []
133
104
  end
134
105
 
135
- it "fetches meeting info when the meeting is running" do
136
- mocked_api.should_receive(:get_meeting_info).
137
- with(room.meeting_id, room.moderator_password).and_return(hash_info2)
138
- room.server = mocked_server
139
-
140
- room.fetch_meeting_info
141
- room.running.should == true
142
- room.has_been_forcibly_ended.should == false
143
- room.participant_count.should == 4
144
- room.moderator_count.should == 2
145
- room.start_time.should == DateTime.parse("Wed Apr 06 17:09:57 UTC 2011")
146
- room.end_time.should == nil
147
-
148
- users.each do |att|
149
- attendee = BigbluebuttonAttendee.new
150
- attendee.from_hash(att)
151
- room.attendees.should include(attendee)
152
- end
106
+ it "meetingid if it's nil" do
107
+ room.meetingid.should_not be_nil
153
108
  end
154
-
155
109
  end
156
110
 
157
- describe "#send_end" do
111
+ context "using the api" do
112
+ before { mock_server_and_api }
113
+ let(:room) { Factory.create(:bigbluebutton_room) }
114
+
115
+ describe "#fetch_is_running?" do
116
+
117
+ it { should respond_to(:fetch_is_running?) }
118
+
119
+ it "fetches is_running? when not running" do
120
+ mocked_api.should_receive(:is_meeting_running?).with(room.meetingid).and_return(false)
121
+ room.server = mocked_server
122
+ room.fetch_is_running?
123
+ room.running.should == false
124
+ room.is_running?.should == false
125
+ end
158
126
 
159
- it { should respond_to(:send_end) }
127
+ it "fetches is_running? when running" do
128
+ mocked_api.should_receive(:is_meeting_running?).with(room.meetingid).and_return(true)
129
+ room.server = mocked_server
130
+ room.fetch_is_running?
131
+ room.running.should == true
132
+ room.is_running?.should == true
133
+ end
160
134
 
161
- it "send end_meeting" do
162
- mocked_api.should_receive(:end_meeting).with(room.meeting_id, room.moderator_password)
163
- room.server = mocked_server
164
- room.send_end
165
135
  end
166
136
 
167
- end
137
+ describe "#fetch_meeting_info" do
168
138
 
169
- describe "#send_create" do
170
- let(:attendee_password) { Forgery(:basic).password }
171
- let(:moderator_password) { Forgery(:basic).password }
172
- let(:hash_create) {
173
- {
174
- :returncode => "SUCCESS", :meetingID => "test_id",
175
- :attendeePW => attendee_password, :moderatorPW => moderator_password,
176
- :hasBeenForciblyEnded => "false", :messageKey => {}, :message => {}
139
+ # these hashes should be exactly as returned by bigbluebutton-api-ruby to be sure we are testing it right
140
+ let(:hash_info) {
141
+ { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
142
+ :running=>false, :hasBeenForciblyEnded=>false, :startTime=>nil, :endTime=>nil,
143
+ :participantCount=>0, :moderatorCount=>0, :attendees=>[], :messageKey=>"", :message=>""
144
+ }
177
145
  }
178
- }
146
+ let(:users) {
147
+ [
148
+ {:userID=>"ndw1fnaev0rj", :fullName=>"House M.D.", :role=>:moderator},
149
+ {:userID=>"gn9e22b7ynna", :fullName=>"Dexter Morgan", :role=>:moderator},
150
+ {:userID=>"llzihbndryc3", :fullName=>"Cameron Palmer", :role=>:viewer},
151
+ {:userID=>"rbepbovolsxt", :fullName=>"Trinity", :role=>:viewer}
152
+ ]
153
+ }
154
+ let(:hash_info2) {
155
+ { :returncode=>true, :meetingID=>"test_id", :attendeePW=>"1234", :moderatorPW=>"4321",
156
+ :running=>true, :hasBeenForciblyEnded=>false, :startTime=>DateTime.parse("Wed Apr 06 17:09:57 UTC 2011"),
157
+ :endTime=>nil, :participantCount=>4, :moderatorCount=>2,
158
+ :attendees=>users, :messageKey=>{ }, :message=>{ }
159
+ }
160
+ }
161
+
162
+ it { should respond_to(:fetch_meeting_info) }
163
+
164
+ it "fetches meeting info when the meeting is not running" do
165
+ mocked_api.should_receive(:get_meeting_info).
166
+ with(room.meetingid, room.moderator_password).and_return(hash_info)
167
+ room.server = mocked_server
168
+
169
+ room.fetch_meeting_info
170
+ room.running.should == false
171
+ room.has_been_forcibly_ended.should == false
172
+ room.participant_count.should == 0
173
+ room.moderator_count.should == 0
174
+ room.start_time.should == nil
175
+ room.end_time.should == nil
176
+ room.attendees.should == []
177
+ end
179
178
 
180
- it { should respond_to(:send_create) }
179
+ it "fetches meeting info when the meeting is running" do
180
+ mocked_api.should_receive(:get_meeting_info).
181
+ with(room.meetingid, room.moderator_password).and_return(hash_info2)
182
+ room.server = mocked_server
183
+
184
+ room.fetch_meeting_info
185
+ room.running.should == true
186
+ room.has_been_forcibly_ended.should == false
187
+ room.participant_count.should == 4
188
+ room.moderator_count.should == 2
189
+ room.start_time.should == DateTime.parse("Wed Apr 06 17:09:57 UTC 2011")
190
+ room.end_time.should == nil
191
+
192
+ users.each do |att|
193
+ attendee = BigbluebuttonAttendee.new
194
+ attendee.from_hash(att)
195
+ room.attendees.should include(attendee)
196
+ end
197
+ end
181
198
 
182
- it "send create_meeting" do
183
- mocked_api.should_receive(:create_meeting).
184
- with(room.name, room.meeting_id, room.moderator_password,
185
- room.attendee_password, room.welcome_msg)
186
- room.server = mocked_server
187
- room.send_create
188
199
  end
189
200
 
190
- it "send create_meeting" do
191
- mocked_api.should_receive(:create_meeting).
192
- with(room.name, room.meeting_id, room.moderator_password,
193
- room.attendee_password, room.welcome_msg).and_return(hash_create)
194
- room.server = mocked_server
195
- room.send_create
201
+ describe "#send_end" do
202
+
203
+ it { should respond_to(:send_end) }
196
204
 
197
- room.attendee_password.should == attendee_password
198
- room.moderator_password.should == moderator_password
205
+ it "send end_meeting" do
206
+ mocked_api.should_receive(:end_meeting).with(room.meetingid, room.moderator_password)
207
+ room.server = mocked_server
208
+ room.send_end
209
+ end
199
210
 
200
- # to be sure that the model was saved
201
- saved = BigbluebuttonRoom.find(room.id)
202
- saved.attendee_password.should == attendee_password
203
- saved.moderator_password.should == moderator_password
204
211
  end
205
212
 
206
- end
213
+ describe "#send_create" do
214
+ let(:attendee_password) { Forgery(:basic).password }
215
+ let(:moderator_password) { Forgery(:basic).password }
216
+ let(:hash_create) {
217
+ {
218
+ :returncode => "SUCCESS", :meetingID => "test_id",
219
+ :attendeePW => attendee_password, :moderatorPW => moderator_password,
220
+ :hasBeenForciblyEnded => "false", :messageKey => {}, :message => {}
221
+ }
222
+ }
207
223
 
208
- describe "#join_url" do
209
- let(:username) { Forgery(:name).full_name }
224
+ it { should respond_to(:send_create) }
210
225
 
211
- it { should respond_to(:join_url) }
226
+ it "send create_meeting" do
227
+ mocked_api.should_receive(:create_meeting).
228
+ with(room.name, room.meetingid, room.moderator_password,
229
+ room.attendee_password, room.welcome_msg, room.dial_number,
230
+ room.logout_url, room.max_participants, room.voice_bridge)
231
+ room.server = mocked_server
232
+ room.send_create
233
+ end
234
+
235
+ it "send create_meeting" do
236
+ mocked_api.should_receive(:create_meeting).
237
+ with(room.name, room.meetingid, room.moderator_password,
238
+ room.attendee_password, room.welcome_msg, room.dial_number,
239
+ room.logout_url, room.max_participants, room.voice_bridge).
240
+ and_return(hash_create)
241
+ room.server = mocked_server
242
+ room.send_create
243
+
244
+ room.attendee_password.should == attendee_password
245
+ room.moderator_password.should == moderator_password
246
+
247
+ # to be sure that the model was saved
248
+ saved = BigbluebuttonRoom.find(room.id)
249
+ saved.attendee_password.should == attendee_password
250
+ saved.moderator_password.should == moderator_password
251
+ end
252
+
253
+ context "randomizes meetingid" do
254
+ let(:fail_hash) { { :returncode => true, :meetingID => "new id",
255
+ :messageKey => "duplicateWarning" } }
256
+ let(:success_hash) { { :returncode => true, :meetingID => "new id",
257
+ :messageKey => "" } }
258
+ let(:new_id) { "new id" }
259
+ before {
260
+ room.randomize_meetingid = true
261
+ room.server = mocked_server
262
+ }
263
+
264
+ it "before calling create" do
265
+ room.should_receive(:random_meetingid).and_return(new_id)
266
+ mocked_api.should_receive(:create_meeting).
267
+ with(room.name, new_id, room.moderator_password,
268
+ room.attendee_password, room.welcome_msg, room.dial_number,
269
+ room.logout_url, room.max_participants, room.voice_bridge)
270
+ room.send_create
271
+ end
272
+
273
+ it "and tries again on error" do
274
+ # fails twice and them succeds
275
+ room.should_receive(:random_meetingid).exactly(3).times.and_return(new_id)
276
+ mocked_api.should_receive(:create_meeting).
277
+ with(room.name, new_id, room.moderator_password,
278
+ room.attendee_password, room.welcome_msg, room.dial_number,
279
+ room.logout_url, room.max_participants, room.voice_bridge).
280
+ twice.
281
+ and_return(fail_hash)
282
+ mocked_api.should_receive(:create_meeting).
283
+ with(room.name, new_id, room.moderator_password,
284
+ room.attendee_password, room.welcome_msg, room.dial_number,
285
+ room.logout_url, room.max_participants, room.voice_bridge).
286
+ once.
287
+ and_return(success_hash)
288
+ room.send_create
289
+ end
290
+
291
+ it "and limits to 10 tries" do
292
+ room.should_receive(:random_meetingid).exactly(11).times.and_return(new_id)
293
+ mocked_api.should_receive(:create_meeting).
294
+ with(room.name, new_id, room.moderator_password,
295
+ room.attendee_password, room.welcome_msg, room.dial_number,
296
+ room.logout_url, room.max_participants, room.voice_bridge).
297
+ exactly(10).times.
298
+ and_return(fail_hash)
299
+ room.send_create
300
+ end
301
+ end
212
302
 
213
- it "with moderator role" do
214
- mocked_api.should_receive(:join_meeting_url).
215
- with(room.meeting_id, username, room.moderator_password)
216
- room.server = mocked_server
217
- room.join_url(username, :moderator)
218
303
  end
219
304
 
220
- it "with attendee role" do
221
- mocked_api.should_receive(:join_meeting_url).
222
- with(room.meeting_id, username, room.attendee_password)
223
- room.server = mocked_server
224
- room.join_url(username, :attendee)
305
+ describe "#join_url" do
306
+ let(:username) { Forgery(:name).full_name }
307
+
308
+ it { should respond_to(:join_url) }
309
+
310
+ it "with moderator role" do
311
+ mocked_api.should_receive(:join_meeting_url).
312
+ with(room.meetingid, username, room.moderator_password)
313
+ room.server = mocked_server
314
+ room.join_url(username, :moderator)
315
+ end
316
+
317
+ it "with attendee role" do
318
+ mocked_api.should_receive(:join_meeting_url).
319
+ with(room.meetingid, username, room.attendee_password)
320
+ room.server = mocked_server
321
+ room.join_url(username, :attendee)
322
+ end
323
+
225
324
  end
226
325
 
227
326
  end