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