bigbluebutton-api-ruby 0.0.11 → 0.1.0.rc1

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