ably-rest 0.7.3 → 0.7.5

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.
Files changed (69) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +1 -0
  3. data/SPEC.md +480 -472
  4. data/lib/ably-rest.rb +1 -1
  5. data/lib/submodules/ably-ruby/LICENSE.txt +1 -1
  6. data/lib/submodules/ably-ruby/README.md +107 -24
  7. data/lib/submodules/ably-ruby/SPEC.md +531 -398
  8. data/lib/submodules/ably-ruby/lib/ably/auth.rb +24 -16
  9. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +9 -0
  10. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +17 -9
  11. data/lib/submodules/ably-ruby/lib/ably/models/paginated_resource.rb +12 -8
  12. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +18 -10
  13. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +15 -4
  14. data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +4 -3
  15. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +31 -2
  16. data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +77 -0
  17. data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +71 -0
  18. data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +41 -0
  19. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +28 -8
  20. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +0 -5
  21. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +24 -29
  22. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +54 -11
  23. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +21 -6
  24. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +7 -2
  25. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +29 -26
  26. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +4 -4
  27. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +41 -9
  28. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +72 -24
  29. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +26 -4
  30. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +19 -6
  31. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +74 -208
  32. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +264 -0
  33. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/presence_manager.rb +59 -0
  34. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/presence_state_machine.rb +64 -0
  35. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +1 -1
  36. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +6 -2
  37. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
  38. data/lib/submodules/ably-ruby/lib/ably/util/pub_sub.rb +3 -1
  39. data/lib/submodules/ably-ruby/lib/ably/util/safe_deferrable.rb +18 -0
  40. data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
  41. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +2 -2
  42. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +28 -6
  43. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +116 -46
  44. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +55 -10
  45. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +32 -0
  46. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +456 -96
  47. data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +2 -2
  48. data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +2 -2
  49. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +96 -7
  50. data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +8 -0
  51. data/lib/submodules/ably-ruby/spec/shared/safe_deferrable_behaviour.rb +71 -0
  52. data/lib/submodules/ably-ruby/spec/support/api_helper.rb +1 -1
  53. data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +1 -1
  54. data/lib/submodules/ably-ruby/spec/support/test_app.rb +13 -7
  55. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +15 -14
  56. data/lib/submodules/ably-ruby/spec/unit/models/paginated_resource_spec.rb +4 -4
  57. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +17 -17
  58. data/lib/submodules/ably-ruby/spec/unit/models/stat_spec.rb +4 -4
  59. data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +28 -9
  60. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +50 -0
  61. data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +76 -2
  62. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +51 -20
  63. data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +3 -3
  64. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +30 -0
  65. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +52 -26
  66. data/lib/submodules/ably-ruby/spec/unit/realtime/safe_deferrable_spec.rb +12 -0
  67. data/spec/spec_helper.rb +5 -0
  68. metadata +12 -4
  69. data/lib/submodules/ably-ruby/.ruby-version.old +0 -1
@@ -9,7 +9,7 @@ File.expand_path('submodules/ably-ruby/lib', File.dirname(__FILE__)).tap do |lib
9
9
  end
10
10
 
11
11
  %w(modules util).each do |namespace|
12
- ignore_modules = /^async|event_machine|state_machine/
12
+ ignore_modules = /^async|event_machine|state_machine|deferrable/
13
13
  Dir.glob(File.expand_path("submodules/ably-ruby/lib/ably/#{namespace}/*.rb", File.dirname(__FILE__))).each do |file|
14
14
  require file unless File.basename(file).match(ignore_modules)
15
15
  end
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Ably
1
+ Copyright (c) 2015 Ably
2
2
 
3
3
  MIT License
4
4
 
@@ -5,6 +5,10 @@
5
5
 
