bigbluebutton-api-ruby 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
1
  *.gem
2
2
  pkg
3
- *.*~
3
+ *~
4
4
  test/config.yml
5
5
  doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+ if [ -e '.rvmrc_custom' ]; then
3
+ source .rvmrc_custom;
4
+ else
5
+ rvm --create use 1.9.2@bigbluebutton-api-ruby;
6
+ fi
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.0.11
2
+
3
+ * The file "bigbluebutton-api" was renamed to "bigbluebutton_api". All "require" calls must be updated.
4
+ * Splitted the library in more files (more modular) and created rspec tests for it.
5
+ * Added a BigBlueButtonApi.timeout attribute to timeout get requests and avoid blocks when the server is down. Defaults to 2 secs.
6
+ * New method last_http_response to access the last HTTP response object.
7
+ * Automatically detects the BBB server version if not informed by the user.
8
+
1
9
  == 0.0.10
2
10
 
3
11
  * Returning hash now will *always* have these 3 values: :returncode (boolean), :messageKey (string) and :message (string).
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'nokogiri', '1.4.1'
4
+
5
+ group :developement do
6
+ gem 'rspec', '~> 2.6'
7
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ nokogiri (1.4.1)
6
+ rspec (2.6.0)
7
+ rspec-core (~> 2.6.0)
8
+ rspec-expectations (~> 2.6.0)
9
+ rspec-mocks (~> 2.6.0)
10
+ rspec-core (2.6.4)
11
+ rspec-expectations (2.6.0)
12
+ diff-lcs (~> 1.1.2)
13
+ rspec-mocks (2.6.0)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ nokogiri (= 1.4.1)
20
+ rspec (~> 2.6)
@@ -2,7 +2,7 @@ $:.push File.expand_path("../lib", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'bigbluebutton-api-ruby'
5
- s.version = '0.0.10'
5
+ s.version = '0.0.11'
6
6
  s.extra_rdoc_files = ['README.rdoc', 'LICENSE', 'CHANGELOG.rdoc']
7
7
  s.summary = 'Provides an interface to the BigBlueButton web meeting API (https://github.com/mconf/bigbluebutton-api-ruby)'
8
8
  s.description = s.summary
@@ -5,26 +5,15 @@ require 'digest/sha1'
5
5
  require 'rubygems'
6
6
  require 'nokogiri'
7
7
  require 'hash_to_xml'
8
+ require 'bigbluebutton_exception'
9
+ require 'bigbluebutton_formatter'
8
10
 
9
11
  module BigBlueButton
10
12
 
11
- class BigBlueButtonException < Exception
12
- attr_accessor :key
13
-
14
- def to_s
15
- unless key.blank?
16
- super.to_s + ", messageKey: #{key}"
17
- else
18
- super
19
- end
20
- end
21
-
22
- end
23
-
24
13
  # This class provides access to the BigBlueButton API. BigBlueButton
25
14
  # is an open source project that provides web conferencing for distance
26
15
  # education (http://code.google.com/p/bigbluebutton/wiki/API). This API
27
- # was developed to support the following version of BBB: 0.64, 0.7
16
+ # was developed to support the following version of BBB: 0.7, 0.8 (soon)
28
17
  #
29
18
  # Sample usage of the API is as follows:
30
19
  # 1) Create a meeting with the create_meeting call
@@ -42,8 +31,6 @@ module BigBlueButton
42
31
  # Copyright:: Copyright (c) 2010 Joe Kinsella
43
32
  # License:: Distributes under same terms as Ruby
44
33
  #
45
- # TODO: Automatically detect API version using request to index - added in 0.7
46
- #
47
34
  # Considerations about the returning hash:
48
35
  # * The XML returned by BBB is converted to a Hash. See the desired method's documentation for examples.
49
36
  # * Three values will *always* exist in the hash: :returncode (boolean), :messageKey (string) and :message (string)
@@ -58,54 +45,38 @@ module BigBlueButton
58
45
  #
59
46
  class BigBlueButtonApi
60
47
 
61
- attr_accessor :url, :supported_versions, :salt, :version, :debug
48
+ attr_accessor :url, :supported_versions, :salt, :version, :debug, :timeout
62
49
 
63
50
  # Initializes an instance
64
51
  # url:: URL to a BigBlueButton server (e.g. http://demo.bigbluebutton.org/bigbluebutton/api)
65
52
  # salt:: Secret salt for this server
66
- # version:: API version: 0.64 or 0.7
53
+ # version:: API version: 0.7 (valid for 0.7, 0.71 and 0.71a)
67
54
  def initialize(url, salt, version='0.7', debug=false)
68
- @supported_versions = ['0.7', '0.64']
69
- unless @supported_versions.include?(version)
70
- raise BigBlueButtonException.new("BigBlueButton error: Invalid API version #{version}. Supported versions: #{@supported_versions.join(', ')}")
71
- end
55
+ @supported_versions = ['0.7']
72
56
  @url = url
73
57
  @salt = salt
74
58
  @debug = debug
75
- @version = version
76
- puts "BigBlueButtonAPI: Using version #{@version}" if @debug
77
- end
59
+ @timeout = 2 # 2 seconds timeout for get requests
78
60
 
79
- # DEPRECATED
80
- # Use join_meeting_url
81
- def moderator_url(meeting_id, user_name, password,
82
- user_id = nil, web_voice_conf = nil)
83
- warn "#{caller[0]}: moderator_url is deprecated and will soon be removed, please use join_meeting_url instead."
84
- join_meeting_url(meeting_id, user_name, password, user_id, web_voice_conf)
85
- end
61
+ @version = version || get_api_version
62
+ unless @supported_versions.include?(@version)
63
+ raise BigBlueButtonException.new("BigBlueButton error: Invalid API version #{version}. Supported versions: #{@supported_versions.join(', ')}")
64
+ end
86
65
 
87
- # DEPRECATED
88
- # Use join_meeting_url
89
- def attendee_url(meeting_id, user_name, password,
90
- user_id = nil, web_voice_conf = nil)
91
- warn "#{caller[0]}: attendee_url is deprecated and will soon be removed, please use join_meeting_url instead."
92
- join_meeting_url(meeting_id, user_name, password, user_id, web_voice_conf)
66
+ puts "BigBlueButtonAPI: Using version #{@version}" if @debug
93
67
  end
94
68
 
95
69
  # Returns the url used to join the meeting
96
70
  # meeting_id:: Unique identifier for the meeting
97
71
  # user_name:: Name of the user
98
72
  # password:: Password for this meeting - used to set the user as moderator or attendee
99
- # user_id:: Unique identifier for this user (>= 0.7)
100
- # web_voice_conf:: Custom voice-extension for users using VoIP (>= 0.7)
73
+ # user_id:: Unique identifier for this user
74
+ # web_voice_conf:: Custom voice-extension for users using VoIP
101
75
  def join_meeting_url(meeting_id, user_name, password,
102
76
  user_id = nil, web_voice_conf = nil)
103
77
 
104
- params = { :meetingID => meeting_id, :password => password, :fullName => user_name }
105
- if @version == '0.7'
106
- params[:userID] = user_id
107
- params[:webVoiceConf] = web_voice_conf
108
- end
78
+ params = { :meetingID => meeting_id, :password => password, :fullName => user_name,
79
+ :userID => user_id, :webVoiceConf => web_voice_conf }
109
80
  get_url(:join, params)
110
81
  end
111
82
 
@@ -118,7 +89,7 @@ module BigBlueButton
118
89
  # welcome_message:: Welcome message to display in chat window
119
90
  # dialin_number:: Dial in number for conference using a regular phone
120
91
  # logout_url:: URL to return user to after exiting meeting
121
- # voice_bridge:: Voice conference number (>= 0.7)
92
+ # voice_bridge:: Voice conference number
122
93
  #
123
94
  # === Return examples (for 0.7)
124
95
  #
@@ -139,7 +110,6 @@ module BigBlueButton
139
110
  # :message=>"This conference was already in existence and may currently be in progress."
140
111
  # }
141
112
  #
142
- # TODO check if voice_bridge exists in 0.64
143
113
  def create_meeting(meeting_name, meeting_id, moderator_password = nil, attendee_password = nil,
144
114
  welcome_message = nil, dial_number = nil, logout_url = nil,
145
115
  max_participants = nil, voice_bridge = nil)
@@ -147,15 +117,16 @@ module BigBlueButton
147
117
  params = { :name => meeting_name, :meetingID => meeting_id,
148
118
  :moderatorPW => moderator_password, :attendeePW => attendee_password,
149
119
  :welcome => welcome_message, :dialNumber => dial_number,
150
- :logoutURL => logout_url, :maxParticpants => max_participants }
151
- params[:voiceBridge] = voice_bridge if @version == '0.7'
120
+ :logoutURL => logout_url, :maxParticpants => max_participants,
121
+ :voiceBridge => voice_bridge }
152
122
 
