bigbluebutton-api-ruby 0.0.11 → 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +5 -2
  2. data/.rvmrc +1 -1
  3. data/.travis.yml +6 -0
  4. data/CHANGELOG.rdoc +19 -8
  5. data/Gemfile +9 -1
  6. data/Gemfile.lock +62 -9
  7. data/LICENSE +5 -7
  8. data/LICENSE_003 +20 -0
  9. data/README.rdoc +42 -19
  10. data/Rakefile +31 -19
  11. data/bigbluebutton-api-ruby.gemspec +5 -5
  12. data/examples/get_version_example.rb +18 -0
  13. data/examples/join_example.rb +59 -0
  14. data/examples/overall_0.7_example.rb +92 -0
  15. data/examples/prepare.rb +38 -0
  16. data/extras/bigbluebutton_bot.rb +64 -0
  17. data/extras/download_bot_from.txt +1 -0
  18. data/extras/test-presentation.pdf +0 -0
  19. data/features/check_status.feature +45 -0
  20. data/features/config.yml.example +21 -0
  21. data/features/create_meetings.feature +29 -0
  22. data/features/end_meetings.feature +27 -0
  23. data/features/join_meetings.feature +29 -0
  24. data/features/pre_upload_slides.feature +14 -0
  25. data/features/recordings.feature +34 -0
  26. data/features/step_definitions/check_status_steps.rb +119 -0
  27. data/features/step_definitions/common_steps.rb +122 -0
  28. data/features/step_definitions/create_meetings_steps.rb +54 -0
  29. data/features/step_definitions/end_meetings_steps.rb +49 -0
  30. data/features/step_definitions/join_meetings_steps.rb +39 -0
  31. data/features/step_definitions/pre_upload_slides_steps.rb +13 -0
  32. data/features/step_definitions/recordings_steps.rb +38 -0
  33. data/features/support/api_tests/configs.rb +51 -0
  34. data/features/support/env.rb +7 -0
  35. data/features/support/hooks.rb +11 -0
  36. data/lib/bigbluebutton_api.rb +301 -97
  37. data/lib/bigbluebutton_formatter.rb +105 -19
  38. data/lib/bigbluebutton_modules.rb +92 -0
  39. data/lib/hash_to_xml.rb +22 -51
  40. data/spec/bigbluebutton_api_0.8_spec.rb +273 -0
  41. data/spec/bigbluebutton_api_spec.rb +211 -117
  42. data/spec/bigbluebutton_formatter_spec.rb +178 -29
  43. data/spec/bigbluebutton_modules_spec.rb +95 -0
  44. data/spec/data/hash_to_xml_complex.xml +45 -0
  45. data/spec/hash_to_xml_spec.rb +143 -0
  46. data/spec/spec_helper.rb +4 -2
  47. data/spec/support/forgery/forgeries/random_name.rb +7 -0
  48. data/spec/support/forgery/forgeries/url.rb +5 -0
  49. metadata +47 -12
  50. data/test/config.yml.example +0 -9
  51. data/test/test.rb +0 -154
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
+ # Note: this file tests the functioning of the API object using BBB API version 0.7 as a basis
3
4
  describe BigBlueButton::BigBlueButtonApi do
4
5
 
5
6
  # default variables and API object for all tests
@@ -16,8 +17,9 @@ describe BigBlueButton::BigBlueButtonApi do
16
17
  it { subject.salt.should be(salt) }
17
18
  it { subject.version.should be(version) }
18
19
  it { subject.debug.should be(debug) }
19
- it { subject.timeout.should be(2) }
20
+ it { subject.timeout.should be(10) }
20
21
  it { subject.supported_versions.should include("0.7") }
22
+ it { subject.supported_versions.should include("0.8") }
21
23
  end
22
24
 
23
25
  context "when the version is not informed, get it from the BBB server" do
@@ -34,51 +36,55 @@ describe BigBlueButton::BigBlueButtonApi do
34
36
 
35
37
  context "current supported versions" do
36
38
  subject { BigBlueButton::BigBlueButtonApi.new(url, salt) }
37
- it { subject.supported_versions.should == ["0.7"] }
39
+ it { subject.supported_versions.should == ["0.7", "0.8"] }
38
40
  end
39
41
  end
40
42
 
