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.
- data/.gitignore +5 -2
- data/.rvmrc +1 -1
- data/.travis.yml +6 -0
- data/CHANGELOG.rdoc +19 -8
- data/Gemfile +9 -1
- data/Gemfile.lock +62 -9
- data/LICENSE +5 -7
- data/LICENSE_003 +20 -0
- data/README.rdoc +42 -19
- data/Rakefile +31 -19
- data/bigbluebutton-api-ruby.gemspec +5 -5
- data/examples/get_version_example.rb +18 -0
- data/examples/join_example.rb +59 -0
- data/examples/overall_0.7_example.rb +92 -0
- data/examples/prepare.rb +38 -0
- data/extras/bigbluebutton_bot.rb +64 -0
- data/extras/download_bot_from.txt +1 -0
- data/extras/test-presentation.pdf +0 -0
- data/features/check_status.feature +45 -0
- data/features/config.yml.example +21 -0
- data/features/create_meetings.feature +29 -0
- data/features/end_meetings.feature +27 -0
- data/features/join_meetings.feature +29 -0
- data/features/pre_upload_slides.feature +14 -0
- data/features/recordings.feature +34 -0
- data/features/step_definitions/check_status_steps.rb +119 -0
- data/features/step_definitions/common_steps.rb +122 -0
- data/features/step_definitions/create_meetings_steps.rb +54 -0
- data/features/step_definitions/end_meetings_steps.rb +49 -0
- data/features/step_definitions/join_meetings_steps.rb +39 -0
- data/features/step_definitions/pre_upload_slides_steps.rb +13 -0
- data/features/step_definitions/recordings_steps.rb +38 -0
- data/features/support/api_tests/configs.rb +51 -0
- data/features/support/env.rb +7 -0
- data/features/support/hooks.rb +11 -0
- data/lib/bigbluebutton_api.rb +301 -97
- data/lib/bigbluebutton_formatter.rb +105 -19
- data/lib/bigbluebutton_modules.rb +92 -0
- data/lib/hash_to_xml.rb +22 -51
- data/spec/bigbluebutton_api_0.8_spec.rb +273 -0
- data/spec/bigbluebutton_api_spec.rb +211 -117
- data/spec/bigbluebutton_formatter_spec.rb +178 -29
- data/spec/bigbluebutton_modules_spec.rb +95 -0
- data/spec/data/hash_to_xml_complex.xml +45 -0
- data/spec/hash_to_xml_spec.rb +143 -0
- data/spec/spec_helper.rb +4 -2
- data/spec/support/forgery/forgeries/random_name.rb +7 -0
- data/spec/support/forgery/forgeries/url.rb +5 -0
- metadata +47 -12
- data/test/config.yml.example +0 -9
- data/test/test.rb +0 -154
@@ -5,12 +5,25 @@ module BigBlueButton
|
|
5
5
|
attr_accessor :hash
|
6
6
|
|
7
7
|
def initialize(hash)
|
8
|
-
@hash = hash
|
8
|
+
@hash = hash || {}
|
9
9
|
end
|
10
10
|
|
11
11
|
# converts a value in the @hash to boolean
|
12
12
|
def to_boolean(key)
|
13
|
-
|
13
|
+
unless @hash.has_key?(key)
|
14
|
+
false
|
15
|
+
else
|
16
|
+
@hash[key] = @hash[key].downcase == "true"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# converts a value in the @hash to int
|
21
|
+
def to_int(key)
|
22
|
+
unless @hash.has_key?(key)
|
23
|
+
0
|
24
|
+
else
|
25
|
+
@hash[key] = @hash[key].to_i
|
26
|
+
end
|
14
27
|
end
|
15
28
|
|
16
29
|
# converts a value in the @hash to string
|
@@ -20,14 +33,51 @@ module BigBlueButton
|
|
20
33
|
|
21
34
|
# converts a value in the @hash to DateTime
|
22
35
|
def to_datetime(key)
|
23
|
-
|
36
|
+
unless @hash.has_key?(key) and @hash[key]
|
37
|
+
nil
|
38
|
+
else
|
39
|
+
# BBB >= 0.8 uses the unix epoch for all time related values
|
40
|
+
# older versions use strings
|
41
|
+
|
42
|
+
# a number but in a String class
|
43
|
+
if (@hash[key].class == String && @hash[key].to_i.to_s == @hash[key])
|
44
|
+
value = @hash[key].to_i
|
45
|
+
else
|
46
|
+
value = @hash[key]
|
47
|
+
end
|
48
|
+
|
49
|
+
if value.is_a?(Numeric)
|
50
|
+
result = value == 0 ? nil : DateTime.parse(Time.at(value/1000.0).to_s)
|
51
|
+
else
|
52
|
+
if value.downcase == "null"
|
53
|
+
result = nil
|
54
|
+
else
|
55
|
+
result = DateTime.parse(value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
@hash[key] = result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# converts a value in the @hash to a symbol
|
64
|
+
def to_sym(key)
|
65
|
+
unless @hash.has_key?(key)
|
66
|
+
""
|
67
|
+
else
|
68
|
+
if @hash[key].instance_of?(Symbol)
|
69
|
+
@hash[key]
|
70
|
+
elsif @hash[key].empty?
|
71
|
+
""
|
72
|
+
else
|
73
|
+
@hash[key] = @hash[key].downcase.to_sym
|
74
|
+
end
|
75
|
+
end
|
24
76
|
end
|
25
77
|
|
26
78
|
# Default formatting for all responses given by a BBB server
|
27
79
|
def default_formatting
|
28
|
-
|
29
|
-
# remove the "response" node
|
30
|
-
response = Hash[@hash[:response]].inject({}){|h,(k,v)| h[k] = v; h}
|
80
|
+
response = @hash
|
31
81
|
|
32
82
|
# Adjust some values. There will always be a returncode, a message and a messageKey in the hash.
|
33
83
|
response[:returncode] = response[:returncode].downcase == "success" # true instead of "SUCCESS"
|
@@ -37,25 +87,61 @@ module BigBlueButton
|
|
37
87
|
@hash = response
|
38
88
|
end
|
39
89
|
|
40
|
-
#
|
41
|
-
def format_meeting(meeting)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
90
|
+
# Default formatting for a meeting hash
|
91
|
+
def self.format_meeting(meeting)
|
92
|
+
f = BigBlueButtonFormatter.new(meeting)
|
93
|
+
f.to_string(:meetingID)
|
94
|
+
f.to_string(:moderatorPW)
|
95
|
+
f.to_string(:attendeePW)
|
96
|
+
f.to_boolean(:hasBeenForciblyEnded)
|
97
|
+
f.to_boolean(:running)
|
98
|
+
f.to_int(:createTime) if meeting.has_key?(:createTime)
|
47
99
|
meeting
|
48
100
|
end
|
49
101
|
|
50
|
-
#
|
51
|
-
def format_attendee(attendee)
|
52
|
-
|
53
|
-
|
102
|
+
# Default formatting for an attendee hash
|
103
|
+
def self.format_attendee(attendee)
|
104
|
+
f = BigBlueButtonFormatter.new(attendee)
|
105
|
+
f.to_string(:userID)
|
106
|
+
f.to_sym(:role)
|
54
107
|
attendee
|
55
108
|
end
|
56
109
|
|
57
|
-
#
|
58
|
-
|
110
|
+
# Default formatting for a recording hash
|
111
|
+
def self.format_recording(rec)
|
112
|
+
f = BigBlueButtonFormatter.new(rec)
|
113
|
+
f.to_string(:recordID)
|
114
|
+
f.to_string(:meetingID)
|
115
|
+
f.to_string(:name)
|
116
|
+
f.to_boolean(:published)
|
117
|
+
f.to_datetime(:startTime)
|
118
|
+
f.to_datetime(:endTime)
|
119
|
+
rec
|
120
|
+
end
|
121
|
+
|
122
|
+
# Simplifies the XML-styled hash node 'first'. Its value will then always be an Array.
|
123
|
+
#
|
124
|
+
# For example, if the current hash is:
|
125
|
+
# { :name => "Test", :attendees => { :attendee => [ { :name => "attendee1" }, { :name => "attendee2" } ] } }
|
126
|
+
#
|
127
|
+
# Calling:
|
128
|
+
# flatten_objects(:attendees, :attendee)
|
129
|
+
#
|
130
|
+
# The hash will become:
|
131
|
+
# { :name => "Test", :attendees => [ { :name => "attendee1" }, { :name => "attendee2" } ] }
|
132
|
+
#
|
133
|
+
# Other examples:
|
134
|
+
#
|
135
|
+
# Hash:
|
136
|
+
# { :name => "Test", :attendees => {} }
|
137
|
+
# Result:
|
138
|
+
# { :name => "Test", :attendees => [] }
|
139
|
+
#
|
140
|
+
# Hash:
|
141
|
+
# { :name => "Test", :attendees => { :attendee => { :name => "attendee1" } } }
|
142
|
+
# Result:
|
143
|
+
# { :name => "Test", :attendees => [ { :name => "attendee1" } ] }
|
144
|
+
#
|
59
145
|
def flatten_objects(first, second)
|
60
146
|
if @hash[first].empty?
|
61
147
|
collection = []
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
3
|
+
module BigBlueButton
|
4
|
+
|
5
|
+
# An object to store the modules configuration to be passed in
|
6
|
+
# BigBlueButtonApi#create_meeting().
|
7
|
+
#
|
8
|
+
# === Usage example:
|
9
|
+
#
|
10
|
+
# modules = BigBlueButton::BigBlueButtonModules.new
|
11
|
+
#
|
12
|
+
# # adds presentations by URL
|
13
|
+
# modules.add_presentation(:url, "http://www.samplepdf.com/sample.pdf")
|
14
|
+
# modules.add_presentation(:url, "http://www.samplepdf.com/sample2.pdf")
|
15
|
+
#
|
16
|
+
# # adds presentations from a local file
|
17
|
+
# # the file will be opened and encoded in base64
|
18
|
+
# modules.add_presentation(:file, "presentations/class01.ppt")
|
19
|
+
#
|
20
|
+
# # adds a base64 encoded presentation
|
21
|
+
# modules.add_presentation(:base64, "JVBERi0xLjQKJ....[clipped here]....0CiUlRU9GCg==", "first-class.pdf")
|
22
|
+
#
|
23
|
+
class BigBlueButtonModules
|
24
|
+
|
25
|
+
attr_accessor :presentation_urls
|
26
|
+
attr_accessor :presentation_files
|
27
|
+
attr_accessor :presentation_base64s
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@presentation_urls = []
|
31
|
+
@presentation_files = []
|
32
|
+
@presentation_base64s = []
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_presentation(type, value, name=nil)
|
36
|
+
case type
|
37
|
+
when :url
|
38
|
+
@presentation_urls.push(value)
|
39
|
+
when :file
|
40
|
+
@presentation_files.push(value)
|
41
|
+
when :base64
|
42
|
+
@presentation_base64s.push([name, value])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_xml
|
47
|
+
unless has_presentations?
|
48
|
+
""
|
49
|
+
else
|
50
|
+
xml = xml_header
|
51
|
+
xml << presentations_to_xml
|
52
|
+
xml << xml_footer
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def has_presentations?
|
59
|
+
!@presentation_urls.empty? or
|
60
|
+
!@presentation_files.empty? or
|
61
|
+
!@presentation_base64s.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def xml_header
|
65
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><modules>"
|
66
|
+
end
|
67
|
+
|
68
|
+
def xml_footer
|
69
|
+
"</modules>"
|
70
|
+
end
|
71
|
+
|
72
|
+
def presentations_to_xml
|
73
|
+
xml = "<module name=\"presentation\">"
|
74
|
+
@presentation_urls.each { |url| xml << "<document url=\"#{url}\" />" }
|
75
|
+
@presentation_base64s.each do |name, data|
|
76
|
+
xml << "<document name=\"#{name}\">"
|
77
|
+
xml << data
|
78
|
+
xml << "</document>"
|
79
|
+
end
|
80
|
+
@presentation_files.each do |filename|
|
81
|
+
xml << "<document name=\"#{File.basename(filename)}\">"
|
82
|
+
File.open(filename, "r") do |file|
|
83
|
+
xml << Base64.encode64(file.read)
|
84
|
+
end
|
85
|
+
xml << "</document>"
|
86
|
+
end
|
87
|
+
xml << "</module>"
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/lib/hash_to_xml.rb
CHANGED
@@ -1,62 +1,33 @@
|
|
1
|
-
|
2
|
-
# USAGE: Hash.from_xml:(YOUR_XML_STRING)
|
3
|
-
# modified from http://stackoverflow.com/questions/1230741/convert-a-nokogiri-document-to-a-ruby-hash/1231297#1231297
|
1
|
+
require 'xmlsimple'
|
4
2
|
|
5
3
|
class Hash
|
6
4
|
class << self
|
7
|
-
def from_xml(xml_io)
|
5
|
+
def from_xml(xml_io)
|
8
6
|
begin
|
9
|
-
|
10
|
-
|
7
|
+
# we'll not use 'KeyToSymbol' because it doesn't symbolize the keys for node attributes
|
8
|
+
opts = { 'ForceArray' => false, 'ForceContent' => false } #
|
9
|
+
hash = XmlSimple.xml_in(xml_io, opts)
|
10
|
+
return symbolize_keys(hash)
|
11
11
|
rescue Exception => e
|
12
12
|
raise BigBlueButton::BigBlueButtonException.new("Impossible to convert XML to hash. Error: #{e.message}")
|
13
13
|
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def xml_node_to_hash(node)
|
17
|
-
# If we are at the root of the document, start the hash
|
18
|
-
if node.element?
|
19
|
-
result_hash = {}
|
20
|
-
if node.attributes != {}
|
21
|
-
result_hash[:attributes] = {}
|
22
|
-
node.attributes.keys.each do |key|
|
23
|
-
result_hash[:attributes][node.attributes[key].name.to_sym] = prepare(node.attributes[key].value)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
if node.children.size > 0
|
27
|
-
node.children.each do |child|
|
28
|
-
result = xml_node_to_hash(child)
|
29
|
-
|
30
|
-
if child.name == "text"
|
31
|
-
unless child.next_sibling || child.previous_sibling
|
32
|
-
return prepare(result)
|
33
|
-
end
|
34
|
-
elsif result_hash[child.name.to_sym]
|
35
|
-
if result_hash[child.name.to_sym].is_a?(Object::Array)
|
36
|
-
result_hash[child.name.to_sym] << prepare(result)
|
37
|
-
else
|
38
|
-
result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << prepare(result)
|
39
|
-
end
|
40
|
-
else
|
41
|
-
result_hash[child.name.to_sym] = prepare(result)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
return result_hash
|
46
|
-
else
|
47
|
-
return result_hash
|
48
|
-
end
|
49
|
-
else
|
50
|
-
return prepare(node.content.to_s)
|
51
|
-
end
|
52
|
-
end
|
14
|
+
end
|
53
15
|
|
54
|
-
def
|
55
|
-
|
16
|
+
def symbolize_keys(arg)
|
17
|
+
case arg
|
18
|
+
when Array
|
19
|
+
arg.map { |elem| symbolize_keys elem }
|
20
|
+
when Hash
|
21
|
+
Hash[
|
22
|
+
arg.map { |key, value|
|
23
|
+
k = key.is_a?(String) ? key.to_sym : key
|
24
|
+
v = symbolize_keys value
|
25
|
+
[k,v]
|
26
|
+
}]
|
27
|
+
else
|
28
|
+
arg
|
29
|
+
end
|
56
30
|
end
|
57
|
-
|
58
|
-
|
59
|
-
def to_struct(struct_name)
|
60
|
-
Struct.new(struct_name,*keys).new(*values)
|
31
|
+
|
61
32
|
end
|
62
33
|
end
|
@@ -0,0 +1,273 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Tests for BBB API version 0.8
|
4
|
+
describe BigBlueButton::BigBlueButtonApi do
|
5
|
+
|
6
|
+
# default variables and API object for all tests
|
7
|
+
let(:url) { "http://server.com" }
|
8
|
+
let(:salt) { "1234567890abcdefghijkl" }
|
9
|
+
let(:version) { "0.8" }
|
10
|
+
let(:debug) { false }
|
11
|
+
let(:api) { BigBlueButton::BigBlueButtonApi.new(url, salt, version, debug) }
|
12
|
+
|
13
|
+
describe "#create_meeting" do
|
14
|
+
|
15
|
+
context "without modules" do
|
16
|
+
let(:req_params) {
|
17
|
+
{ :name => "name", :meetingID => "meeting-id", :moderatorPW => "mp", :attendeePW => "ap",
|
18
|
+
:welcome => "Welcome!", :dialNumber => 12345678, :logoutURL => "http://example.com",
|
19
|
+
:maxParticipants => 25, :voiceBridge => 12345, :record => "true", :duration => 20,
|
20
|
+
:meta_1 => "meta1", :meta_2 => "meta2" }
|
21
|
+
}
|
22
|
+
let(:req_response) {
|
23
|
+
{ :meetingID => 123, :moderatorPW => 111, :attendeePW => 222, :hasBeenForciblyEnded => "FALSE", :createTime => "123123123" }
|
24
|
+
}
|
25
|
+
let(:final_response) {
|
26
|
+
{ :meetingID => "123", :moderatorPW => "111", :attendeePW => "222", :hasBeenForciblyEnded => false, :createTime => 123123123 }
|
27
|
+
}
|
28
|
+
|
29
|
+
before { api.should_receive(:send_api_request).with(:create, req_params).and_return(req_response) }
|
30
|
+
subject {
|
31
|
+
options = { :moderatorPW => "mp", :attendeePW => "ap", :welcome => "Welcome!", :dialNumber => 12345678,
|
32
|
+
:logoutURL => "http://example.com", :maxParticipants => 25, :voiceBridge => 12345, :record => true,
|
33
|
+
:duration => 20, :meta_1 => "meta1", :meta_2 => "meta2" }
|
34
|
+
api.create_meeting("name", "meeting-id", options)
|
35
|
+
}
|
36
|
+
it { subject.should == final_response }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with modules" do
|
40
|
+
let(:req_params) {
|
41
|
+
{ :name => "name", :meetingID => "meeting-id", :moderatorPW => "mp", :attendeePW => "ap" }
|
42
|
+
}
|
43
|
+
let(:req_response) {
|
44
|
+
{ :meetingID => 123, :moderatorPW => 111, :attendeePW => 222, :hasBeenForciblyEnded => "FALSE", :createTime => "123123123" }
|
45
|
+
}
|
46
|
+
let(:final_response) {
|
47
|
+
{ :meetingID => "123", :moderatorPW => "111", :attendeePW => "222", :hasBeenForciblyEnded => false, :createTime => 123123123 }
|
48
|
+
}
|
49
|
+
let(:modules) {
|
50
|
+
m = BigBlueButton::BigBlueButtonModules.new
|
51
|
+
m.add_presentation(:url, "http://www.samplepdf.com/sample.pdf")
|
52
|
+
m.add_presentation(:url, "http://www.samplepdf.com/sample2.pdf")
|
53
|
+
m.add_presentation(:base64, "JVBERi0xLjQKJ....[clipped here]....0CiUlRU9GCg==", "first-class.pdf")
|
54
|
+
m
|
55
|
+
}
|
56
|
+
|
57
|
+
before {
|
58
|
+
api.should_receive(:send_api_request).with(:create, req_params, modules.to_xml).
|
59
|
+
and_return(req_response)
|
60
|
+
}
|
61
|
+
subject {
|
62
|
+
options = { :moderatorPW => "mp", :attendeePW => "ap" }
|
63
|
+
api.create_meeting("name", "meeting-id", options, modules)
|
64
|
+
}
|
65
|
+
it { subject.should == final_response }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#join_meeting_url" do
|
70
|
+
let(:params) {
|
71
|
+
{ :meetingID => "meeting-id", :password => "pw", :fullName => "Name",
|
72
|
+
:userID => "id123", :webVoiceConf => 12345678, :createTime => 9876543 }
|
73
|
+
}
|
74
|
+
|
75
|
+
before { api.should_receive(:get_url).with(:join, params).and_return("test-url") }
|
76
|
+
it {
|
77
|
+
options = { :userID => "id123", :webVoiceConf => 12345678, :createTime => 9876543 }
|
78
|
+
api.join_meeting_url("meeting-id", "Name", "pw", options).should == "test-url"
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#join_meeting" do
|
83
|
+
let(:params) {
|
84
|
+
{ :meetingID => "meeting-id", :password => "pw", :fullName => "Name",
|
85
|
+
:userID => "id123", :webVoiceConf => 12345678, :createTime => 9876543 }
|
86
|
+
}
|
87
|
+
|
88
|
+
before { api.should_receive(:send_api_request).with(:join, params).and_return("join-return") }
|
89
|
+
it {
|
90
|
+
options = { :userID => "id123", :webVoiceConf => 12345678, :createTime => 9876543 }
|
91
|
+
api.join_meeting("meeting-id", "Name", "pw", options).should == "join-return"
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#get_recordings" do
|
96
|
+
let(:recording1) { { :recordID => "id1", :meetindID => "meeting-id" } } # simplified "recording" node in the response
|
97
|
+
let(:recording2) { { :recordID => "id2", :meetindID => "meeting-id" } }
|
98
|
+
let(:response) {
|
99
|
+
{ :returncode => true, :recordings => { :recording => [ recording1, recording2 ] }, :messageKey => "mkey", :message => "m" }
|
100
|
+
}
|
101
|
+
let(:flattened_response) {
|
102
|
+
{ :returncode => true, :recordings => [ recording1, recording2 ], :messageKey => "mkey", :message => "m" }
|
103
|
+
} # hash *after* the flatten_objects call
|
104
|
+
|
105
|
+
context "only supported for >= 0.8" do
|
106
|
+
let(:api) { BigBlueButton::BigBlueButtonApi.new(url, salt, "0.7", debug) }
|
107
|
+
it { expect { api.get_recordings }.to raise_error(BigBlueButton::BigBlueButtonException) }
|
108
|
+
end
|
109
|
+
|
110
|
+
context "discards invalid options" do
|
111
|
+
let(:req_params) { { :meetingID => "meeting-id" } }
|
112
|
+
before { api.should_receive(:send_api_request).with(:getRecordings, req_params).and_return(response) }
|
113
|
+
it { api.get_recordings({ :meetingID => "meeting-id", :invalidParam1 => "1" }) }
|
114
|
+
end
|
115
|
+
|
116
|
+
context "without meeting ID" do
|
117
|
+
before { api.should_receive(:send_api_request).with(:getRecordings, {}).and_return(response) }
|
118
|
+
it { api.get_recordings.should == response }
|
119
|
+
end
|
120
|
+
|
121
|
+
context "with one meeting ID" do
|
122
|
+
context "in an array" do
|
123
|
+
let(:options) { { :meetingID => ["meeting-id"] } }
|
124
|
+
let(:req_params) { { :meetingID => "meeting-id" } }
|
125
|
+
before { api.should_receive(:send_api_request).with(:getRecordings, req_params).and_return(response) }
|
126
|
+
it { api.get_recordings(options).should == response }
|
127
|
+
end
|
128
|
+
|
129
|
+
context "in a string" do
|
130
|
+
let(:options) { { :meetingID => "meeting-id" } }
|
131
|
+
let(:req_params) { { :meetingID => "meeting-id" } }
|
132
|
+
before { api.should_receive(:send_api_request).with(:getRecordings, req_params).and_return(response) }
|
133
|
+
it { api.get_recordings(options).should == response }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "with several meeting IDs" do
|
138
|
+
context "in an array" do
|
139
|
+
let(:options) { { :meetingID => ["meeting-id-1", "meeting-id-2"] } }
|
140
|
+
let(:req_params) { { :meetingID => "meeting-id-1,meeting-id-2" } }
|
141
|
+
before { api.should_receive(:send_api_request).with(:getRecordings, req_params).and_return(response) }
|
142
|
+
it { api.get_recordings(options).should == response }
|
143
|
+
end
|
144
|
+
|
145
|
+
context "in a string" do
|
146
|
+
let(:options) { { :meetingID => "meeting-id-1,meeting-id-2" } }
|
147
|
+
let(:req_params) { { :meetingID => "meeting-id-1,meeting-id-2" } }
|
148
|
+
before { api.should_receive(:send_api_request).with(:getRecordings, req_params).and_return(response) }
|
149
|
+
it { api.get_recordings(options).should == response }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "formats the response" do
|
154
|
+
before {
|
155
|
+
api.should_receive(:send_api_request).with(:getRecordings, anything).and_return(flattened_response)
|
156
|
+
formatter_mock = mock(BigBlueButton::BigBlueButtonFormatter)
|
157
|
+
formatter_mock.should_receive(:flatten_objects).with(:recordings, :recording)
|
158
|
+
BigBlueButton::BigBlueButtonFormatter.should_receive(:format_recording).with(recording1)
|
159
|
+
BigBlueButton::BigBlueButtonFormatter.should_receive(:format_recording).with(recording2)
|
160
|
+
BigBlueButton::BigBlueButtonFormatter.should_receive(:new).and_return(formatter_mock)
|
161
|
+
}
|
162
|
+
it { api.get_recordings }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "#publish_recordings" do
|
167
|
+
context "only supported for >= 0.8" do
|
168
|
+
let(:api) { BigBlueButton::BigBlueButtonApi.new(url, salt, "0.7", debug) }
|
169
|
+
it { expect { api.publish_recordings("id", true) }.to raise_error(BigBlueButton::BigBlueButtonException) }
|
170
|
+
end
|
171
|
+
|
172
|
+
context "publish is converted to string" do
|
173
|
+
let(:recordIDs) { "any" }
|
174
|
+
let(:req_params) { { :publish => "false", :recordID => "any" } }
|
175
|
+
before { api.should_receive(:send_api_request).with(:publishRecordings, req_params) }
|
176
|
+
it { api.publish_recordings(recordIDs, false) }
|
177
|
+
end
|
178
|
+
|
179
|
+
context "with one recording ID" do
|
180
|
+
context "in an array" do
|
181
|
+
let(:recordIDs) { ["id-1"] }
|
182
|
+
let(:req_params) { { :publish => "true", :recordID => "id-1" } }
|
183
|
+
before { api.should_receive(:send_api_request).with(:publishRecordings, req_params) }
|
184
|
+
it { api.publish_recordings(recordIDs, true) }
|
185
|
+
end
|
186
|
+
|
187
|
+
context "in a string" do
|
188
|
+
let(:recordIDs) { "id-1" }
|
189
|
+
let(:req_params) { { :publish => "true", :recordID => "id-1" } }
|
190
|
+
before { api.should_receive(:send_api_request).with(:publishRecordings, req_params) }
|
191
|
+
it { api.publish_recordings(recordIDs, true) }
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "with several recording IDs" do
|
196
|
+
context "in an array" do
|
197
|
+
let(:recordIDs) { ["id-1", "id-2"] }
|
198
|
+
let(:req_params) { { :publish => "true", :recordID => "id-1,id-2" } }
|
199
|
+
before { api.should_receive(:send_api_request).with(:publishRecordings, req_params) }
|
200
|
+
it { api.publish_recordings(recordIDs, true) }
|
201
|
+
end
|
202
|
+
|
203
|
+
context "in a string" do
|
204
|
+
let(:recordIDs) { "id-1,id-2,id-3" }
|
205
|
+
let(:req_params) { { :publish => "true", :recordID => "id-1,id-2,id-3" } }
|
206
|
+
before { api.should_receive(:send_api_request).with(:publishRecordings, req_params) }
|
207
|
+
it { api.publish_recordings(recordIDs, true) }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "#delete_recordings" do
|
213
|
+
context "only supported for >= 0.8" do
|
214
|
+
let(:api) { BigBlueButton::BigBlueButtonApi.new(url, salt, "0.7", debug) }
|
215
|
+
it { expect { api.delete_recordings("id") }.to raise_error(BigBlueButton::BigBlueButtonException) }
|
216
|
+
end
|
217
|
+
|
218
|
+
context "with one recording ID" do
|
219
|
+
context "in an array" do
|
220
|
+
let(:recordIDs) { ["id-1"] }
|
221
|
+
let(:req_params) { { :recordID => "id-1" } }
|
222
|
+
before { api.should_receive(:send_api_request).with(:deleteRecordings, req_params) }
|
223
|
+
it { api.delete_recordings(recordIDs) }
|
224
|
+
end
|
225
|
+
|
226
|
+
context "in a string" do
|
227
|
+
let(:recordIDs) { "id-1" }
|
228
|
+
let(:req_params) { { :recordID => "id-1" } }
|
229
|
+
before { api.should_receive(:send_api_request).with(:deleteRecordings, req_params) }
|
230
|
+
it { api.delete_recordings(recordIDs) }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "with several recording IDs" do
|
235
|
+
context "in an array" do
|
236
|
+
let(:recordIDs) { ["id-1", "id-2"] }
|
237
|
+
let(:req_params) { { :recordID => "id-1,id-2" } }
|
238
|
+
before { api.should_receive(:send_api_request).with(:deleteRecordings, req_params) }
|
239
|
+
it { api.delete_recordings(recordIDs) }
|
240
|
+
end
|
241
|
+
|
242
|
+
context "in a string" do
|
243
|
+
let(:recordIDs) { "id-1,id-2,id-3" }
|
244
|
+
let(:req_params) { { :recordID => "id-1,id-2,id-3" } }
|
245
|
+
before { api.should_receive(:send_api_request).with(:deleteRecordings, req_params) }
|
246
|
+
it { api.delete_recordings(recordIDs) }
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe "#get_meeting_info" do
|
252
|
+
let(:params) { { :meetingID => "meeting-id", :password => "password" } }
|
253
|
+
|
254
|
+
# new values were added in the response in 0.8 (we'll only test these values):
|
255
|
+
# meetingName, participantCount, maxUsers, voiceBridge, recording, metadata
|
256
|
+
let(:response) {
|
257
|
+
{ :meetingName => 123, :maxUsers => "100", :voiceBridge => "12341234",
|
258
|
+
:createTime => "123123123", :attendees => { :attendee => [ ] },
|
259
|
+
:messageKey => "mkey", :message => "m", :recording => "false", :meta_1 => "abc", :meta_2 => "2" }
|
260
|
+
}
|
261
|
+
|
262
|
+
before { api.should_receive(:send_api_request).with(:getMeetingInfo, params).and_return(response) }
|
263
|
+
subject { api.get_meeting_info("meeting-id", "password") }
|
264
|
+
it { subject[:meetingName].should == "123" }
|
265
|
+
it { subject[:maxUsers].should == 100 }
|
266
|
+
it { subject[:voiceBridge].should == 12341234 }
|
267
|
+
it { subject[:createTime].should == 123123123 }
|
268
|
+
it { subject[:recording].should == false }
|
269
|
+
it { subject[:meta_1].should == "abc" }
|
270
|
+
it { subject[:meta_2].should == "2" }
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|