153
123
  response = send_api_request(:create, params)
154
124
 
155
- response[:meetingID] = response[:meetingID].to_s
156
- response[:moderatorPW] = response[:moderatorPW].to_s
157
- response[:attendeePW] = response[:attendeePW].to_s
158
- response[:hasBeenForciblyEnded] = response[:hasBeenForciblyEnded].downcase == "true"
125
+ formatter = BigBlueButtonFormatter.new(response)
126
+ formatter.to_string(:meetingID)
127
+ formatter.to_string(:moderatorPW)
128
+ formatter.to_string(:attendeePW)
129
+ formatter.to_boolean(:hasBeenForciblyEnded)
159
130
 
160
131
  response
161
132
  end
@@ -183,7 +154,7 @@ module BigBlueButton
183
154
  # meeting_id:: Unique identifier for the meeting
184
155
  def is_meeting_running?(meeting_id)
185
156
  hash = send_api_request(:isMeetingRunning, { :meetingID => meeting_id } )
186
- hash[:running].downcase == "true"
157
+ BigBlueButtonFormatter.new(hash).to_boolean(:running)
187
158
  end
188
159
 
189
160
  # Warning: As of this version of the gem, this call does not work
@@ -196,16 +167,11 @@ module BigBlueButton
196
167
  # meeting_id:: Unique identifier for the meeting
197
168
  # user_name:: Name of the user
198
169
  # password:: Moderator or attendee password for this meeting
199
- # user_id:: Unique identifier for this user (>=0.7)
200
- # web_voice_conf:: Custom voice-extension for users using VoIP (>=0.7)
170
+ # user_id:: Unique identifier for this user
171
+ # web_voice_conf:: Custom voice-extension for users using VoIP
201
172
  def join_meeting(meeting_id, user_name, password, user_id = nil, web_voice_conf = nil)
202
- params = { :meetingID => meeting_id, :password => password, :fullName => user_name }
203
- if @version == '0.64'
204
- params[:redirectImmediately] = 0
205
- elsif @version == '0.7'
206
- params[:userID] = user_id
207
- params[:webVoiceConf] = web_voice_conf
208
- end
173
+ params = { :meetingID => meeting_id, :password => password, :fullName => user_name,
174
+ :userID => user_id, :webVoiceConf => web_voice_conf }
209
175
  send_api_request(:join, params)
210
176
  end