41
- describe "#join_meeting_url" do
42
- let(:meeting_id) { "meeting-id" }
43
- let(:password) { "password" }
44
- let(:user_name) { "user-name" }
45
- let(:user_id) { "user-id" }
46
- let(:web_voice_conf) { "web-voice-conf" }
47
- let(:params) {
48
- { :meetingID => meeting_id, :password => password, :fullName => user_name,
49
- :userID => user_id, :webVoiceConf => web_voice_conf }
50
- }
43
+ describe "#create_meeting" do
44
+ context "standard case" do
45
+ let(:req_params) {
46
+ { :name => "name", :meetingID => "meeting-id", :moderatorPW => "mp", :attendeePW => "ap",
47
+ :welcome => "Welcome!", :dialNumber => 12345678, :logoutURL => "http://example.com",
48
+ :maxParticipants => 25, :voiceBridge => 12345, :webVoice => "12345abc" }
49
+ }
50
+ let(:req_response) {
51
+ { :meetingID => 123, :moderatorPW => 111, :attendeePW => 222, :hasBeenForciblyEnded => "FALSE" }
52
+ }
53
+ let(:final_response) {
54
+ { :meetingID => "123", :moderatorPW => "111", :attendeePW => "222", :hasBeenForciblyEnded => false }
55
+ }
56
+
57
+ # ps: not mocking the formatter here because it's easier to just check the results (final_response)
58
+ before { api.should_receive(:send_api_request).with(:create, req_params).and_return(req_response) }
59
+ subject {
60
+ options = { :moderatorPW => "mp", :attendeePW => "ap", :welcome => "Welcome!", :dialNumber => 12345678,
61
+ :logoutURL => "http://example.com", :maxParticipants => 25, :voiceBridge => 12345, :webVoice => "12345abc" }
62
+ api.create_meeting("name", "meeting-id", options)
63
+ }
64
+ it { subject.should == final_response }
65
+ end
51
66
 
52
- before { api.should_receive(:get_url).with(:join, params).and_return("test-url") }
53
- it { api.join_meeting_url(meeting_id, user_name, password, user_id, web_voice_conf).should == "test-url" }
54
- end
67
+ context "discards invalid options" do
68
+ let(:req_params) {
69
+ { :name => "name", :meetingID => "meeting-id", :moderatorPW => "mp", :attendeePW => "ap" }
70
+ }
71
+ before { api.should_receive(:send_api_request).with(:create, req_params) }
72
+ it {
73
+ options = { :invalidParam => "1", :moderatorPW => "mp", :attendeePW => "ap", :invalidParam2 => "1" }
74
+ api.create_meeting("name", "meeting-id", options)
75
+ }
76
+ end
55
77
 
56
- describe "#create_meeting" do
57
- let(:meeting_name) { "name" }
58
- let(:meeting_id) { "meeting-id" }
59
- let(:moderator_password) { "moderator-password" }
60
- let(:attendee_password) { "attendee-password" }
61
- let(:welcome_message) { "welcome" }
62
- let(:dial_number) { "dial-number" }
63
- let(:logout_url) { "logout-url" }
64
- let(:max_participants) { "max-participants" }
65
- let(:voice_bridge) { "voice-bridge" }
66
- let(:params) {
67
- { :name => meeting_name, :meetingID => meeting_id,
68
- :moderatorPW => moderator_password, :attendeePW => attendee_password,
69
- :welcome => welcome_message, :dialNumber => dial_number,
70
- :logoutURL => logout_url, :maxParticpants => max_participants,
71
- :voiceBridge => voice_bridge }
72
- }
73
- let(:response) { { :meetingID => 123, :moderatorPW => 111, :attendeePW => 222, :hasBeenForciblyEnded => "FALSE" } }
74
- let(:expected_response) { { :meetingID => "123", :moderatorPW => "111", :attendeePW => "222", :hasBeenForciblyEnded => false } }
75
-
76
- # ps: not mocking the formatter here because it's easier to just check the results (expected_response)
77
- before { api.should_receive(:send_api_request).with(:create, params).and_return(response) }
78
- subject { api.create_meeting(meeting_name, meeting_id, moderator_password,
79
- attendee_password, welcome_message, dial_number,
80
- logout_url, max_participants, voice_bridge) }
81
- it { subject.should == expected_response }
78
+ context "discards options for >0.7" do
79
+ let(:req_params) {
80
+ { :name => "name", :meetingID => "meeting-id" }
81
+ }
82
+ before { api.should_receive(:send_api_request).with(:create, req_params) }
83
+ it {
84
+ options = { :record => true, :duration => 25, :meta_any => "meta" }
85
+ api.create_meeting("name", "meeting-id", options)
86
+ }
87
+ end
82
88
  end
83
89
 
84
90
  describe "#end_meeting" do
@@ -108,19 +114,78 @@ describe BigBlueButton::BigBlueButtonApi do
108
114
  end
109
115
  end
110
116
 