6
6
  A Ruby client library for [ably.io](https://ably.io), the real-time messaging service.
7
7
 
8
+ ## Documentation
9
+
10
+ Visit https://ably.io/documentation for a complete API reference and more examples.
11
+
8
12
  ## Installation
9
13
 
10
14
  The client library is available as a [gem from RubyGems.org](https://rubygems.org/gems/ably).
@@ -13,7 +17,7 @@ Add this line to your application's Gemfile:
13
17
 
14
18
  gem 'ably'
15
19
 
16
- And then execute:
20
+ And then install this Bundler dependency:
17
21
 
18
22
  $ bundle
19
23
 
@@ -23,12 +27,46 @@ Or install it yourself as:
23
27
 
24
28
  ## Using the Realtime API
25
29
 
30
+ ### Introduction
31
+
32
+ All examples must be run within an [EventMachine](https://github.com/eventmachine/eventmachine) [reactor](https://github.com/eventmachine/eventmachine/wiki/General-Introduction) as follows:
33
+
34
+ ```ruby
35
+ EventMachine.run do
36
+ # ...
37
+ end
38
+ ```
39
+
40
+ All examples assume a client has been created as follows:
41
+
42
+ ```ruby
43
+ client = Ably::Realtime.new(api_key: "xxxxx")
44
+ ```
45
+
46
+ ### Connection
47
+
48
+ Successful connection:
49
+
50
+ ```ruby
51
+ client.connection.connect do
52
+ # successful connection
53
+ end
54
+ ```
55
+
56
+ Failed connection:
57
+
58
+ ```ruby
59
+ connection_result = client.connection.connect
60
+ connection_result.errback = Proc.new do
61
+ # failed connection
62
+ end
63
+ ```
64
+
26
65
  ### Subscribing to a channel
27
66
 
28
67
  Given:
29
68
 
30
69
  ```ruby
31
- client = Ably::Realtime.new(api_key: "xxxxx")
32
70
  channel = client.channel("test")
33
71
  ```
34
72
 
@@ -53,70 +91,115 @@ end
53
91
  ### Publishing to a channel
54
92
 
55
93
  ```ruby
56
- client = Ably::Realtime.new(api_key: "xxxxx")
57
- channel = client.channel("test")
58
94
  channel.publish("greeting", "Hello World!")
59
95
  ```
60
96
 
97
+ ### Querying the History
98
+
99
+ ```ruby
100
+ channel.history do |messages|
101
+ messages # Ably::Models::PaginatedResource
102
+ messages.first # Ably::Models::Message
103
+ messages.length # number of messages in the retrieved history page
104
+ messages.next_page # Ably::Models::PaginatedResource
105
+ end
106
+ ```
107
+
61
108
  ### Presence on a channel
62
109
 
63
110
  ```ruby
64
- client = Ably::Realtime.new(api_key: "xxxxx")
65
- channel = client.channel("test")
66
111
  channel.presence.enter(data: 'john.doe') do |presence|
67
112
  presence.get #=> [Array of members present]
68
113
  end
69
114
  ```
70
115
 
116
+ ### Querying the Presence History
117
+
118
+ ```ruby
119
+ channel.presence.history do |presence_messages|
120
+ presence_messages.first.action # Any of :enter, :update or :leave
121
+ presence_messages.first.client_id
122
+ presence_messages.first.data
123
+ presence_messages.next_page # Ably::Models::PaginatedResource
124
+ end
125
+ ```
126
+
71
127
  ## Using the REST API
72
128
 
73
- ### Publishing a message to a channel
129
+ ### Introduction
130
+
131
+ Unlike the Realtime API, all calls are synchronous and are not run within an [EventMachine](https://github.com/eventmachine/eventmachine) [reactor](https://github.com/eventmachine/eventmachine/wiki/General-Introduction).
132
+
133
+ All examples assume a client and/or channel has been created as follows:
74
134
 
75
135
  ```ruby
76
136
  client = Ably::Rest.new(api_key: "xxxxx")
77
- channel = client.channel("test")
137
+ channel = client.channel('test')
138
+ ```
139
+
140
+ ### Publishing a message to a channel
141
+
142
+ ```ruby
78
143
  channel.publish("myEvent", "Hello!") #=> true
79
144
  ```
80
145
 
81
- ### Fetching a channel's history
146
+ ### Querying the History
82
147
 
83
148
  ```ruby
84
- client = Ably::Rest.new(api_key: "xxxxx")
85
- channel = client.channel("test")
86
- channel.history #=> [{:name=>"test", :data=>"payload"}]
149
+ channel.history #=> #<Ably::Models::PaginatedResource ...>
87
150
  ```
88
151
 
89
- ### Authentication with a token
152
+ ### Presence on a channel
90
153
 
91
154
  ```ruby
92
- client = Ably::Rest.new(api_key: "xxxxx")
93
- client.auth.authorise # creates a token and will use token authentication moving forwards
94
- client.auth.current_token #=> #<Ably::Models::Token>
95
- channel.publish("myEvent", "Hello!") #=> true, sent using token authentication
155
+ channel.presence.get # => #<Ably::Models::PaginatedResource ...>
96
156
  ```
97
157
 
98
- ### Fetching your application's stats
158
+ ### Querying the Presence History
99
159
 
100
160
  ```ruby
101
- client = Ably::Rest.new(api_key: "xxxxx")
102
- client.stats #=> [{:channels=>..., :apiRequests=>..., ...}]
161
+ channel.presence.history # => #<Ably::Models::PaginatedResource ...>
103
162
  ```
104
163
 
105
- ### Fetching the Ably service time
164
+ ### Generate Token and Token Request
106
165
 
107
166
  ```ruby
108
- client = Ably::Rest.new(api_key: "xxxxx")
109
- client.time #=> 2013-12-12 14:23:34 +0000
167
+ client.auth.request_token
168
+ # => #<Ably::Models::Token ...>
169
+
170
+ client.auth.create_token_request
171
+ # => {"id"=>...,
172
+ # "clientId"=>nil,
173
+ # "ttl"=>3600,
174
+ # "timestamp"=>...,
175
+ # "capability"=>"{\"*\":[\"*\"]}",
176
+ # "nonce"=>...,
177
+ # "mac"=>...}
178
+ ```
179
+
180
+ ### Fetching your application's stats
181
+
182
+ ```ruby
183
+ client.stats #=> PaginatedResource [{:channels=>..., :apiRequests=>..., ...}]
110
184
  ```
111
185
 
112
186
  ## Dependencies
113
187
 
114
188
  If you only need to use the REST features of this library and do not want EventMachine as a dependency, then you should use the [Ably Ruby REST gem](https://rubygems.org/gems/ably-rest).
115
189
 
190
+ ## Support and feedback
191
+
192
+ Please visit https://support.ably.io/ for access to our knowledgebase and to ask for any assistance.
193
+
116
194
  ## Contributing
117
195
 
118
196
  1. Fork it
119
197
  2. Create your feature branch (`git checkout -b my-new-feature`)
120
198
  3. Commit your changes (`git commit -am 'Add some feature'`)
199
+ 4. Ensure you have added suitable tests and the test suite is passing(`bundle exec rspec`)
121
200
  4. Push to the branch (`git push origin my-new-feature`)
122
- 5. Create new Pull Request
201
+ 5. Create a new Pull Request
202
+
203
+ ## License
204
+
205
+ Copyright (c) 2015 Ably, Licensed under an MIT license. Refer to [LICENSE.txt](LICENSE.txt) for the license terms.
@@ -1,9 +1,9 @@
1
- # Ably Real-time & REST Client Library 0.7.1 Specification
1
+ # Ably Real-time & REST Client Library 0.7.3 Specification
2
2
 
3
3
  ### Ably::Realtime::Channel#history
4
4
  _(see [spec/acceptance/realtime/channel_history_spec.rb](./spec/acceptance/realtime/channel_history_spec.rb))_
5
5
  * using JSON and MsgPack protocol
6
- * [returns a Deferrable](./spec/acceptance/realtime/channel_history_spec.rb#L20)
6
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/channel_history_spec.rb#L20)
7
7
  * with a single client publishing and receiving
8
8
  * [retrieves real-time history](./spec/acceptance/realtime/channel_history_spec.rb#L33)
9
9
  * with two clients publishing messages on the same channel
@@ -31,8 +31,8 @@ _(see [spec/acceptance/realtime/channel_spec.rb](./spec/acceptance/realtime/chan
31
31
  * [ignores subsequent #attach calls but calls the success callback if provided](./spec/acceptance/realtime/channel_spec.rb#L59)
32
32
  * [attaches to a channel](./spec/acceptance/realtime/channel_spec.rb#L72)
33
33
  * [attaches to a channel and calls the provided block](./spec/acceptance/realtime/channel_spec.rb#L80)
34
- * [returns a Deferrable](./spec/acceptance/realtime/channel_spec.rb#L87)
35
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/channel_spec.rb#L92)
34
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/channel_spec.rb#L87)
35
+ * [calls the SafeDeferrable callback on success](./spec/acceptance/realtime/channel_spec.rb#L92)
36
36
  * when state is :failed
37
37
  * [reattaches](./spec/acceptance/realtime/channel_spec.rb#L103)
38
38
  * when state is :detaching
@@ -44,58 +44,60 @@ _(see [spec/acceptance/realtime/channel_spec.rb](./spec/acceptance/realtime/chan
44
44
  * [calls the errback of the returned Deferrable](./spec/acceptance/realtime/channel_spec.rb#L174)
45
45
  * [triggers an error event](./spec/acceptance/realtime/channel_spec.rb#L182)
46
46
  * [updates the error_reason](./spec/acceptance/realtime/channel_spec.rb#L191)
47
+ * and subsequent authorisation with suitable permissions
48
+ * [attaches to the channel successfully and resets the channel error_reason](./spec/acceptance/realtime/channel_spec.rb#L200)
47
49
  * #detach
48
- * [detaches from a channel](./spec/acceptance/realtime/channel_spec.rb#L202)
49
- * [detaches from a channel and calls the provided block](./spec/acceptance/realtime/channel_spec.rb#L212)
50
- * [emits :detaching then :detached events](./spec/acceptance/realtime/channel_spec.rb#L221)
51
- * [returns a Deferrable](./spec/acceptance/realtime/channel_spec.rb#L233)
52
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/channel_spec.rb#L238)
50
+ * [detaches from a channel](./spec/acceptance/realtime/channel_spec.rb#L222)
51
+ * [detaches from a channel and calls the provided block](./spec/acceptance/realtime/channel_spec.rb#L232)
52
+ * [emits :detaching then :detached events](./spec/acceptance/realtime/channel_spec.rb#L241)
53
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/channel_spec.rb#L253)
54
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/channel_spec.rb#L260)
53
55
  * when state is :failed
54
- * [raises an exception](./spec/acceptance/realtime/channel_spec.rb#L251)
56
+ * [raises an exception](./spec/acceptance/realtime/channel_spec.rb#L273)
55
57
  * when state is :attaching
56
- * [moves straight to :detaching state and skips :attached](./spec/acceptance/realtime/channel_spec.rb#L262)
58
+ * [moves straight to :detaching state and skips :attached](./spec/acceptance/realtime/channel_spec.rb#L284)
57
59
  * when state is :detaching
58
- * [ignores subsequent #detach calls but calls the callback if provided](./spec/acceptance/realtime/channel_spec.rb#L280)
60
+ * [ignores subsequent #detach calls but calls the callback if provided](./spec/acceptance/realtime/channel_spec.rb#L302)
59
61
  * channel recovery in :attaching state
60
62
  * the transport is disconnected before the ATTACHED protocol message is received
61
- * PENDING: *[attach times out and fails if not ATTACHED protocol message received](./spec/acceptance/realtime/channel_spec.rb#L299)*
62
- * PENDING: *[channel is ATTACHED if ATTACHED protocol message is later received](./spec/acceptance/realtime/channel_spec.rb#L300)*
63
- * PENDING: *[sends an ATTACH protocol message in response to a channel message being received on the attaching channel](./spec/acceptance/realtime/channel_spec.rb#L301)*
63
+ * PENDING: *[attach times out and fails if not ATTACHED protocol message received](./spec/acceptance/realtime/channel_spec.rb#L321)*
64
+ * PENDING: *[channel is ATTACHED if ATTACHED protocol message is later received](./spec/acceptance/realtime/channel_spec.rb#L322)*
65
+ * PENDING: *[sends an ATTACH protocol message in response to a channel message being received on the attaching channel](./spec/acceptance/realtime/channel_spec.rb#L323)*
64
66
  * #publish
65
67
  * when attached
66
- * [publishes messages](./spec/acceptance/realtime/channel_spec.rb#L307)
68
+ * [publishes messages](./spec/acceptance/realtime/channel_spec.rb#L329)
67
69
  * when not yet attached
68
- * [publishes queued messages once attached](./spec/acceptance/realtime/channel_spec.rb#L319)
69
- * [publishes queued messages within a single protocol message](./spec/acceptance/realtime/channel_spec.rb#L327)
70
+ * [publishes queued messages once attached](./spec/acceptance/realtime/channel_spec.rb#L341)
71
+ * [publishes queued messages within a single protocol message](./spec/acceptance/realtime/channel_spec.rb#L349)
70
72
  * #subscribe
71
73
  * with an event argument
72
- * [subscribes for a single event](./spec/acceptance/realtime/channel_spec.rb#L350)
74
+ * [subscribes for a single event](./spec/acceptance/realtime/channel_spec.rb#L372)
73
75
  * with no event argument
74
- * [subscribes for all events](./spec/acceptance/realtime/channel_spec.rb#L360)
76
+ * [subscribes for all events](./spec/acceptance/realtime/channel_spec.rb#L382)
75
77
  * many times with different event names
76
- * [filters events accordingly to each callback](./spec/acceptance/realtime/channel_spec.rb#L370)
78
+ * [filters events accordingly to each callback](./spec/acceptance/realtime/channel_spec.rb#L392)
77
79
  * #unsubscribe
78
80
  * with an event argument
79
- * [unsubscribes for a single event](./spec/acceptance/realtime/channel_spec.rb#L393)
81
+ * [unsubscribes for a single event](./spec/acceptance/realtime/channel_spec.rb#L415)
80
82
  * with no event argument
81
- * [unsubscribes for a single event](./spec/acceptance/realtime/channel_spec.rb#L406)
83
+ * [unsubscribes for a single event](./spec/acceptance/realtime/channel_spec.rb#L428)
82
84
  * when connection state changes to
83
85
  * :failed
84
86
  * an :attached channel
85
- * [transitions state to :failed](./spec/acceptance/realtime/channel_spec.rb#L429)
86
- * [triggers an error event on the channel](./spec/acceptance/realtime/channel_spec.rb#L439)
87
- * [updates the channel error_reason](./spec/acceptance/realtime/channel_spec.rb#L449)
87
+ * [transitions state to :failed](./spec/acceptance/realtime/channel_spec.rb#L451)
88
+ * [triggers an error event on the channel](./spec/acceptance/realtime/channel_spec.rb#L461)
89
+ * [updates the channel error_reason](./spec/acceptance/realtime/channel_spec.rb#L471)
88
90
  * a :detached channel
89
- * [remains in the :detached state](./spec/acceptance/realtime/channel_spec.rb#L461)
91
+ * [remains in the :detached state](./spec/acceptance/realtime/channel_spec.rb#L483)
90
92
  * a :failed channel
91
- * [remains in the :failed state and ignores the failure error](./spec/acceptance/realtime/channel_spec.rb#L481)
93
+ * [remains in the :failed state and ignores the failure error](./spec/acceptance/realtime/channel_spec.rb#L503)
92
94
  * :closed
93
95
  * an :attached channel
94
- * [transitions state to :detached](./spec/acceptance/realtime/channel_spec.rb#L504)
96
+ * [transitions state to :detached](./spec/acceptance/realtime/channel_spec.rb#L526)
95
97
  * a :detached channel
96
- * [remains in the :detached state](./spec/acceptance/realtime/channel_spec.rb#L515)
98
+ * [remains in the :detached state](./spec/acceptance/realtime/channel_spec.rb#L537)
97
99
  * a :failed channel
98
- * [remains in the :failed state and retains the error_reason](./spec/acceptance/realtime/channel_spec.rb#L536)
100
+ * [remains in the :failed state and retains the error_reason](./spec/acceptance/realtime/channel_spec.rb#L558)
99
101
 
100
102
  ### Ably::Realtime::Client
101
103
  _(see [spec/acceptance/realtime/client_spec.rb](./spec/acceptance/realtime/client_spec.rb))_
@@ -137,162 +139,175 @@ _(see [spec/acceptance/realtime/connection_failures_spec.rb](./spec/acceptance/r
137
139
  * automatic connection retry
138
140
  * with invalid WebSocket host
139
141
  * when disconnected
140
- * [enters the suspended state after multiple attempts to connect](./spec/acceptance/realtime/connection_failures_spec.rb#L94)
142
+ * [enters the suspended state after multiple attempts to connect](./spec/acceptance/realtime/connection_failures_spec.rb#L95)
141
143
  * #close
142
- * [transitions connection state to :closed](./spec/acceptance/realtime/connection_failures_spec.rb#L111)
144
+ * [transitions connection state to :closed](./spec/acceptance/realtime/connection_failures_spec.rb#L112)
143
145
  * when connection state is :suspended
144
- * [enters the failed state after multiple attempts](./spec/acceptance/realtime/connection_failures_spec.rb#L130)
146
+ * [enters the failed state after multiple attempts if the max_time_in_state is set](./spec/acceptance/realtime/connection_failures_spec.rb#L131)
145
147
  * #close
146
- * [transitions connection state to :closed](./spec/acceptance/realtime/connection_failures_spec.rb#L150)
148
+ * [transitions connection state to :closed](./spec/acceptance/realtime/connection_failures_spec.rb#L151)
147
149
  * when connection state is :failed
148
150
  * #close
149
- * [will not transition state to :close and raises a StateChangeError exception](./spec/acceptance/realtime/connection_failures_spec.rb#L169)
151
+ * [will not transition state to :close and raises a StateChangeError exception](./spec/acceptance/realtime/connection_failures_spec.rb#L170)
150
152
  * #error_reason
151
- * [contains the error when state is disconnected](./spec/acceptance/realtime/connection_failures_spec.rb#L183)
152
- * [contains the error when state is suspended](./spec/acceptance/realtime/connection_failures_spec.rb#L183)
153
- * [contains the error when state is failed](./spec/acceptance/realtime/connection_failures_spec.rb#L183)
154
- * [is reset to nil when :connected](./spec/acceptance/realtime/connection_failures_spec.rb#L192)
155
- * [is reset to nil when :closed](./spec/acceptance/realtime/connection_failures_spec.rb#L203)
153
+ * [contains the error when state is disconnected](./spec/acceptance/realtime/connection_failures_spec.rb#L184)
154
+ * [contains the error when state is suspended](./spec/acceptance/realtime/connection_failures_spec.rb#L184)
155
+ * [contains the error when state is failed](./spec/acceptance/realtime/connection_failures_spec.rb#L184)
156
+ * [is reset to nil when :connected](./spec/acceptance/realtime/connection_failures_spec.rb#L193)
157
+ * [is reset to nil when :closed](./spec/acceptance/realtime/connection_failures_spec.rb#L204)
156
158
  * #connect
157
159
  * connection opening times out
158
- * [attempts to reconnect](./spec/acceptance/realtime/connection_failures_spec.rb#L230)
159
- * [calls the errback of the returned Deferrable object when first connection attempt fails](./spec/acceptance/realtime/connection_failures_spec.rb#L243)
160
+ * [attempts to reconnect](./spec/acceptance/realtime/connection_failures_spec.rb#L231)
161
+ * [calls the errback of the returned Deferrable object when first connection attempt fails](./spec/acceptance/realtime/connection_failures_spec.rb#L244)
160
162
  * when retry intervals are stubbed to attempt reconnection quickly
161
- * [never calls the provided success block](./spec/acceptance/realtime/connection_failures_spec.rb#L262)
163
+ * [never calls the provided success block](./spec/acceptance/realtime/connection_failures_spec.rb#L263)
162
164
  * connection resume
163
165
  * when DISCONNECTED ProtocolMessage received from the server
164
- * [reconnects automatically](./spec/acceptance/realtime/connection_failures_spec.rb#L291)
166
+ * [reconnects automatically and immediately](./spec/acceptance/realtime/connection_failures_spec.rb#L292)
167
+ * and subsequently fails to reconnect
168
+ * [retries every CONNECT_RETRY_CONFIG[:disconnected][:retry_every] seconds](./spec/acceptance/realtime/connection_failures_spec.rb#L322)
165
169
  * when websocket transport is closed
166
- * [reconnects automatically](./spec/acceptance/realtime/connection_failures_spec.rb#L309)
170
+ * [reconnects automatically](./spec/acceptance/realtime/connection_failures_spec.rb#L365)
167
171
  * after successfully reconnecting and resuming
168
- * [retains connection_id and connection_key](./spec/acceptance/realtime/connection_failures_spec.rb#L326)
169
- * [retains channel subscription state](./spec/acceptance/realtime/connection_failures_spec.rb#L343)
172
+ * [retains connection_id and connection_key](./spec/acceptance/realtime/connection_failures_spec.rb#L382)
173
+ * [retains channel subscription state](./spec/acceptance/realtime/connection_failures_spec.rb#L399)
170
174
  * when messages were published whilst the client was disconnected
171
- * [receives the messages published whilst offline](./spec/acceptance/realtime/connection_failures_spec.rb#L363)
172
- * when failing to resume because the connection_key is not or no longer valid
173
- * [updates the connection_id and connection_key](./spec/acceptance/realtime/connection_failures_spec.rb#L403)
174
- * [detaches all channels](./spec/acceptance/realtime/connection_failures_spec.rb#L418)
175
- * [emits an error on the channel and sets the error reason](./spec/acceptance/realtime/connection_failures_spec.rb#L436)
175
+ * [receives the messages published whilst offline](./spec/acceptance/realtime/connection_failures_spec.rb#L429)
176
+ * when failing to resume
177
+ * because the connection_key is not or no longer valid
178
+ * [updates the connection_id and connection_key](./spec/acceptance/realtime/connection_failures_spec.rb#L470)
179
+ * [detaches all channels](./spec/acceptance/realtime/connection_failures_spec.rb#L485)
180
+ * [emits an error on the channel and sets the error reason](./spec/acceptance/realtime/connection_failures_spec.rb#L503)
176
181
  * fallback host feature
177
182
  * with custom realtime websocket host option
178
- * [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L472)
183
+ * [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L542)
179
184
  * with non-production environment
180
- * [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L489)
185
+ * [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L559)
181
186
  * with production environment
182
187
  * when the Internet is down
183
- * [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L517)
188
+ * [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L587)
184
189
  * when the Internet is up
185
- * [uses a fallback host on every subsequent disconnected attempt until suspended](./spec/acceptance/realtime/connection_failures_spec.rb#L534)
186
- * [uses the primary host when suspended, and a fallback host on every subsequent suspended attempt](./spec/acceptance/realtime/connection_failures_spec.rb#L553)
190
+ * [uses a fallback host on every subsequent disconnected attempt until suspended](./spec/acceptance/realtime/connection_failures_spec.rb#L604)
191
+ * [uses the primary host when suspended, and a fallback host on every subsequent suspended attempt](./spec/acceptance/realtime/connection_failures_spec.rb#L623)
187
192
 
188
193
  ### Ably::Realtime::Connection
189
194
  _(see [spec/acceptance/realtime/connection_spec.rb](./spec/acceptance/realtime/connection_spec.rb))_
190
195
  * using JSON and MsgPack protocol
191
196
  * intialization
192
- * [connects automatically](./spec/acceptance/realtime/connection_spec.rb#L22)
197
+ * [connects automatically](./spec/acceptance/realtime/connection_spec.rb#L23)
193
198
  * with :connect_automatically option set to false
194
- * [does not connect automatically](./spec/acceptance/realtime/connection_spec.rb#L34)
195
- * [connects when method #connect is called](./spec/acceptance/realtime/connection_spec.rb#L42)
199
+ * [does not connect automatically](./spec/acceptance/realtime/connection_spec.rb#L35)
200
+ * [connects when method #connect is called](./spec/acceptance/realtime/connection_spec.rb#L43)
196
201
  * with token auth
197
202
  * for renewable tokens
198
203
  * that are valid for the duration of the test
199
204
  * with valid pre authorised token expiring in the future
200
- * [uses the existing token created by Auth](./spec/acceptance/realtime/connection_spec.rb#L60)
205
+ * [uses the existing token created by Auth](./spec/acceptance/realtime/connection_spec.rb#L61)
201
206
  * with implicit authorisation
202
- * [uses the token created by the implicit authorisation](./spec/acceptance/realtime/connection_spec.rb#L72)
207
+ * [uses the token created by the implicit authorisation](./spec/acceptance/realtime/connection_spec.rb#L73)
203
208
  * that expire
204
209
  * opening a new connection
205
210
  * with recently expired token
206
- * [renews the token on connect](./spec/acceptance/realtime/connection_spec.rb#L93)
211
+ * [renews the token on connect](./spec/acceptance/realtime/connection_spec.rb#L94)
207
212
  * with immediately expiring token
208
- * [renews the token on connect, and only makes one subsequent attempt to obtain a new token](./spec/acceptance/realtime/connection_spec.rb#L107)
209
- * [uses the primary host for subsequent connection and auth requests](./spec/acceptance/realtime/connection_spec.rb#L117)
213
+ * [renews the token on connect, and only makes one subsequent attempt to obtain a new token](./spec/acceptance/realtime/connection_spec.rb#L108)
214
+ * [uses the primary host for subsequent connection and auth requests](./spec/acceptance/realtime/connection_spec.rb#L118)
210
215
  * when connected with a valid non-expired token
211
216
  * that then expires following the connection being opened
212
- * PENDING: *[retains connection state](./spec/acceptance/realtime/connection_spec.rb#L167)*
213
- * PENDING: *[changes state to failed if a new token cannot be issued](./spec/acceptance/realtime/connection_spec.rb#L168)*
217
+ * PENDING: *[retains connection state](./spec/acceptance/realtime/connection_spec.rb#L166)*
218
+ * PENDING: *[changes state to failed if a new token cannot be issued](./spec/acceptance/realtime/connection_spec.rb#L167)*
214
219
  * the server
215
- * [disconnects the client, and the client automatically renews the token and then reconnects](./spec/acceptance/realtime/connection_spec.rb#L144)
220
+ * [disconnects the client, and the client automatically renews the token and then reconnects](./spec/acceptance/realtime/connection_spec.rb#L145)
216
221
  * for non-renewable tokens
217
222
  * that are expired
218
223
  * opening a new connection
219
- * [transitions state to failed](./spec/acceptance/realtime/connection_spec.rb#L183)
224
+ * [transitions state to failed](./spec/acceptance/realtime/connection_spec.rb#L182)
220
225
  * when connected
221
- * PENDING: *[transitions state to failed](./spec/acceptance/realtime/connection_spec.rb#L196)*
226
+ * PENDING: *[transitions state to failed](./spec/acceptance/realtime/connection_spec.rb#L195)*
222
227
  * initialization state changes
223
228
  * with implicit #connect
224
- * [are triggered in order](./spec/acceptance/realtime/connection_spec.rb#L223)
229
+ * [are triggered in order](./spec/acceptance/realtime/connection_spec.rb#L222)
225
230
  * with explicit #connect
226
- * [are triggered in order](./spec/acceptance/realtime/connection_spec.rb#L229)
231
+ * [are triggered in order](./spec/acceptance/realtime/connection_spec.rb#L228)
227
232
  * #connect
228
- * [returns a Deferrable](./spec/acceptance/realtime/connection_spec.rb#L237)
229
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/connection_spec.rb#L242)
233
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/connection_spec.rb#L236)
234
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/connection_spec.rb#L241)
230
235
  * when already connected
231
- * [does nothing and no further state changes are emitted](./spec/acceptance/realtime/connection_spec.rb#L251)
236
+ * [does nothing and no further state changes are emitted](./spec/acceptance/realtime/connection_spec.rb#L250)
232
237
  * once connected
233
238
  * connection#id
234
- * [is a string](./spec/acceptance/realtime/connection_spec.rb#L268)
235
- * [is unique from the connection#key](./spec/acceptance/realtime/connection_spec.rb#L275)
236
- * [is unique for every connection](./spec/acceptance/realtime/connection_spec.rb#L282)
239
+ * [is a string](./spec/acceptance/realtime/connection_spec.rb#L267)
240
+ * [is unique from the connection#key](./spec/acceptance/realtime/connection_spec.rb#L274)
241
+ * [is unique for every connection](./spec/acceptance/realtime/connection_spec.rb#L281)
237
242
  * connection#key
238
- * [is a string](./spec/acceptance/realtime/connection_spec.rb#L291)
239
- * [is unique from the connection#id](./spec/acceptance/realtime/connection_spec.rb#L298)
240
- * [is unique for every connection](./spec/acceptance/realtime/connection_spec.rb#L305)
243
+ * [is a string](./spec/acceptance/realtime/connection_spec.rb#L290)
244
+ * [is unique from the connection#id](./spec/acceptance/realtime/connection_spec.rb#L297)
245
+ * [is unique for every connection](./spec/acceptance/realtime/connection_spec.rb#L304)
241
246
  * following a previous connection being opened and closed
242
- * [reconnects and is provided with a new connection ID and connection key from the server](./spec/acceptance/realtime/connection_spec.rb#L315)
247
+ * [reconnects and is provided with a new connection ID and connection key from the server](./spec/acceptance/realtime/connection_spec.rb#L314)
243
248
  * #serial connection serial
244
- * [is set to -1 when a new connection is opened](./spec/acceptance/realtime/connection_spec.rb#L335)
245
- * [is set to 0 when a message sent ACK is received](./spec/acceptance/realtime/connection_spec.rb#L357)
246
- * [is set to 1 when the second message sent ACK is received](./spec/acceptance/realtime/connection_spec.rb#L364)
249
+ * [is set to -1 when a new connection is opened](./spec/acceptance/realtime/connection_spec.rb#L334)
250
+ * [is set to 0 when a message sent ACK is received](./spec/acceptance/realtime/connection_spec.rb#L356)
251
+ * [is set to 1 when the second message sent ACK is received](./spec/acceptance/realtime/connection_spec.rb#L363)
247
252
  * when a message is sent but the ACK has not yet been received
248
- * [the sent message msgSerial is 0 but the connection serial remains at -1](./spec/acceptance/realtime/connection_spec.rb#L344)
253
+ * [the sent message msgSerial is 0 but the connection serial remains at -1](./spec/acceptance/realtime/connection_spec.rb#L343)
249
254
  * #close
250
- * [returns a Deferrable](./spec/acceptance/realtime/connection_spec.rb#L375)
251
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/connection_spec.rb#L382)
255
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/connection_spec.rb#L374)
256
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/connection_spec.rb#L381)
252
257
  * when already closed
253
- * [does nothing and no further state changes are emitted](./spec/acceptance/realtime/connection_spec.rb#L393)
258
+ * [does nothing and no further state changes are emitted](./spec/acceptance/realtime/connection_spec.rb#L392)
254
259
  * when connection state is
255
260
  * :initialized
256
- * [changes the connection state to :closing and then immediately :closed without sending a ProtocolMessage CLOSE](./spec/acceptance/realtime/connection_spec.rb#L421)
261
+ * [changes the connection state to :closing and then immediately :closed without sending a ProtocolMessage CLOSE](./spec/acceptance/realtime/connection_spec.rb#L420)
257
262
  * :connected
258
- * [changes the connection state to :closing and waits for the server to confirm connection is :closed with a ProtocolMessage](./spec/acceptance/realtime/connection_spec.rb#L439)
263
+ * [changes the connection state to :closing and waits for the server to confirm connection is :closed with a ProtocolMessage](./spec/acceptance/realtime/connection_spec.rb#L438)
259
264
  * with an unresponsive connection
260
- * [force closes the connection when a :closed ProtocolMessage response is not received](./spec/acceptance/realtime/connection_spec.rb#L469)
265
+ * [force closes the connection when a :closed ProtocolMessage response is not received](./spec/acceptance/realtime/connection_spec.rb#L468)
261
266
  * #ping
262
- * [echoes a heart beat](./spec/acceptance/realtime/connection_spec.rb#L492)
267
+ * [echoes a heart beat](./spec/acceptance/realtime/connection_spec.rb#L491)
263
268
  * when not connected
264
- * [raises an exception](./spec/acceptance/realtime/connection_spec.rb#L502)
269
+ * [raises an exception](./spec/acceptance/realtime/connection_spec.rb#L501)
270
+ * with a success block that raises an exception
271
+ * [catches the exception and logs the error](./spec/acceptance/realtime/connection_spec.rb#L508)
265
272
  * recovery
266
273
  * #recovery_key
267
- * [is composed of connection id and serial that is kept up to date with each message ACK received](./spec/acceptance/realtime/connection_spec.rb#L535)
268
- * [is available when connection is in one of the states: connecting, connected, disconnected, suspended, failed](./spec/acceptance/realtime/connection_spec.rb#L556)
269
- * [is nil when connection is explicitly CLOSED](./spec/acceptance/realtime/connection_spec.rb#L580)
274
+ * [is composed of connection id and serial that is kept up to date with each message ACK received](./spec/acceptance/realtime/connection_spec.rb#L545)
275
+ * [is available when connection is in one of the states: connecting, connected, disconnected, suspended, failed](./spec/acceptance/realtime/connection_spec.rb#L566)
276
+ * [is nil when connection is explicitly CLOSED](./spec/acceptance/realtime/connection_spec.rb#L590)
270
277
  * opening a new connection using a recently disconnected connection's #recovery_key
271
278
  * connection#id and connection#key after recovery
272
- * [remain the same](./spec/acceptance/realtime/connection_spec.rb#L594)
279
+ * [remains the same](./spec/acceptance/realtime/connection_spec.rb#L604)
273
280
  * when messages have been sent whilst the old connection is disconnected
274
281
  * the new connection
275
- * [recovers server-side queued messages](./spec/acceptance/realtime/connection_spec.rb#L619)
282
+ * [recovers server-side queued messages](./spec/acceptance/realtime/connection_spec.rb#L645)
276
283
  * with :recover option
277
284
  * with invalid syntax
278
- * [raises an exception](./spec/acceptance/realtime/connection_spec.rb#L644)
285
+ * [raises an exception](./spec/acceptance/realtime/connection_spec.rb#L670)
279
286
  * with invalid formatted value sent to server
280
- * [triggers a fatal error on the connection object, sets the #error_reason and disconnects](./spec/acceptance/realtime/connection_spec.rb#L653)
287
+ * [triggers a fatal error on the connection object, sets the #error_reason and disconnects](./spec/acceptance/realtime/connection_spec.rb#L679)
281
288
  * with expired (missing) value sent to server
282
- * [triggers an error on the connection object, sets the #error_reason, yet will connect anyway](./spec/acceptance/realtime/connection_spec.rb#L667)
289
+ * [triggers an error on the connection object, sets the #error_reason, yet will connect anyway](./spec/acceptance/realtime/connection_spec.rb#L694)
283
290
  * with many connections simultaneously
284
- * [opens each with a unique connection#id and connection#key](./spec/acceptance/realtime/connection_spec.rb#L685)
291
+ * [opens each with a unique connection#id and connection#key](./spec/acceptance/realtime/connection_spec.rb#L713)
285
292
  * when a state transition is unsupported
286
- * [emits a StateChangeError](./spec/acceptance/realtime/connection_spec.rb#L705)
293
+ * [emits a StateChangeError](./spec/acceptance/realtime/connection_spec.rb#L733)
294
+ * protocol failure
295
+ * receiving an invalid ProtocolMessage
296
+ * [emits an error on the connection and logs a fatal error message](./spec/acceptance/realtime/connection_spec.rb#L749)
287
297
  * undocumented method
288
298
  * #internet_up?
289
- * [returns a Deferrable](./spec/acceptance/realtime/connection_spec.rb#L720)
299
+ * [returns a Deferrable](./spec/acceptance/realtime/connection_spec.rb#L765)
300
+ * internet up URL protocol
301
+ * when using TLS for the connection
302
+ * [uses TLS for the Internet check to https://internet-up.ably-realtime.com/is-the-internet-up.txt](./spec/acceptance/realtime/connection_spec.rb#L776)
303
+ * when using a non-secured connection
304
+ * [uses TLS for the Internet check to http://internet-up.ably-realtime.com/is-the-internet-up.txt](./spec/acceptance/realtime/connection_spec.rb#L786)
290
305
  * when the Internet is up
291
- * [calls the block with true](./spec/acceptance/realtime/connection_spec.rb#L726)
292
- * [calls the success callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#L733)
306
+ * [calls the block with true](./spec/acceptance/realtime/connection_spec.rb#L795)
307
+ * [calls the success callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#L802)
293
308
  * when the Internet is down
294
- * [calls the block with false](./spec/acceptance/realtime/connection_spec.rb#L745)
295
- * [calls the failure callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#L752)
309
+ * [calls the block with false](./spec/acceptance/realtime/connection_spec.rb#L814)
310
+ * [calls the failure callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#L821)
296
311
 
297
312
  ### Ably::Realtime::Channel Message
298
313
  _(see [spec/acceptance/realtime/message_spec.rb](./spec/acceptance/realtime/message_spec.rb))_
@@ -315,66 +330,68 @@ _(see [spec/acceptance/realtime/message_spec.rb](./spec/acceptance/realtime/mess
315
330
  * [sends and receives the messages on both opened connections and calls the success callbacks for each message published](./spec/acceptance/realtime/message_spec.rb#L138)
316
331
  * without suitable publishing permissions
317
332
  * [calls the error callback](./spec/acceptance/realtime/message_spec.rb#L183)
333
+ * server incorrectly resends a message that was already received by the client library
334
+ * [discards the message and logs it as an error to the channel](./spec/acceptance/realtime/message_spec.rb#L202)
318
335
  * encoding and decoding encrypted messages
319
336
  * with AES-128-CBC using crypto-data-128.json fixtures
320
337
  * item 0 with encrypted encoding utf-8/cipher+aes-128-cbc/base64
321
338
  * behaves like an Ably encrypter and decrypter
322
339
  * with #publish and #subscribe
323
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
324
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
340
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
341
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
325
342
  * item 1 with encrypted encoding cipher+aes-128-cbc/base64
326
343
  * behaves like an Ably encrypter and decrypter
327
344
  * with #publish and #subscribe
328
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
329
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
345
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
346
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
330
347
  * item 2 with encrypted encoding json/utf-8/cipher+aes-128-cbc/base64
331
348
  * behaves like an Ably encrypter and decrypter
332
349
  * with #publish and #subscribe
333
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
334
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
350
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
351
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
335
352
  * item 3 with encrypted encoding json/utf-8/cipher+aes-128-cbc/base64
336
353
  * behaves like an Ably encrypter and decrypter
337
354
  * with #publish and #subscribe
338
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
339
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
355
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
356
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
340
357
  * with AES-256-CBC using crypto-data-256.json fixtures
341
358
  * item 0 with encrypted encoding utf-8/cipher+aes-256-cbc/base64
342
359
  * behaves like an Ably encrypter and decrypter
343
360
  * with #publish and #subscribe
344
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
345
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
361
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
362
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
346
363
  * item 1 with encrypted encoding cipher+aes-256-cbc/base64
347
364
  * behaves like an Ably encrypter and decrypter
348
365
  * with #publish and #subscribe
349
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
350
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
366
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
367
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
351
368
  * item 2 with encrypted encoding json/utf-8/cipher+aes-256-cbc/base64
352
369
  * behaves like an Ably encrypter and decrypter
353
370
  * with #publish and #subscribe
354
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
355
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
371
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
372
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
356
373
  * item 3 with encrypted encoding json/utf-8/cipher+aes-256-cbc/base64
357
374
  * behaves like an Ably encrypter and decrypter
358
375
  * with #publish and #subscribe
359
- * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L235)
360
- * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L253)
376
+ * [encrypts message automatically before they are pushed to the server](./spec/acceptance/realtime/message_spec.rb#L266)
377
+ * [sends and receives messages that are encrypted & decrypted by the Ably library](./spec/acceptance/realtime/message_spec.rb#L284)
361
378
  * with multiple sends from one client to another
362
- * [encrypts and decrypts all messages](./spec/acceptance/realtime/message_spec.rb#L292)
379
+ * [encrypts and decrypts all messages](./spec/acceptance/realtime/message_spec.rb#L323)
363
380
  * subscribing with a different transport protocol
364
- * [delivers a String ASCII-8BIT payload to the receiver](./spec/acceptance/realtime/message_spec.rb#L335)
365
- * [delivers a String UTF-8 payload to the receiver](./spec/acceptance/realtime/message_spec.rb#L335)
366
- * [delivers a Hash payload to the receiver](./spec/acceptance/realtime/message_spec.rb#L335)
381
+ * [delivers a String ASCII-8BIT payload to the receiver](./spec/acceptance/realtime/message_spec.rb#L366)
382
+ * [delivers a String UTF-8 payload to the receiver](./spec/acceptance/realtime/message_spec.rb#L366)
383
+ * [delivers a Hash payload to the receiver](./spec/acceptance/realtime/message_spec.rb#L366)
367
384
  * publishing on an unencrypted channel and subscribing on an encrypted channel with another client
368
- * [does not attempt to decrypt the message](./spec/acceptance/realtime/message_spec.rb#L354)
385
+ * [does not attempt to decrypt the message](./spec/acceptance/realtime/message_spec.rb#L385)
369
386
  * publishing on an encrypted channel and subscribing on an unencrypted channel with another client
370
- * [delivers the message but still encrypted with a value in the #encoding attribute](./spec/acceptance/realtime/message_spec.rb#L372)
371
- * [triggers a Cipher error on the channel](./spec/acceptance/realtime/message_spec.rb#L381)
372
- * publishing on an encrypted channel and subscribing with a different algorithm on another client
373
- * [delivers the message but still encrypted with the cipher detials in the #encoding attribute](./spec/acceptance/realtime/message_spec.rb#L403)
387
+ * [delivers the message but still encrypted with a value in the #encoding attribute](./spec/acceptance/realtime/message_spec.rb#L403)
374
388
  * [triggers a Cipher error on the channel](./spec/acceptance/realtime/message_spec.rb#L412)
375
- * publishing on an encrypted channel and subscribing with a different key on another client
376
- * [delivers the message but still encrypted with the cipher details in the #encoding attribute](./spec/acceptance/realtime/message_spec.rb#L434)
389
+ * publishing on an encrypted channel and subscribing with a different algorithm on another client
390
+ * [delivers the message but still encrypted with the cipher detials in the #encoding attribute](./spec/acceptance/realtime/message_spec.rb#L434)
377
391
  * [triggers a Cipher error on the channel](./spec/acceptance/realtime/message_spec.rb#L443)
392
+ * publishing on an encrypted channel and subscribing with a different key on another client
393
+ * [delivers the message but still encrypted with the cipher details in the #encoding attribute](./spec/acceptance/realtime/message_spec.rb#L465)
394
+ * [triggers a Cipher error on the channel](./spec/acceptance/realtime/message_spec.rb#L474)
378
395
 
379
396
  ### Ably::Realtime::Presence history
380
397
  _(see [spec/acceptance/realtime/presence_history_spec.rb](./spec/acceptance/realtime/presence_history_spec.rb))_
@@ -385,246 +402,301 @@ _(see [spec/acceptance/realtime/presence_history_spec.rb](./spec/acceptance/real
385
402
  ### Ably::Realtime::Presence
386
403
  _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/presence_spec.rb))_
387
404
  * using JSON and MsgPack protocol
388
- * PENDING: *[ensure connection_id is unique and updated on ENTER](./spec/acceptance/realtime/presence_spec.rb#L995)*
389
- * PENDING: *[ensure connection_id for presence member matches the messages they publish on the channel](./spec/acceptance/realtime/presence_spec.rb#L996)*
390
- * PENDING: *[stop a call to get when the channel has not been entered](./spec/acceptance/realtime/presence_spec.rb#L997)*
391
- * PENDING: *[stop a call to get when the channel has been entered but the list is not up to date](./spec/acceptance/realtime/presence_spec.rb#L998)*
392
- * PENDING: *[presence will resume sync if connection is dropped mid-way](./spec/acceptance/realtime/presence_spec.rb#L999)*
393
405
  * when attached (but not present) on a presence channel with an anonymous client (no client ID)
394
- * [maintains state as other clients enter and leave the channel](./spec/acceptance/realtime/presence_spec.rb#L24)
406
+ * [maintains state as other clients enter and leave the channel](./spec/acceptance/realtime/presence_spec.rb#L118)
395
407
  * #sync_complete?
396
408
  * when attaching to a channel without any members present
397
- * [is true and the presence channel is considered synced immediately](./spec/acceptance/realtime/presence_spec.rb#L53)
409
+ * [is true and the presence channel is considered synced immediately](./spec/acceptance/realtime/presence_spec.rb#L190)
398
410
  * when attaching to a channel with members present
399
- * [is false and the presence channel will subsequently be synced](./spec/acceptance/realtime/presence_spec.rb#L62)
400
- * when the SYNC of a presence channel spans multiple ProtocolMessage messages
401
- * with 250 existing (present) members
402
- * when a new client attaches to the presence channel
403
- * [emits :present for each member](./spec/acceptance/realtime/presence_spec.rb#L83)
411
+ * [is false and the presence channel will subsequently be synced](./spec/acceptance/realtime/presence_spec.rb#L199)
412
+ * 250 existing (present) members on a channel (3 SYNC pages)
413
+ * requires at least 3 SYNC ProtocolMessages
414
+ * when a client attaches to the presence channel
415
+ * [emits :present for each member](./spec/acceptance/realtime/presence_spec.rb#L231)
416
+ * and a member leaves before the SYNC operation is complete
417
+ * [emits :leave immediately as the member leaves](./spec/acceptance/realtime/presence_spec.rb#L245)
418
+ * [ignores presence events with timestamps prior to the current :present event in the MembersMap](./spec/acceptance/realtime/presence_spec.rb#L283)
419
+ * [does not emit :present after the :leave event has been emitted, and that member is not included in the list of members via #get](./spec/acceptance/realtime/presence_spec.rb#L322)
404
420
  * #get
405
- * [#waits until sync is complete](./spec/acceptance/realtime/presence_spec.rb#L102)
421
+ * [waits until sync is complete](./spec/acceptance/realtime/presence_spec.rb#L368)
406
422
  * automatic attachment of channel on access to presence object
407
- * [is implicit if presence state is initalized](./spec/acceptance/realtime/presence_spec.rb#L122)
408
- * [is disabled if presence state is not initialized](./spec/acceptance/realtime/presence_spec.rb#L130)
423
+ * [is implicit if presence state is initialized](./spec/acceptance/realtime/presence_spec.rb#L388)
424
+ * [is disabled if presence state is not initialized](./spec/acceptance/realtime/presence_spec.rb#L396)
409
425
  * state
410
426
  * once opened
411
- * [once opened, enters the :left state if the channel detaches](./spec/acceptance/realtime/presence_spec.rb#L147)
427
+ * [once opened, enters the :left state if the channel detaches](./spec/acceptance/realtime/presence_spec.rb#L413)
412
428
  * #enter
413
- * [allows client_id to be set on enter for anonymous clients](./spec/acceptance/realtime/presence_spec.rb#L170)
414
- * [raises an exception if client_id is not set](./spec/acceptance/realtime/presence_spec.rb#L204)
415
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L209)
416
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L214)
429
+ * [allows client_id to be set on enter for anonymous clients](./spec/acceptance/realtime/presence_spec.rb#L436)
430
+ * [raises an exception if client_id is not set](./spec/acceptance/realtime/presence_spec.rb#L483)
417
431
  * data attribute
418
432
  * when provided as argument option to #enter
419
- * [remains intact following #leave](./spec/acceptance/realtime/presence_spec.rb#L181)
433
+ * [remains intact following #leave](./spec/acceptance/realtime/presence_spec.rb#L447)
434
+ * message #connection_id
435
+ * [matches the current client connection_id](./spec/acceptance/realtime/presence_spec.rb#L471)
436
+ * without necessary capabilities to join presence
437
+ * [calls the Deferrable errback on capabilities failure](./spec/acceptance/realtime/presence_spec.rb#L495)
438
+ * it should behave like a public presence method
439
+ * [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L44)
440
+ * [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L44)
441
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L56)
442
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L63)
443
+ * [catches exceptions in the provided method block and logs them to the logger](./spec/acceptance/realtime/presence_spec.rb#L73)
444
+ * if connection fails before success
445
+ * [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L94)
420
446
  * #update
421
- * [without previous #enter automatically enters](./spec/acceptance/realtime/presence_spec.rb#L224)
422
- * [updates the data if :data argument provided](./spec/acceptance/realtime/presence_spec.rb#L249)
423
- * [updates the data to nil if :data argument is not provided (assumes nil value)](./spec/acceptance/realtime/presence_spec.rb#L259)
424
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L269)
425
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L276)
447
+ * [without previous #enter automatically enters](./spec/acceptance/realtime/presence_spec.rb#L507)
448
+ * [updates the data if :data argument provided](./spec/acceptance/realtime/presence_spec.rb#L532)
449
+ * [updates the data to nil if :data argument is not provided (assumes nil value)](./spec/acceptance/realtime/presence_spec.rb#L542)
426
450
  * when ENTERED
427
- * [has no effect on the state](./spec/acceptance/realtime/presence_spec.rb#L234)
451
+ * [has no effect on the state](./spec/acceptance/realtime/presence_spec.rb#L517)
452
+ * it should behave like a public presence method
453
+ * [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L44)
454
+ * [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L44)
455
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L56)
456
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L63)
457
+ * [catches exceptions in the provided method block and logs them to the logger](./spec/acceptance/realtime/presence_spec.rb#L73)
458
+ * if connection fails before success
459
+ * [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L94)
428
460
  * #leave
429
- * [raises an exception if not entered](./spec/acceptance/realtime/presence_spec.rb#L332)
430
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L337)
431
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L344)
461
+ * [raises an exception if not entered](./spec/acceptance/realtime/presence_spec.rb#L600)
432
462
  * :data option
433
463
  * when set to a string
434
- * [emits the new data for the leave event](./spec/acceptance/realtime/presence_spec.rb#L293)
464
+ * [emits the new data for the leave event](./spec/acceptance/realtime/presence_spec.rb#L561)
435
465
  * when set to nil
436
- * [emits the previously defined value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L306)
466
+ * [emits the previously defined value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L574)
437
467
  * when not passed as an argument
438
- * [emits the previously defined value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L319)
468
+ * [emits the previously defined value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L587)
469
+ * it should behave like a public presence method
470
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L56)
471
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L63)
472
+ * [catches exceptions in the provided method block and logs them to the logger](./spec/acceptance/realtime/presence_spec.rb#L73)
473
+ * if connection fails before success
474
+ * [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L94)
439
475
  * :left event
440
- * [emits the data defined in enter](./spec/acceptance/realtime/presence_spec.rb#L356)
441
- * [emits the data defined in update](./spec/acceptance/realtime/presence_spec.rb#L367)
476
+ * [emits the data defined in enter](./spec/acceptance/realtime/presence_spec.rb#L609)
477
+ * [emits the data defined in update](./spec/acceptance/realtime/presence_spec.rb#L620)
442
478
  * entering/updating/leaving presence state on behalf of another client_id
443
479
  * #enter_client
444
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L418)
445
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L423)
446
480
  * multiple times on the same channel with different client_ids
447
- * [has no affect on the client's presence state and only enters on behalf of the provided client_id](./spec/acceptance/realtime/presence_spec.rb#L388)
448
- * [enters a channel and sets the data based on the provided :data option](./spec/acceptance/realtime/presence_spec.rb#L402)
481
+ * [has no affect on the client's presence state and only enters on behalf of the provided client_id](./spec/acceptance/realtime/presence_spec.rb#L641)
482
+ * [enters a channel and sets the data based on the provided :data option](./spec/acceptance/realtime/presence_spec.rb#L655)
483
+ * message #connection_id
484
+ * [matches the current client connection_id](./spec/acceptance/realtime/presence_spec.rb#L674)
485
+ * it should behave like a public presence method
486
+ * [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L44)
487
+ * [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L44)
488
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L56)
489
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L63)
490
+ * [catches exceptions in the provided method block and logs them to the logger](./spec/acceptance/realtime/presence_spec.rb#L73)
491
+ * if connection fails before success
492
+ * [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L94)
493
+ * without necessary capabilities to enter on behalf of another client
494
+ * [calls the Deferrable errback on capabilities failure](./spec/acceptance/realtime/presence_spec.rb#L696)
449
495
  * #update_client
450
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L492)
451
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L497)
452
496
  * multiple times on the same channel with different client_ids
453
- * [updates the data attribute for the member when :data option provided](./spec/acceptance/realtime/presence_spec.rb#L433)
454
- * [updates the data attribute to null for the member when :data option is not provided (assumed null)](./spec/acceptance/realtime/presence_spec.rb#L457)
455
- * [enters if not already entered](./spec/acceptance/realtime/presence_spec.rb#L469)
497
+ * [updates the data attribute for the member when :data option provided](./spec/acceptance/realtime/presence_spec.rb#L707)
498
+ * [updates the data attribute to null for the member when :data option is not provided (assumed null)](./spec/acceptance/realtime/presence_spec.rb#L731)
499
+ * [enters if not already entered](./spec/acceptance/realtime/presence_spec.rb#L743)
500
+ * it should behave like a public presence method
501
+ * [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L44)
502
+ * [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L44)
503
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L56)
504
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L63)
505
+ * [catches exceptions in the provided method block and logs them to the logger](./spec/acceptance/realtime/presence_spec.rb#L73)
506
+ * if connection fails before success
507
+ * [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L94)
456
508
  * #leave_client
457
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L595)
458
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L600)
459
509
  * leaves a channel
460
510
  * multiple times on the same channel with different client_ids
461
- * [emits the :leave event for each client_id](./spec/acceptance/realtime/presence_spec.rb#L508)
462
- * [succeeds if that client_id has not previously entered the channel](./spec/acceptance/realtime/presence_spec.rb#L532)
511
+ * [emits the :leave event for each client_id](./spec/acceptance/realtime/presence_spec.rb#L772)
512
+ * [succeeds if that client_id has not previously entered the channel](./spec/acceptance/realtime/presence_spec.rb#L796)
463
513
  * with a new value in :data option
464
- * [emits the leave event with the new data value](./spec/acceptance/realtime/presence_spec.rb#L556)
514
+ * [emits the leave event with the new data value](./spec/acceptance/realtime/presence_spec.rb#L820)
465
515
  * with a nil value in :data option
466
- * [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L569)
516
+ * [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L833)
467
517
  * with no :data option
468
- * [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L582)
518
+ * [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L846)
519
+ * it should behave like a public presence method
520
+ * [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L44)
521
+ * [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L44)
522
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L56)
523
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L63)
524
+ * [catches exceptions in the provided method block and logs them to the logger](./spec/acceptance/realtime/presence_spec.rb#L73)
525
+ * if connection fails before success
526
+ * [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L94)
469
527
  * #get
470
- * [returns a Deferrable](./spec/acceptance/realtime/presence_spec.rb#L610)
471
- * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L615)
472
- * [returns the current members on the channel](./spec/acceptance/realtime/presence_spec.rb#L622)
473
- * [filters by connection_id option if provided](./spec/acceptance/realtime/presence_spec.rb#L637)
474
- * [filters by client_id option if provided](./spec/acceptance/realtime/presence_spec.rb#L659)
475
- * [does not wait for SYNC to complete if :wait_for_sync option is false](./spec/acceptance/realtime/presence_spec.rb#L683)
528
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L864)
529
+ * [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L869)
530
+ * [catches exceptions in the provided method block](./spec/acceptance/realtime/presence_spec.rb#L876)
531
+ * [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L884)
532
+ * [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L884)
533
+ * [returns the current members on the channel](./spec/acceptance/realtime/presence_spec.rb#L959)
534
+ * [filters by connection_id option if provided](./spec/acceptance/realtime/presence_spec.rb#L974)
535
+ * [filters by client_id option if provided](./spec/acceptance/realtime/presence_spec.rb#L996)
536
+ * [does not wait for SYNC to complete if :wait_for_sync option is false](./spec/acceptance/realtime/presence_spec.rb#L1020)
537
+ * during a sync
538
+ * [fails if the connection fails](./spec/acceptance/realtime/presence_spec.rb#L914)
539
+ * [fails if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L934)
476
540
  * when a member enters and then leaves
477
- * [has no members](./spec/acceptance/realtime/presence_spec.rb#L693)
541
+ * [has no members](./spec/acceptance/realtime/presence_spec.rb#L1030)
478
542
  * with lots of members on different clients
479
- * [returns a complete list of members on all clients](./spec/acceptance/realtime/presence_spec.rb#L710)
543
+ * [returns a complete list of members on all clients](./spec/acceptance/realtime/presence_spec.rb#L1047)
480
544
  * #subscribe
481
545
  * with no arguments
482
- * [calls the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#L746)
546
+ * [calls the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#L1083)
483
547
  * #unsubscribe
484
548
  * with no arguments
485
- * [removes the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#L766)
549
+ * [removes the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#L1105)
486
550
  * REST #get
487
- * [returns current members](./spec/acceptance/realtime/presence_spec.rb#L785)
488
- * [returns no members once left](./spec/acceptance/realtime/presence_spec.rb#L798)
551
+ * [returns current members](./spec/acceptance/realtime/presence_spec.rb#L1124)
552
+ * [returns no members once left](./spec/acceptance/realtime/presence_spec.rb#L1137)
489
553
  * client_id with ASCII_8BIT
490
554
  * in connection set up
491
- * [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#L815)
555
+ * [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#L1154)
492
556
  * in channel options
493
- * [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#L828)
557
+ * [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#L1167)
494
558
  * encoding and decoding of presence message data
495
- * [encrypts presence message data](./spec/acceptance/realtime/presence_spec.rb#L852)
559
+ * [encrypts presence message data](./spec/acceptance/realtime/presence_spec.rb#L1191)
496
560
  * #subscribe
497
- * [emits decrypted enter events](./spec/acceptance/realtime/presence_spec.rb#L871)
498
- * [emits decrypted update events](./spec/acceptance/realtime/presence_spec.rb#L883)
499
- * [emits previously set data for leave events](./spec/acceptance/realtime/presence_spec.rb#L897)
561
+ * [emits decrypted enter events](./spec/acceptance/realtime/presence_spec.rb#L1210)
562
+ * [emits decrypted update events](./spec/acceptance/realtime/presence_spec.rb#L1222)
563
+ * [emits previously set data for leave events](./spec/acceptance/realtime/presence_spec.rb#L1236)
500
564
  * #get
501
- * [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#L913)
565
+ * [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#L1252)
502
566
  * REST #get
503
- * [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#L926)
567
+ * [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#L1265)
504
568
  * when cipher settings do not match publisher
505
- * [delivers an unencoded presence message left with encoding value](./spec/acceptance/realtime/presence_spec.rb#L941)
506
- * [emits an error when cipher does not match and presence data cannot be decoded](./spec/acceptance/realtime/presence_spec.rb#L954)
569
+ * [delivers an unencoded presence message left with encoding value](./spec/acceptance/realtime/presence_spec.rb#L1280)
570
+ * [emits an error when cipher does not match and presence data cannot be decoded](./spec/acceptance/realtime/presence_spec.rb#L1293)
507
571
  * leaving
508
- * [expect :left event once underlying connection is closed](./spec/acceptance/realtime/presence_spec.rb#L971)
509
- * [expect :left event with client data from enter event](./spec/acceptance/realtime/presence_spec.rb#L981)
572
+ * [expect :left event once underlying connection is closed](./spec/acceptance/realtime/presence_spec.rb#L1310)
573
+ * [expect :left event with client data from enter event](./spec/acceptance/realtime/presence_spec.rb#L1320)
574
+ * connection failure mid-way through a large member sync
575
+ * PENDING: *[resumes the SYNC operation](./spec/acceptance/realtime/presence_spec.rb#L1339)*
510
576
 
511
577
  ### Ably::Realtime::Client#stats
512
578
  _(see [spec/acceptance/realtime/stats_spec.rb](./spec/acceptance/realtime/stats_spec.rb))_
513
579
  * using JSON and MsgPack protocol
514
580
  * fetching stats
515
581
  * [should return a PaginatedResource](./spec/acceptance/realtime/stats_spec.rb#L10)
516
- * [should return a Deferrable object](./spec/acceptance/realtime/stats_spec.rb#L17)
582
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/stats_spec.rb#L17)
517
583
 
518
584
  ### Ably::Realtime::Client#time
519
585
  _(see [spec/acceptance/realtime/time_spec.rb](./spec/acceptance/realtime/time_spec.rb))_
520
586
  * using JSON and MsgPack protocol
521
587
  * fetching the service time
522
588
  * [should return the service time as a Time object](./spec/acceptance/realtime/time_spec.rb#L10)
523
- * [should return a deferrable object](./spec/acceptance/realtime/time_spec.rb#L19)
589
+ * [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/time_spec.rb#L19)
524
590
 
525
591
  ### Ably::Auth
526
592
  _(see [spec/acceptance/rest/auth_spec.rb](./spec/acceptance/rest/auth_spec.rb))_
527
593
  * using JSON and MsgPack protocol
528
594
  * [has immutable options](./spec/acceptance/rest/auth_spec.rb#L54)
529
595
  * #request_token
530
- * [returns the requested token](./spec/acceptance/rest/auth_spec.rb#L62)
596
+ * [returns a valid requested token in the expected format with valid issued_at and expires_at attributes](./spec/acceptance/rest/auth_spec.rb#L69)
531
597
  * with option :client_id
532
- * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L93)
598
+ * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L95)
533
599
  * with option :capability
534
- * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L93)
600
+ * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L95)
535
601
  * with option :nonce
536
- * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L93)
602
+ * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L95)
537
603
  * with option :timestamp
538
- * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L93)
604
+ * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L95)
539
605
  * with option :ttl
540
- * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L93)
606
+ * [overrides default and uses camelCase notation for all attributes](./spec/acceptance/rest/auth_spec.rb#L95)
541
607
  * with :key_id & :key_secret options
542
- * [key_id is used in request and signing uses key_secret](./spec/acceptance/rest/auth_spec.rb#L122)
608
+ * [key_id is used in request and signing uses key_secret](./spec/acceptance/rest/auth_spec.rb#L124)
543
609
  * with :query_time option
544
- * [queries the server for the time](./spec/acceptance/rest/auth_spec.rb#L130)
610
+ * [queries the server for the time](./spec/acceptance/rest/auth_spec.rb#L132)
545
611
  * without :query_time option
546
- * [does not query the server for the time](./spec/acceptance/rest/auth_spec.rb#L139)
612
+ * [does not query the server for the time](./spec/acceptance/rest/auth_spec.rb#L141)
547
613
  * with :auth_url option
548
- * when response is valid
549
- * [requests a token from :auth_url using an HTTP GET request](./spec/acceptance/rest/auth_spec.rb#L186)
614
+ * when response from :auth_url is a valid token request
615
+ * [requests a token from :auth_url using an HTTP GET request](./spec/acceptance/rest/auth_spec.rb#L188)
616
+ * [returns a valid token generated from the token request](./spec/acceptance/rest/auth_spec.rb#L193)
550
617
  * with :query_params
551
- * [requests a token from :auth_url with the :query_params](./spec/acceptance/rest/auth_spec.rb#L194)
618
+ * [requests a token from :auth_url with the :query_params](./spec/acceptance/rest/auth_spec.rb#L200)
552
619
  * with :headers
553
- * [requests a token from :auth_url with the HTTP headers set](./spec/acceptance/rest/auth_spec.rb#L202)
620
+ * [requests a token from :auth_url with the HTTP headers set](./spec/acceptance/rest/auth_spec.rb#L208)
554
621
  * with POST
555
- * [requests a token from :auth_url using an HTTP POST instead of the default GET](./spec/acceptance/rest/auth_spec.rb#L210)
622
+ * [requests a token from :auth_url using an HTTP POST instead of the default GET](./spec/acceptance/rest/auth_spec.rb#L216)
623
+ * when response from :auth_url is a token
624
+ * [returns a Token created from the token JSON](./spec/acceptance/rest/auth_spec.rb#L240)
556
625
  * when response is invalid
557
626
  * 500
558
- * [raises ServerError](./spec/acceptance/rest/auth_spec.rb#L223)
627
+ * [raises ServerError](./spec/acceptance/rest/auth_spec.rb#L255)
559
628
  * XML
560
- * [raises InvalidResponseBody](./spec/acceptance/rest/auth_spec.rb#L234)
561
- * with token_request_block
562
- * [calls the block when authenticating to obtain the request token](./spec/acceptance/rest/auth_spec.rb#L252)
563
- * [uses the token request from the block when requesting a new token](./spec/acceptance/rest/auth_spec.rb#L257)
629
+ * [raises InvalidResponseBody](./spec/acceptance/rest/auth_spec.rb#L266)
630
+ * with token_request_block that returns a token request
631
+ * [calls the block when authenticating to obtain the request token](./spec/acceptance/rest/auth_spec.rb#L284)
632
+ * [uses the token request from the block when requesting a new token](./spec/acceptance/rest/auth_spec.rb#L289)
633
+ * with token_request_block that returns a token
634
+ * [calls the block when authenticating to obtain the request token](./spec/acceptance/rest/auth_spec.rb#L317)
635
+ * [uses the token request from the block when requesting a new token](./spec/acceptance/rest/auth_spec.rb#L322)
564
636
  * before #authorise has been called
565
- * [has no current_token](./spec/acceptance/rest/auth_spec.rb#L264)
637
+ * [has no current_token](./spec/acceptance/rest/auth_spec.rb#L334)
566
638
  * #authorise
567
- * [updates the persisted auth options thare are then used for subsequent authorise requests](./spec/acceptance/rest/auth_spec.rb#L311)
639
+ * [updates the persisted auth options thare are then used for subsequent authorise requests](./spec/acceptance/rest/auth_spec.rb#L381)
568
640
  * when called for the first time since the client has been instantiated
569
- * [passes all options to #request_token](./spec/acceptance/rest/auth_spec.rb#L275)
570
- * [returns a valid token](./spec/acceptance/rest/auth_spec.rb#L280)
571
- * [issues a new token if option :force => true](./spec/acceptance/rest/auth_spec.rb#L284)
641
+ * [passes all options to #request_token](./spec/acceptance/rest/auth_spec.rb#L345)
642
+ * [returns a valid token](./spec/acceptance/rest/auth_spec.rb#L350)
643
+ * [issues a new token if option :force => true](./spec/acceptance/rest/auth_spec.rb#L354)
572
644
  * with previous authorisation
573
- * [does not request a token if current_token has not expired](./spec/acceptance/rest/auth_spec.rb#L295)
574
- * [requests a new token if token is expired](./spec/acceptance/rest/auth_spec.rb#L300)
575
- * [issues a new token if option :force => true](./spec/acceptance/rest/auth_spec.rb#L306)
645
+ * [does not request a token if current_token has not expired](./spec/acceptance/rest/auth_spec.rb#L365)
646
+ * [requests a new token if token is expired](./spec/acceptance/rest/auth_spec.rb#L370)
647
+ * [issues a new token if option :force => true](./spec/acceptance/rest/auth_spec.rb#L376)
576
648
  * with token_request_block
577
- * [calls the block](./spec/acceptance/rest/auth_spec.rb#L327)
578
- * [uses the token request returned from the block when requesting a new token](./spec/acceptance/rest/auth_spec.rb#L331)
649
+ * [calls the block](./spec/acceptance/rest/auth_spec.rb#L397)
650
+ * [uses the token request returned from the block when requesting a new token](./spec/acceptance/rest/auth_spec.rb#L401)
579
651
  * for every subsequent #request_token
580
652
  * without a provided block
581
- * [calls the originally provided block](./spec/acceptance/rest/auth_spec.rb#L337)
653
+ * [calls the originally provided block](./spec/acceptance/rest/auth_spec.rb#L407)
582
654
  * with a provided block
583
- * [does not call the originally provided block and calls the new #request_token block](./spec/acceptance/rest/auth_spec.rb#L344)
655
+ * [does not call the originally provided block and calls the new #request_token block](./spec/acceptance/rest/auth_spec.rb#L414)
584
656
  * #create_token_request
585
- * [uses the key ID from the client](./spec/acceptance/rest/auth_spec.rb#L360)
586
- * [uses the default TTL](./spec/acceptance/rest/auth_spec.rb#L364)
587
- * [uses the default capability](./spec/acceptance/rest/auth_spec.rb#L368)
657
+ * [uses the key ID from the client](./spec/acceptance/rest/auth_spec.rb#L430)
658
+ * [uses the default TTL](./spec/acceptance/rest/auth_spec.rb#L434)
659
+ * [uses the default capability](./spec/acceptance/rest/auth_spec.rb#L438)
588
660
  * the nonce
589
- * [is unique for every request](./spec/acceptance/rest/auth_spec.rb#L373)
590
- * [is at least 16 characters](./spec/acceptance/rest/auth_spec.rb#L378)
661
+ * [is unique for every request](./spec/acceptance/rest/auth_spec.rb#L443)
662
+ * [is at least 16 characters](./spec/acceptance/rest/auth_spec.rb#L448)
591
663
  * with option :ttl
592
- * [overrides default](./spec/acceptance/rest/auth_spec.rb#L389)
664
+ * [overrides default](./spec/acceptance/rest/auth_spec.rb#L459)
593
665
  * with option :capability
594
- * [overrides default](./spec/acceptance/rest/auth_spec.rb#L389)
666
+ * [overrides default](./spec/acceptance/rest/auth_spec.rb#L459)
595
667
  * with option :nonce
596
- * [overrides default](./spec/acceptance/rest/auth_spec.rb#L389)
668
+ * [overrides default](./spec/acceptance/rest/auth_spec.rb#L459)
597
669
  * with option :timestamp
598
- * [overrides default](./spec/acceptance/rest/auth_spec.rb#L389)
670
+ * [overrides default](./spec/acceptance/rest/auth_spec.rb#L459)
599
671
  * with option :client_id
600
- * [overrides default](./spec/acceptance/rest/auth_spec.rb#L389)
672
+ * [overrides default](./spec/acceptance/rest/auth_spec.rb#L459)
601
673
  * with additional invalid attributes
602
- * [are ignored](./spec/acceptance/rest/auth_spec.rb#L397)
674
+ * [are ignored](./spec/acceptance/rest/auth_spec.rb#L467)
603
675
  * when required fields are missing
604
- * [should raise an exception if key secret is missing](./spec/acceptance/rest/auth_spec.rb#L408)
605
- * [should raise an exception if key id is missing](./spec/acceptance/rest/auth_spec.rb#L412)
676
+ * [should raise an exception if key secret is missing](./spec/acceptance/rest/auth_spec.rb#L478)
677
+ * [should raise an exception if key id is missing](./spec/acceptance/rest/auth_spec.rb#L482)
606
678
  * with :query_time option
607
- * [queries the server for the timestamp](./spec/acceptance/rest/auth_spec.rb#L421)
679
+ * [queries the server for the timestamp](./spec/acceptance/rest/auth_spec.rb#L491)
608
680
  * with :timestamp option
609
- * [uses the provided timestamp in the token request](./spec/acceptance/rest/auth_spec.rb#L431)
681
+ * [uses the provided timestamp in the token request](./spec/acceptance/rest/auth_spec.rb#L501)
610
682
  * signing
611
- * [generates a valid HMAC](./spec/acceptance/rest/auth_spec.rb#L448)
683
+ * [generates a valid HMAC](./spec/acceptance/rest/auth_spec.rb#L518)
612
684
  * using token authentication
613
685
  * with :token_id option
614
- * [authenticates successfully using the provided :token_id](./spec/acceptance/rest/auth_spec.rb#L471)
615
- * [disallows publishing on unspecified capability channels](./spec/acceptance/rest/auth_spec.rb#L475)
616
- * [fails if timestamp is invalid](./spec/acceptance/rest/auth_spec.rb#L483)
617
- * [cannot be renewed automatically](./spec/acceptance/rest/auth_spec.rb#L491)
686
+ * [authenticates successfully using the provided :token_id](./spec/acceptance/rest/auth_spec.rb#L541)
687
+ * [disallows publishing on unspecified capability channels](./spec/acceptance/rest/auth_spec.rb#L545)
688
+ * [fails if timestamp is invalid](./spec/acceptance/rest/auth_spec.rb#L553)
689
+ * [cannot be renewed automatically](./spec/acceptance/rest/auth_spec.rb#L561)
618
690
  * when implicit as a result of using :client id
619
691
  * and requests to the Ably server are mocked
620
- * [will send a token request to the server](./spec/acceptance/rest/auth_spec.rb#L521)
692
+ * [will send a token request to the server](./spec/acceptance/rest/auth_spec.rb#L591)
621
693
  * a token is created
622
- * [before a request is made](./spec/acceptance/rest/auth_spec.rb#L530)
623
- * [when a message is published](./spec/acceptance/rest/auth_spec.rb#L534)
624
- * [with capability and TTL defaults](./spec/acceptance/rest/auth_spec.rb#L538)
694
+ * [before a request is made](./spec/acceptance/rest/auth_spec.rb#L600)
695
+ * [when a message is published](./spec/acceptance/rest/auth_spec.rb#L604)
696
+ * [with capability and TTL defaults](./spec/acceptance/rest/auth_spec.rb#L608)
625
697
  * when using an :api_key and basic auth
626
- * [#using_token_auth? is false](./spec/acceptance/rest/auth_spec.rb#L553)
627
- * [#using_basic_auth? is true](./spec/acceptance/rest/auth_spec.rb#L557)
698
+ * [#using_token_auth? is false](./spec/acceptance/rest/auth_spec.rb#L623)
699
+ * [#using_basic_auth? is true](./spec/acceptance/rest/auth_spec.rb#L627)
628
700
 
629
701
  ### Ably::Rest
630
702
  _(see [spec/acceptance/rest/base_spec.rb](./spec/acceptance/rest/base_spec.rb))_
@@ -832,41 +904,41 @@ _(see [spec/acceptance/rest/presence_spec.rb](./spec/acceptance/rest/presence_sp
832
904
  * using JSON and MsgPack protocol
833
905
  * tested against presence fixture data set up in test app
834
906
  * #get
835
- * [returns current members on the channel with their action set to :present](./spec/acceptance/rest/presence_spec.rb#L31)
907
+ * [returns current members on the channel with their action set to :present](./spec/acceptance/rest/presence_spec.rb#L30)
836
908
  * with :limit option
837
- * [returns a paged response limiting number of members per page](./spec/acceptance/rest/presence_spec.rb#L45)
909
+ * [returns a paged response limiting number of members per page](./spec/acceptance/rest/presence_spec.rb#L44)
838
910
  * #history
839
- * [returns recent presence activity](./spec/acceptance/rest/presence_spec.rb#L64)
911
+ * [returns recent presence activity](./spec/acceptance/rest/presence_spec.rb#L62)
840
912
  * with options
841
913
  * direction: :forwards
842
- * [returns recent presence activity forwards with most recent history last](./spec/acceptance/rest/presence_spec.rb#L80)
914
+ * [returns recent presence activity forwards with most recent history last](./spec/acceptance/rest/presence_spec.rb#L78)
843
915
  * direction: :backwards
844
- * [returns recent presence activity backwards with most recent history first](./spec/acceptance/rest/presence_spec.rb#L95)
916
+ * [returns recent presence activity backwards with most recent history first](./spec/acceptance/rest/presence_spec.rb#L93)
845
917
  * #history
846
918
  * with time range options
847
919
  * :start
848
920
  * with milliseconds since epoch value
849
- * [uses this value in the history request](./spec/acceptance/rest/presence_spec.rb#L140)
921
+ * [uses this value in the history request](./spec/acceptance/rest/presence_spec.rb#L138)
850
922
  * with Time object value
851
- * [converts the value to milliseconds since epoch in the hisotry request](./spec/acceptance/rest/presence_spec.rb#L150)
923
+ * [converts the value to milliseconds since epoch in the hisotry request](./spec/acceptance/rest/presence_spec.rb#L148)
852
924
  * :end
853
925
  * with milliseconds since epoch value
854
- * [uses this value in the history request](./spec/acceptance/rest/presence_spec.rb#L140)
926
+ * [uses this value in the history request](./spec/acceptance/rest/presence_spec.rb#L138)
855
927
  * with Time object value
856
- * [converts the value to milliseconds since epoch in the hisotry request](./spec/acceptance/rest/presence_spec.rb#L150)
928
+ * [converts the value to milliseconds since epoch in the hisotry request](./spec/acceptance/rest/presence_spec.rb#L148)
857
929
  * decoding
858
930
  * valid decodeable content
859
931
  * #get
860
- * [automaticaly decodes presence messages](./spec/acceptance/rest/presence_spec.rb#L208)
932
+ * [automaticaly decodes presence messages](./spec/acceptance/rest/presence_spec.rb#L206)
861
933
  * #history
862
- * [automaticaly decodes presence messages](./spec/acceptance/rest/presence_spec.rb#L225)
934
+ * [automaticaly decodes presence messages](./spec/acceptance/rest/presence_spec.rb#L223)
863
935
  * invalid data
864
936
  * #get
865
- * [returns the messages still encoded](./spec/acceptance/rest/presence_spec.rb#L256)
866
- * [logs a cipher error](./spec/acceptance/rest/presence_spec.rb#L260)
937
+ * [returns the messages still encoded](./spec/acceptance/rest/presence_spec.rb#L254)
938
+ * [logs a cipher error](./spec/acceptance/rest/presence_spec.rb#L258)
867
939
  * #history
868
- * [returns the messages still encoded](./spec/acceptance/rest/presence_spec.rb#L280)
869
- * [logs a cipher error](./spec/acceptance/rest/presence_spec.rb#L284)
940
+ * [returns the messages still encoded](./spec/acceptance/rest/presence_spec.rb#L278)
941
+ * [logs a cipher error](./spec/acceptance/rest/presence_spec.rb#L282)
870
942
 
871
943
  ### Ably::Rest::Client#stats
872
944
  _(see [spec/acceptance/rest/stats_spec.rb](./spec/acceptance/rest/stats_spec.rb))_
@@ -874,31 +946,31 @@ _(see [spec/acceptance/rest/stats_spec.rb](./spec/acceptance/rest/stats_spec.rb)
874
946
  * fetching application stats
875
947
  * by minute
876
948
  * with :from set to last interval and :limit set to 1
877
- * [retrieves only one stat](./spec/acceptance/rest/stats_spec.rb#L51)
878
- * [returns accurate all aggregated message data](./spec/acceptance/rest/stats_spec.rb#L55)
879
- * [returns accurate inbound realtime all data](./spec/acceptance/rest/stats_spec.rb#L60)
880
- * [returns accurate inbound realtime message data](./spec/acceptance/rest/stats_spec.rb#L65)
881
- * [returns accurate outbound realtime all data](./spec/acceptance/rest/stats_spec.rb#L70)
882
- * [returns accurate persisted presence all data](./spec/acceptance/rest/stats_spec.rb#L75)
883
- * [returns accurate connections all data](./spec/acceptance/rest/stats_spec.rb#L80)
884
- * [returns accurate channels all data](./spec/acceptance/rest/stats_spec.rb#L85)
885
- * [returns accurate api_requests data](./spec/acceptance/rest/stats_spec.rb#L90)
886
- * [returns accurate token_requests data](./spec/acceptance/rest/stats_spec.rb#L95)
887
- * [returns stat objects with #interval_granularity equal to :minute](./spec/acceptance/rest/stats_spec.rb#L100)
888
- * [returns stat objects with #interval_id matching :start](./spec/acceptance/rest/stats_spec.rb#L104)
889
- * [returns stat objects with #interval_time matching :start Time](./spec/acceptance/rest/stats_spec.rb#L108)
949
+ * [retrieves only one stat](./spec/acceptance/rest/stats_spec.rb#L50)
950
+ * [returns all aggregated message data](./spec/acceptance/rest/stats_spec.rb#L54)
951
+ * [returns inbound realtime all data](./spec/acceptance/rest/stats_spec.rb#L59)
952
+ * [returns inbound realtime message data](./spec/acceptance/rest/stats_spec.rb#L64)
953
+ * [returns outbound realtime all data](./spec/acceptance/rest/stats_spec.rb#L69)
954
+ * [returns persisted presence all data](./spec/acceptance/rest/stats_spec.rb#L74)
955
+ * [returns connections all data](./spec/acceptance/rest/stats_spec.rb#L79)
956
+ * [returns channels all data](./spec/acceptance/rest/stats_spec.rb#L84)
957
+ * [returns api_requests data](./spec/acceptance/rest/stats_spec.rb#L89)
958
+ * [returns token_requests data](./spec/acceptance/rest/stats_spec.rb#L94)
959
+ * [returns stat objects with #interval_granularity equal to :minute](./spec/acceptance/rest/stats_spec.rb#L99)
960
+ * [returns stat objects with #interval_id matching :start](./spec/acceptance/rest/stats_spec.rb#L103)
961
+ * [returns stat objects with #interval_time matching :start Time](./spec/acceptance/rest/stats_spec.rb#L107)
890
962
  * with :start set to first interval, :limit set to 1 and direction :forwards
891
- * [returns the first interval stats as stats are provided forwards from :start](./spec/acceptance/rest/stats_spec.rb#L118)
892
- * [returns 3 pages of stats](./spec/acceptance/rest/stats_spec.rb#L122)
963
+ * [returns the first interval stats as stats are provided forwards from :start](./spec/acceptance/rest/stats_spec.rb#L117)
964
+ * [returns 3 pages of stats](./spec/acceptance/rest/stats_spec.rb#L121)
893
965
  * with :end set to last interval, :limit set to 1 and direction :backwards
894
- * [returns the 3rd interval stats first as stats are provided backwards from :end](./spec/acceptance/rest/stats_spec.rb#L135)
895
- * [returns 3 pages of stats](./spec/acceptance/rest/stats_spec.rb#L139)
966
+ * [returns the 3rd interval stats first as stats are provided backwards from :end](./spec/acceptance/rest/stats_spec.rb#L134)
967
+ * [returns 3 pages of stats](./spec/acceptance/rest/stats_spec.rb#L138)
896
968
  * by hour
897
- * [should aggregate the stats for that period](./spec/acceptance/rest/stats_spec.rb#L163)
969
+ * [should aggregate the stats for that period](./spec/acceptance/rest/stats_spec.rb#L162)
898
970
  * by day
899
- * [should aggregate the stats for that period](./spec/acceptance/rest/stats_spec.rb#L163)
971
+ * [should aggregate the stats for that period](./spec/acceptance/rest/stats_spec.rb#L162)
900
972
  * by month
901
- * [should aggregate the stats for that period](./spec/acceptance/rest/stats_spec.rb#L163)
973
+ * [should aggregate the stats for that period](./spec/acceptance/rest/stats_spec.rb#L162)
902
974
 
903
975
  ### Ably::Rest::Client#time
904
976
  _(see [spec/acceptance/rest/time_spec.rb](./spec/acceptance/rest/time_spec.rb))_
@@ -1119,61 +1191,61 @@ _(see [spec/unit/models/message_spec.rb](./spec/unit/models/message_spec.rb))_
1119
1191
  * [prevents changes](./spec/shared/model_behaviour.rb#L76)
1120
1192
  * [dups options](./spec/shared/model_behaviour.rb#L80)
1121
1193
  * #timestamp
1122
- * [retrieves attribute :timestamp as Time object from ProtocolMessage](./spec/unit/models/message_spec.rb#L21)
1194
+ * [retrieves attribute :timestamp as Time object from ProtocolMessage](./spec/unit/models/message_spec.rb#L22)
1123
1195
  * #connection_id attribute
1124
1196
  * when this model has a connectionId attribute
1125
1197
  * but no protocol message
1126
- * [uses the model value](./spec/unit/models/message_spec.rb#L36)
1198
+ * [uses the model value](./spec/unit/models/message_spec.rb#L37)
1127
1199
  * with a protocol message with a different connectionId
1128
- * [uses the model value](./spec/unit/models/message_spec.rb#L44)
1200
+ * [uses the model value](./spec/unit/models/message_spec.rb#L45)
1129
1201
  * when this model has no connectionId attribute
1130
1202
  * and no protocol message
1131
- * [uses the model value](./spec/unit/models/message_spec.rb#L54)
1203
+ * [uses the model value](./spec/unit/models/message_spec.rb#L55)
1132
1204
  * with a protocol message with a connectionId
1133
- * [uses the model value](./spec/unit/models/message_spec.rb#L62)
1205
+ * [uses the model value](./spec/unit/models/message_spec.rb#L63)
1134
1206
  * initialized with
1135
1207
  * :name
1136
1208
  * as UTF_8 string
1137
- * [is permitted](./spec/unit/models/message_spec.rb#L89)
1138
- * [remains as UTF-8](./spec/unit/models/message_spec.rb#L93)
1209
+ * [is permitted](./spec/unit/models/message_spec.rb#L90)
1210
+ * [remains as UTF-8](./spec/unit/models/message_spec.rb#L94)
1139
1211
  * as SHIFT_JIS string
1140
- * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L101)
1141
- * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L105)
1212
+ * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L102)
1213
+ * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L106)
1142
1214
  * as ASCII_8BIT string
1143
- * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L113)
1144
- * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L117)
1215
+ * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L114)
1216
+ * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L118)
1145
1217
  * as Integer
1146
- * [raises an argument error](./spec/unit/models/message_spec.rb#L125)
1218
+ * [raises an argument error](./spec/unit/models/message_spec.rb#L126)
1147
1219
  * as Nil
1148
- * [is permitted](./spec/unit/models/message_spec.rb#L133)
1220
+ * [is permitted](./spec/unit/models/message_spec.rb#L134)
1149
1221
  * :client_id
1150
1222
  * as UTF_8 string
1151
- * [is permitted](./spec/unit/models/message_spec.rb#L89)
1152
- * [remains as UTF-8](./spec/unit/models/message_spec.rb#L93)
1223
+ * [is permitted](./spec/unit/models/message_spec.rb#L90)
1224
+ * [remains as UTF-8](./spec/unit/models/message_spec.rb#L94)
1153
1225
  * as SHIFT_JIS string
1154
- * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L101)
1155
- * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L105)
1226
+ * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L102)
1227
+ * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L106)
1156
1228
  * as ASCII_8BIT string
1157
- * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L113)
1158
- * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L117)
1229
+ * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L114)
1230
+ * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L118)
1159
1231
  * as Integer
1160
- * [raises an argument error](./spec/unit/models/message_spec.rb#L125)
1232
+ * [raises an argument error](./spec/unit/models/message_spec.rb#L126)
1161
1233
  * as Nil
1162
- * [is permitted](./spec/unit/models/message_spec.rb#L133)
1234
+ * [is permitted](./spec/unit/models/message_spec.rb#L134)
1163
1235
  * :encoding
1164
1236
  * as UTF_8 string
1165
- * [is permitted](./spec/unit/models/message_spec.rb#L89)
1166
- * [remains as UTF-8](./spec/unit/models/message_spec.rb#L93)
1237
+ * [is permitted](./spec/unit/models/message_spec.rb#L90)
1238
+ * [remains as UTF-8](./spec/unit/models/message_spec.rb#L94)
1167
1239
  * as SHIFT_JIS string
1168
- * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L101)
1169
- * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L105)
1240
+ * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L102)
1241
+ * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L106)
1170
1242
  * as ASCII_8BIT string
1171
- * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L113)
1172
- * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L117)
1243
+ * [gets converted to UTF-8](./spec/unit/models/message_spec.rb#L114)
1244
+ * [is compatible with original encoding](./spec/unit/models/message_spec.rb#L118)
1173
1245
  * as Integer
1174
- * [raises an argument error](./spec/unit/models/message_spec.rb#L125)
1246
+ * [raises an argument error](./spec/unit/models/message_spec.rb#L126)
1175
1247
  * as Nil
1176
- * [is permitted](./spec/unit/models/message_spec.rb#L133)
1248
+ * [is permitted](./spec/unit/models/message_spec.rb#L134)
1177
1249
 
1178
1250
  ### Ably::Models::PaginatedResource
1179
1251
  _(see [spec/unit/models/paginated_resource_spec.rb](./spec/unit/models/paginated_resource_spec.rb))_
@@ -1462,42 +1534,49 @@ _(see [spec/unit/models/token_spec.rb](./spec/unit/models/token_spec.rb))_
1462
1534
  ### Ably::Modules::EventEmitter
1463
1535
  _(see [spec/unit/modules/event_emitter_spec.rb](./spec/unit/modules/event_emitter_spec.rb))_
1464
1536
  * #trigger event fan out
1465
- * [should emit an event for any number of subscribers](./spec/unit/modules/event_emitter_spec.rb#L18)
1466
- * [sends only messages to matching event names](./spec/unit/modules/event_emitter_spec.rb#L27)
1537
+ * [should emit an event for any number of subscribers](./spec/unit/modules/event_emitter_spec.rb#L19)
1538
+ * [sends only messages to matching event names](./spec/unit/modules/event_emitter_spec.rb#L28)
1467
1539
  * #on subscribe to multiple events
1468
- * [with the same block](./spec/unit/modules/event_emitter_spec.rb#L59)
1540
+ * [with the same block](./spec/unit/modules/event_emitter_spec.rb#L60)
1469
1541
  * event callback changes within the callback block
1470
1542
  * when new event callbacks are added
1471
- * [is unaffected and processes the prior event callbacks once](./spec/unit/modules/event_emitter_spec.rb#L83)
1472
- * [adds them for the next emitted event](./spec/unit/modules/event_emitter_spec.rb#L89)
1543
+ * [is unaffected and processes the prior event callbacks once](./spec/unit/modules/event_emitter_spec.rb#L84)
1544
+ * [adds them for the next emitted event](./spec/unit/modules/event_emitter_spec.rb#L90)
1473
1545
  * when callbacks are removed
1474
- * [is unaffected and processes the prior event callbacks once](./spec/unit/modules/event_emitter_spec.rb#L110)
1475
- * [removes them for the next emitted event](./spec/unit/modules/event_emitter_spec.rb#L115)
1546
+ * [is unaffected and processes the prior event callbacks once](./spec/unit/modules/event_emitter_spec.rb#L111)
1547
+ * [removes them for the next emitted event](./spec/unit/modules/event_emitter_spec.rb#L116)
1548
+ * #on
1549
+ * [calls the block every time an event is emitted only](./spec/unit/modules/event_emitter_spec.rb#L129)
1550
+ * [catches exceptions in the provided block, logs the error and continues](./spec/unit/modules/event_emitter_spec.rb#L136)
1476
1551
  * #once
1477
- * [calls the block the first time an event is emitted only](./spec/unit/modules/event_emitter_spec.rb#L128)
1478
- * [does not remove other blocks after it is called](./spec/unit/modules/event_emitter_spec.rb#L135)
1552
+ * [calls the block the first time an event is emitted only](./spec/unit/modules/event_emitter_spec.rb#L158)
1553
+ * [does not remove other blocks after it is called](./spec/unit/modules/event_emitter_spec.rb#L165)
1554
+ * [catches exceptions in the provided block, logs the error and continues](./spec/unit/modules/event_emitter_spec.rb#L173)
1555
+ * #unsafe_once
1556
+ * [calls the block the first time an event is emitted only](./spec/unit/modules/event_emitter_spec.rb#L181)
1557
+ * [does not catch exceptions in provided blocks](./spec/unit/modules/event_emitter_spec.rb#L188)
1479
1558
  * #off
1480
1559
  * with event names as arguments
1481
- * [deletes matching callbacks](./spec/unit/modules/event_emitter_spec.rb#L156)
1482
- * [deletes all callbacks if not block given](./spec/unit/modules/event_emitter_spec.rb#L161)
1483
- * [continues if the block does not exist](./spec/unit/modules/event_emitter_spec.rb#L166)
1560
+ * [deletes matching callbacks](./spec/unit/modules/event_emitter_spec.rb#L206)
1561
+ * [deletes all callbacks if not block given](./spec/unit/modules/event_emitter_spec.rb#L211)
1562
+ * [continues if the block does not exist](./spec/unit/modules/event_emitter_spec.rb#L216)
1484
1563
  * without any event names
1485
- * [deletes all matching callbacks](./spec/unit/modules/event_emitter_spec.rb#L173)
1486
- * [deletes all callbacks if not block given](./spec/unit/modules/event_emitter_spec.rb#L178)
1564
+ * [deletes all matching callbacks](./spec/unit/modules/event_emitter_spec.rb#L223)
1565
+ * [deletes all callbacks if not block given](./spec/unit/modules/event_emitter_spec.rb#L228)
1487
1566
 
1488
1567
  ### Ably::Modules::StateEmitter
1489
1568
  _(see [spec/unit/modules/state_emitter_spec.rb](./spec/unit/modules/state_emitter_spec.rb))_
1490
- * [#state returns current state](./spec/unit/modules/state_emitter_spec.rb#L25)
1491
- * [#state= sets current state](./spec/unit/modules/state_emitter_spec.rb#L29)
1492
- * [#change_state sets current state](./spec/unit/modules/state_emitter_spec.rb#L33)
1569
+ * [#state returns current state](./spec/unit/modules/state_emitter_spec.rb#L28)
1570
+ * [#state= sets current state](./spec/unit/modules/state_emitter_spec.rb#L32)
1571
+ * [#change_state sets current state](./spec/unit/modules/state_emitter_spec.rb#L36)
1493
1572
  * #change_state with arguments
1494
- * [passes the arguments through to the triggered callback](./spec/unit/modules/state_emitter_spec.rb#L41)
1573
+ * [passes the arguments through to the triggered callback](./spec/unit/modules/state_emitter_spec.rb#L44)
1495
1574
  * #state?
1496
- * [returns true if state matches](./spec/unit/modules/state_emitter_spec.rb#L52)
1497
- * [returns false if state does not match](./spec/unit/modules/state_emitter_spec.rb#L56)
1575
+ * [returns true if state matches](./spec/unit/modules/state_emitter_spec.rb#L55)
1576
+ * [returns false if state does not match](./spec/unit/modules/state_emitter_spec.rb#L59)
1498
1577
  * and convenience predicates for states
1499
- * [returns true for #initializing? if state matches](./spec/unit/modules/state_emitter_spec.rb#L61)
1500
- * [returns false for #connecting? if state does not match](./spec/unit/modules/state_emitter_spec.rb#L65)
1578
+ * [returns true for #initializing? if state matches](./spec/unit/modules/state_emitter_spec.rb#L64)
1579
+ * [returns false for #connecting? if state does not match](./spec/unit/modules/state_emitter_spec.rb#L68)
1501
1580
 
1502
1581
  ### Ably::Realtime::Channel
1503
1582
  _(see [spec/unit/realtime/channel_spec.rb](./spec/unit/realtime/channel_spec.rb))_
@@ -1531,13 +1610,17 @@ _(see [spec/unit/realtime/channel_spec.rb](./spec/unit/realtime/channel_spec.rb)
1531
1610
  * [fail with unacceptable STATE event names](./spec/unit/realtime/channel_spec.rb#L124)
1532
1611
  * subscriptions
1533
1612
  * #subscribe
1534
- * [to all events](./spec/unit/realtime/channel_spec.rb#L159)
1535
- * [to specific events](./spec/unit/realtime/channel_spec.rb#L165)
1613
+ * [without a block raises an invalid ArgumentError](./spec/unit/realtime/channel_spec.rb#L162)
1614
+ * [with no event name specified subscribes the provided block to all events](./spec/unit/realtime/channel_spec.rb#L166)
1615
+ * [with a single event name subscribes that block to matching events](./spec/unit/realtime/channel_spec.rb#L172)
1616
+ * [with a multiple event name arguments subscribes that block to all of those event names](./spec/unit/realtime/channel_spec.rb#L179)
1617
+ * [with a multiple duplicate event name arguments subscribes that block to all of those unique event names once](./spec/unit/realtime/channel_spec.rb#L191)
1536
1618
  * #unsubscribe
1537
- * [to all events](./spec/unit/realtime/channel_spec.rb#L181)
1538
- * [to specific events](./spec/unit/realtime/channel_spec.rb#L187)
1539
- * [to specific non-matching events](./spec/unit/realtime/channel_spec.rb#L193)
1540
- * [all callbacks by not providing a callback](./spec/unit/realtime/channel_spec.rb#L199)
1619
+ * [with no event name specified unsubscribes that block from all events](./spec/unit/realtime/channel_spec.rb#L206)
1620
+ * [with a single event name argument unsubscribes the provided block with the matching event name](./spec/unit/realtime/channel_spec.rb#L212)
1621
+ * [with multiple event name arguments unsubscribes each of those matching event names with the provided block](./spec/unit/realtime/channel_spec.rb#L218)
1622
+ * [with a non-matching event name argument has no effect](./spec/unit/realtime/channel_spec.rb#L224)
1623
+ * [with no block argument unsubscribes all blocks for the event name argument](./spec/unit/realtime/channel_spec.rb#L230)
1541
1624
 
1542
1625
  ### Ably::Realtime::Channels
1543
1626
  _(see [spec/unit/realtime/channels_spec.rb](./spec/unit/realtime/channels_spec.rb))_
@@ -1549,7 +1632,7 @@ _(see [spec/unit/realtime/channels_spec.rb](./spec/unit/realtime/channels_spec.r
1549
1632
  * [retrieves a channel if it exists](./spec/unit/realtime/channels_spec.rb#L31)
1550
1633
  * [calls the block if channel is missing](./spec/unit/realtime/channels_spec.rb#L36)
1551
1634
  * destroying channels
1552
- * [#release detatches and then releases the channel resoures](./spec/unit/realtime/channels_spec.rb#L44)
1635
+ * [#release detaches and then releases the channel resources](./spec/unit/realtime/channels_spec.rb#L44)
1553
1636
  * is Enumerable
1554
1637
  * [allows enumeration](./spec/unit/realtime/channels_spec.rb#L61)
1555
1638
  * [provides #length](./spec/unit/realtime/channels_spec.rb#L77)
@@ -1584,29 +1667,31 @@ _(see [spec/unit/realtime/client_spec.rb](./spec/unit/realtime/client_spec.rb))_
1584
1667
  * [sets the api_key](./spec/shared/client_initializer_behaviour.rb#L103)
1585
1668
  * [sets the key_id](./spec/shared/client_initializer_behaviour.rb#L107)
1586
1669
  * [sets the key_secret](./spec/shared/client_initializer_behaviour.rb#L111)
1587
- * with token
1670
+ * with a string token key instead of options hash
1588
1671
  * [sets the token_id](./spec/shared/client_initializer_behaviour.rb#L119)
1672
+ * with token
1673
+ * [sets the token_id](./spec/shared/client_initializer_behaviour.rb#L127)
1589
1674
  * endpoint
1590
- * [defaults to production](./spec/shared/client_initializer_behaviour.rb#L125)
1675
+ * [defaults to production](./spec/shared/client_initializer_behaviour.rb#L133)
1591
1676
  * with environment option
1592
- * [uses an alternate endpoint](./spec/shared/client_initializer_behaviour.rb#L132)
1677
+ * [uses an alternate endpoint](./spec/shared/client_initializer_behaviour.rb#L140)
1593
1678
  * tls
1594
- * [defaults to TLS](./spec/shared/client_initializer_behaviour.rb#L151)
1679
+ * [defaults to TLS](./spec/shared/client_initializer_behaviour.rb#L159)
1595
1680
  * set to false
1596
- * [uses plain text](./spec/shared/client_initializer_behaviour.rb#L142)
1597
- * [uses HTTP](./spec/shared/client_initializer_behaviour.rb#L146)
1681
+ * [uses plain text](./spec/shared/client_initializer_behaviour.rb#L150)
1682
+ * [uses HTTP](./spec/shared/client_initializer_behaviour.rb#L154)
1598
1683
  * logger
1599
1684
  * default
1600
- * [uses Ruby Logger](./spec/shared/client_initializer_behaviour.rb#L158)
1601
- * [specifies Logger::ERROR log level](./spec/shared/client_initializer_behaviour.rb#L162)
1685
+ * [uses Ruby Logger](./spec/shared/client_initializer_behaviour.rb#L166)
1686
+ * [specifies Logger::ERROR log level](./spec/shared/client_initializer_behaviour.rb#L170)
1602
1687
  * with log_level :none
1603
- * [silences all logging with a NilLogger](./spec/shared/client_initializer_behaviour.rb#L170)
1688
+ * [silences all logging with a NilLogger](./spec/shared/client_initializer_behaviour.rb#L178)
1604
1689
  * with custom logger and log_level
1605
- * [uses the custom logger](./spec/shared/client_initializer_behaviour.rb#L188)
1606
- * [sets the custom log level](./spec/shared/client_initializer_behaviour.rb#L192)
1690
+ * [uses the custom logger](./spec/shared/client_initializer_behaviour.rb#L196)
1691
+ * [sets the custom log level](./spec/shared/client_initializer_behaviour.rb#L200)
1607
1692
  * delegators
1608
- * [delegates :client_id to .auth](./spec/shared/client_initializer_behaviour.rb#L202)
1609
- * [delegates :auth_options to .auth](./spec/shared/client_initializer_behaviour.rb#L207)
1693
+ * [delegates :client_id to .auth](./spec/shared/client_initializer_behaviour.rb#L210)
1694
+ * [delegates :auth_options to .auth](./spec/shared/client_initializer_behaviour.rb#L215)
1610
1695
  * delegation to the REST Client
1611
1696
  * [passes on the options to the initializer](./spec/unit/realtime/client_spec.rb#L15)
1612
1697
  * for attribute
@@ -1628,18 +1713,64 @@ _(see [spec/unit/realtime/presence_spec.rb](./spec/unit/realtime/presence_spec.r
1628
1713
  * [fail with unacceptable STATE event names](./spec/unit/realtime/presence_spec.rb#L19)
1629
1714
  * subscriptions
1630
1715
  * #subscribe
1631
- * [to all presence state actions](./spec/unit/realtime/presence_spec.rb#L60)
1632
- * [to specific presence state actions](./spec/unit/realtime/presence_spec.rb#L66)
1716
+ * [without a block raises an invalid ArgumentError](./spec/unit/realtime/presence_spec.rb#L62)
1717
+ * [with no action specified subscribes the provided block to all action](./spec/unit/realtime/presence_spec.rb#L66)
1718
+ * [with a single action argument subscribes that block to matching actions](./spec/unit/realtime/presence_spec.rb#L72)
1719
+ * [with a multiple action arguments subscribes that block to all of those actions](./spec/unit/realtime/presence_spec.rb#L79)
1720
+ * [with a multiple duplicate action arguments subscribes that block to all of those unique actions once](./spec/unit/realtime/presence_spec.rb#L91)
1633
1721
  * #unsubscribe
1634
- * [to all presence state actions](./spec/unit/realtime/presence_spec.rb#L86)
1635
- * [to specific presence state actions](./spec/unit/realtime/presence_spec.rb#L92)
1636
- * [to specific non-matching presence state actions](./spec/unit/realtime/presence_spec.rb#L98)
1637
- * [all callbacks by not providing a callback](./spec/unit/realtime/presence_spec.rb#L104)
1722
+ * [with no action specified unsubscribes that block from all events](./spec/unit/realtime/presence_spec.rb#L106)
1723
+ * [with a single action argument unsubscribes the provided block with the matching action](./spec/unit/realtime/presence_spec.rb#L112)
1724
+ * [with multiple action arguments unsubscribes each of those matching actions with the provided block](./spec/unit/realtime/presence_spec.rb#L118)
1725
+ * [with a non-matching action argument has no effect](./spec/unit/realtime/presence_spec.rb#L124)
1726
+ * [with no block argument unsubscribes all blocks for the action argument](./spec/unit/realtime/presence_spec.rb#L130)
1638
1727
 
1639
1728
  ### Ably::Realtime
1640
1729
  _(see [spec/unit/realtime/realtime_spec.rb](./spec/unit/realtime/realtime_spec.rb))_
1641
1730
  * [constructor returns an Ably::Realtime::Client](./spec/unit/realtime/realtime_spec.rb#L6)
1642
1731
 
1732
+ ### Ably::Models::ProtocolMessage
1733
+ _(see [spec/unit/realtime/safe_deferrable_spec.rb](./spec/unit/realtime/safe_deferrable_spec.rb))_
1734
+ * behaves like a safe Deferrable
1735
+ * #errback
1736
+ * [adds a callback that is called when #fail is called](./spec/shared/safe_deferrable_behaviour.rb#L15)
1737
+ * [catches exceptions in the callback and logs the error to the logger](./spec/shared/safe_deferrable_behaviour.rb#L22)
1738
+ * #fail
1739
+ * [calls the callbacks defined with #errback, but not the ones added for success #callback](./spec/shared/safe_deferrable_behaviour.rb#L32)
1740
+ * #callback
1741
+ * [adds a callback that is called when #succed is called](./spec/shared/safe_deferrable_behaviour.rb#L44)
1742
+ * [catches exceptions in the callback and logs the error to the logger](./spec/shared/safe_deferrable_behaviour.rb#L51)
1743
+ * #succeed
1744
+ * [calls the callbacks defined with #callback, but not the ones added for #errback](./spec/shared/safe_deferrable_behaviour.rb#L61)
1745
+
1746
+ ### Ably::Models::Message
1747
+ _(see [spec/unit/realtime/safe_deferrable_spec.rb](./spec/unit/realtime/safe_deferrable_spec.rb))_
1748
+ * behaves like a safe Deferrable
1749
+ * #errback
1750
+ * [adds a callback that is called when #fail is called](./spec/shared/safe_deferrable_behaviour.rb#L15)
1751
+ * [catches exceptions in the callback and logs the error to the logger](./spec/shared/safe_deferrable_behaviour.rb#L22)
1752
+ * #fail
1753
+ * [calls the callbacks defined with #errback, but not the ones added for success #callback](./spec/shared/safe_deferrable_behaviour.rb#L32)
1754
+ * #callback
1755
+ * [adds a callback that is called when #succed is called](./spec/shared/safe_deferrable_behaviour.rb#L44)
1756
+ * [catches exceptions in the callback and logs the error to the logger](./spec/shared/safe_deferrable_behaviour.rb#L51)
1757
+ * #succeed
1758
+ * [calls the callbacks defined with #callback, but not the ones added for #errback](./spec/shared/safe_deferrable_behaviour.rb#L61)
1759
+
1760
+ ### Ably::Models::PresenceMessage
1761
+ _(see [spec/unit/realtime/safe_deferrable_spec.rb](./spec/unit/realtime/safe_deferrable_spec.rb))_
1762
+ * behaves like a safe Deferrable
1763
+ * #errback
1764
+ * [adds a callback that is called when #fail is called](./spec/shared/safe_deferrable_behaviour.rb#L15)
1765
+ * [catches exceptions in the callback and logs the error to the logger](./spec/shared/safe_deferrable_behaviour.rb#L22)
1766
+ * #fail
1767
+ * [calls the callbacks defined with #errback, but not the ones added for success #callback](./spec/shared/safe_deferrable_behaviour.rb#L32)
1768
+ * #callback
1769
+ * [adds a callback that is called when #succed is called](./spec/shared/safe_deferrable_behaviour.rb#L44)
1770
+ * [catches exceptions in the callback and logs the error to the logger](./spec/shared/safe_deferrable_behaviour.rb#L51)
1771
+ * #succeed
1772
+ * [calls the callbacks defined with #callback, but not the ones added for #errback](./spec/shared/safe_deferrable_behaviour.rb#L61)
1773
+
1643
1774
  ### Ably::Rest::Channels
1644
1775
  _(see [spec/unit/rest/channel_spec.rb](./spec/unit/rest/channel_spec.rb))_
1645
1776
  * #initializer
@@ -1713,29 +1844,31 @@ _(see [spec/unit/rest/client_spec.rb](./spec/unit/rest/client_spec.rb))_
1713
1844
  * [sets the api_key](./spec/shared/client_initializer_behaviour.rb#L103)
1714
1845
  * [sets the key_id](./spec/shared/client_initializer_behaviour.rb#L107)
1715
1846
  * [sets the key_secret](./spec/shared/client_initializer_behaviour.rb#L111)
1716
- * with token
1847
+ * with a string token key instead of options hash
1717
1848
  * [sets the token_id](./spec/shared/client_initializer_behaviour.rb#L119)
1849
+ * with token
1850
+ * [sets the token_id](./spec/shared/client_initializer_behaviour.rb#L127)
1718
1851
  * endpoint
1719
- * [defaults to production](./spec/shared/client_initializer_behaviour.rb#L125)
1852
+ * [defaults to production](./spec/shared/client_initializer_behaviour.rb#L133)
1720
1853
  * with environment option
1721
- * [uses an alternate endpoint](./spec/shared/client_initializer_behaviour.rb#L132)
1854
+ * [uses an alternate endpoint](./spec/shared/client_initializer_behaviour.rb#L140)
1722
1855
  * tls
1723
- * [defaults to TLS](./spec/shared/client_initializer_behaviour.rb#L151)
1856
+ * [defaults to TLS](./spec/shared/client_initializer_behaviour.rb#L159)
1724
1857
  * set to false
1725
- * [uses plain text](./spec/shared/client_initializer_behaviour.rb#L142)
1726
- * [uses HTTP](./spec/shared/client_initializer_behaviour.rb#L146)
1858
+ * [uses plain text](./spec/shared/client_initializer_behaviour.rb#L150)
1859
+ * [uses HTTP](./spec/shared/client_initializer_behaviour.rb#L154)
1727
1860
  * logger
1728
1861
  * default
1729
- * [uses Ruby Logger](./spec/shared/client_initializer_behaviour.rb#L158)
1730
- * [specifies Logger::ERROR log level](./spec/shared/client_initializer_behaviour.rb#L162)
1862
+ * [uses Ruby Logger](./spec/shared/client_initializer_behaviour.rb#L166)
1863
+ * [specifies Logger::ERROR log level](./spec/shared/client_initializer_behaviour.rb#L170)
1731
1864
  * with log_level :none
1732
- * [silences all logging with a NilLogger](./spec/shared/client_initializer_behaviour.rb#L170)
1865
+ * [silences all logging with a NilLogger](./spec/shared/client_initializer_behaviour.rb#L178)
1733
1866
  * with custom logger and log_level
1734
- * [uses the custom logger](./spec/shared/client_initializer_behaviour.rb#L188)
1735
- * [sets the custom log level](./spec/shared/client_initializer_behaviour.rb#L192)
1867
+ * [uses the custom logger](./spec/shared/client_initializer_behaviour.rb#L196)
1868
+ * [sets the custom log level](./spec/shared/client_initializer_behaviour.rb#L200)
1736
1869
  * delegators
1737
- * [delegates :client_id to .auth](./spec/shared/client_initializer_behaviour.rb#L202)
1738
- * [delegates :auth_options to .auth](./spec/shared/client_initializer_behaviour.rb#L207)
1870
+ * [delegates :client_id to .auth](./spec/shared/client_initializer_behaviour.rb#L210)
1871
+ * [delegates :auth_options to .auth](./spec/shared/client_initializer_behaviour.rb#L215)
1739
1872
  * initializer options
1740
1873
  * TLS
1741
1874
  * disabled
@@ -1789,6 +1922,6 @@ _(see [spec/unit/util/pub_sub_spec.rb](./spec/unit/util/pub_sub_spec.rb))_
1789
1922
 
1790
1923
  ## Test summary
1791
1924
 
1792
- * Passing tests: 864
1793
- * Pending tests: 11
1925
+ * Passing tests: 942
1926
+ * Pending tests: 7
1794
1927
  * Failing tests: 0