211
177
 
@@ -242,30 +208,17 @@ module BigBlueButton
242
208
  def get_meeting_info(meeting_id, password)
243
209
  response = send_api_request(:getMeetingInfo, { :meetingID => meeting_id, :password => password } )
244
210
 
245
- # simplify the hash making a node :attendees with an array with all attendees
246
- if response[:attendees].empty?
247
- attendees = []
248
- else
249
- node = response[:attendees][:attendee]
250
- if node.kind_of?(Array)
251
- attendees = node
252
- else
253
- attendees = []
254
- attendees << node
255
- end
256
- end
257
- response[:attendees] = attendees
258
- response[:attendees].each { |att| att[:role] = att[:role].downcase.to_sym }
259
-
260
- response[:meetingID] = response[:meetingID].to_s
261
- response[:moderatorPW] = response[:moderatorPW].to_s
262
- response[:attendeePW] = response[:attendeePW].to_s
263
- response[:hasBeenForciblyEnded] = response[:hasBeenForciblyEnded].downcase == "true"
264
- response[:running] = response[:running].downcase == "true"
265
- response[:startTime] = response[:startTime].downcase == "null" ?
266
- nil : DateTime.parse(response[:startTime])
267
- response[:endTime] = response[:endTime].downcase == "null" ?
268
- nil : DateTime.parse(response[:endTime])
211
+ formatter = BigBlueButtonFormatter.new(response)
212
+ formatter.flatten_objects(:attendees, :attendee)
213
+ response[:attendees].each { |a| formatter.format_attendee(a) }
214
+
215
+ formatter.to_string(:meetingID)
216
+ formatter.to_string(:moderatorPW)
217
+ formatter.to_string(:attendeePW)
218
+ formatter.to_boolean(:hasBeenForciblyEnded)
219
+ formatter.to_boolean(:running)
220
+ formatter.to_datetime(:startTime)
221
+ formatter.to_datetime(:endTime)
269
222
 
270
223
  response
271
224
  end
@@ -292,52 +245,23 @@ module BigBlueButton
292
245
  def get_meetings
293
246
  response = send_api_request(:getMeetings, { :random => rand(9999999999) } )
294
247
 
295
- # simplify the hash making a node :meetings with an array with all meetings
296
- if response[:meetings].empty?
297
- meetings = []
298
- else
299
- node = response[:meetings][:meeting]
300
- if node.kind_of?(Array)
301
- meetings = node
302
- else
303
- meetings = []
304
- meetings << node
305
- end
306
- end
307
- response[:meetings] = meetings
308
-
309
- response[:meetings].each do |meeting|
310
- meeting[:meetingID] = meeting[:meetingID].to_s
311
- meeting[:moderatorPW] = meeting[:moderatorPW].to_s
312
- meeting[:attendeePW] = meeting[:attendeePW].to_s
313
- meeting[:hasBeenForciblyEnded] = meeting[:hasBeenForciblyEnded].downcase == "true"
314
- meeting[:running] = meeting[:running].downcase == "true"
315
- end
316
-
248
+ formatter = BigBlueButtonFormatter.new(response)
249
+ formatter.flatten_objects(:meetings, :meeting)
250
+ response[:meetings].each { |m| formatter.format_meeting(m) }
317
251
  response
318
252
  end
319
253
 
320
254
  # Returns the API version (as string) of the associated server. This actually returns
321
- # the version requested to the BBB server, and not the version set by the user in
322
- # the initialization.
323
- #
324
- # Works for BBB >= 0.7 only. For earlier versions, returns an empty string.
255
+ # the version returned by the BBB server, and not the version set by the user in
256
+ # the initialization of this object.
325
257
  def get_api_version
326
258
  response = send_api_request(:index)
327
- if response[:returncode]
328
- response[:version].to_s
329
- else
330
- ""
331
- end
259
+ response[:returncode] ? response[:version].to_s : ""
332
260
  end
333
261
 
334
262
  # Make a simple request to the server to test the connection
335
263
  def test_connection
336
- if @version == '0.7'
337
- response = send_api_request(:index)
338
- else
339
- response = get_meetings
340
- end
264
+ response = send_api_request(:index)
341
265
  response[:returncode]
342
266
  end
343
267
 
@@ -350,56 +274,50 @@ module BigBlueButton
350
274
  r
351
275
  end
352
276
 
353
- protected
277
+ def last_http_response
278
+ @http_response
279
+ end
354
280
 
355
- def get_url(method, data)
281
+ def get_url(method, data={})
356
282
  if method == :index
357
283
  return @url
358
284
  end
359
285
 
360
286
  url = "#{@url}/#{method}?"
361
287
 
288
+ # stringify and escape all params
362
289
  data.delete_if { |k, v| v.nil? } unless data.nil?
363
290
  params = ""
364
291
  params = data.map{ |k,v| "#{k}=" + CGI::escape(v.to_s) unless k.nil? || v.nil? }.join("&")
365
292
 
293
+ # checksum calc
366
294
  checksum_param = params + @salt
367
- checksum_param = method.to_s + checksum_param if @version == '0.7'
295
+ checksum_param = method.to_s + checksum_param
368
296
  checksum = Digest::SHA1.hexdigest(checksum_param)
369
297
 
370
- "#{url}#{params}&checksum=#{checksum}"
298
+ # final url
299
+ url += "#{params}&" unless params.empty?
300
+ url += "checksum=#{checksum}"
371
301
  end
372
302
 
373
303
  def send_api_request(method, data = {})
374
304
  url = get_url(method, data)