117
+ describe "#join_meeting_url" do
118
+ context "standard case" do
119
+ let(:params) {
120
+ { :meetingID => "meeting-id", :password => "pw", :fullName => "Name",
121
+ :userID => "id123", :webVoiceConf => 12345678 }
122
+ }
123
+
124
+ before { api.should_receive(:get_url).with(:join, params).and_return("test-url") }
125
+ it {
126
+ options = { :userID => "id123", :webVoiceConf => 12345678 }
127
+ api.join_meeting_url("meeting-id", "Name", "pw", options).should == "test-url"
128
+ }
129
+ end
130
+
131
+ context "discards invalid options" do
132
+ let(:params) {
133
+ { :meetingID => "meeting-id", :password => "pw", :fullName => "Name", :userID => "id123" }
134
+ }
135
+ before { api.should_receive(:get_url).with(:join, params) }
136
+ it {
137
+ options = { :invalidParam => "1", :userID => "id123", :invalidParam2 => "1" }
138
+ api.join_meeting_url("meeting-id", "Name", "pw", options)
139
+ }
140
+ end
141
+
142
+ context "discards options for <= 0.7" do
143
+ let(:params) {
144
+ { :meetingID => "meeting-id", :password => "pw", :fullName => "Name" }
145
+ }
146
+ before { api.should_receive(:get_url).with(:join, params) }
147
+ it {
148
+ options = { :createTime => 123456789 }
149
+ api.join_meeting_url("meeting-id", "Name", "pw", options)
150
+ }
151
+ end
152
+ end
153
+
111
154
  describe "#join_meeting" do
112
- let(:meeting_id) { "meeting-id" }
113
- let(:password) { "password" }
114
- let(:user_name) { "user-name" }
115
- let(:user_id) { "user-id" }
116
- let(:web_voice_conf) { "web-voice-conf" }
117
- let(:params) {
118
- { :meetingID => meeting_id, :password => password, :fullName => user_name,
119
- :userID => user_id, :webVoiceConf => web_voice_conf }
120
- }
155
+ context "standard case" do
156
+ let(:params) {
157
+ { :meetingID => "meeting-id", :password => "pw", :fullName => "Name",
158
+ :userID => "id123", :webVoiceConf => 12345678 }
159
+ }
160
+
161
+ before { api.should_receive(:send_api_request).with(:join, params).and_return("join-return") }
162
+ it {
163
+ options = { :userID => "id123", :webVoiceConf => 12345678 }
164
+ api.join_meeting("meeting-id", "Name", "pw", options).should == "join-return"
165
+ }
166
+ end
167
+
168
+ context "discards invalid options" do
169
+ let(:params) {
170
+ { :meetingID => "meeting-id", :password => "pw", :fullName => "Name", :userID => "id123" }
171
+ }
172
+ before { api.should_receive(:send_api_request).with(:join, params) }
173
+ it {
174
+ options = { :invalidParam => "1", :userID => "id123", :invalidParam2 => "1" }
175
+ api.join_meeting("meeting-id", "Name", "pw", options)
176
+ }
177
+ end
121
178
 
122
- before { api.should_receive(:send_api_request).with(:join, params).and_return("join-return") }
123
- it { api.join_meeting(meeting_id, user_name, password, user_id, web_voice_conf).should == "join-return" }
179
+ context "discards options for <= 0.7" do
180
+ let(:params) {
181
+ { :meetingID => "meeting-id", :password => "pw", :fullName => "Name" }
182
+ }
183
+ before { api.should_receive(:send_api_request).with(:join, params) }
184
+ it {
185
+ options = { :createTime => 123456789 }
186
+ api.join_meeting("meeting-id", "Name", "pw", options)
187
+ }
188
+ end
124
189
  end
125
190
 
126
191
  describe "#get_meeting_info" do
@@ -133,20 +198,22 @@ describe BigBlueButton::BigBlueButtonApi do
133
198
  let(:response) {
134
199
  { :meetingID => 123, :moderatorPW => 111, :attendeePW => 222, :hasBeenForciblyEnded => "FALSE",
135
200
  :running => "TRUE", :startTime => "Thu Sep 01 17:51:42 UTC 2011", :endTime => "null",
136
- :returncode => true, :attendees => { :attendee => [ attendee1, attendee2 ] }, :messageKey => "mkey", :message => "m" }
137
- } # hash after the send_api_request call, before the specific formatting
201
+ :returncode => true, :attendees => { :attendee => [ attendee1, attendee2 ] },
202
+ :messageKey => "mkey", :message => "m", :participantCount => "50", :moderatorCount => "3" }
203
+ } # hash after the send_api_request call, before the formatting
138
204
 
139
205
  let(:expected_attendee1) { { :userID => "123", :fullName => "Dexter Morgan", :role => :moderator } }
140
206
  let(:expected_attendee2) { { :userID => "id2", :fullName => "Cameron", :role => :viewer } }
141
- let(:expected_response) {
207
+ let(:final_response) {
142
208
  { :meetingID => "123", :moderatorPW => "111", :attendeePW => "222", :hasBeenForciblyEnded => false,
143
209
  :running => true, :startTime => DateTime.parse("Thu Sep 01 17:51:42 UTC 2011"), :endTime => nil,
144
- :returncode => true, :attendees => [ expected_attendee1, expected_attendee2 ], :messageKey => "mkey", :message => "m" }
210
+ :returncode => true, :attendees => [ expected_attendee1, expected_attendee2 ],
211
+ :messageKey => "mkey", :message => "m", :participantCount => 50, :moderatorCount => 3 }
145
212
  } # expected return hash after all the formatting
