diff --git a/README.md b/README.md index 3d4c538b..1e7a8d5f 100644 --- a/README.md +++ b/README.md @@ -486,10 +486,42 @@ for more details. You can also change the layout of an individual stream dynamically. Refer to [working with Streams](#working-with-streams). -### Force disconnect +### Working with Connections + +#### Listing Connections + +You can retrieve a list of clients connected to a session using the `OpenTok::Connetions#list` method, passing in the Session ID of the session, for example: + +```ruby +connection_list = opentok.connections.list('abcdefg12345') +``` + +This will return an iterable `ConnectionList` object with `total` and `session_id` getter methods: + +```ruby +connection_list.total # => 5 +connection_list.session_id # => 'abcdefg12345' +``` + +The items in the connection list are `Connection` objects, each representing a client connection to the session. You can access data on individual connection objects: + +```ruby +connection_1 = connection_list.first +connection_1.connection_id # => "249b7640-1bcf-4f49-8fc7-3d7998ff218b" +connection_1.connection_state # => "Connected" +connection_1.created_at # => 1779287104931 +``` + +#### Force disconnect You can cause a client to be forced to disconnect from a session by using the -`opentok.connections.forceDisconnect(session_id, connection_id)` method. +`opentok.connections.forceDisconnect(session_id, connection_id)` method and passing in the Session ID and Connection ID. + +You can also call the `Connection#force_disconnect` method on a `Connection` object returned when listing connections: + +```ruby +connection_1.force_disconnect +``` ### Forcing clients in a session to mute published audio diff --git a/lib/opentok/client.rb b/lib/opentok/client.rb index 3a99f202..7d35b68f 100644 --- a/lib/opentok/client.rb +++ b/lib/opentok/client.rb @@ -48,7 +48,7 @@ def create_session(opts) opts.extend(HashExtensions) response = self.class.post("/session/create", { :body => opts.camelize_keys!, - :headers => generate_headers + :headers => generate_headers("Content-Type" => "application/x-www-form-urlencoded") }) case response.code when (200..300) @@ -411,6 +411,30 @@ def stop_live_captions(captions_id) # Connections methods + def list_connections(session_id, offset, count) + query = Hash.new + query[:offset] = offset unless offset.nil? + query[:count] = count unless count.nil? + response = self.class.get("/v2/project/#{@api_key}/session/#{session_id}/connection", { + :query => query.empty? ? nil : query, + :headers => generate_headers + }) + case response.code + when 200 + response + when 400 + raise ArgumentError, "Invalid request. This response may indicate that some parameter of your query is invalid." + when 403 + raise OpenTokAuthenticationError, "Authentication failed while retrieving connections. API Key: #{@api_key}" + when 404 + raise OpenTokConnectionError, "Either the OpenTok session could not be found, or no clients are actively connected to the session." + else + raise OpenTokConnectionError, "The connections could not be retrieved." + end + rescue StandardError => e + raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}" + end + def forceDisconnect(session_id, connection_id) response = self.class.delete("/v2/project/#{@api_key}/session/#{session_id}/connection/#{connection_id}", { :headers => generate_headers("Content-Type" => "application/json") diff --git a/lib/opentok/connection.rb b/lib/opentok/connection.rb new file mode 100644 index 00000000..76d843ef --- /dev/null +++ b/lib/opentok/connection.rb @@ -0,0 +1,47 @@ +require "active_support/inflector" + +module OpenTok + # Represents a connection in an OpenTok session. + # + # @attr [String] connection_id + # The ID of the connection. + # + # @attr [Integer] created_at + # The timestamp when the connection was created, expressed in milliseconds since the Unix epoch. + # + # @attr [String] connection_state + # The state of the connection. + # + class Connection + # @private + def initialize(interface, session_id, json) + @interface = interface + @session_id = session_id + # TODO: validate json fits schema + @json = json + end + + # A JSON-encoded string representation of the connection. + def to_json + @json.to_json + end + + # Forces the disconnection of this connection from the OpenTok session. + # + # A client must be actively connected to the OpenTok session for you to disconnect it. + def force_disconnect + # TODO: validate returned json fits schema + @json = @interface.forceDisconnect(@session_id, @json['connectionId']) + end + + # @private ignore + def method_missing(method, *args, &block) + camelized_method = method.to_s.camelize(:lower) + if @json.has_key? camelized_method and args.empty? + @json[camelized_method] + else + super method, *args, &block + end + end + end +end diff --git a/lib/opentok/connection_list.rb b/lib/opentok/connection_list.rb new file mode 100644 index 00000000..711576bb --- /dev/null +++ b/lib/opentok/connection_list.rb @@ -0,0 +1,18 @@ +require "opentok/connection" + +module OpenTok + # A class for accessing an array of Connection objects. + class ConnectionList < Array + + # The total number of connections. + attr_reader :total, :session_id + + # @private + def initialize(interface, json) + @total = json['count'] + @session_id = json['sessionId'] + super json['items'].map { |item| Connection.new interface, session_id, item } + end + + end +end diff --git a/lib/opentok/connections.rb b/lib/opentok/connections.rb index 86919a2e..2bde439e 100644 --- a/lib/opentok/connections.rb +++ b/lib/opentok/connections.rb @@ -1,3 +1,7 @@ +require "opentok/client" +require "opentok/connection" +require "opentok/connection_list" + module OpenTok # A class for working with OpenTok connections. class Connections @@ -6,6 +10,23 @@ def initialize(client) @client = client end + # Returns a ConnectionList, which is an array of connections that are active in a session, + # for your API key. + # + # @param [String] session_id The session ID of the OpenTok session. + # @param [Hash] options A hash with keys defining which range of connections to retrieve. + # @option options [integer] :offset Optional. The index offset of the first connection. If you do not specify an offset, 0 is used. + # @option options [integer] :count Optional. The number of connections to be returned. The maximum + # number of connections returned is 1000. If you do not specify a count, 50 is used. + # + # @return [ConnectionList] A ConnectionList object, which is an array of Connection objects. + def list(session_id, options = {}) + raise ArgumentError, "session_id not provided" if session_id.to_s.empty? + raise ArgumentError, "count must be between 1 and 1000" if options[:count] && (options[:count] < 1 || options[:count] > 1000) + connections_list_json = @client.list_connections(session_id, options[:offset], options[:count]) + ConnectionList.new self, connections_list_json + end + # Force a client to disconnect from an OpenTok session. # # A client must be actively connected to the OpenTok session for you to disconnect it. @@ -17,7 +38,7 @@ def initialize(client) # @raise [OpenTokAuthenticationError] You are not authorized to disconnect the connection. Check your authentication credentials. # @raise [OpenTokConnectionError] The client specified by the connection_id property is not connected to the session. # - def forceDisconnect(session_id, connection_id ) + def forceDisconnect(session_id, connection_id) raise ArgumentError, "session_id not provided" if session_id.to_s.empty? raise ArgumentError, "connection_id not provided" if connection_id.to_s.empty? response = @client.forceDisconnect(session_id, connection_id) diff --git a/lib/opentok/websocket.rb b/lib/opentok/websocket.rb index 2389a049..6f252d7b 100644 --- a/lib/opentok/websocket.rb +++ b/lib/opentok/websocket.rb @@ -27,6 +27,8 @@ class WebSocket # @option opts [Hash] :headers (optional) A hash of key-value pairs of headers to be sent to your WebSocket server with each message, # with a maximum length of 512 bytes. # @option opts [Boolean] :bidirectional (optional) Whether the WebSocket connection should be bidirectional. + # @option opts [Integer] :audio_rate (optional) A number representing the audio sampling rate in Hz for the WebSocket stream. + # - Must be one of: 8000, 16000, 24000 def connect(session_id, token, websocket_uri, opts = {}) response = @client.connect_websocket(session_id, token, websocket_uri, opts) end diff --git a/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_all_connections.yml b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_all_connections.yml new file mode 100644 index 00000000..541c77fa --- /dev/null +++ b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_all_connections.yml @@ -0,0 +1,63 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.opentok.com/v2/project/123456/session/SESSIONID/connection + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - OpenTok-Ruby-SDK/<%= version %> + X-Opentok-Auth: + - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Tue, 19 May 2026 14:06:41 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + body: + encoding: UTF-8 + string: |- + { + "count" : 5, + "projectId" : "123456", + "sessionId" : "2_MX40NzIwMzJ-flR1ZSBPY3QgMjkgMTI6MTM6MjMgUERUIDIwMTN-MC45NDQ2MzE2NH4", + "items" : [{ + "connectionId": "527775e1-626e-42c3-b0e8-e2122d20661a", + "createdAt": 1747655658197, + "connectionState": "Connected" + },{ + "connectionId": "c6db93f0-8692-438c-944b-cfbaf577c878", + "createdAt": 1747655658227, + "connectionState": "Connected" + },{ + "connectionId": "d95f6496-df6e-4f49-86d6-832e00303602", + "createdAt": 1747655658258, + "connectionState": "Connected" + },{ + "connectionId": "15d73844-d503-4656-afdd-3eb10c96f4dc", + "createdAt": 1747655658300, + "connectionState": "Connected" + },{ + "connectionId": "6f2a13b1-8d59-40ba-9719-891498aba89e", + "createdAt": 1747655658400, + "connectionState": "Connected" + }] + } + recorded_at: Tue, 19 May 2026 14:06:41 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_connections_with_an_offset.yml b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_connections_with_an_offset.yml new file mode 100644 index 00000000..7147b976 --- /dev/null +++ b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_connections_with_an_offset.yml @@ -0,0 +1,55 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.opentok.com/v2/project/123456/session/SESSIONID/connection?offset=2 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - OpenTok-Ruby-SDK/<%= version %> + X-Opentok-Auth: + - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Tue, 19 May 2026 14:06:41 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + body: + encoding: UTF-8 + string: |- + { + "count" : 3, + "projectId" : "123456", + "sessionId" : "2_MX40NzIwMzJ-flR1ZSBPY3QgMjkgMTI6MTM6MjMgUERUIDIwMTN-MC45NDQ2MzE2NH4", + "items" : [{ + "connectionId": "d95f6496-df6e-4f49-86d6-832e00303602", + "createdAt": 1747655658258, + "connectionState": "Connected" + },{ + "connectionId": "15d73844-d503-4656-afdd-3eb10c96f4dc", + "createdAt": 1747655658300, + "connectionState": "Connected" + },{ + "connectionId": "6f2a13b1-8d59-40ba-9719-891498aba89e", + "createdAt": 1747655658400, + "connectionState": "Connected" + }] + } + recorded_at: Tue, 19 May 2026 14:06:41 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_count_number_of_connections.yml b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_count_number_of_connections.yml new file mode 100644 index 00000000..004e5adc --- /dev/null +++ b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_count_number_of_connections.yml @@ -0,0 +1,51 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.opentok.com/v2/project/123456/session/SESSIONID/connection?count=2 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - OpenTok-Ruby-SDK/<%= version %> + X-Opentok-Auth: + - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Tue, 19 May 2026 14:06:41 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + body: + encoding: UTF-8 + string: |- + { + "count" : 2, + "projectId" : "123456", + "sessionId" : "2_MX40NzIwMzJ-flR1ZSBPY3QgMjkgMTI6MTM6MjMgUERUIDIwMTN-MC45NDQ2MzE2NH4", + "items" : [{ + "connectionId": "527775e1-626e-42c3-b0e8-e2122d20661a", + "createdAt": 1747655658197, + "connectionState": "Connected" + },{ + "connectionId": "c6db93f0-8692-438c-944b-cfbaf577c878", + "createdAt": 1747655658227, + "connectionState": "Connected" + }] + } + recorded_at: Tue, 19 May 2026 14:06:41 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_part_of_the_connections_when_using_offset_and_count.yml b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_part_of_the_connections_when_using_offset_and_count.yml new file mode 100644 index 00000000..6e76dc2b --- /dev/null +++ b/spec/cassettes/OpenTok_Connections/when_attempting_to_list_connections/should_return_part_of_the_connections_when_using_offset_and_count.yml @@ -0,0 +1,51 @@ +--- +http_interactions: +- request: + method: get + uri: https://api.opentok.com/v2/project/123456/session/SESSIONID/connection?count=2&offset=1 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - OpenTok-Ruby-SDK/<%= version %> + X-Opentok-Auth: + - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Tue, 19 May 2026 14:06:41 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + body: + encoding: UTF-8 + string: |- + { + "count" : 2, + "projectId" : "123456", + "sessionId" : "2_MX40NzIwMzJ-flR1ZSBPY3QgMjkgMTI6MTM6MjMgUERUIDIwMTN-MC45NDQ2MzE2NH4", + "items" : [{ + "connectionId": "c6db93f0-8692-438c-944b-cfbaf577c878", + "createdAt": 1747655658227, + "connectionState": "Connected" + },{ + "connectionId": "d95f6496-df6e-4f49-86d6-832e00303602", + "createdAt": 1747655658258, + "connectionState": "Connected" + }] + } + recorded_at: Tue, 19 May 2026 14:06:41 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions.yml index 2c72b59d..c417e4ad 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions.yml @@ -13,6 +13,7 @@ http_interactions: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name.yml index 832ae740..7861959c 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name.yml @@ -15,6 +15,7 @@ http_interactions: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: - "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name_and_resolution.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name_and_resolution.yml index e7fd264f..c6ca7f7a 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name_and_resolution.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_name_and_resolution.yml @@ -15,6 +15,7 @@ http_interactions: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: - "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_resolution.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_resolution.yml index 4b366efb..4b196586 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_resolution.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions_with_a_set_archive_resolution.yml @@ -15,6 +15,7 @@ http_interactions: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: - "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml index aa53cbee..44c15dcd 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml @@ -11,8 +11,11 @@ http_interactions: - OpenTok-Ruby-SDK/<%= version %> X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 - Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_e2ee_sessions.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_e2ee_sessions.yml index 3bcd7c20..706b43e0 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_e2ee_sessions.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_e2ee_sessions.yml @@ -13,6 +13,7 @@ http_interactions: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml index e4084483..7e9f9bf8 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_for_invalid_media_modes.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_for_invalid_media_modes.yml index fb9f74c8..ed54230f 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_for_invalid_media_modes.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_for_invalid_media_modes.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml index 2420b668..67390b63 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml index 5414ed09..ca9bad74 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml index df866d70..5fa6d7c9 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml index db873262..326005e8 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/with_an_addendum_to_the_user_agent_string/should_append_the_addendum_to_the_user_agent_header.yml b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/with_an_addendum_to_the_user_agent_string/should_append_the_addendum_to_the_user_agent_header.yml index c0ff305b..c22b1307 100644 --- a/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/with_an_addendum_to_the_user_agent_string/should_append_the_addendum_to_the_user_agent_header.yml +++ b/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/with_an_addendum_to_the_user_agent_string/should_append_the_addendum_to_the_user_agent_header.yml @@ -12,7 +12,8 @@ http_interactions: X-Opentok-Auth: - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 Accept-Encoding: "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" - Accept: "*/*" + Accept: "*/*" + Content-Type: "application/x-www-form-urlencoded" response: status: code: 200 diff --git a/spec/opentok/connection_spec.rb b/spec/opentok/connection_spec.rb index 662714a4..7ff00308 100644 --- a/spec/opentok/connection_spec.rb +++ b/spec/opentok/connection_spec.rb @@ -14,25 +14,73 @@ let(:session_id) { "SESSIONID" } let(:connection_id) { "CONNID" } let(:opentok) { OpenTok::OpenTok.new api_key, api_secret } - let(:connection) { opentok.connections } + let(:connections) { opentok.connections } - subject { connection } + subject { connections } - it 'raise an error on nil session_id' do + it 'raises an error on nil session_id when attempting to force disconnect' do expect { - connection.forceDisconnect(nil,connection_id) + connections.forceDisconnect(nil,connection_id) }.to raise_error(ArgumentError) end - it 'raise an error on nil connection_id' do + it 'raises an error on nil connection_id when attempting to force disconnect' do expect { - connection.forceDisconnect(session_id,nil) + connections.forceDisconnect(session_id,nil) }.to raise_error(ArgumentError) end it "forces a connection to be terminated", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do - response = connection.forceDisconnect(session_id, connection_id) + response = connections.forceDisconnect(session_id, connection_id) expect(response).not_to be_nil end + + context "when attempting to list connections" do + it 'raises an error on nil session_id' do + expect { + connections.list(nil) + }.to raise_error(ArgumentError) + end + + it 'raises an error with count too low' do + expect { + connections.list(session_id, :count => 0) + }.to raise_error(ArgumentError) + end + + it 'raises an error with count too high' do + expect { + connections.list(session_id, :count => 1001) + }.to raise_error(ArgumentError) + end + + it "should return all connections", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do + connections_list = connections.list(session_id) + expect(connections_list).to be_an_instance_of OpenTok::ConnectionList + expect(connections_list.total).to eq 5 + expect(connections_list.count).to eq 5 + end + + it "should return connections with an offset", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do + connections_list = connections.list(session_id, :offset => 2) + expect(connections_list).to be_an_instance_of OpenTok::ConnectionList + expect(connections_list.total).to eq 3 + expect(connections_list.count).to eq 3 + end + + it "should return count number of connections", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do + connections_list = connections.list(session_id, :count => 2) + expect(connections_list).to be_an_instance_of OpenTok::ConnectionList + expect(connections_list.total).to eq 2 + expect(connections_list.count).to eq 2 + end + + it "should return part of the connections when using offset and count", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do + connections_list = connections.list(session_id, :offset => 1, :count => 2) + expect(connections_list).to be_an_instance_of OpenTok::ConnectionList + expect(connections_list.total).to eq 2 + expect(connections_list.count).to eq 2 + end + end end