375
- begin
376
- res = Net::HTTP.get_response(URI.parse(url))
377
- puts "BigBlueButtonAPI: URL request = #{url}" if @debug
378
- puts "BigBlueButtonAPI: URL response = #{res.body}" if @debug
379
- rescue Exception => socketerror
380
- raise BigBlueButtonException.new("Connection error. Your URL is probably incorrect: \"#{@url}\"")
381
- end
382
305
 
383
- if res.body.empty?
384
- raise BigBlueButtonException.new("No response body")
385
- end
306
+ @http_response = send_request(url)
307
+ return { } if @http_response.body.empty?
386
308
 
387
309
  # 'Hashify' the XML
388
- hash = Hash.from_xml res.body
310
+ hash = Hash.from_xml(@http_response.body)
389
311
 
390
312
  # simple validation of the xml body
391
313
  unless hash.has_key?(:response) and hash[:response].has_key?(:returncode)
392
314
  raise BigBlueButtonException.new("Invalid response body. Is the API URL correct? \"#{@url}\", version #{@version}")
393
315
  end
394
316
 
395
- # and remove the "response" node
396
- hash = Hash[hash[:response]].inject({}){|h,(k,v)| h[k] = v; h}
397
-
398
- # Adjust some values. There will always be a returncode, message and messageKey in the hash.
399
- hash[:returncode] = hash[:returncode].downcase == "success" # true instead of "SUCCESS"
400
- hash[:messageKey] = "" if !hash.has_key?(:messageKey) or hash[:messageKey].empty? # "" instead of {}
401
- hash[:message] = "" if !hash.has_key?(:message) or hash[:message].empty? # "" instead of {}
317
+ # default cleanup in the response
318
+ hash = BigBlueButtonFormatter.new(hash).default_formatting
402
319
 
320
+ # all responses should have a returncode
403
321
  unless hash[:returncode]
404
322
  exception = BigBlueButtonException.new(hash[:message])
405
323
  exception.key = hash.has_key?(:messageKey) ? hash[:messageKey] : ""
@@ -409,6 +327,25 @@ module BigBlueButton
409
327
  hash
410
328
  end
411
329
 
330
+ protected
331
+
332
+ def send_request(url)
333
+ begin
334
+ puts "BigBlueButtonAPI: URL request = #{url}" if @debug
335
+ url_parsed = URI.parse(url)
336
+ http = Net::HTTP.new(url_parsed.host, url_parsed.port)
337
+ http.open_timeout = @timeout
338
+ http.read_timeout = @timeout
339
+ response = http.get(url_parsed.request_uri)
340
+ puts "BigBlueButtonAPI: URL response = #{response.body}" if @debug
341
+ rescue TimeoutError => error
342
+ raise BigBlueButtonException.new("Timeout error. Your server is probably down: \"#{@url}\"")
343
+ rescue Exception => error
344
+ raise BigBlueButtonException.new("Connection error. Your URL is probably incorrect: \"#{@url}\"")
345
+ end
346
+ response
347
+ end
348
+
412
349
  end
413
350
  end
414
351
 