146
213
 
147
- # ps: not mocking the formatter here because it's easier to just check the results (expected_response)
214
+ # ps: not mocking the formatter here because it's easier to just check the results (final_response)
148
215
  before { api.should_receive(:send_api_request).with(:getMeetingInfo, params).and_return(response) }
149
- it { api.get_meeting_info(meeting_id, password).should == expected_response }
216
+ it { api.get_meeting_info(meeting_id, password).should == final_response }
150
217
  end
151
218
 
152
219
  describe "#get_meetings" do
@@ -157,13 +224,13 @@ describe BigBlueButton::BigBlueButtonApi do
157
224
  } # hash *after* the flatten_objects call
158
225
 
159
226
  before {
160
- # FIXME: how to expect a hash with a random value in the should_receive below?
161
- api.should_receive(:send_api_request).with(:getMeetings, anything).and_return(flattened_response)
227
+ api.should_receive(:send_api_request).with(:getMeetings, hash_including(:random => kind_of(Integer))).
228
+ and_return(flattened_response)
162
229
  formatter_mock = mock(BigBlueButton::BigBlueButtonFormatter)
163
230
  formatter_mock.should_receive(:flatten_objects).with(:meetings, :meeting)
164
- formatter_mock.should_receive(:format_meeting).with(meeting_hash1)
165
- formatter_mock.should_receive(:format_meeting).with(meeting_hash2)
166
231
  BigBlueButton::BigBlueButtonFormatter.should_receive(:new).and_return(formatter_mock)
232
+ BigBlueButton::BigBlueButtonFormatter.should_receive(:format_meeting).with(meeting_hash1)
233
+ BigBlueButton::BigBlueButtonFormatter.should_receive(:format_meeting).with(meeting_hash2)
167
234
  }
168
235
  it { api.get_meetings }
169
236
  end
@@ -232,6 +299,20 @@ describe BigBlueButton::BigBlueButtonApi do
232
299
  it { api.last_http_response.should == request_mock }
233
300
  end
234
301
 
302
+ describe "#last_xml_response" do
303
+ # we test this through a #test_connection call
304
+
305
+ let(:request_mock) { mock }
306
+ let(:expected_xml) { "<response><returncode>SUCCESS</returncode></response>" }
307
+ before {
308
+ api.should_receive(:get_url)
309
+ api.should_receive(:send_request).and_return(request_mock)
310
+ request_mock.should_receive(:body).at_least(1).and_return(expected_xml)
311
+ api.test_connection
312
+ }
313
+ it { api.last_xml_response.should == expected_xml }
314
+ end
315
+
235
316
  describe "#get_url" do
236
317
 
237
318
  context "when method = :index" do
@@ -243,7 +324,14 @@ describe BigBlueButton::BigBlueButtonApi do
243
324
  context "with params" do
244
325
  let(:params) { { :param1 => "value1", :param2 => "value2" } }
245
326
  subject { api.get_url(:join, params) }
