ably 0.2.0 → 0.6.2
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.
- checksums.yaml +4 -4
- data/lib/ably/models/paginated_resource.rb +40 -13
- data/lib/ably/modules/async_wrapper.rb +60 -0
- data/lib/ably/realtime/channel.rb +13 -2
- data/lib/ably/realtime/client.rb +21 -8
- data/lib/ably/realtime/presence.rb +32 -6
- data/lib/ably/rest/channel.rb +8 -2
- data/lib/ably/rest/presence.rb +31 -5
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +33 -21
- data/spec/acceptance/realtime/presence_history_spec.rb +14 -12
- data/spec/acceptance/realtime/stats_spec.rb +31 -0
- data/spec/acceptance/realtime/time_spec.rb +31 -0
- data/spec/acceptance/rest/presence_spec.rb +2 -0
- data/spec/acceptance/rest/stats_spec.rb +1 -1
- data/spec/acceptance/rest/time_spec.rb +2 -3
- data/spec/unit/models/paginated_resource_spec.rb +55 -13
- data/spec/unit/modules/async_wrapper_spec.rb +125 -0
- data/spec/unit/realtime/client_spec.rb +0 -10
- data/spec/unit/realtime/presence_spec.rb +3 -1
- data/spec/unit/realtime/websocket_transport_spec.rb +3 -2
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee3e7490507273d4da5f34286db1f6ee1e0bc968
|
4
|
+
data.tar.gz: a1558974a048679f9572bb607ce4ea00746364ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8b0da46c04457a191111f3c58a004d8f12dbeee12ad9f47836a86c836132d99b7e4675220644050c8c7ab1342e71c84d1477f5dc1256d593f7e028bbbe94298
|
7
|
+
data.tar.gz: da2d88e2cba687467a1b5cd79259cf6ec78cb00de7f9ae22f26641b154197dc3dfded91be3adddceed1e0e48b79ac53055af3b23c6dec3444adf4b039c31e42a
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Ably::Models
|
2
|
-
# Wraps any Ably HTTP response that supports paging and automatically provides
|
2
|
+
# Wraps any Ably HTTP response that supports paging and automatically provides methods to iterate through
|
3
3
|
# the array of resources using {#first_page}, {#next_page}, {#first_page?} and {#last_page?}
|
4
4
|
#
|
5
5
|
# Paging information is provided by Ably in the LINK HTTP headers
|
6
6
|
class PaginatedResource
|
7
7
|
include Enumerable
|
8
|
+
include Ably::Modules::AsyncWrapper
|
8
9
|
|
9
10
|
# @param [Faraday::Response] http_response Initial HTTP response from an Ably request to a paged resource
|
10
11
|
# @param [String] base_url Base URL for request that generated the http_response so that subsequent paged requests can be made
|
@@ -12,6 +13,8 @@ module Ably::Models
|
|
12
13
|
# @param [Hash] options Options for this paged resource
|
13
14
|
# @option options [Symbol,String] :coerce_into symbol or string representing class that should be used to create each item in the PaginatedResource
|
14
15
|
#
|
16
|
+
# @yield [Object] block will be called for each resource object for the current page. This is a useful way to apply a transformation to any page resources after they are retrieved
|
17
|
+
#
|
15
18
|
# @return [PaginatedResource]
|
16
19
|
def initialize(http_response, base_url, client, options = {}, &each_block)
|
17
20
|
@http_response = http_response
|
@@ -20,6 +23,7 @@ module Ably::Models
|
|
20
23
|
@coerce_into = options[:coerce_into]
|
21
24
|
@raw_body = http_response.body
|
22
25
|
@each_block = each_block
|
26
|
+
@make_async = options.fetch(:async_blocking_operations, false)
|
23
27
|
|
24
28
|
@body = if @coerce_into
|
25
29
|
http_response.body.map do |item|
|
@@ -34,19 +38,27 @@ module Ably::Models
|
|
34
38
|
end if block_given?
|
35
39
|
end
|
36
40
|
|
37
|
-
# Retrieve the first page of results
|
41
|
+
# Retrieve the first page of results.
|
42
|
+
# When used as part of the {Ably::Realtime} library, it will return a {EventMachine::Deferrable} object,
|
43
|
+
# and allows an optional success callback block to be provided.
|
38
44
|
#
|
39
|
-
# @return [PaginatedResource]
|
40
|
-
def first_page
|
41
|
-
|
45
|
+
# @return [PaginatedResource,EventMachine::Deferrable]
|
46
|
+
def first_page(&success_callback)
|
47
|
+
async_wrap_if(make_async, success_callback) do
|
48
|
+
PaginatedResource.new(client.get(pagination_url('first')), base_url, client, pagination_options, &each_block)
|
49
|
+
end
|
42
50
|
end
|
43
51
|
|
44
|
-
# Retrieve the next page of results
|
52
|
+
# Retrieve the next page of results.
|
53
|
+
# When used as part of the {Ably::Realtime} library, it will return a {EventMachine::Deferrable} object,
|
54
|
+
# and allows an optional success callback block to be provided.
|
45
55
|
#
|
46
|
-
# @return [PaginatedResource]
|
47
|
-
def next_page
|
48
|
-
|
49
|
-
|
56
|
+
# @return [PaginatedResource,EventMachine::Deferrable]
|
57
|
+
def next_page(&success_callback)
|
58
|
+
async_wrap_if(make_async, success_callback) do
|
59
|
+
raise Ably::Exceptions::InvalidPageError, 'There are no more pages' if supports_pagination? && last_page?
|
60
|
+
PaginatedResource.new(client.get(pagination_url('next')), base_url, client, pagination_options, &each_block)
|
61
|
+
end
|
50
62
|
end
|
51
63
|
|
52
64
|
# True if this is the last page in the paged resource set
|
@@ -84,7 +96,7 @@ module Ably::Models
|
|
84
96
|
alias_method :count, :length
|
85
97
|
alias_method :size, :length
|
86
98
|
|
87
|
-
# Method
|
99
|
+
# Method to allow {PaginatedResource} to be {http://ruby-doc.org/core-2.1.3/Enumerable.html Enumerable}
|
88
100
|
def each(&block)
|
89
101
|
body.each do |item|
|
90
102
|
if block_given?
|
@@ -95,7 +107,7 @@ module Ably::Models
|
|
95
107
|
end
|
96
108
|
end
|
97
109
|
|
98
|
-
#
|
110
|
+
# First item in this page
|
99
111
|
def first
|
100
112
|
body.first
|
101
113
|
end
|
@@ -118,7 +130,7 @@ module Ably::Models
|
|
118
130
|
end
|
119
131
|
|
120
132
|
private
|
121
|
-
attr_reader :body, :http_response, :base_url, :client, :coerce_into, :raw_body, :each_block
|
133
|
+
attr_reader :body, :http_response, :base_url, :client, :coerce_into, :raw_body, :each_block, :make_async
|
122
134
|
|
123
135
|
def pagination_headers
|
124
136
|
link_regex = %r{<(?<url>[^>]+)>; rel="(?<rel>[^"]+)"}
|
@@ -146,5 +158,20 @@ module Ably::Models
|
|
146
158
|
pagination_header[id]
|
147
159
|
end
|
148
160
|
end
|
161
|
+
|
162
|
+
def pagination_options
|
163
|
+
{
|
164
|
+
coerce_into: coerce_into,
|
165
|
+
async_blocking_operations: make_async
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def async_wrap_if(is_realtime, success_callback, &operation)
|
170
|
+
if is_realtime
|
171
|
+
async_wrap success_callback, &operation
|
172
|
+
else
|
173
|
+
yield
|
174
|
+
end
|
175
|
+
end
|
149
176
|
end
|
150
177
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Ably::Modules
|
2
|
+
# Provides methods to convert synchronous operations into async operations through the use of
|
3
|
+
# {EventMachine#defer http://www.rubydoc.info/github/eventmachine/eventmachine/EventMachine#defer-class_method}.
|
4
|
+
# The async_wrap method can only be called from within an EventMachine reactor, and must be thread safe.
|
5
|
+
#
|
6
|
+
# @note using this AsyncWrapper should only be used for methods that are used less frequently and typically
|
7
|
+
# not run with levels of concurrency due to the limited number of threads available to EventMachine by default.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class BlockingOperation
|
11
|
+
# include Aby::Modules::AsyncWrapper
|
12
|
+
#
|
13
|
+
# def operation(&success_callback)
|
14
|
+
# async_wrap(success_callback) do
|
15
|
+
# sleep 1
|
16
|
+
# 'slept'
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# blocking_object = BlockingOperation.new
|
22
|
+
# deferrable = blocking_object.operation do |result|
|
23
|
+
# puts "Done with result: #{result}"
|
24
|
+
# end
|
25
|
+
# puts "Starting"
|
26
|
+
#
|
27
|
+
# # => 'Starting'
|
28
|
+
# # => 'Done with result: slept'
|
29
|
+
#
|
30
|
+
module AsyncWrapper
|
31
|
+
private
|
32
|
+
|
33
|
+
# Will yield the provided block in a new thread and return an {EventMachine::Deferrable http://www.rubydoc.info/github/eventmachine/eventmachine/EventMachine/Deferrable}
|
34
|
+
#
|
35
|
+
# @yield [Object] operation block that is run in a thread
|
36
|
+
# @return [EventMachine::Deferrable]
|
37
|
+
#
|
38
|
+
def async_wrap(success_callback = nil, &operation)
|
39
|
+
raise ArgumentError, "Operation block is missing" unless block_given?
|
40
|
+
|
41
|
+
EventMachine::DefaultDeferrable.new.tap do |deferrable|
|
42
|
+
deferrable.callback &success_callback if success_callback
|
43
|
+
|
44
|
+
operation_with_exception_handling = proc do
|
45
|
+
begin
|
46
|
+
yield
|
47
|
+
rescue StandardError => e
|
48
|
+
deferrable.fail e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
complete_callback = proc do |result|
|
53
|
+
deferrable.succeed result
|
54
|
+
end
|
55
|
+
|
56
|
+
EventMachine.defer operation_with_exception_handling, complete_callback
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -36,6 +36,7 @@ module Ably
|
|
36
36
|
include Ably::Modules::Conversions
|
37
37
|
include Ably::Modules::EventEmitter
|
38
38
|
include Ably::Modules::EventMachineHelpers
|
39
|
+
include Ably::Modules::AsyncWrapper
|
39
40
|
extend Ably::Modules::Enum
|
40
41
|
|
41
42
|
STATE = ruby_enum('STATE',
|
@@ -102,6 +103,8 @@ module Ably
|
|
102
103
|
# @param name [String] The event name of the message to subscribe to if provided. Defaults to all events.
|
103
104
|
# @yield [Ably::Models::Message] For each message received, the block is called
|
104
105
|
#
|
106
|
+
# @return [void]
|
107
|
+
#
|
105
108
|
def subscribe(name = :all, &blk)
|
106
109
|
attach unless attached? || attaching?
|
107
110
|
subscriptions[message_name_key(name)] << blk
|
@@ -112,6 +115,8 @@ module Ably
|
|
112
115
|
#
|
113
116
|
# @param name [String] The event name of the message to subscribe to if provided. Defaults to all events.
|
114
117
|
#
|
118
|
+
# @return [void]
|
119
|
+
#
|
115
120
|
def unsubscribe(name = :all, &blk)
|
116
121
|
if message_name_key(name) == :all
|
117
122
|
subscriptions.keys
|
@@ -174,8 +179,14 @@ module Ably
|
|
174
179
|
#
|
175
180
|
# @param (see Ably::Rest::Channel#history)
|
176
181
|
# @option options (see Ably::Rest::Channel#history)
|
177
|
-
|
178
|
-
|
182
|
+
#
|
183
|
+
# @yield [Ably::Models::PaginatedResource<Ably::Models::Message>] An Array of {Ably::Models::Message} objects that supports paging (#next_page, #first_page)
|
184
|
+
#
|
185
|
+
# @return [EventMachine::Deferrable]
|
186
|
+
def history(options = {}, &callback)
|
187
|
+
async_wrap(callback) do
|
188
|
+
rest_channel.history(options.merge(async_blocking_operations: true))
|
189
|
+
end
|
179
190
|
end
|
180
191
|
|
181
192
|
# @!attribute [r] __incoming_msgbus__
|
data/lib/ably/realtime/client.rb
CHANGED
@@ -23,6 +23,7 @@ module Ably
|
|
23
23
|
# @!attribute [r] protocol_binary?
|
24
24
|
# (see Ably::Rest::Client#protocol_binary?)
|
25
25
|
class Client
|
26
|
+
include Ably::Modules::AsyncWrapper
|
26
27
|
extend Forwardable
|
27
28
|
|
28
29
|
DOMAIN = 'realtime.ably.io'
|
@@ -66,20 +67,32 @@ module Ably
|
|
66
67
|
# Return a {Ably::Realtime::Channel Realtime Channel} for the given name
|
67
68
|
#
|
68
69
|
# @param (see Ably::Realtime::Channels#get)
|
69
|
-
#
|
70
70
|
# @return (see Ably::Realtime::Channels#get)
|
71
|
+
#
|
71
72
|
def channel(name, channel_options = {})
|
72
73
|
channels.get(name, channel_options)
|
73
74
|
end
|
74
75
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
76
|
+
# Retrieve the Ably service time
|
77
|
+
#
|
78
|
+
# @yield [Time] The time as reported by the Ably service
|
79
|
+
# @return [EventMachine::Deferrable]
|
80
|
+
#
|
81
|
+
def time(&success_callback)
|
82
|
+
async_wrap(success_callback) do
|
83
|
+
rest_client.time
|
84
|
+
end
|
78
85
|
end
|
79
86
|
|
80
|
-
#
|
81
|
-
|
82
|
-
|
87
|
+
# Retrieve the stats for the application
|
88
|
+
#
|
89
|
+
# @yield [Array] An Array of hashes representing the stats
|
90
|
+
# @return [EventMachine::Deferrable]
|
91
|
+
#
|
92
|
+
def stats(params = {}, &success_callback)
|
93
|
+
async_wrap(success_callback) do
|
94
|
+
rest_client.stats(params)
|
95
|
+
end
|
83
96
|
end
|
84
97
|
|
85
98
|
# (see Ably::Realtime::Connection#close)
|
@@ -103,7 +116,7 @@ module Ably
|
|
103
116
|
end
|
104
117
|
|
105
118
|
# @!attribute [r] custom_socket_host
|
106
|
-
# @return [String,
|
119
|
+
# @return [String,NilClass] Returns the custom socket host that is being used if it was provided with the option :ws_host when the {Client} was created
|
107
120
|
def custom_socket_host
|
108
121
|
@custom_socket_host
|
109
122
|
end
|
@@ -2,6 +2,7 @@ module Ably::Realtime
|
|
2
2
|
# Presence provides access to presence operations and state for the associated Channel
|
3
3
|
class Presence
|
4
4
|
include Ably::Modules::EventEmitter
|
5
|
+
include Ably::Modules::AsyncWrapper
|
5
6
|
extend Ably::Modules::Enum
|
6
7
|
|
7
8
|
STATE = ruby_enum('STATE',
|
@@ -14,12 +15,15 @@ module Ably::Realtime
|
|
14
15
|
)
|
15
16
|
include Ably::Modules::StateEmitter
|
16
17
|
|
17
|
-
# {Ably::Realtime::Channel} this Presence object is
|
18
|
+
# {Ably::Realtime::Channel} this Presence object is associated with
|
19
|
+
# @return {Ably::Realtime::Channel}
|
18
20
|
attr_reader :channel
|
19
21
|
|
20
22
|
# A unique member identifier for this channel client, disambiguating situations where a given
|
21
23
|
# client_id is present on multiple connections simultaneously.
|
22
|
-
#
|
24
|
+
#
|
25
|
+
# @note TODO: This does not work at present as no ACK is sent from the server with a memberId
|
26
|
+
# @return {String}
|
23
27
|
attr_reader :member_id
|
24
28
|
|
25
29
|
def initialize(channel)
|
@@ -36,13 +40,16 @@ module Ably::Realtime
|
|
36
40
|
|
37
41
|
# Enter this client into this channel. This client will be added to the presence set
|
38
42
|
# and presence subscribers will see an enter message for this client.
|
43
|
+
#
|
39
44
|
# @param [Hash,String] options an options Hash to specify client data and/or client ID, or a String with the client data
|
40
45
|
# @option options [String] :data optional data (eg a status message) for this member
|
41
46
|
# @option options [String] :client_id the optional id of the client.
|
42
47
|
# This option is provided to support connections from server instances that act on behalf of
|
43
48
|
# multiple client_ids. In order to be able to enter the channel with this method, the client
|
44
49
|
# library must have been instanced either with a key, or with a token bound to the wildcard clientId.
|
50
|
+
#
|
45
51
|
# @yield [Ably::Realtime::Presence] On success, will call the block with the {Ably::Realtime::Presence}
|
52
|
+
#
|
46
53
|
# @return [Ably::Models::PresenceMessage] Deferrable {Ably::Models::PresenceMessage} that supports both success (callback) and failure (errback) callbacks
|
47
54
|
#
|
48
55
|
def enter(options = {}, &blk)
|
@@ -71,6 +78,7 @@ module Ably::Realtime
|
|
71
78
|
|
72
79
|
# Leave this client from this channel. This client will be removed from the presence
|
73
80
|
# set and presence subscribers will see a leave message for this client.
|
81
|
+
#
|
74
82
|
# @param (see Presence#enter)
|
75
83
|
# @yield (see Presence#enter)
|
76
84
|
# @return (see Presence#enter)
|
@@ -101,6 +109,7 @@ module Ably::Realtime
|
|
101
109
|
# Update the presence data for this client. If the client is not already a member of
|
102
110
|
# the presence set it will be added, and presence subscribers will see an enter or
|
103
111
|
# update message for this client.
|
112
|
+
#
|
104
113
|
# @param (see Presence#enter)
|
105
114
|
# @yield (see Presence#enter)
|
106
115
|
# @return (see Presence#enter)
|
@@ -120,9 +129,15 @@ module Ably::Realtime
|
|
120
129
|
|
121
130
|
# Get the presence state for this Channel.
|
122
131
|
# Optionally get a member's {Ably::Models::PresenceMessage} state by member_id
|
132
|
+
#
|
123
133
|
# @return [Array<Ably::Models::PresenceMessage>, Ably::Models::PresenceMessage] members on the channel
|
124
|
-
|
125
|
-
|
134
|
+
#
|
135
|
+
def get(member_id = nil)
|
136
|
+
if member_id
|
137
|
+
members.find { |key, presence| presence.member_id == member_id }
|
138
|
+
else
|
139
|
+
members.map { |key, presence| presence }
|
140
|
+
end
|
126
141
|
end
|
127
142
|
|
128
143
|
# Subscribe to presence events on the associated Channel.
|
@@ -131,6 +146,8 @@ module Ably::Realtime
|
|
131
146
|
# @param action [Ably::Models::PresenceMessage::ACTION] Optional, the state change action to subscribe to. Defaults to all presence actions
|
132
147
|
# @yield [Ably::Models::PresenceMessage] For each presence state change event, the block is called
|
133
148
|
#
|
149
|
+
# @return [void]
|
150
|
+
#
|
134
151
|
def subscribe(action = :all, &blk)
|
135
152
|
ensure_channel_attached do
|
136
153
|
subscriptions[message_action_key(action)] << blk
|
@@ -142,6 +159,8 @@ module Ably::Realtime
|
|
142
159
|
#
|
143
160
|
# @param action [Ably::Models::PresenceMessage::ACTION] Optional, the state change action to subscribe to. Defaults to all presence actions
|
144
161
|
#
|
162
|
+
# @return [void]
|
163
|
+
#
|
145
164
|
def unsubscribe(action = :all, &blk)
|
146
165
|
if message_action_key(action) == :all
|
147
166
|
subscriptions.keys
|
@@ -158,8 +177,15 @@ module Ably::Realtime
|
|
158
177
|
#
|
159
178
|
# @param (see Ably::Rest::Presence#history)
|
160
179
|
# @option options (see Ably::Rest::Presence#history)
|
161
|
-
|
162
|
-
|
180
|
+
#
|
181
|
+
# @yield [Ably::Models::PaginatedResource<Ably::Models::PresenceMessage>] An Array of {Ably::Models::PresenceMessage} objects that supports paging (#next_page, #first_page)
|
182
|
+
#
|
183
|
+
# @return [EventMachine::Deferrable]
|
184
|
+
#
|
185
|
+
def history(options = {}, &callback)
|
186
|
+
async_wrap(callback) do
|
187
|
+
rest_presence.history(options.merge(async_blocking_operations: true))
|
188
|
+
end
|
163
189
|
end
|
164
190
|
|
165
191
|
# @!attribute [r] __incoming_msgbus__
|
data/lib/ably/rest/channel.rb
CHANGED
@@ -57,16 +57,22 @@ module Ably
|
|
57
57
|
# @option options [Integer] :limit Maximum number of messages to retrieve up to 10,000
|
58
58
|
# @option options [Symbol] :by `:message`, `:bundle` or `:hour`. Defaults to `:message`
|
59
59
|
#
|
60
|
-
# @return [Ably::Models::PaginatedResource<Ably::Models::Message>] An Array of
|
60
|
+
# @return [Ably::Models::PaginatedResource<Ably::Models::Message>] An Array of {Ably::Models::Message} objects that supports paging (#next_page, #first_page)
|
61
61
|
def history(options = {})
|
62
62
|
url = "#{base_path}/messages"
|
63
|
+
options = options.dup
|
63
64
|
|
64
65
|
merge_options = { live: true } # TODO: Remove live param as all history should be live
|
65
66
|
[:start, :end].each { |option| merge_options[option] = as_since_epoch(options[option]) if options.has_key?(option) }
|
66
67
|
|
68
|
+
paginated_options = {
|
69
|
+
coerce_into: 'Ably::Models::Message',
|
70
|
+
async_blocking_operations: options.delete(:async_blocking_operations),
|
71
|
+
}
|
72
|
+
|
67
73
|
response = client.get(url, options.merge(merge_options))
|
68
74
|
|
69
|
-
Ably::Models::PaginatedResource.new(response, url, client,
|
75
|
+
Ably::Models::PaginatedResource.new(response, url, client, paginated_options) do |message|
|
70
76
|
message.tap do |message|
|
71
77
|
message.decode self
|
72
78
|
end
|
data/lib/ably/rest/presence.rb
CHANGED
@@ -3,7 +3,13 @@ module Ably
|
|
3
3
|
class Presence
|
4
4
|
include Ably::Modules::Conversions
|
5
5
|
|
6
|
-
|
6
|
+
# {Ably::Rest::Client} for this Presence object
|
7
|
+
# @return {Ably::Rest::Client}
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
# {Ably::Rest::Channel} this Presence object is associated with
|
11
|
+
# @return {Ably::Rest::Channel}
|
12
|
+
attr_reader :channel
|
7
13
|
|
8
14
|
# Initialize a new Presence object
|
9
15
|
#
|
@@ -16,11 +22,25 @@ module Ably
|
|
16
22
|
|
17
23
|
# Obtain the set of members currently present for a channel
|
18
24
|
#
|
19
|
-
# @
|
25
|
+
# @param [Hash] options the options for the set of members present
|
26
|
+
# @option options [Integer,Time] :start Time or millisecond since epoch
|
27
|
+
# @option options [Integer,Time] :end Time or millisecond since epoch
|
28
|
+
# @option options [Symbol] :direction `:forwards` or `:backwards`
|
29
|
+
# @option options [Integer] :limit Maximum number of members to retrieve up to 10,000
|
30
|
+
#
|
31
|
+
# @return [Ably::Models::PaginatedResource<Ably::Models::PresenceMessage>] An Array of {Ably::Models::PresenceMessage} objects that supports paging (#next_page, #first_page)
|
20
32
|
#
|
21
33
|
def get(options = {})
|
34
|
+
options = options.dup
|
35
|
+
|
36
|
+
paginated_options = {
|
37
|
+
coerce_into: 'Ably::Models::PresenceMessage',
|
38
|
+
async_blocking_operations: options.delete(:async_blocking_operations),
|
39
|
+
}
|
40
|
+
|
22
41
|
response = client.get(base_path, options)
|
23
|
-
|
42
|
+
|
43
|
+
Ably::Models::PaginatedResource.new(response, base_path, client, paginated_options) do |presence_message|
|
24
44
|
presence_message.tap do |message|
|
25
45
|
message.decode self.channel
|
26
46
|
end
|
@@ -35,17 +55,23 @@ module Ably
|
|
35
55
|
# @option options [Symbol] :direction `:forwards` or `:backwards`
|
36
56
|
# @option options [Integer] :limit Maximum number of presence messages to retrieve up to 10,000
|
37
57
|
#
|
38
|
-
# @return [Ably::Models::PaginatedResource<Ably::Models::PresenceMessage>] An Array of
|
58
|
+
# @return [Ably::Models::PaginatedResource<Ably::Models::PresenceMessage>] An Array of {Ably::Models::PresenceMessage} objects that supports paging (#next_page, #first_page)
|
39
59
|
#
|
40
60
|
def history(options = {})
|
41
61
|
url = "#{base_path}/history"
|
62
|
+
options = options.dup
|
42
63
|
|
43
64
|
merge_options = { live: true } # TODO: Remove live param as all history should be live
|
44
65
|
[:start, :end].each { |option| merge_options[option] = as_since_epoch(options[option]) if options.has_key?(option) }
|
45
66
|
|
67
|
+
paginated_options = {
|
68
|
+
coerce_into: 'Ably::Models::PresenceMessage',
|
69
|
+
async_blocking_operations: options.delete(:async_blocking_operations),
|
70
|
+
}
|
71
|
+
|
46
72
|
response = client.get(url, options.merge(merge_options))
|
47
73
|
|
48
|
-
Ably::Models::PaginatedResource.new(response, url, client,
|
74
|
+
Ably::Models::PaginatedResource.new(response, url, client, paginated_options) do |presence_message|
|
49
75
|
presence_message.tap do |message|
|
50
76
|
message.decode self.channel
|
51
77
|
end
|
data/lib/ably/version.rb
CHANGED
@@ -4,7 +4,7 @@ require 'securerandom'
|
|
4
4
|
describe Ably::Realtime::Channel do
|
5
5
|
include RSpec::EventMachine
|
6
6
|
|
7
|
-
[:
|
7
|
+
[:json].each do |protocol| # :msgpack,
|
8
8
|
context "over #{protocol}" do
|
9
9
|
let(:default_options) { options.merge(api_key: api_key, environment: environment, protocol: protocol) }
|
10
10
|
|
@@ -24,25 +24,36 @@ describe Ably::Realtime::Channel do
|
|
24
24
|
|
25
25
|
let(:options) { { :protocol => :json } }
|
26
26
|
|
27
|
-
it '
|
27
|
+
it 'returns a Deferrable' do
|
28
28
|
run_reactor do
|
29
29
|
channel.publish('event', payload) do |message|
|
30
|
-
|
31
|
-
expect(history.length).to eql(1)
|
32
|
-
expect(history[0].data).to eql(payload)
|
30
|
+
expect(channel.history).to be_a(EventMachine::Deferrable)
|
33
31
|
stop_reactor
|
34
32
|
end
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
36
|
+
it 'retrieves real-time history' do
|
37
|
+
run_reactor do
|
38
|
+
channel.publish('event', payload) do |message|
|
39
|
+
channel.history do |history|
|
40
|
+
expect(history.length).to eql(1)
|
41
|
+
expect(history[0].data).to eql(payload)
|
42
|
+
stop_reactor
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
38
48
|
it 'retrieves real-time history across two channels' do
|
39
49
|
run_reactor do
|
40
50
|
channel.publish('event', payload) do |message|
|
41
51
|
channel2.publish('event', payload) do |message|
|
42
|
-
history
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
channel2.history do |history|
|
53
|
+
expect(history.length).to eql(2)
|
54
|
+
expect(history.map(&:data).uniq).to eql([payload])
|
55
|
+
stop_reactor
|
56
|
+
end
|
46
57
|
end
|
47
58
|
end
|
48
59
|
end
|
@@ -53,21 +64,22 @@ describe Ably::Realtime::Channel do
|
|
53
64
|
let(:limit) { 10 }
|
54
65
|
|
55
66
|
def check_limited_history(direction)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
67
|
+
channel.history(direction: direction, limit: limit) do |history|
|
68
|
+
expect(history.length).to eql(limit)
|
69
|
+
limit.times do |index|
|
70
|
+
expect(history[index].data).to eql("history#{index}")
|
71
|
+
end
|
61
72
|
|
62
|
-
|
73
|
+
history.next_page do |history|
|
74
|
+
expect(history.length).to eql(limit)
|
75
|
+
limit.times do |index|
|
76
|
+
expect(history[index].data).to eql("history#{index + limit}")
|
77
|
+
end
|
78
|
+
expect(history.last_page?).to eql(true)
|
63
79
|
|
64
|
-
|
65
|
-
|
66
|
-
expect(history[index].data).to eql("history#{index + limit}")
|
80
|
+
stop_reactor
|
81
|
+
end
|
67
82
|
end
|
68
|
-
expect(history.last_page?).to eql(true)
|
69
|
-
|
70
|
-
stop_reactor
|
71
83
|
end
|
72
84
|
|
73
85
|
context 'as one ProtocolMessage' do
|
@@ -24,17 +24,18 @@ describe 'Ably::Realtime::Presence Messages' do
|
|
24
24
|
run_reactor do
|
25
25
|
presence_client_one.enter(data: data) do
|
26
26
|
presence_client_one.leave do
|
27
|
-
history
|
28
|
-
|
27
|
+
presence_client_one.history do |history|
|
28
|
+
expect(history.count).to eql(2)
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
expect(history[1].action).to eq(:enter)
|
31
|
+
expect(history[1].client_id).to eq(client_one.client_id)
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
expect(history[0].action).to eq(:leave)
|
34
|
+
expect(history[0].client_id).to eq(client_one.client_id)
|
35
|
+
expect(history[0].data).to eql(data)
|
36
36
|
|
37
|
-
|
37
|
+
stop_reactor
|
38
|
+
end
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -43,11 +44,12 @@ describe 'Ably::Realtime::Presence Messages' do
|
|
43
44
|
it 'ensures REST presence history message IDs match ProtocolMessage wrapped message IDs via Realtime' do
|
44
45
|
run_reactor do
|
45
46
|
presence_client_one.subscribe(:enter) do |message|
|
46
|
-
history
|
47
|
-
|
47
|
+
presence_client_one.history do |history|
|
48
|
+
expect(history.count).to eql(1)
|
48
49
|
|
49
|
-
|
50
|
-
|
50
|
+
expect(history[0].id).to eql(message.id)
|
51
|
+
stop_reactor
|
52
|
+
end
|
51
53
|
end
|
52
54
|
|
53
55
|
presence_client_one.enter(data: data)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Ably::Realtime::Client stats' do
|
4
|
+
include RSpec::EventMachine
|
5
|
+
|
6
|
+
[:msgpack, :json].each do |protocol|
|
7
|
+
context "over #{protocol}" do
|
8
|
+
let(:client) do
|
9
|
+
Ably::Realtime::Client.new(api_key: api_key, environment: environment, protocol: protocol)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'fetching stats' do
|
13
|
+
it 'should return a Hash' do
|
14
|
+
run_reactor do
|
15
|
+
client.stats do |stats|
|
16
|
+
expect(stats).to be_a(Array)
|
17
|
+
stop_reactor
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return a deferrable object' do
|
23
|
+
run_reactor do
|
24
|
+
expect(client.stats).to be_a(EventMachine::Deferrable)
|
25
|
+
stop_reactor
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Ably::Realtime::Client time' do
|
4
|
+
include RSpec::EventMachine
|
5
|
+
|
6
|
+
[:msgpack, :json].each do |protocol|
|
7
|
+
context "over #{protocol}" do
|
8
|
+
let(:client) do
|
9
|
+
Ably::Realtime::Client.new(api_key: api_key, environment: environment, protocol: protocol)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'fetching the service time' do
|
13
|
+
it 'should return the service time as a Time object' do
|
14
|
+
run_reactor do
|
15
|
+
client.time do |time|
|
16
|
+
expect(time).to be_within(2).of(Time.now)
|
17
|
+
stop_reactor
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return a deferrable object' do
|
23
|
+
run_reactor do
|
24
|
+
expect(client.time).to be_a(EventMachine::Deferrable)
|
25
|
+
stop_reactor
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'securerandom'
|
3
2
|
|
4
|
-
describe 'Ably::REST time' do
|
3
|
+
describe 'Ably::REST::Client time' do
|
5
4
|
[:msgpack, :json].each do |protocol|
|
6
5
|
context "over #{protocol}" do
|
7
6
|
let(:client) do
|
@@ -9,7 +8,7 @@ describe 'Ably::REST time' do
|
|
9
8
|
end
|
10
9
|
|
11
10
|
describe 'fetching the service time' do
|
12
|
-
it
|
11
|
+
it 'should return the service time as a Time object' do
|
13
12
|
expect(client.time).to be_within(2).of(Time.now)
|
14
13
|
end
|
15
14
|
end
|
@@ -67,7 +67,7 @@ describe Ably::Models::PaginatedResource do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
context '
|
70
|
+
context 'paged transformations' do
|
71
71
|
let(:headers) do
|
72
72
|
{
|
73
73
|
'link' => [
|
@@ -93,23 +93,65 @@ describe Ably::Models::PaginatedResource do
|
|
93
93
|
})
|
94
94
|
end
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
context 'with each block' do
|
97
|
+
subject do
|
98
|
+
paginated_resource_class.new(http_response, full_url, paged_client, paginated_resource_options) do |resource|
|
99
|
+
resource[:added_attribute_from_block] = "id:#{resource[:id]}"
|
100
|
+
resource
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'calls the block for each resource after retrieving the resources' do
|
105
|
+
expect(subject[0][:added_attribute_from_block]).to eql("id:#{body[0][:id]}")
|
100
106
|
end
|
101
|
-
end
|
102
107
|
|
103
|
-
|
104
|
-
|
108
|
+
it 'calls the block for each resource on second page after retrieving the resources' do
|
109
|
+
page_1_first_id = subject[0][:id]
|
110
|
+
next_page = subject.next_page
|
111
|
+
|
112
|
+
expect(next_page[0][:added_attribute_from_block]).to eql("id:#{body_page2[0][:id]}")
|
113
|
+
expect(next_page[0][:id]).to_not eql(page_1_first_id)
|
114
|
+
end
|
105
115
|
end
|
106
116
|
|
107
|
-
|
108
|
-
|
109
|
-
|
117
|
+
context 'with option async_blocking_operations: true' do
|
118
|
+
include RSpec::EventMachine
|
119
|
+
|
120
|
+
subject do
|
121
|
+
paginated_resource_class.new(http_response, full_url, paged_client, async_blocking_operations: true)
|
122
|
+
end
|
110
123
|
|
111
|
-
|
112
|
-
|
124
|
+
context '#next_page' do
|
125
|
+
it 'returns a deferrable object' do
|
126
|
+
run_reactor do
|
127
|
+
expect(subject.next_page).to be_a(EventMachine::Deferrable)
|
128
|
+
stop_reactor
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'allows a success callback block to be added' do
|
133
|
+
run_reactor do
|
134
|
+
subject.next_page do |paginated_resource|
|
135
|
+
expect(paginated_resource).to be_a(Ably::Models::PaginatedResource)
|
136
|
+
stop_reactor
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context '#first_page' do
|
143
|
+
it 'calls the errback callback when first page headers are missing' do
|
144
|
+
run_reactor do
|
145
|
+
subject.next_page do |paginated_resource|
|
146
|
+
deferrable = subject.first_page
|
147
|
+
deferrable.errback do |error|
|
148
|
+
expect(error).to be_a(Ably::Exceptions::InvalidPageError)
|
149
|
+
stop_reactor
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
113
155
|
end
|
114
156
|
end
|
115
157
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
describe Ably::Modules::AsyncWrapper do
|
5
|
+
include RSpec::EventMachine
|
6
|
+
|
7
|
+
let(:class_with_module) do
|
8
|
+
Class.new do
|
9
|
+
include Ably::Modules::AsyncWrapper
|
10
|
+
|
11
|
+
def operation(&success_callback)
|
12
|
+
async_wrap success_callback, &@block
|
13
|
+
end
|
14
|
+
|
15
|
+
def block=(block)
|
16
|
+
@block = block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
let(:subject) { class_with_module.new }
|
21
|
+
let(:result) { SecureRandom.hex }
|
22
|
+
let(:sleep_time) { 0.1 }
|
23
|
+
|
24
|
+
before do
|
25
|
+
subject.block = block
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#async_wrap blocking block' do
|
29
|
+
context 'returns result' do
|
30
|
+
let(:block) do
|
31
|
+
proc do
|
32
|
+
sleep sleep_time
|
33
|
+
result
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'calls the success_callback block with result when provided' do
|
38
|
+
run_reactor do
|
39
|
+
subject.operation do |result|
|
40
|
+
expect(result).to eql(result)
|
41
|
+
stop_reactor
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns a deferrable that succeeds with result' do
|
47
|
+
run_reactor do
|
48
|
+
deferrable = subject.operation
|
49
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
50
|
+
deferrable.callback do |result|
|
51
|
+
expect(result).to eql(result)
|
52
|
+
stop_reactor
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'does not call the errback' do
|
58
|
+
run_reactor do
|
59
|
+
deferrable = subject.operation
|
60
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
61
|
+
deferrable.callback do |result|
|
62
|
+
expect(result).to eql(result)
|
63
|
+
EventMachine.add_timer(sleep_time * 2) { stop_reactor }
|
64
|
+
end
|
65
|
+
deferrable.errback do |result|
|
66
|
+
raise 'Errback should not have been called'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'does not block EventMachine' do
|
72
|
+
run_reactor do
|
73
|
+
timers_called = 0
|
74
|
+
EventMachine.add_periodic_timer(sleep_time / 5) { timers_called += 1 }
|
75
|
+
|
76
|
+
subject.operation do |result|
|
77
|
+
expect(timers_called).to be >= 4
|
78
|
+
stop_reactor
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'raises an Exception' do
|
85
|
+
let(:block) do
|
86
|
+
proc do
|
87
|
+
sleep sleep_time
|
88
|
+
raise RuntimeError, 'Intentional'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'calls the errback block of the deferrable' do
|
93
|
+
run_reactor do
|
94
|
+
deferrable = subject.operation
|
95
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
96
|
+
deferrable.errback do |error|
|
97
|
+
expect(error).to be_a(RuntimeError)
|
98
|
+
expect(error.message).to match(/Intentional/)
|
99
|
+
stop_reactor
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'does not call the success_callback block' do
|
105
|
+
run_reactor do
|
106
|
+
subject.operation do |result|
|
107
|
+
raise 'Callback should not have been called'
|
108
|
+
end
|
109
|
+
EventMachine.add_timer(sleep_time * 2) { stop_reactor }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'does not call the callback block of the deferrable' do
|
114
|
+
run_reactor do
|
115
|
+
deferrable = subject.operation
|
116
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
117
|
+
deferrable.callback do |result|
|
118
|
+
raise 'Callback should not have been called'
|
119
|
+
end
|
120
|
+
EventMachine.add_timer(sleep_time * 2) { stop_reactor }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -16,16 +16,6 @@ describe Ably::Realtime::Client do
|
|
16
16
|
subject
|
17
17
|
end
|
18
18
|
|
19
|
-
specify '#time' do
|
20
|
-
expect(subject.rest_client).to receive(:time)
|
21
|
-
subject.time
|
22
|
-
end
|
23
|
-
|
24
|
-
specify '#stats' do
|
25
|
-
expect(subject.rest_client).to receive(:stats).with(options)
|
26
|
-
subject.stats options
|
27
|
-
end
|
28
|
-
|
29
19
|
context 'for attribute' do
|
30
20
|
[:environment, :use_tls?, :log_level].each do |attribute|
|
31
21
|
specify "##{attribute}" do
|
@@ -47,7 +47,9 @@ describe Ably::Realtime::Presence do
|
|
47
47
|
context 'subscriptions' do
|
48
48
|
let(:message_history) { Hash.new { |hash, key| hash[key] = 0 } }
|
49
49
|
let(:presence_action) { Ably::Models::PresenceMessage::ACTION.Enter }
|
50
|
-
let(:message)
|
50
|
+
let(:message) do
|
51
|
+
instance_double('Ably::Models::PresenceMessage', action: presence_action, member_id: SecureRandom.hex, decode: true)
|
52
|
+
end
|
51
53
|
|
52
54
|
context '#subscribe' do
|
53
55
|
specify 'to all presence state actions' do
|
@@ -3,11 +3,12 @@ require 'support/protocol_msgbus_helper'
|
|
3
3
|
|
4
4
|
describe Ably::Realtime::Connection::WebsocketTransport do
|
5
5
|
let(:client_ignored) { double('Ably::Realtime::Client').as_null_object }
|
6
|
-
let(:connection)
|
6
|
+
let(:connection) { instance_double('Ably::Realtime::Connection', client: client_ignored, id: nil) }
|
7
|
+
let(:url) { 'http://ably.io/' }
|
7
8
|
|
8
9
|
let(:websocket_transport_without_eventmachine) do
|
9
10
|
Ably::Realtime::Connection::WebsocketTransport.send(:allocate).tap do |websocket_transport|
|
10
|
-
websocket_transport.send(:initialize, connection)
|
11
|
+
websocket_transport.send(:initialize, connection, url)
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ably
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lewis Marshall
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-12-
|
12
|
+
date: 2014-12-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/ably/models/presence_message.rb
|
211
211
|
- lib/ably/models/protocol_message.rb
|
212
212
|
- lib/ably/models/token.rb
|
213
|
+
- lib/ably/modules/async_wrapper.rb
|
213
214
|
- lib/ably/modules/channels_collection.rb
|
214
215
|
- lib/ably/modules/conversions.rb
|
215
216
|
- lib/ably/modules/encodeable.rb
|
@@ -253,6 +254,8 @@ files:
|
|
253
254
|
- spec/acceptance/realtime/message_spec.rb
|
254
255
|
- spec/acceptance/realtime/presence_history_spec.rb
|
255
256
|
- spec/acceptance/realtime/presence_spec.rb
|
257
|
+
- spec/acceptance/realtime/stats_spec.rb
|
258
|
+
- spec/acceptance/realtime/time_spec.rb
|
256
259
|
- spec/acceptance/rest/auth_spec.rb
|
257
260
|
- spec/acceptance/rest/base_spec.rb
|
258
261
|
- spec/acceptance/rest/channel_spec.rb
|
@@ -284,6 +287,7 @@ files:
|
|
284
287
|
- spec/unit/models/presence_message_spec.rb
|
285
288
|
- spec/unit/models/protocol_message_spec.rb
|
286
289
|
- spec/unit/models/token_spec.rb
|
290
|
+
- spec/unit/modules/async_wrapper_spec.rb
|
287
291
|
- spec/unit/modules/conversions_spec.rb
|
288
292
|
- spec/unit/modules/enum_spec.rb
|
289
293
|
- spec/unit/modules/event_emitter_spec.rb
|
@@ -330,6 +334,8 @@ test_files:
|
|
330
334
|
- spec/acceptance/realtime/message_spec.rb
|
331
335
|
- spec/acceptance/realtime/presence_history_spec.rb
|
332
336
|
- spec/acceptance/realtime/presence_spec.rb
|
337
|
+
- spec/acceptance/realtime/stats_spec.rb
|
338
|
+
- spec/acceptance/realtime/time_spec.rb
|
333
339
|
- spec/acceptance/rest/auth_spec.rb
|
334
340
|
- spec/acceptance/rest/base_spec.rb
|
335
341
|
- spec/acceptance/rest/channel_spec.rb
|
@@ -361,6 +367,7 @@ test_files:
|
|
361
367
|
- spec/unit/models/presence_message_spec.rb
|
362
368
|
- spec/unit/models/protocol_message_spec.rb
|
363
369
|
- spec/unit/models/token_spec.rb
|
370
|
+
- spec/unit/modules/async_wrapper_spec.rb
|
364
371
|
- spec/unit/modules/conversions_spec.rb
|
365
372
|
- spec/unit/modules/enum_spec.rb
|
366
373
|
- spec/unit/modules/event_emitter_spec.rb
|