@@ -0,0 +1,13 @@
1
+ module BigBlueButton
2
+
3
+ class BigBlueButtonException < Exception
4
+ attr_accessor :key
5
+
6
+ def to_s
7
+ s = super.to_s
8
+ s += ", messageKey: #{key.to_s}" unless key.nil? or key.to_s.empty?
9
+ s
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,76 @@
1
+ module BigBlueButton
2
+
3
+ # Helper class to format the response hash received when the BigBlueButtonApi makes API calls
4
+ class BigBlueButtonFormatter
5
+ attr_accessor :hash
6
+
7
+ def initialize(hash)
8
+ @hash = hash
9
+ end
10
+
11
+ # converts a value in the @hash to boolean
12
+ def to_boolean(key)
13
+ @hash[key] = @hash[key].downcase == "true"
14
+ end
15
+
16
+ # converts a value in the @hash to string
17
+ def to_string(key)
18
+ @hash[key] = @hash[key].to_s
19
+ end
20
+
21
+ # converts a value in the @hash to DateTime
22
+ def to_datetime(key)
23
+ @hash[key] = @hash[key].downcase == "null" ? nil : DateTime.parse(@hash[key])
24
+ end
25
+
26
+ # Default formatting for all responses given by a BBB server
27
+ def default_formatting
28
+
29
+ # remove the "response" node
30
+ response = Hash[@hash[:response]].inject({}){|h,(k,v)| h[k] = v; h}
31
+
32
+ # Adjust some values. There will always be a returncode, a message and a messageKey in the hash.
33
+ response[:returncode] = response[:returncode].downcase == "success" # true instead of "SUCCESS"
34
+ response[:messageKey] = "" if !response.has_key?(:messageKey) or response[:messageKey].empty? # "" instead of {}
35
+ response[:message] = "" if !response.has_key?(:message) or response[:message].empty? # "" instead of {}
36
+
37
+ @hash = response
38
+ end
39
+
40
+ # default formatting for a meeting hash
41
+ def format_meeting(meeting)
42
+ meeting[:meetingID] = meeting[:meetingID].to_s
43
+ meeting[:moderatorPW] = meeting[:moderatorPW].to_s
44
+ meeting[:attendeePW] = meeting[:attendeePW].to_s
45
+ meeting[:hasBeenForciblyEnded] = meeting[:hasBeenForciblyEnded].downcase == "true"
46
+ meeting[:running] = meeting[:running].downcase == "true"
47
+ meeting
48
+ end
49
+
50
+ # default formatting for an attendee hash
51
+ def format_attendee(attendee)
52
+ attendee[:userID] = attendee[:userID].to_s
53
+ attendee[:role] = attendee[:role].downcase.to_sym
54
+ attendee
55
+ end
56
+
57
+ # simplifies the hash making a node e.g. :attendee with an array with all attendees
58
+ # TODO: comments with the expected @hash at this point
59
+ def flatten_objects(first, second)
60
+ if @hash[first].empty?
61
+ collection = []
62
+ else
63
+ node = @hash[first][second]
64
+ if node.kind_of?(Array)
65
+ collection = node
66
+ else
67
+ collection = []
68
+ collection << node
69
+ end
70
+ end
71
+ @hash[first] = collection
72
+ @hash
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,386 @@
1
+ require 'spec_helper'
2
+
3
+ describe BigBlueButton::BigBlueButtonApi do
4
+
5
+ # default variables and API object for all tests
6
+ let(:url) { "http://server.com" }
7
+ let(:salt) { "1234567890abcdefghijkl" }
8
+ let(:version) { "0.7" }
9
+ let(:debug) { false }
10
+ let(:api) { BigBlueButton::BigBlueButtonApi.new(url, salt, version, debug) }
11
+
12
+ describe "#initialize" do
13
+ context "standard initialization" do
14
+ subject { BigBlueButton::BigBlueButtonApi.new(url, salt, version, debug) }
15
+ it { subject.url.should be(url) }
16
+ it { subject.salt.should be(salt) }
17
+ it { subject.version.should be(version) }
18
+ it { subject.debug.should be(debug) }
19
+ it { subject.timeout.should be(2) }
20
+ it { subject.supported_versions.should include("0.7") }
21
+ end
22
+
23
+ context "when the version is not informed, get it from the BBB server" do
24
+ before { BigBlueButton::BigBlueButtonApi.any_instance.should_receive(:get_api_version).and_return("0.7") }
25
+ subject { BigBlueButton::BigBlueButtonApi.new(url, salt, nil) }
26
+ it { subject.version.should == "0.7" }
27
+ end
28
+
29
+ it "when the version is not supported raise an error" do
30
+ expect {
31
+ BigBlueButton::BigBlueButtonApi.new(url, salt, "0.not-supported", nil)
32
+ }.to raise_error(BigBlueButton::BigBlueButtonException)
33
+ end
34
+
35
+ context "current supported versions" do
36
+ subject { BigBlueButton::BigBlueButtonApi.new(url, salt) }
37
+ it { subject.supported_versions.should == ["0.7"] }
38
+ end
39
+ end
40
+
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
+ }
51
+
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
55
+
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 }
82
+ end
83
+
84
+ describe "#end_meeting" do
85
+ let(:meeting_id) { "meeting-id" }
86
+ let(:moderator_password) { "password" }
87
+ let(:params) { { :meetingID => meeting_id, :password => moderator_password } }
88
+ let(:response) { "anything" }
89
+
90
+ before { api.should_receive(:send_api_request).with(:end, params).and_return(response) }
91
+ it { api.end_meeting(meeting_id, moderator_password).should == response }
92
+ end
93
+
94
+ describe "#is_meeting_running?" do
95
+ let(:meeting_id) { "meeting-id" }
96
+ let(:params) { { :meetingID => meeting_id } }
97
+
98
+ context "when the meeting is running" do
99
+ let(:response) { { :running => "TRUE" } }
100
+ before { api.should_receive(:send_api_request).with(:isMeetingRunning, params).and_return(response) }
101
+ it { api.is_meeting_running?(meeting_id).should == true }
102
+ end
103
+
104
+ context "when the meeting is not running" do
105
+ let(:response) { { :running => "FALSE" } }
106
+ before { api.should_receive(:send_api_request).with(:isMeetingRunning, params).and_return(response) }
107
+ it { api.is_meeting_running?(meeting_id).should == false }
108
+ end
109
+ end
110
+
111
+ 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
+ }
121
+
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" }
124
+ end
125
+
126
+ describe "#get_meeting_info" do
127
+ let(:meeting_id) { "meeting-id" }
128
+ let(:password) { "password" }
129
+ let(:params) { { :meetingID => meeting_id, :password => password } }
130
+
131
+ let(:attendee1) { { :userID => 123, :fullName => "Dexter Morgan", :role => "MODERATOR" } }
132
+ let(:attendee2) { { :userID => "id2", :fullName => "Cameron", :role => "VIEWER" } }
133
+ let(:response) {
134
+ { :meetingID => 123, :moderatorPW => 111, :attendeePW => 222, :hasBeenForciblyEnded => "FALSE",
135
+ :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
138
+
139
+ let(:expected_attendee1) { { :userID => "123", :fullName => "Dexter Morgan", :role => :moderator } }
140
+ let(:expected_attendee2) { { :userID => "id2", :fullName => "Cameron", :role => :viewer } }
141
+ let(:expected_response) {
142
+ { :meetingID => "123", :moderatorPW => "111", :attendeePW => "222", :hasBeenForciblyEnded => false,
143
+ :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" }
145
+ } # expected return hash after all the formatting
146
+
147
+ # ps: not mocking the formatter here because it's easier to just check the results (expected_response)
148
+ 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 }
150
+ end
151
+
152
+ describe "#get_meetings" do
153
+ let(:meeting_hash1) { { :meetingID => "Demo Meeting", :attendeePW => "ap", :moderatorPW => "mp", :hasBeenForciblyEnded => false, :running => true } }
154
+ let(:meeting_hash2) { { :meetingID => "Ended Meeting", :attendeePW => "pass", :moderatorPW => "pass", :hasBeenForciblyEnded => true, :running => false } }
155
+ let(:flattened_response) {
156
+ { :returncode => true, :meetings => [ meeting_hash1, meeting_hash2 ], :messageKey => "mkey", :message => "m" }
157
+ } # hash *after* the flatten_objects call
158
+
159
+ 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)
162
+ formatter_mock = mock(BigBlueButton::BigBlueButtonFormatter)
163
+ 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
+ BigBlueButton::BigBlueButtonFormatter.should_receive(:new).and_return(formatter_mock)
167
+ }
168
+ it { api.get_meetings }
169
+ end
170
+
171
+ describe "#get_api_version" do
172
+ context "returns the version returned by the server" do
173
+ let(:hash) { { :returncode => true, :version => "0.7" } }
174
+ before { api.should_receive(:send_api_request).with(:index).and_return(hash) }
175
+ it { api.get_api_version.should == "0.7" }
176
+ end
177
+
178
+ context "returns an empty string when the server responds with an empty hash" do
179
+ before { api.should_receive(:send_api_request).with(:index).and_return({}) }
180
+ it { api.get_api_version.should == "" }
181
+ end
182
+ end
183
+
184
+ describe "#test_connection" do
185
+ context "returns the returncode returned by the server" do
186
+ let(:hash) { { :returncode => "any-value" } }
187
+ before { api.should_receive(:send_api_request).with(:index).and_return(hash) }
188
+ it { api.test_connection.should == "any-value" }
189
+ end
190
+ end
191
+
192
+ describe "#==" do
193
+ let(:api2) { BigBlueButton::BigBlueButtonApi.new(url, salt, version, debug) }
194
+
195
+ context "compares attributes" do
196
+ it { api.should == api2 }
197
+ end
198
+
199
+ context "differs #debug" do
200
+ before { api2.debug = !api.debug }
201
+ it { api.should_not == api2 }
202
+ end
203
+
204
+ context "differs #salt" do
205
+ before { api2.salt = api.salt + "x" }
206
+ it { api.should_not == api2 }
207
+ end
208
+
209
+ context "differs #version" do
210
+ before { api2.version = api.version + "x" }
211
+ it { api.should_not == api2 }
212
+ end
213
+
214
+ context "differs #supported_versions" do
215
+ before { api2.supported_versions << "x" }
216
+ it { api.should_not == api2 }
217
+ end
218
+ end
219
+
220
+ describe "#last_http_response" do
221
+ # we test this through a #test_connection call
222
+
223
+ let(:request_mock) { mock }
224
+ before {
225
+ api.should_receive(:get_url)
226
+ # this return value will be stored in @http_response
227
+ api.should_receive(:send_request).and_return(request_mock)
228
+ # to return fast from #send_api_request
229
+ request_mock.should_receive(:body).and_return("")
230
+ api.test_connection
231
+ }
232
+ it { api.last_http_response.should == request_mock }
233
+ end
234
+
235
+ describe "#get_url" do
236
+
237
+ context "when method = :index" do
238
+ it { api.get_url(:index).should == api.url }
239
+ end
240
+
241
+ context "when method != :index" do
242
+ context "validates the entire url" do
243
+ context "with params" do
244
+ let(:params) { { :param1 => "value1", :param2 => "value2" } }
245
+ subject { api.get_url(:join, params) }
246
+ it { subject.should match(/#{url}\/join\?param1=value1&param2=value2/) }
247
+ end
248
+
249
+ context "without params" do
250
+ subject { api.get_url(:join) }
251
+ it { subject.should match(/#{url}\/join\?[^&]/) }
252
+ end
253
+ end
254
+
255
+ context "discards params with nil value" do
256
+ let(:params) { { :param1 => "value1", :param2 => nil } }
257
+ subject { api.get_url(:join, params) }
258
+ it { subject.should_not match(/param2=/) }
259
+ end
260
+
261
+ context "escapes all params" do
262
+ let(:params) { { :param1 => "value with spaces", :param2 => "@$" } }
263
+ subject { api.get_url(:join, params) }
264
+ it { subject.should match(/param1=value\+with\+spaces/) }
265
+ it { subject.should match(/param2=%40%24/) }
266
+ end
267
+
268
+ context "includes the checksum" do
269
+ let(:params) { { :param1 => "value1", :param2 => "value2" } }
270
+ let(:checksum) { Digest::SHA1.hexdigest("joinparam1=value1&param2=value2#{salt}") }
271
+ subject { api.get_url(:join, params) }
272
+ it { subject.should match(/checksum=#{checksum}$/) }
273
+ end
274
+ end
275
+ end
276
+
277
+ # FIXME: this complex test means that the method is too complex - try to refactor it
278
+ describe "#send_api_request" do
279
+ let(:method) { :join }
280
+ 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) }
284
+
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
317
+
318
+ context "returns an empty hash if the response body is empty" do
319
+ before do
320
+ setup_http_mock
321
+ response_mock = mock()
322
+ @http_mock.should_receive(:get).and_return(response_mock)
323
+ response_mock.should_receive(:body).and_return("")
324
+ end
325
+ it { make_request.should == { } }
326
+ end
327
+
328
+ context "hashfies and validates the response body" do
329
+ before do
330
+ setup_http_mock
331
+ response_mock = mock()
332
+ @http_mock.should_receive(:get).and_return(response_mock)
333
+ response_mock.should_receive(:body).twice.and_return("response-body")
334
+ end
335
+
336
+ context "checking if it has a :response key" do
337
+ before { Hash.should_receive(:from_xml).with("response-body").and_return({ }) }
338
+ it { expect { make_request }.to raise_error(BigBlueButton::BigBlueButtonException) }
339
+ end
340
+
341
+ context "checking if it the :response key has a :returncode key" do
342
+ before { Hash.should_receive(:from_xml).with("response-body").and_return({ :response => { } }) }
343
+ it { expect { make_request }.to raise_error(BigBlueButton::BigBlueButtonException) }
344
+ end
345
+ end
346
+
347
+ context "formats the response hash" do
348
+ let(:response) { { :response => { :returncode => true } } }
349
+ let(:formatted_response) { { :returncode => true } }
350
+ before do
351
+ setup_http_mock
352
+
353
+ response_mock = mock()
354
+ @http_mock.should_receive(:get).and_return(response_mock)
355
+ response_mock.should_receive(:body).twice.and_return("response-body")
356
+ Hash.should_receive(:from_xml).with("response-body").and_return(response)
357
+
358
+ # here starts the validation
359
+ formatter_mock = mock(BigBlueButton::BigBlueButtonFormatter)
360
+ BigBlueButton::BigBlueButtonFormatter.should_receive(:new).with(response).and_return(formatter_mock)
361
+ formatter_mock.should_receive(:default_formatting).and_return(formatted_response)
362
+ end
363
+ it { make_request }
364
+ end
365
+
366
+ context "raise an error if the formatted response has no :returncode" do
367
+ let(:response) { { :response => { :returncode => true } } }
368
+ let(:formatted_response) { { } }
369
+ before do
370
+ setup_http_mock
371
+
372
+ response_mock = mock()
373
+ @http_mock.should_receive(:get).and_return(response_mock)
374
+ response_mock.should_receive(:body).twice.and_return("response-body")
375
+ Hash.should_receive(:from_xml).with("response-body").and_return(response)
376
+
377
+ formatter_mock = mock(BigBlueButton::BigBlueButtonFormatter)
378
+ BigBlueButton::BigBlueButtonFormatter.should_receive(:new).with(response).and_return(formatter_mock)
379
+ formatter_mock.should_receive(:default_formatting).and_return(formatted_response)
380
+ end
381
+ it { expect { make_request }.to raise_error(BigBlueButton::BigBlueButtonException) }
382
+ end
383
+
384
+ end
385
+
386
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe BigBlueButton::BigBlueButtonException do
4
+
5
+ describe "#key" do
6
+ subject { BigBlueButton::BigBlueButtonException.new }
7
+ it { should respond_to(:key) }
8
+ it { should respond_to("key=") }
9
+ end
10
+
11
+ describe "#to_s" do
12
+ context "when key is set" do
13
+ let(:api) { BigBlueButton::BigBlueButtonException.new("super-msg") }
14
+ before { api.key = "key-msg" }
15
+ it { api.to_s.should == "super-msg, messageKey: key-msg" }
16
+ end
17
+
18
+ context "when key is not set" do
19
+ let(:api) { BigBlueButton::BigBlueButtonException.new("super-msg") }
20
+ before { api.key = nil }
21
+ it { api.to_s.should == "super-msg" }
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ describe BigBlueButton::BigBlueButtonFormatter do
4
+
5
+ describe "#hash" do
6
+ subject { BigBlueButton::BigBlueButtonFormatter.new({}) }
7
+ it { subject.should respond_to(:hash) }
8
+ it { subject.should respond_to(:"hash=") }
9
+ end
10
+
11
+ describe "#to_stringtring" do
12
+ 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" }
17
+ end
18
+
19
+ describe "#to_booleanoolean" do
20
+ 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 }
26
+ end
27
+
28
+ 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 }
34
+ end
35
+
36
+ describe "#default_formatting" do
37
+ let(:input) { { :response => { :returncode => "SUCCESS", :messageKey => "mkey", :message => "m" } } }
38
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new(input) }
39
+
40
+ context "standard case" do
41
+ let(:expected_output) { { :returncode => true, :messageKey => "mkey", :message => "m" } }
42
+ subject { formatter.default_formatting }
43
+ it { subject.should == expected_output }
44
+ end
45
+
46
+ context "when :returncode should be false" do
47
+ before { input[:response][:returncode] = "ERROR" }
48
+ subject { formatter.default_formatting }
49
+ it { subject[:returncode].should be_false }
50
+ end
51
+
52
+ context "when :messageKey is empty" do
53
+ before { input[:response][:messageKey] = {} }
54
+ subject { formatter.default_formatting }
55
+ it { subject[:messageKey].should == "" }
56
+ end
57
+
58
+ context "when :messageKey is nil" do
59
+ before { input[:response].delete(:messageKey) }
60
+ subject { formatter.default_formatting }
61
+ it { subject[:messageKey].should == "" }
62
+ end
63
+
64
+ context "when :message is empty" do
65
+ before { input[:response][:message] = {} }
66
+ subject { formatter.default_formatting }
67
+ it { subject[:message].should == "" }
68
+ end
69
+
70
+ context "when there's no :message key" do
71
+ before { input[:response].delete(:message) }
72
+ subject { formatter.default_formatting }
73
+ it { subject[:message].should == "" }
74
+ end
75
+ end
76
+
77
+ describe "#format_meeting" do
78
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new({}) }
79
+ let(:hash) {
80
+ { :meetingID => 123, :moderatorPW => 111, :attendeePW => 222,
81
+ :hasBeenForciblyEnded => "FALSE", :running => "TRUE" }
82
+ }
83
+
84
+ subject { formatter.format_meeting(hash) }
85
+ it { subject[:meetingID].should == "123" }
86
+ it { subject[:moderatorPW].should == "111" }
87
+ it { subject[:attendeePW].should == "222" }
88
+ it { subject[:hasBeenForciblyEnded].should == false }
89
+ it { subject[:running].should == true }
90
+ end
91
+
92
+ describe "#format_attendee" do
93
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new({}) }
94
+ let(:hash) { { :userID => 123, :fullName => "Cameron", :role => "VIEWER" } }
95
+
96
+ subject { formatter.format_attendee(hash) }
97
+ it { subject[:userID].should == "123" }
98
+ it { subject[:fullName].should == "Cameron" }
99
+ it { subject[:role].should == :viewer }
100
+ end
101
+
102
+ describe "#flatten_objects" do
103
+ let(:formatter) { BigBlueButton::BigBlueButtonFormatter.new({ }) }
104
+
105
+ context "standard case" do
106
+ context "when the target key is empty" do
107
+ let(:hash) { { :objects => {} } }
108
+ before { formatter.hash = hash }
109
+ subject { formatter.flatten_objects(:objects, :object) }
110
+ it { subject.should == { :objects => [] } }
111
+ end
112
+
113
+ context "when there's only one object in the list" do
114
+ let(:object_hash) { { :id => 1 } }
115
+ let(:hash) { { :objects => { :object => object_hash } } }
116
+ before { formatter.hash = hash }
117
+ subject { formatter.flatten_objects(:objects, :object) }
118
+ it { subject.should == { :objects => [ object_hash ] } }
119
+ end
120
+
121
+ context "when there are several objects in the list" do
122
+ let(:object_hash1) { { :id => 1 } }
123
+ let(:object_hash2) { { :id => 2 } }
124
+ let(:hash) { { :objects => { :object => [ object_hash1, object_hash2 ] } } }
125
+ before { formatter.hash = hash }
126
+ subject { formatter.flatten_objects(:objects, :object) }
127
+ it { subject.should == { :objects => [ object_hash1, object_hash2 ] } }
128
+ end
129
+ end
130
+
131
+ context "using different keys" do
132
+ let(:hash1) { { :any => 1 } }
133
+ let(:hash2) { { :any => 2 } }
134
+ let(:collection_hash) { { :foos => { :bar => [ hash1, hash2 ] } } }
135
+ before { formatter.hash = collection_hash }
136
+ subject { formatter.flatten_objects(:foos, :bar) }
137
+ it { subject.should == { :foos => [ hash1, hash2 ] } }
138
+ end
139
+
140
+ end
141
+
142
+
143
+ end
@@ -0,0 +1,13 @@
1
+ # Load support files
2
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
3
+
4
+ # Load Factories
5
+ #require 'factory_girl'
6
+ #require 'forgery'
7
+ #Dir["#{ File.dirname(__FILE__)}/factories/*.rb"].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec
11
+ end
12
+
13
+ require "bigbluebutton_api"
data/test/test.rb CHANGED
@@ -1,10 +1,13 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__))
2
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
3
+
1
4
  require 'bigbluebutton-api'