246
- it { subject.should match(/#{url}\/join\?param1=value1&param2=value2/) }
327
+ it {
328
+ # the hash can be sorted differently depending on the ruby version
329
+ if params.map{ |k,v| "#{k}" }.join =~ /^param1/
330
+ subject.should match(/#{url}\/join\?param1=value1&param2=value2/)
331
+ else
332
+ subject.should match(/#{url}\/join\?param2=value2&param1=value1/)
333
+ end
334
+ }
247
335
  end
248
336
 
249
337
  context "without params" do
@@ -267,59 +355,33 @@ describe BigBlueButton::BigBlueButtonApi do
267
355
 
268
356
  context "includes the checksum" do
269
357
  let(:params) { { :param1 => "value1", :param2 => "value2" } }
270
- let(:checksum) { Digest::SHA1.hexdigest("joinparam1=value1&param2=value2#{salt}") }
358
+ let(:checksum) {
359
+ # the hash can be sorted differently depending on the ruby version
360
+ if params.map{ |k,v| "#{k}" }.join =~ /^param1/
361
+ "67882ae54f49600f56f358c10d24697ef7d8c6b2"
362
+ else
363
+ "85a54e28e4ec18bfdcb214a73f74d35b09a84176"
364
+ end
365
+ }
271
366
  subject { api.get_url(:join, params) }
272
367
  it { subject.should match(/checksum=#{checksum}$/) }
273
368
  end
274
369
  end
275
370
  end
276
371
 
277
- # FIXME: this complex test means that the method is too complex - try to refactor it
278
372
  describe "#send_api_request" do
279
373
  let(:method) { :join }
280
374
  let(:params) { { :param1 => "value1" } }
281
- let(:target_url) { "http://test-server:8080?param1=value1&checksum=12345" }
282
- let(:make_request) { api.send_api_request(method, params) }
283
- before { api.should_receive(:get_url).with(method, params).and_return(target_url) }
375
+ let(:data) { "any data" }
376
+ let(:url) { "http://test-server:8080?param1=value1&checksum=12345" }
377
+ let(:make_request) { api.send_api_request(method, params, data) }
378
+ let(:response_mock) { mock() } # mock of what send_request() would return
284
379
 
285
- def setup_http_mock
286
- @http_mock = mock(Net::HTTP)
287
- Net::HTTP.should_receive(:new).with("test-server", 8080).and_return(@http_mock)
288
- @http_mock.should_receive(:"open_timeout=").with(api.timeout)
289
- @http_mock.should_receive(:"read_timeout=").with(api.timeout)
290
- end
291
-
292
- context "sets up the Net::HTTP object correctly" do
293
- before do
294
- setup_http_mock
295
- response_mock = mock()
296
- @http_mock.should_receive(:get).and_return(response_mock)
297
- response_mock.should_receive(:body).and_return("") # so the method exits right after the setup
298
- end
299
- it { make_request }
300
- end
301
-
302
- context "handles a TimeoutError" do
303
- before do
304
- setup_http_mock
305
- @http_mock.should_receive(:get) { raise TimeoutError }
306
- end
307
- it { expect { make_request }.to raise_error(BigBlueButton::BigBlueButtonException) }
308
- end
309
-
310
- context "handles general Exceptions" do
311
- before do
312
- setup_http_mock
313
- @http_mock.should_receive(:get) { raise Exception }
314
- end
315
- it { expect { make_request }.to raise_error(BigBlueButton::BigBlueButtonException) }
316
- end
380
+ before { api.should_receive(:get_url).with(method, params).and_return(url) }
317
381
 
318
382
  context "returns an empty hash if the response body is empty" do
319
383
  before do
320
- setup_http_mock
321
- response_mock = mock()
322
- @http_mock.should_receive(:get).and_return(response_mock)
384
+ api.should_receive(:send_request).with(url, data).and_return(response_mock)
323
385
  response_mock.should_receive(:body).and_return("")
324
386
  end
325
387
  it { make_request.should == { } }
@@ -327,9 +389,7 @@ describe BigBlueButton::BigBlueButtonApi do
327
389
 
328
390
  context "hashfies and validates the response body" do
329
391
  before do
330
- setup_http_mock
331
- response_mock = mock()
332
- @http_mock.should_receive(:get).and_return(response_mock)
392
+ api.should_receive(:send_request).with(url, data).and_return(response_mock)
333
393
  response_mock.should_receive(:body).twice.and_return("response-body")
334
394
  end
335
395
 
@@ -345,17 +405,15 @@ describe BigBlueButton::BigBlueButtonApi do
345
405
  end
346
406
 
347
407
  context "formats the response hash" do
348
- let(:response) { { :response => { :returncode => true } } }
349
- let(:formatted_response) { { :returncode => true } }
408
+ let(:response) { { :returncode => "SUCCESS" } }
409
+ let(:formatted_response) { { :returncode => true, :messageKey => "", :message => "" } }
350
410
  before do
351
- setup_http_mock
352
-
353
- response_mock = mock()
354
- @http_mock.should_receive(:get).and_return(response_mock)
411
+ api.should_receive(:send_request).with(url, data).and_return(response_mock)
355
412
  response_mock.should_receive(:body).twice.and_return("response-body")
356
413
  Hash.should_receive(:from_xml).with("response-body").and_return(response)
357
414
 
358
415
  # here starts the validation
416
+ # doesn't test the resulting format, only that the formatter was called
359
417
  formatter_mock = mock(BigBlueButton::BigBlueButtonFormatter)
360
418
  BigBlueButton::BigBlueButtonFormatter.should_receive(:new).with(response).and_return(formatter_mock)
361
419
  formatter_mock.should_receive(:default_formatting).and_return(formatted_response)
@@ -364,13 +422,10 @@ describe BigBlueButton::BigBlueButtonApi do
364
422
  end
365
423
 
366
424
  context "raise an error if the formatted response has no :returncode" do
367
- let(:response) { { :response => { :returncode => true } } }
425
+ let(:response) { { :returncode => true } }
368
426
  let(:formatted_response) { { } }
369
427
  before do
370
- setup_http_mock
371
-
372
- response_mock = mock()
373
- @http_mock.should_receive(:get).and_return(response_mock)
428
+ api.should_receive(:send_request).with(url, data).and_return(response_mock)
374
429
  response_mock.should_receive(:body).twice.and_return("response-body")
375
430
  Hash.should_receive(:from_xml).with("response-body").and_return(response)
376
431
 
@@ -380,6 +435,45 @@ describe BigBlueButton::BigBlueButtonApi do
380
435
  end
381
436
  it { expect { make_request }.to raise_error(BigBlueButton::BigBlueButtonException) }
382
437
  end
438
+ end
439
+
440
+ describe "#send_request" do
441
+ let(:url) { "http://test-server:8080/res?param1=value1&checksum=12345" }
442
+ let(:url_parsed) { URI.parse(url) }
443
+
444
+ before do
445
+ @http_mock = mock(Net::HTTP)
446
+ @http_mock.should_receive(:"open_timeout=").with(api.timeout)
447
+ @http_mock.should_receive(:"read_timeout=").with(api.timeout)
448
+ Net::HTTP.should_receive(:new).with("test-server", 8080).and_return(@http_mock)
449
+ end
450
+
451
+ context "standard case" do
452
+ before { @http_mock.should_receive(:get).with("/res?param1=value1&checksum=12345").and_return("ok") }
453
+ it { api.send(:send_request, url).should == "ok" }
454
+ end
455
+
456
+ context "handles a TimeoutError" do
457
+ before { @http_mock.should_receive(:get) { raise TimeoutError } }
458
+ it { expect { api.send(:send_request, url) }.to raise_error(BigBlueButton::BigBlueButtonException) }
459
+ end
460
+
461
+ context "handles general Exceptions" do
462
+ before { @http_mock.should_receive(:get) { raise Exception } }
463
+ it { expect { api.send(:send_request, url) }.to raise_error(BigBlueButton::BigBlueButtonException) }
464
+ end
465
+
466
+ context "with data" do
467
+ let(:data) { "any data" }
468
+ before {
469
+ path = "/res?param1=value1&checksum=12345"
470
+ opts = { 'Content-Type' => 'text/xml' }
471
+ @http_mock.should_receive(:post).with(path, data, opts).and_return("ok")
472
+ }
473
+ it {
474
+ api.send(:send_request, url, data).should == "ok"
475
+ }
476
+ end
383
477
 
384
478
  end
385
479
 
@@ -8,33 +8,158 @@ describe BigBlueButton::BigBlueButtonFormatter do
8
8
  it { subject.should respond_to(:"hash=") }
9
9
  end
10
10
 
11
- describe "#to_stringtring" do
11
+ describe "#initialize" do
12
+ context "with a hash" do
13
+ let(:hash) { { :param1 => "123", :param2 => 123, :param3 => true } }
14
+ subject { BigBlueButton::BigBlueButtonFormatter.new(hash) }
15
+ it { subject.hash.should == hash }
16
+ end
17
+
18
+ context "without a hash" do
19
+ subject { BigBlueButton::BigBlueButtonFormatter.new(nil) }
20
+ it { subject.hash.should == { } }
21
+ end
22
+ end
23
+
24
+ describe "#to_string" do
12
25
  let(:hash) { { :param1 => "123", :param2 => 123, :param3 => true } }
13
- subject { BigBlueButton::BigBlueButtonFormatter.new(hash) }
14
- it { subject.to_string(:param1).should == "123" }
15
- it { subject.to_string(:param2).should == "123" }
16
- it { subject.to_string(:param3).should == "true" }
26
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(hash) }
27
+ before {
28
+ formatter.to_string(:param1)
29
+ formatter.to_string(:param2)
30
+ formatter.to_string(:param3)
31
+ }
32
+ it { hash[:param1].should == "123" }
33
+ it { hash[:param2].should == "123" }
34
+ it { hash[:param3].should == "true" }
35
+
36
+ context "returns empty string if the param doesn't exists" do
37
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => 1 }) }
38
+ it { subject.to_string(:inexistent).should == "" }
39
+ end
40
+
41
+ context "returns empty string if the hash is nil" do
42
+ subject { BigBlueButton::BigBlueButtonFormatter.new(nil) }
43
+ it { subject.to_string(:inexistent).should == "" }
44
+ end
17
45
  end
18
46
 
19
- describe "#to_booleanoolean" do
47
+ describe "#to_boolean" do
20
48
  let(:hash) { { :true1 => "TRUE", :true2 => "true", :false1 => "FALSE", :false2 => "false" } }
21
- subject { BigBlueButton::BigBlueButtonFormatter.new(hash) }
22
- it { subject.to_boolean(:true1).should be_true }
23
- it { subject.to_boolean(:true2).should be_true }
24
- it { subject.to_boolean(:false1).should be_false }
25
- it { subject.to_boolean(:false2).should be_false }
49
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(hash) }
50
+ before {
51
+ formatter.to_boolean(:true1)
52
+ formatter.to_boolean(:true2)
53
+ formatter.to_boolean(:false1)
54
+ formatter.to_boolean(:false2)
55
+ }
56
+ it { hash[:true1].should be_true }
57
+ it { hash[:true2].should be_true }
58
+ it { hash[:false1].should be_false }
59
+ it { hash[:false2].should be_false }
60
+
61
+ context "returns false if the param doesn't exists" do
62
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => 1}) }
63
+ it { subject.to_boolean(:inexistent).should == false }
64
+ end
65
+
66
+ context "returns false if the hash is nil" do
67
+ subject { BigBlueButton::BigBlueButtonFormatter.new(nil) }
68
+ it { subject.to_boolean(:inexistent).should == false }
69
+ end
26
70
  end
