bigbluebutton_rails 0.0.2 → 0.0.3

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 (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