2
5
  require 'thread'
3
6
  require 'yaml'
4
7
 
5
8
  def prepare
6
9
 
7
- config_file = 'test/config.yml'
10
+ config_file = File.join(File.dirname(__FILE__), 'config.yml')
8
11
  unless File.exist? config_file
9
12
  puts config_file + " does not exists. Copy the example and configure your server."
10
13
  puts "cp test/config.yml.example test/config.yml"
@@ -135,8 +138,17 @@ def join_test
135
138
 
136
139
  end
137
140
 
141
+ def get_version_test
142
+ @api = BigBlueButton::BigBlueButtonApi.new(@config['bbb_url'], @config['bbb_salt'], nil, true)
143
+
144
+ puts
145
+ puts "---------------------------------------------------"
146
+ puts "The version of your BBB server is: #{@api.version}"
147
+ end
148
+
138
149
  begin
139
150
  prepare
140
151
  general_test
141
152
  #join_test
153
+ #get_version_test
142
154
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bigbluebutton-api-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-04-28 00:00:00.000000000Z
13
+ date: 2011-09-02 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
17
- requirement: &80178430 !ruby/object:Gem::Requirement
17
+ requirement: &20159120 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,7 +22,7 @@ dependencies:
22
22
  version: 1.4.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *80178430
25
+ version_requirements: *20159120
26
26
  description: Provides an interface to the BigBlueButton web meeting API (https://github.com/mconf/bigbluebutton-api-ruby)
27
27
  email:
28
28
  - leonardodaronco@gmail.com
@@ -35,13 +35,23 @@ extra_rdoc_files:
35
35
  - CHANGELOG.rdoc
36
36
  files:
37
37
  - .gitignore
38
+ - .rspec
39
+ - .rvmrc
38
40
  - CHANGELOG.rdoc
41
+ - Gemfile
42
+ - Gemfile.lock
39
43
  - LICENSE
40
44
  - README.rdoc
41
45
  - Rakefile
42
46
  - bigbluebutton-api-ruby.gemspec
43
- - lib/bigbluebutton-api.rb
47
+ - lib/bigbluebutton_api.rb
48
+ - lib/bigbluebutton_exception.rb
49
+ - lib/bigbluebutton_formatter.rb
44
50
  - lib/hash_to_xml.rb
51
+ - spec/bigbluebutton_api_spec.rb
52
+ - spec/bigbluebutton_exception_spec.rb
53
+ - spec/bigbluebutton_formatter_spec.rb
54
+ - spec/spec_helper.rb
45
55
  - test/config.yml.example
46
56
  - test/test.rb
47
57
  homepage: https://github.com/mconf/bigbluebutton-api-ruby/
@@ -64,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
74
  version: '0'
65
75
  requirements: []
66
76
  rubyforge_project:
67
- rubygems_version: 1.7.2
77
+ rubygems_version: 1.8.10
68
78
  signing_key:
69
79
  specification_version: 3
70
80
  summary: Provides an interface to the BigBlueButton web meeting API (https://github.com/mconf/bigbluebutton-api-ruby)