27
71
 
28
72
  describe "#to_datetime" do
29
- let(:hash) { { :param1 => "Thu Sep 01 17:51:42 UTC 2011", :param2 => "Thu Sep 08", :param3 => "NULL" } }
30
- subject { BigBlueButton::BigBlueButtonFormatter.new(hash) }
31
- it { subject.to_datetime(:param1).should == DateTime.parse("Thu Sep 01 17:51:42 UTC 2011") }
32
- it { subject.to_datetime(:param2).should == DateTime.parse("Thu Sep 08") }
33
- it { subject.to_datetime(:param3).should == nil }
73
+ let(:hash) { { :param1 => "Thu Sep 01 17:51:42 UTC 2011", :param2 => "Thu Sep 08",
74
+ :param3 => 1315254777880, :param4 => "1315254777880",
75
+ :param5 => "0", :param6 => 0,
76
+ :param7 => "NULL", :param8 => nil } }
77
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(hash) }
78
+ before {
79
+ formatter.to_datetime(:param1)
80
+ formatter.to_datetime(:param2)
81
+ formatter.to_datetime(:param3)
82
+ formatter.to_datetime(:param4)
83
+ formatter.to_datetime(:param5)
84
+ formatter.to_datetime(:param6)
85
+ formatter.to_datetime(:param7)
86
+ }
87
+ it { hash[:param1].should == DateTime.parse("Thu Sep 01 17:51:42 UTC 2011") }
88
+ it { hash[:param2].should == DateTime.parse("Thu Sep 08") }
89
+ it { hash[:param3].should == DateTime.parse("2011-09-05 17:32:57 -0300") }
90
+ it { hash[:param4].should == DateTime.parse("2011-09-05 17:32:57 -0300") }
91
+ it { hash[:param5].should == nil }
92
+ it { hash[:param6].should == nil }
93
+ it { hash[:param7].should == nil }
94
+ it { hash[:param8].should == nil }
95
+
96
+ context "returns nil if the param doesn't exists" do
97
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => 1}) }
98
+ it { subject.to_datetime(:inexistent).should == nil }
99
+ end
100
+
101
+ context "returns nil if the hash is nil" do
102
+ subject { BigBlueButton::BigBlueButtonFormatter.new(nil) }
103
+ it { subject.to_datetime(:inexistent).should == nil }
104
+ end
105
+ end
106
+
107
+ describe "#to_sym" do
108
+ let(:hash) { { :param1 => :sym1, :param2 => "sym2", :param3 => "SyM3" } }
109
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(hash) }
110
+ before {
111
+ formatter.to_sym(:param1)
112
+ formatter.to_sym(:param2)
113
+ formatter.to_sym(:param3)
114
+ }
115
+ it { hash[:param1].should == :sym1 }
116
+ it { hash[:param2].should == :sym2 }
117
+ it { hash[:param3].should == :sym3 }
118
+
119
+ context "returns empty string if the param doesn't exists" do
120
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => 1 }) }
121
+ it { subject.to_string(:inexistent).should == "" }
122
+ end
123
+
124
+ context "returns empty string if the hash is nil" do
125
+ subject { BigBlueButton::BigBlueButtonFormatter.new(nil) }
126
+ it { subject.to_string(:inexistent).should == "" }
127
+ end
128
+
129
+ context "returns empty string if the value to be converted is an empty string" do
130
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => "" }) }
131
+ it { subject.to_string(:param).should == "" }
132
+ end
133
+ end
134
+
135
+ describe "#to_int" do
136
+ let(:hash) { { :param1 => 5, :param2 => "5" } }
137
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(hash) }
138
+ before {
139
+ formatter.to_int(:param1)
140
+ formatter.to_int(:param2)
141
+ }
142
+ it { hash[:param1].should == 5 }
143
+ it { hash[:param2].should == 5 }
144
+
145
+ context "returns 0 if the param doesn't exists" do
146
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => 1 }) }
147
+ it { subject.to_int(:inexistent).should == 0 }
148
+ end
149
+
150
+ context "returns 0 if the hash is nil" do
151
+ subject { BigBlueButton::BigBlueButtonFormatter.new(nil) }
152
+ it { subject.to_int(:inexistent).should == 0 }
153
+ end
154
+
155
+ context "returns 0 if the value to be converted is invalid" do
156
+ subject { BigBlueButton::BigBlueButtonFormatter.new({ :param => "invalid" }) }
157
+ it { subject.to_int(:param).should == 0 }
158
+ end
34
159
  end
35
160
 
36
161
  describe "#default_formatting" do
37
- let(:input) { { :response => { :returncode => "SUCCESS", :messageKey => "mkey", :message => "m" } } }
162
+ let(:input) { { :returncode => "SUCCESS", :messageKey => "mkey", :message => "m" } }
38
163
  let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(input) }
39
164
 
40
165
  context "standard case" do
@@ -44,61 +169,85 @@ describe BigBlueButton::BigBlueButtonFormatter do
44
169
  end
45
170
 
46
171
  context "when :returncode should be false" do
47
- before { input[:response][:returncode] = "ERROR" }
172
+ before { input[:returncode] = "ERROR" }
48
173
  subject { formatter.default_formatting }
49
174
  it { subject[:returncode].should be_false }
50
175
  end
51
176
 
52
177
  context "when :messageKey is empty" do
53
- before { input[:response][:messageKey] = {} }
178
+ before { input[:messageKey] = {} }
54
179
  subject { formatter.default_formatting }
55
180
  it { subject[:messageKey].should == "" }
56
181
  end
57
182
 
58
183
  context "when :messageKey is nil" do
59
- before { input[:response].delete(:messageKey) }
184
+ before { input.delete(:messageKey) }
60
185
  subject { formatter.default_formatting }
61
186
  it { subject[:messageKey].should == "" }
62
187
  end
63
188
 
64
189
  context "when :message is empty" do
65
- before { input[:response][:message] = {} }
190
+ before { input[:message] = {} }
66
191
  subject { formatter.default_formatting }
67
192
  it { subject[:message].should == "" }
68
193
  end
69
194
 
70
195
  context "when there's no :message key" do
71
- before { input[:response].delete(:message) }
196
+ before { input.delete(:message) }
72
197
  subject { formatter.default_formatting }
73
198
  it { subject[:message].should == "" }
74
199
  end
75
200
  end
76
201
 
77
- describe "#format_meeting" do
78
- let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new({}) }
202
+ describe ".format_meeting" do
79
203
  let(:hash) {
80
204
  { :meetingID => 123, :moderatorPW => 111, :attendeePW => 222,
81
- :hasBeenForciblyEnded => "FALSE", :running => "TRUE" }
205
+ :hasBeenForciblyEnded => "FALSE", :running => "TRUE", :createTime => "123456789" }
82
206
  }
83
207
 
84
- subject { formatter.format_meeting(hash) }
208
+ subject { BigBlueButton::BigBlueButtonFormatter.format_meeting(hash) }
85
209
  it { subject[:meetingID].should == "123" }
86
210
  it { subject[:moderatorPW].should == "111" }
87
211
  it { subject[:attendeePW].should == "222" }
88
212
  it { subject[:hasBeenForciblyEnded].should == false }
89
213
  it { subject[:running].should == true }
214
+ it { subject[:createTime].should == 123456789 }
90
215
  end
91
216
 
92
- describe "#format_attendee" do
93
- let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new({}) }
217
+ describe ".format_attendee" do
94
218
  let(:hash) { { :userID => 123, :fullName => "Cameron", :role => "VIEWER" } }
95
219
 
96
- subject { formatter.format_attendee(hash) }
220
+ subject { BigBlueButton::BigBlueButtonFormatter.format_attendee(hash) }
97
221
  it { subject[:userID].should == "123" }
98
222
  it { subject[:fullName].should == "Cameron" }
99
223
  it { subject[:role].should == :viewer }
100
224
  end
101
225
 
226
+ describe ".format_recording" do
227
+ let(:hash) { { :recordID => 123, :meetingID => 123, :name => 123, :published => "true",
228
+ :startTime => "Thu Mar 04 14:05:56 UTC 2010",
229
+ :endTime => "Thu Mar 04 15:01:01 UTC 2010",
230
+ :metadata => {
231
+ :title => "Test Recording", :subject => "English 232 session",
232
+ :description => "First Class", :creator => "Fred Dixon",
233
+ :contributor => "Richard Alam", :language => "en_US"
234
+ },
235
+ :playback => {
236
+ :format => {
237
+ :type => "simple",
238
+ :url => "http://server.com/simple/playback?recordID=183f0bf3a0982a127bdb8161-1",
239
+ :length => 62 }
240
+ }
241
+ } }
242
+
243
+ subject { BigBlueButton::BigBlueButtonFormatter.format_recording(hash) }
244
+ it { subject[:recordID].should == "123" }
245
+ it { subject[:meetingID].should == "123" }
246
+ it { subject[:name].should == "123" }
247
+ it { subject[:startTime].should == DateTime.parse("Thu Mar 04 14:05:56 UTC 2010") }
248
+ it { subject[:endTime].should == DateTime.parse("Thu Mar 04 15:01:01 UTC 2010") }
249
+ end
250
+
102
251
  describe "#flatten_objects" do
103
252
  let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new({ }) }
104
253