ably 0.8.8 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/LICENSE +2 -2
- data/README.md +81 -20
- data/SPEC.md +235 -178
- data/lib/ably/auth.rb +1 -1
- data/lib/ably/exceptions.rb +10 -1
- data/lib/ably/models/cipher_params.rb +114 -0
- data/lib/ably/models/connection_details.rb +8 -6
- data/lib/ably/models/error_info.rb +3 -3
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +27 -20
- data/lib/ably/models/message.rb +15 -15
- data/lib/ably/models/message_encoders/cipher.rb +8 -7
- data/lib/ably/models/presence_message.rb +17 -17
- data/lib/ably/models/protocol_message.rb +26 -19
- data/lib/ably/models/stats.rb +15 -15
- data/lib/ably/models/token_details.rb +14 -12
- data/lib/ably/models/token_request.rb +16 -14
- data/lib/ably/modules/async_wrapper.rb +1 -1
- data/lib/ably/modules/encodeable.rb +10 -10
- data/lib/ably/modules/model_common.rb +13 -5
- data/lib/ably/realtime/channel.rb +1 -2
- data/lib/ably/realtime/presence.rb +29 -58
- data/lib/ably/realtime/presence/members_map.rb +2 -2
- data/lib/ably/rest/channel.rb +1 -2
- data/lib/ably/rest/middleware/exceptions.rb +14 -4
- data/lib/ably/rest/presence.rb +3 -1
- data/lib/ably/util/crypto.rb +50 -40
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/message_spec.rb +20 -20
- data/spec/acceptance/realtime/presence_history_spec.rb +7 -7
- data/spec/acceptance/realtime/presence_spec.rb +65 -77
- data/spec/acceptance/rest/auth_spec.rb +8 -8
- data/spec/acceptance/rest/base_spec.rb +4 -4
- data/spec/acceptance/rest/channel_spec.rb +1 -1
- data/spec/acceptance/rest/client_spec.rb +1 -1
- data/spec/acceptance/rest/encoders_spec.rb +4 -4
- data/spec/acceptance/rest/message_spec.rb +15 -15
- data/spec/acceptance/rest/presence_spec.rb +4 -4
- data/spec/shared/model_behaviour.rb +7 -7
- data/spec/unit/models/cipher_params_spec.rb +140 -0
- data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +15 -8
- data/spec/unit/models/message_encoders/cipher_spec.rb +28 -22
- data/spec/unit/models/message_encoders/json_spec.rb +24 -0
- data/spec/unit/models/protocol_message_spec.rb +3 -3
- data/spec/unit/util/crypto_spec.rb +50 -17
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cd4a525c4afb786a1994c05d636351ad5440585
|
4
|
+
data.tar.gz: eed7ec593d7bfeb68d5b7663bd438549d30f8c9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b530e68c8e7f13cadd783e43061d1f52230aa60e7744714635e9c097753ef84ce9491016a1fa2ee9718c587a0f8d5a8cec4b554b85b646291d8e04a7f434fea0
|
7
|
+
data.tar.gz: 1a6fc49f90ce35216ba8290acad13e80f7d4b62f5a88d8658b11bed27261708b290a2bf509b079c78f3fc1858d502f9c05a187bd2006def26c43519779280ab4
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,27 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [v0.8.
|
3
|
+
## [v0.8.4](https://github.com/ably/ably-ruby/tree/v0.8.9) (2015-03-01)
|
4
4
|
|
5
|
-
[Full Changelog](https://github.com/ably/ably-ruby/compare/v0.8.7...v0.8.
|
5
|
+
[Full Changelog](https://github.com/ably/ably-ruby/compare/v0.8.7...v0.8.9)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- Support enter\(data\) [\#79](https://github.com/ably/ably-ruby/issues/79)
|
10
|
+
|
11
|
+
- Update documentation to hide private API methods [\#77](https://github.com/ably/ably-ruby/issues/77)
|
6
12
|
|
7
13
|
**Closed issues:**
|
8
14
|
|
15
|
+
- New Crypto Spec [\#80](https://github.com/ably/ably-ruby/issues/80)
|
16
|
+
|
9
17
|
- Support :key in ClientOptions and deprecate :api\_key [\#73](https://github.com/ably/ably-ruby/issues/73)
|
10
18
|
|
19
|
+
**Merged pull requests:**
|
20
|
+
|
21
|
+
- Various fixes for open issues [\#82](https://github.com/ably/ably-ruby/pull/82) ([mattheworiordan](https://github.com/mattheworiordan))
|
22
|
+
|
23
|
+
- Encryption spec update [\#81](https://github.com/ably/ably-ruby/pull/81) ([mattheworiordan](https://github.com/mattheworiordan))
|
24
|
+
|
11
25
|
## [v0.8.7](https://github.com/ably/ably-ruby/tree/v0.8.7) (2015-12-31)
|
12
26
|
|
13
27
|
[Full Changelog](https://github.com/ably/ably-ruby/compare/v0.8.6...v0.8.7)
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -38,7 +38,7 @@ EventMachine.run do
|
|
38
38
|
end
|
39
39
|
```
|
40
40
|
|
41
|
-
All examples assume a client has been created
|
41
|
+
All examples assume a client has been created using one of the following:
|
42
42
|
|
43
43
|
```ruby
|
44
44
|
# basic auth with an API key
|
@@ -48,6 +48,8 @@ client = Ably::Realtime.new(key: 'xxxxx')
|
|
48
48
|
client = Ably::Realtime.new(token: 'xxxxx')
|
49
49
|
```
|
50
50
|
|
51
|
+
If you do not have an API key, [sign up for a free API key now](https://www.ably.io/signup)
|
52
|
+
|
51
53
|
### Connection
|
52
54
|
|
53
55
|
Successful connection:
|
@@ -67,20 +69,29 @@ connection_result.errback = Proc.new do
|
|
67
69
|
end
|
68
70
|
```
|
69
71
|
|
72
|
+
Subscribing to connection state changes:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
client.connection.on do |state_change|
|
76
|
+
state_change.current #=> :connected
|
77
|
+
state_change.previous #=> :connecting
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
70
81
|
### Subscribing to a channel
|
71
82
|
|
72
|
-
Given:
|
83
|
+
Given a channel is created as follows:
|
73
84
|
|
74
85
|
```ruby
|
75
|
-
channel = client.
|
86
|
+
channel = client.channels.get('test')
|
76
87
|
```
|
77
88
|
|
78
89
|
Subscribe to all events:
|
79
90
|
|
80
91
|
```ruby
|
81
92
|
channel.subscribe do |message|
|
82
|
-
message
|
83
|
-
message
|
93
|
+
message.name #=> "greeting"
|
94
|
+
message.data #=> "Hello World!"
|
84
95
|
end
|
85
96
|
```
|
86
97
|
|
@@ -88,12 +99,12 @@ Only certain events:
|
|
88
99
|
|
89
100
|
```ruby
|
90
101
|
channel.subscribe('myEvent') do |message|
|
91
|
-
message
|
92
|
-
message
|
102
|
+
message.name #=> "myEvent"
|
103
|
+
message.data #=> "myData"
|
93
104
|
end
|
94
105
|
```
|
95
106
|
|
96
|
-
### Publishing to a channel
|
107
|
+
### Publishing a message to a channel
|
97
108
|
|
98
109
|
```ruby
|
99
110
|
channel.publish('greeting', 'Hello World!')
|
@@ -107,7 +118,9 @@ channel.history do |messages_page|
|
|
107
118
|
messages_page.items.first # #<Ably::Models::Message ...>
|
108
119
|
messages_page.items.first.data # payload for the message
|
109
120
|
messages_page.items.length # number of messages in the current page of history
|
110
|
-
messages_page.next
|
121
|
+
messages_page.next do |next_page|
|
122
|
+
next_page #=> the next page => #<Ably::Models::PaginatedResult ...>
|
123
|
+
end
|
111
124
|
messages_page.has_next? # false, there are more pages
|
112
125
|
end
|
113
126
|
```
|
@@ -115,8 +128,18 @@ end
|
|
115
128
|
### Presence on a channel
|
116
129
|
|
117
130
|
```ruby
|
118
|
-
channel.presence.enter(data: '
|
119
|
-
presence.get
|
131
|
+
channel.presence.enter(data: 'metadata') do |presence|
|
132
|
+
presence.get do |members|
|
133
|
+
members #=> [Array of members present]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
### Subscribing to presence events
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
channel.presence.subscribe do |member|
|
142
|
+
member #=> { action: :enter, client_id: 'bob' }
|
120
143
|
end
|
121
144
|
```
|
122
145
|
|
@@ -127,10 +150,26 @@ channel.presence.history do |presence_page|
|
|
127
150
|
presence_page.items.first.action # Any of :enter, :update or :leave
|
128
151
|
presence_page.items.first.client_id # client ID of member
|
129
152
|
presence_page.items.first.data # optional data payload of member
|
130
|
-
presence_page.next
|
153
|
+
presence_page.next do |next_page|
|
154
|
+
next_page #=> the next page => #<Ably::Models::PaginatedResult ...>
|
155
|
+
end
|
156
|
+
presence_page.has_next? # false, there are more pages
|
131
157
|
end
|
132
158
|
```
|
133
159
|
|
160
|
+
### Symmetric end-to-end encrypted payloads on a channel
|
161
|
+
|
162
|
+
When a 128 bit or 256 bit key is provided to the library, all payloads are encrypted and decrypted automatically using that key on the channel. The secret key is never transmitted to Ably and thus it is the developer's responsibility to distribute a secret key to both publishers and subscribers.
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
secret_key = Ably::Util::Crypto.generate_random_key
|
166
|
+
channel = client.channels.get('test', cipher: { key: secret_key })
|
167
|
+
channel.subscribe do |message|
|
168
|
+
message.data #=> "sensitive data (encrypted before being published)"
|
169
|
+
end
|
170
|
+
channel.publish "name (not encrypted)", "sensitive data (encrypted before being published)"
|
171
|
+
```
|
172
|
+
|
134
173
|
## Using the REST API
|
135
174
|
|
136
175
|
### Introduction
|
@@ -160,7 +199,7 @@ messages_page.next # retrieves the next page => #<Ably::Models::PaginatedResult
|
|
160
199
|
messages_page.has_next? # false, there are more pages
|
161
200
|
```
|
162
201
|
|
163
|
-
###
|
202
|
+
### Current presence members on a channel
|
164
203
|
|
165
204
|
```ruby
|
166
205
|
members_page = channel.presence.get # => #<Ably::Models::PaginatedResult ...>
|
@@ -170,7 +209,7 @@ members_page.next # retrieves the next page => #<Ably::Models::PaginatedResult .
|
|
170
209
|
members_page.has_next? # false, there are more pages
|
171
210
|
```
|
172
211
|
|
173
|
-
### Querying the
|
212
|
+
### Querying the presence history
|
174
213
|
|
175
214
|
```ruby
|
176
215
|
presence_page = channel.presence.history #=> #<Ably::Models::PaginatedResult ...>
|
@@ -179,22 +218,44 @@ presence_page.items.first.client_id # client ID of first member
|
|
179
218
|
presence_page.next # retrieves the next page => #<Ably::Models::PaginatedResult ...>
|
180
219
|
```
|
181
220
|
|
182
|
-
###
|
221
|
+
### Symmetric end-to-end encrypted payloads on a channel
|
222
|
+
|
223
|
+
When a 128 bit or 256 bit key is provided to the library, all payloads are encrypted and decrypted automatically using that key on the channel. The secret key is never transmitted to Ably and thus it is the developer's responsibility to distribute a secret key to both publishers and subscribers.
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
secret_key = Ably::Util::Crypto.generate_random_key
|
227
|
+
channel = client.channels.get('test', cipher: { key: secret_key })
|
228
|
+
channel.publish nil, "sensitive data" # data will be encrypted before publish
|
229
|
+
messages_page = channel.history
|
230
|
+
messages_page.first.data #=> "sensitive data"
|
231
|
+
```
|
232
|
+
|
233
|
+
### Generate Token
|
234
|
+
|
235
|
+
Tokens are issued by Ably and are readily usable by any client to connect to Ably:
|
183
236
|
|
184
237
|
```ruby
|
185
238
|
token_details = client.auth.request_token
|
186
239
|
# => #<Ably::Models::TokenDetails ...>
|
187
240
|
token_details.token # => "xVLyHw.CLchevH3hF....MDh9ZC_Q"
|
188
|
-
client = Ably::Rest.new(token: token_details
|
241
|
+
client = Ably::Rest.new(token: token_details)
|
242
|
+
```
|
189
243
|
|
190
|
-
|
244
|
+
### Generate a TokenRequest
|
245
|
+
|
246
|
+
Token requests are issued by your servers and signed using your private API key. This is the preferred method of authentication as no secrets are ever shared, and the token request can be issued to trusted clients without communicating with Ably.
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
token_request = client.auth.create_token_request(ttl: 3600, client_id: 'jim')
|
191
250
|
# => {"id"=>...,
|
192
|
-
# "clientId"=>
|
251
|
+
# "clientId"=>"jim",
|
193
252
|
# "ttl"=>3600,
|
194
253
|
# "timestamp"=>...,
|
195
254
|
# "capability"=>"{\"*\":[\"*\"]}",
|
196
255
|
# "nonce"=>...,
|
197
256
|
# "mac"=>...}
|
257
|
+
|
258
|
+
client = Ably::Rest.new(token: token_request)
|
198
259
|
```
|
199
260
|
|
200
261
|
### Fetching your application's stats
|
@@ -213,7 +274,7 @@ client.time #=> 2013-12-12 14:23:34 +0000
|
|
213
274
|
|
214
275
|
## Dependencies
|
215
276
|
|
216
|
-
If you only need to use the REST features of this library and do not want EventMachine as a dependency, then you should
|
277
|
+
If you only need to use the REST features of this library and do not want EventMachine as a dependency, then you should consider using the [Ably Ruby REST gem](https://rubygems.org/gems/ably-rest).
|
217
278
|
|
218
279
|
## Support, feedback and troubleshooting
|
219
280
|
|
@@ -234,4 +295,4 @@ To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANG
|
|
234
295
|
|
235
296
|
## License
|
236
297
|
|
237
|
-
Copyright (c)
|
298
|
+
Copyright (c) 2016 Ably Real-time Ltd, Licensed under the Apache License, Version 2.0. Refer to [LICENSE](LICENSE) for the license terms.
|
data/SPEC.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Ably Realtime & REST Client Library 0.8.
|
1
|
+
# Ably Realtime & REST Client Library 0.8.9 Specification
|
2
2
|
|
3
3
|
### Ably::Realtime::Auth
|
4
4
|
_(see [spec/acceptance/realtime/auth_spec.rb](./spec/acceptance/realtime/auth_spec.rb))_
|
@@ -431,25 +431,25 @@ _(see [spec/acceptance/realtime/connection_failures_spec.rb](./spec/acceptance/r
|
|
431
431
|
* [emits any error received from Ably but leaves the channels attached](./spec/acceptance/realtime/connection_failures_spec.rb#L452)
|
432
432
|
* [retains channel subscription state](./spec/acceptance/realtime/connection_failures_spec.rb#L483)
|
433
433
|
* when messages were published whilst the client was disconnected
|
434
|
-
* [receives the messages published whilst offline](./spec/acceptance/realtime/connection_failures_spec.rb#
|
434
|
+
* [receives the messages published whilst offline](./spec/acceptance/realtime/connection_failures_spec.rb#L511)
|
435
435
|
* when failing to resume
|
436
436
|
* because the connection_key is not or no longer valid
|
437
|
-
* [updates the connection_id and connection_key](./spec/acceptance/realtime/connection_failures_spec.rb#
|
438
|
-
* [detaches all channels](./spec/acceptance/realtime/connection_failures_spec.rb#
|
439
|
-
* [emits an error on the channel and sets the error reason](./spec/acceptance/realtime/connection_failures_spec.rb#
|
437
|
+
* [updates the connection_id and connection_key](./spec/acceptance/realtime/connection_failures_spec.rb#L554)
|
438
|
+
* [detaches all channels](./spec/acceptance/realtime/connection_failures_spec.rb#L569)
|
439
|
+
* [emits an error on the channel and sets the error reason](./spec/acceptance/realtime/connection_failures_spec.rb#L589)
|
440
440
|
* fallback host feature
|
441
441
|
* with custom realtime websocket host option
|
442
|
-
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#
|
442
|
+
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L629)
|
443
443
|
* with custom realtime websocket port option
|
444
|
-
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#
|
444
|
+
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L647)
|
445
445
|
* with non-production environment
|
446
|
-
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#
|
446
|
+
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L666)
|
447
447
|
* with production environment
|
448
448
|
* when the Internet is down
|
449
|
-
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#
|
449
|
+
* [never uses a fallback host](./spec/acceptance/realtime/connection_failures_spec.rb#L696)
|
450
450
|
* when the Internet is up
|
451
|
-
* [uses a fallback host on every subsequent disconnected attempt until suspended](./spec/acceptance/realtime/connection_failures_spec.rb#
|
452
|
-
* [uses the primary host when suspended, and a fallback host on every subsequent suspended attempt](./spec/acceptance/realtime/connection_failures_spec.rb#
|
451
|
+
* [uses a fallback host on every subsequent disconnected attempt until suspended](./spec/acceptance/realtime/connection_failures_spec.rb#L716)
|
452
|
+
* [uses the primary host when suspended, and a fallback host on every subsequent suspended attempt](./spec/acceptance/realtime/connection_failures_spec.rb#L735)
|
453
453
|
|
454
454
|
### Ably::Realtime::Connection
|
455
455
|
_(see [spec/acceptance/realtime/connection_spec.rb](./spec/acceptance/realtime/connection_spec.rb))_
|
@@ -554,69 +554,73 @@ _(see [spec/acceptance/realtime/connection_spec.rb](./spec/acceptance/realtime/c
|
|
554
554
|
* when ping times out
|
555
555
|
* [logs a warning](./spec/acceptance/realtime/connection_spec.rb#L781)
|
556
556
|
* [yields to the block with a nil value](./spec/acceptance/realtime/connection_spec.rb#L791)
|
557
|
+
* #details
|
558
|
+
* [is nil before connected](./spec/acceptance/realtime/connection_spec.rb#L806)
|
559
|
+
* [contains the ConnectionDetails object once connected](./spec/acceptance/realtime/connection_spec.rb#L813)
|
560
|
+
* [contains the new ConnectionDetails object once a subsequent connection is created](./spec/acceptance/realtime/connection_spec.rb#L822)
|
557
561
|
* recovery
|
558
562
|
* #recovery_key
|
559
|
-
* [is composed of connection key and serial that is kept up to date with each message ACK received](./spec/acceptance/realtime/connection_spec.rb#
|
560
|
-
* [is available when connection is in one of the states: connecting, connected, disconnected, suspended, failed](./spec/acceptance/realtime/connection_spec.rb#
|
561
|
-
* [is nil when connection is explicitly CLOSED](./spec/acceptance/realtime/connection_spec.rb#
|
563
|
+
* [is composed of connection key and serial that is kept up to date with each message ACK received](./spec/acceptance/realtime/connection_spec.rb#L864)
|
564
|
+
* [is available when connection is in one of the states: connecting, connected, disconnected, suspended, failed](./spec/acceptance/realtime/connection_spec.rb#L887)
|
565
|
+
* [is nil when connection is explicitly CLOSED](./spec/acceptance/realtime/connection_spec.rb#L916)
|
562
566
|
* opening a new connection using a recently disconnected connection's #recovery_key
|
563
567
|
* connection#id and connection#key after recovery
|
564
|
-
* [remains the same](./spec/acceptance/realtime/connection_spec.rb#
|
568
|
+
* [remains the same for id and party for key](./spec/acceptance/realtime/connection_spec.rb#L928)
|
565
569
|
* when messages have been sent whilst the old connection is disconnected
|
566
570
|
* the new connection
|
567
|
-
* [recovers server-side queued messages](./spec/acceptance/realtime/connection_spec.rb#
|
571
|
+
* [recovers server-side queued messages](./spec/acceptance/realtime/connection_spec.rb#L970)
|
568
572
|
* with :recover option
|
569
573
|
* with invalid syntax
|
570
|
-
* [raises an exception](./spec/acceptance/realtime/connection_spec.rb#
|
574
|
+
* [raises an exception](./spec/acceptance/realtime/connection_spec.rb#L996)
|
571
575
|
* with invalid formatted value sent to server
|
572
|
-
* [emits a fatal error on the connection object, sets the #error_reason and disconnects](./spec/acceptance/realtime/connection_spec.rb#
|
576
|
+
* [emits a fatal error on the connection object, sets the #error_reason and disconnects](./spec/acceptance/realtime/connection_spec.rb#L1005)
|
573
577
|
* with expired (missing) value sent to server
|
574
|
-
* [emits an error on the connection object, sets the #error_reason, yet will connect anyway](./spec/acceptance/realtime/connection_spec.rb#
|
578
|
+
* [emits an error on the connection object, sets the #error_reason, yet will connect anyway](./spec/acceptance/realtime/connection_spec.rb#L1020)
|
575
579
|
* with many connections simultaneously
|
576
|
-
* [opens each with a unique connection#id and connection#key](./spec/acceptance/realtime/connection_spec.rb#
|
580
|
+
* [opens each with a unique connection#id and connection#key](./spec/acceptance/realtime/connection_spec.rb#L1039)
|
577
581
|
* when a state transition is unsupported
|
578
|
-
* [emits a InvalidStateChange](./spec/acceptance/realtime/connection_spec.rb#
|
582
|
+
* [emits a InvalidStateChange](./spec/acceptance/realtime/connection_spec.rb#L1059)
|
579
583
|
* protocol failure
|
580
584
|
* receiving an invalid ProtocolMessage
|
581
|
-
* [emits an error on the connection and logs a fatal error message](./spec/acceptance/realtime/connection_spec.rb#
|
585
|
+
* [emits an error on the connection and logs a fatal error message](./spec/acceptance/realtime/connection_spec.rb#L1075)
|
582
586
|
* undocumented method
|
583
587
|
* #internet_up?
|
584
|
-
* [returns a Deferrable](./spec/acceptance/realtime/connection_spec.rb#
|
588
|
+
* [returns a Deferrable](./spec/acceptance/realtime/connection_spec.rb#L1091)
|
585
589
|
* internet up URL protocol
|
586
590
|
* when using TLS for the connection
|
587
|
-
* [uses TLS for the Internet check to https://internet-up.ably-realtime.com/is-the-internet-up.txt](./spec/acceptance/realtime/connection_spec.rb#
|
591
|
+
* [uses TLS for the Internet check to https://internet-up.ably-realtime.com/is-the-internet-up.txt](./spec/acceptance/realtime/connection_spec.rb#L1102)
|
588
592
|
* when using a non-secured connection
|
589
|
-
* [uses TLS for the Internet check to http://internet-up.ably-realtime.com/is-the-internet-up.txt](./spec/acceptance/realtime/connection_spec.rb#
|
593
|
+
* [uses TLS for the Internet check to http://internet-up.ably-realtime.com/is-the-internet-up.txt](./spec/acceptance/realtime/connection_spec.rb#L1112)
|
590
594
|
* when the Internet is up
|
591
|
-
* [calls the block with true](./spec/acceptance/realtime/connection_spec.rb#
|
592
|
-
* [calls the success callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#
|
595
|
+
* [calls the block with true](./spec/acceptance/realtime/connection_spec.rb#L1143)
|
596
|
+
* [calls the success callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#L1150)
|
593
597
|
* with a TLS connection
|
594
|
-
* [checks the Internet up URL over TLS](./spec/acceptance/realtime/connection_spec.rb#
|
598
|
+
* [checks the Internet up URL over TLS](./spec/acceptance/realtime/connection_spec.rb#L1126)
|
595
599
|
* with a non-TLS connection
|
596
|
-
* [checks the Internet up URL over TLS](./spec/acceptance/realtime/connection_spec.rb#
|
600
|
+
* [checks the Internet up URL over TLS](./spec/acceptance/realtime/connection_spec.rb#L1136)
|
597
601
|
* when the Internet is down
|
598
|
-
* [calls the block with false](./spec/acceptance/realtime/connection_spec.rb#
|
599
|
-
* [calls the failure callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#
|
602
|
+
* [calls the block with false](./spec/acceptance/realtime/connection_spec.rb#L1165)
|
603
|
+
* [calls the failure callback of the Deferrable](./spec/acceptance/realtime/connection_spec.rb#L1172)
|
600
604
|
* state change side effects
|
601
605
|
* when connection enters the :disconnected state
|
602
|
-
* [queues messages to be sent and all channels remain attached](./spec/acceptance/realtime/connection_spec.rb#
|
606
|
+
* [queues messages to be sent and all channels remain attached](./spec/acceptance/realtime/connection_spec.rb#L1186)
|
603
607
|
* when connection enters the :suspended state
|
604
|
-
* [detaches the channels and prevents publishing of messages on those channels](./spec/acceptance/realtime/connection_spec.rb#
|
608
|
+
* [detaches the channels and prevents publishing of messages on those channels](./spec/acceptance/realtime/connection_spec.rb#L1219)
|
605
609
|
* when connection enters the :failed state
|
606
|
-
* [sets all channels to failed and prevents publishing of messages on those channels](./spec/acceptance/realtime/connection_spec.rb#
|
610
|
+
* [sets all channels to failed and prevents publishing of messages on those channels](./spec/acceptance/realtime/connection_spec.rb#L1248)
|
607
611
|
* connection state change
|
608
|
-
* [emits a ConnectionStateChange object](./spec/acceptance/realtime/connection_spec.rb#
|
612
|
+
* [emits a ConnectionStateChange object](./spec/acceptance/realtime/connection_spec.rb#L1259)
|
609
613
|
* ConnectionStateChange object
|
610
|
-
* [has current state](./spec/acceptance/realtime/connection_spec.rb#
|
611
|
-
* [has a previous state](./spec/acceptance/realtime/connection_spec.rb#
|
612
|
-
* [has an empty reason when there is no error](./spec/acceptance/realtime/connection_spec.rb#
|
614
|
+
* [has current state](./spec/acceptance/realtime/connection_spec.rb#L1267)
|
615
|
+
* [has a previous state](./spec/acceptance/realtime/connection_spec.rb#L1274)
|
616
|
+
* [has an empty reason when there is no error](./spec/acceptance/realtime/connection_spec.rb#L1289)
|
613
617
|
* on failure
|
614
|
-
* [has a reason Error object when there is an error on the connection](./spec/acceptance/realtime/connection_spec.rb#
|
618
|
+
* [has a reason Error object when there is an error on the connection](./spec/acceptance/realtime/connection_spec.rb#L1302)
|
615
619
|
* retry_in
|
616
|
-
* [is nil when a retry is not required](./spec/acceptance/realtime/connection_spec.rb#
|
617
|
-
* [is 0 when first attempt to connect fails](./spec/acceptance/realtime/connection_spec.rb#
|
618
|
-
* [is 0 when an immediate reconnect will occur](./spec/acceptance/realtime/connection_spec.rb#
|
619
|
-
* [contains the next retry period when an immediate reconnect will not occur](./spec/acceptance/realtime/connection_spec.rb#
|
620
|
+
* [is nil when a retry is not required](./spec/acceptance/realtime/connection_spec.rb#L1317)
|
621
|
+
* [is 0 when first attempt to connect fails](./spec/acceptance/realtime/connection_spec.rb#L1324)
|
622
|
+
* [is 0 when an immediate reconnect will occur](./spec/acceptance/realtime/connection_spec.rb#L1334)
|
623
|
+
* [contains the next retry period when an immediate reconnect will not occur](./spec/acceptance/realtime/connection_spec.rb#L1344)
|
620
624
|
|
621
625
|
### Ably::Realtime::Channel Message
|
622
626
|
_(see [spec/acceptance/realtime/message_spec.rb](./spec/acceptance/realtime/message_spec.rb))_
|
@@ -756,29 +760,27 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
756
760
|
* 250 existing (present) members on a channel (3 SYNC pages)
|
757
761
|
* requires at least 3 SYNC ProtocolMessages
|
758
762
|
* when a client attaches to the presence channel
|
759
|
-
* [emits :present for each member](./spec/acceptance/realtime/presence_spec.rb#
|
763
|
+
* [emits :present for each member](./spec/acceptance/realtime/presence_spec.rb#L533)
|
760
764
|
* and a member leaves before the SYNC operation is complete
|
761
|
-
* [emits :leave immediately as the member leaves](./spec/acceptance/realtime/presence_spec.rb#
|
762
|
-
* [ignores presence events with timestamps prior to the current :present event in the MembersMap](./spec/acceptance/realtime/presence_spec.rb#
|
763
|
-
* [does not emit :present after the :leave event has been emitted, and that member is not included in the list of members via #get with :wait_for_sync](./spec/acceptance/realtime/presence_spec.rb#
|
765
|
+
* [emits :leave immediately as the member leaves](./spec/acceptance/realtime/presence_spec.rb#L547)
|
766
|
+
* [ignores presence events with timestamps prior to the current :present event in the MembersMap](./spec/acceptance/realtime/presence_spec.rb#L588)
|
767
|
+
* [does not emit :present after the :leave event has been emitted, and that member is not included in the list of members via #get with :wait_for_sync](./spec/acceptance/realtime/presence_spec.rb#L630)
|
764
768
|
* #get
|
765
769
|
* with :wait_for_sync option set to true
|
766
|
-
* [waits until sync is complete](./spec/acceptance/realtime/presence_spec.rb#
|
770
|
+
* [waits until sync is complete](./spec/acceptance/realtime/presence_spec.rb#L680)
|
767
771
|
* by default
|
768
|
-
* [it does not wait for sync](./spec/acceptance/realtime/presence_spec.rb#
|
772
|
+
* [it does not wait for sync](./spec/acceptance/realtime/presence_spec.rb#L699)
|
769
773
|
* state
|
770
774
|
* once opened
|
771
|
-
* [once opened, enters the :left state if the channel detaches](./spec/acceptance/realtime/presence_spec.rb#
|
775
|
+
* [once opened, enters the :left state if the channel detaches](./spec/acceptance/realtime/presence_spec.rb#L725)
|
772
776
|
* #enter
|
773
|
-
* [allows client_id to be set on enter for anonymous clients](./spec/acceptance/realtime/presence_spec.rb#L741)
|
774
|
-
* [raises an exception if client_id is not set](./spec/acceptance/realtime/presence_spec.rb#L788)
|
775
777
|
* data attribute
|
776
778
|
* when provided as argument option to #enter
|
777
|
-
* [
|
779
|
+
* [changes to value provided in #leave](./spec/acceptance/realtime/presence_spec.rb#L750)
|
778
780
|
* message #connection_id
|
779
|
-
* [matches the current client connection_id](./spec/acceptance/realtime/presence_spec.rb#
|
781
|
+
* [matches the current client connection_id](./spec/acceptance/realtime/presence_spec.rb#L774)
|
780
782
|
* without necessary capabilities to join presence
|
781
|
-
* [calls the Deferrable errback on capabilities failure](./spec/acceptance/realtime/presence_spec.rb#
|
783
|
+
* [calls the Deferrable errback on capabilities failure](./spec/acceptance/realtime/presence_spec.rb#L793)
|
782
784
|
* it should behave like a public presence method
|
783
785
|
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L54)
|
784
786
|
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L66)
|
@@ -817,11 +819,11 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
817
819
|
* if connection fails before success
|
818
820
|
* [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L271)
|
819
821
|
* #update
|
820
|
-
* [without previous #enter automatically enters](./spec/acceptance/realtime/presence_spec.rb#
|
821
|
-
* [updates the data if :data argument provided](./spec/acceptance/realtime/presence_spec.rb#
|
822
|
-
* [updates the data to nil if :data argument is not provided (assumes nil value)](./spec/acceptance/realtime/presence_spec.rb#
|
822
|
+
* [without previous #enter automatically enters](./spec/acceptance/realtime/presence_spec.rb#L805)
|
823
|
+
* [updates the data if :data argument provided](./spec/acceptance/realtime/presence_spec.rb#L830)
|
824
|
+
* [updates the data to nil if :data argument is not provided (assumes nil value)](./spec/acceptance/realtime/presence_spec.rb#L840)
|
823
825
|
* when ENTERED
|
824
|
-
* [has no effect on the state](./spec/acceptance/realtime/presence_spec.rb#
|
826
|
+
* [has no effect on the state](./spec/acceptance/realtime/presence_spec.rb#L815)
|
825
827
|
* it should behave like a public presence method
|
826
828
|
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L54)
|
827
829
|
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L66)
|
@@ -860,16 +862,16 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
860
862
|
* if connection fails before success
|
861
863
|
* [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L271)
|
862
864
|
* #leave
|
863
|
-
* [raises an exception if not entered](./spec/acceptance/realtime/presence_spec.rb#
|
865
|
+
* [raises an exception if not entered](./spec/acceptance/realtime/presence_spec.rb#L914)
|
864
866
|
* :data option
|
865
867
|
* when set to a string
|
866
|
-
* [emits the new data for the leave event](./spec/acceptance/realtime/presence_spec.rb#
|
868
|
+
* [emits the new data for the leave event](./spec/acceptance/realtime/presence_spec.rb#L859)
|
867
869
|
* when set to nil
|
868
|
-
* [emits
|
869
|
-
* when not passed as an argument
|
870
|
-
* [emits the
|
870
|
+
* [emits the last value for the data attribute when leaving](./spec/acceptance/realtime/presence_spec.rb#L872)
|
871
|
+
* when not passed as an argument (i.e. nil)
|
872
|
+
* [emits the previous value for the data attribute when leaving](./spec/acceptance/realtime/presence_spec.rb#L885)
|
871
873
|
* and sync is complete
|
872
|
-
* [does not cache members that have left](./spec/acceptance/realtime/presence_spec.rb#
|
874
|
+
* [does not cache members that have left](./spec/acceptance/realtime/presence_spec.rb#L898)
|
873
875
|
* it should behave like a public presence method
|
874
876
|
* [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L234)
|
875
877
|
* [allows a block to be passed in that is executed upon success](./spec/acceptance/realtime/presence_spec.rb#L241)
|
@@ -896,17 +898,17 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
896
898
|
* if connection fails before success
|
897
899
|
* [calls the Deferrable errback if channel is detached](./spec/acceptance/realtime/presence_spec.rb#L271)
|
898
900
|
* :left event
|
899
|
-
* [emits the data defined in enter](./spec/acceptance/realtime/presence_spec.rb#
|
900
|
-
* [emits the data defined in update](./spec/acceptance/realtime/presence_spec.rb#
|
901
|
+
* [emits the data defined in enter](./spec/acceptance/realtime/presence_spec.rb#L923)
|
902
|
+
* [emits the data defined in update](./spec/acceptance/realtime/presence_spec.rb#L934)
|
901
903
|
* entering/updating/leaving presence state on behalf of another client_id
|
902
904
|
* #enter_client
|
903
905
|
* multiple times on the same channel with different client_ids
|
904
|
-
* [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#
|
905
|
-
* [enters a channel and sets the data based on the provided :data option](./spec/acceptance/realtime/presence_spec.rb#
|
906
|
+
* [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#L957)
|
907
|
+
* [enters a channel and sets the data based on the provided :data option](./spec/acceptance/realtime/presence_spec.rb#L971)
|
906
908
|
* message #connection_id
|
907
|
-
* [matches the current client connection_id](./spec/acceptance/realtime/presence_spec.rb#
|
909
|
+
* [matches the current client connection_id](./spec/acceptance/realtime/presence_spec.rb#L990)
|
908
910
|
* without necessary capabilities to enter on behalf of another client
|
909
|
-
* [calls the Deferrable errback on capabilities failure](./spec/acceptance/realtime/presence_spec.rb#
|
911
|
+
* [calls the Deferrable errback on capabilities failure](./spec/acceptance/realtime/presence_spec.rb#L1010)
|
910
912
|
* it should behave like a public presence method
|
911
913
|
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L54)
|
912
914
|
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L66)
|
@@ -974,9 +976,9 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
974
976
|
* [throws an exception](./spec/acceptance/realtime/presence_spec.rb#L403)
|
975
977
|
* #update_client
|
976
978
|
* multiple times on the same channel with different client_ids
|
977
|
-
* [updates the data attribute for the member when :data option provided](./spec/acceptance/realtime/presence_spec.rb#
|
978
|
-
* [updates the data attribute to null for the member when :data option is not provided (assumed null)](./spec/acceptance/realtime/presence_spec.rb#
|
979
|
-
* [enters if not already entered](./spec/acceptance/realtime/presence_spec.rb#
|
979
|
+
* [updates the data attribute for the member when :data option provided](./spec/acceptance/realtime/presence_spec.rb#L1024)
|
980
|
+
* [updates the data attribute to null for the member when :data option is not provided (assumed null)](./spec/acceptance/realtime/presence_spec.rb#L1048)
|
981
|
+
* [enters if not already entered](./spec/acceptance/realtime/presence_spec.rb#L1060)
|
980
982
|
* it should behave like a public presence method
|
981
983
|
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L54)
|
982
984
|
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L66)
|
@@ -1045,14 +1047,14 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
1045
1047
|
* #leave_client
|
1046
1048
|
* leaves a channel
|
1047
1049
|
* multiple times on the same channel with different client_ids
|
1048
|
-
* [emits the :leave event for each client_id](./spec/acceptance/realtime/presence_spec.rb#
|
1049
|
-
* [succeeds if that client_id has not previously entered the channel](./spec/acceptance/realtime/presence_spec.rb#
|
1050
|
+
* [emits the :leave event for each client_id](./spec/acceptance/realtime/presence_spec.rb#L1090)
|
1051
|
+
* [succeeds if that client_id has not previously entered the channel](./spec/acceptance/realtime/presence_spec.rb#L1114)
|
1050
1052
|
* with a new value in :data option
|
1051
|
-
* [emits the leave event with the new data value](./spec/acceptance/realtime/presence_spec.rb#
|
1053
|
+
* [emits the leave event with the new data value](./spec/acceptance/realtime/presence_spec.rb#L1138)
|
1052
1054
|
* with a nil value in :data option
|
1053
|
-
* [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#
|
1055
|
+
* [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L1151)
|
1054
1056
|
* with no :data option
|
1055
|
-
* [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#
|
1057
|
+
* [emits the leave event with the previous value as a convenience](./spec/acceptance/realtime/presence_spec.rb#L1164)
|
1056
1058
|
* it should behave like a public presence method
|
1057
1059
|
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L54)
|
1058
1060
|
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L66)
|
@@ -1119,60 +1121,60 @@ _(see [spec/acceptance/realtime/presence_spec.rb](./spec/acceptance/realtime/pre
|
|
1119
1121
|
* and an empty client_id
|
1120
1122
|
* [throws an exception](./spec/acceptance/realtime/presence_spec.rb#L403)
|
1121
1123
|
* #get
|
1122
|
-
* [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#
|
1123
|
-
* [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#
|
1124
|
-
* [catches exceptions in the provided method block](./spec/acceptance/realtime/presence_spec.rb#
|
1125
|
-
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#
|
1126
|
-
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#
|
1127
|
-
* [returns the current members on the channel](./spec/acceptance/realtime/presence_spec.rb#
|
1128
|
-
* [filters by connection_id option if provided](./spec/acceptance/realtime/presence_spec.rb#
|
1129
|
-
* [filters by client_id option if provided](./spec/acceptance/realtime/presence_spec.rb#
|
1130
|
-
* [does not wait for SYNC to complete if :wait_for_sync option is false](./spec/acceptance/realtime/presence_spec.rb#
|
1124
|
+
* [returns a SafeDeferrable that catches exceptions in callbacks and logs them](./spec/acceptance/realtime/presence_spec.rb#L1183)
|
1125
|
+
* [calls the Deferrable callback on success](./spec/acceptance/realtime/presence_spec.rb#L1188)
|
1126
|
+
* [catches exceptions in the provided method block](./spec/acceptance/realtime/presence_spec.rb#L1195)
|
1127
|
+
* [raise an exception if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L1202)
|
1128
|
+
* [raise an exception if the channel is failed](./spec/acceptance/realtime/presence_spec.rb#L1212)
|
1129
|
+
* [returns the current members on the channel](./spec/acceptance/realtime/presence_spec.rb#L1292)
|
1130
|
+
* [filters by connection_id option if provided](./spec/acceptance/realtime/presence_spec.rb#L1307)
|
1131
|
+
* [filters by client_id option if provided](./spec/acceptance/realtime/presence_spec.rb#L1329)
|
1132
|
+
* [does not wait for SYNC to complete if :wait_for_sync option is false](./spec/acceptance/realtime/presence_spec.rb#L1353)
|
1131
1133
|
* during a sync
|
1132
1134
|
* when :wait_for_sync is true
|
1133
|
-
* [fails if the connection fails](./spec/acceptance/realtime/presence_spec.rb#
|
1134
|
-
* [fails if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#
|
1135
|
+
* [fails if the connection fails](./spec/acceptance/realtime/presence_spec.rb#L1243)
|
1136
|
+
* [fails if the channel is detached](./spec/acceptance/realtime/presence_spec.rb#L1266)
|
1135
1137
|
* when a member enters and then leaves
|
1136
|
-
* [has no members](./spec/acceptance/realtime/presence_spec.rb#
|
1138
|
+
* [has no members](./spec/acceptance/realtime/presence_spec.rb#L1363)
|
1137
1139
|
* with lots of members on different clients
|
1138
|
-
* [returns a complete list of members on all clients](./spec/acceptance/realtime/presence_spec.rb#
|
1140
|
+
* [returns a complete list of members on all clients](./spec/acceptance/realtime/presence_spec.rb#L1382)
|
1139
1141
|
* #subscribe
|
1140
|
-
* [implicitly attaches](./spec/acceptance/realtime/presence_spec.rb#
|
1142
|
+
* [implicitly attaches](./spec/acceptance/realtime/presence_spec.rb#L1457)
|
1141
1143
|
* with no arguments
|
1142
|
-
* [calls the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#
|
1144
|
+
* [calls the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#L1418)
|
1143
1145
|
* with event name
|
1144
|
-
* [calls the callback for specified presence event](./spec/acceptance/realtime/presence_spec.rb#
|
1146
|
+
* [calls the callback for specified presence event](./spec/acceptance/realtime/presence_spec.rb#L1438)
|
1145
1147
|
* #unsubscribe
|
1146
1148
|
* with no arguments
|
1147
|
-
* [removes the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#
|
1149
|
+
* [removes the callback for all presence events](./spec/acceptance/realtime/presence_spec.rb#L1470)
|
1148
1150
|
* with event name
|
1149
|
-
* [removes the callback for specified presence event](./spec/acceptance/realtime/presence_spec.rb#
|
1151
|
+
* [removes the callback for specified presence event](./spec/acceptance/realtime/presence_spec.rb#L1488)
|
1150
1152
|
* REST #get
|
1151
|
-
* [returns current members](./spec/acceptance/realtime/presence_spec.rb#
|
1152
|
-
* [returns no members once left](./spec/acceptance/realtime/presence_spec.rb#
|
1153
|
+
* [returns current members](./spec/acceptance/realtime/presence_spec.rb#L1507)
|
1154
|
+
* [returns no members once left](./spec/acceptance/realtime/presence_spec.rb#L1520)
|
1153
1155
|
* client_id with ASCII_8BIT
|
1154
1156
|
* in connection set up
|
1155
|
-
* [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#
|
1157
|
+
* [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#L1537)
|
1156
1158
|
* in channel options
|
1157
|
-
* [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#
|
1159
|
+
* [is converted into UTF_8](./spec/acceptance/realtime/presence_spec.rb#L1550)
|
1158
1160
|
* encoding and decoding of presence message data
|
1159
|
-
* [encrypts presence message data](./spec/acceptance/realtime/presence_spec.rb#
|
1161
|
+
* [encrypts presence message data](./spec/acceptance/realtime/presence_spec.rb#L1576)
|
1160
1162
|
* #subscribe
|
1161
|
-
* [emits decrypted enter events](./spec/acceptance/realtime/presence_spec.rb#
|
1162
|
-
* [emits decrypted update events](./spec/acceptance/realtime/presence_spec.rb#
|
1163
|
-
* [emits previously set data for leave events](./spec/acceptance/realtime/presence_spec.rb#
|
1163
|
+
* [emits decrypted enter events](./spec/acceptance/realtime/presence_spec.rb#L1595)
|
1164
|
+
* [emits decrypted update events](./spec/acceptance/realtime/presence_spec.rb#L1607)
|
1165
|
+
* [emits previously set data for leave events](./spec/acceptance/realtime/presence_spec.rb#L1621)
|
1164
1166
|
* #get
|
1165
|
-
* [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#
|
1167
|
+
* [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#L1637)
|
1166
1168
|
* REST #get
|
1167
|
-
* [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#
|
1169
|
+
* [returns a list of members with decrypted data](./spec/acceptance/realtime/presence_spec.rb#L1650)
|
1168
1170
|
* when cipher settings do not match publisher
|
1169
|
-
* [delivers an unencoded presence message left with encoding value](./spec/acceptance/realtime/presence_spec.rb#
|
1170
|
-
* [emits an error when cipher does not match and presence data cannot be decoded](./spec/acceptance/realtime/presence_spec.rb#
|
1171
|
+
* [delivers an unencoded presence message left with encoding value](./spec/acceptance/realtime/presence_spec.rb#L1665)
|
1172
|
+
* [emits an error when cipher does not match and presence data cannot be decoded](./spec/acceptance/realtime/presence_spec.rb#L1678)
|
1171
1173
|
* leaving
|
1172
|
-
* [expect :left event once underlying connection is closed](./spec/acceptance/realtime/presence_spec.rb#
|
1173
|
-
* [expect :left event with client data from enter event](./spec/acceptance/realtime/presence_spec.rb#
|
1174
|
+
* [expect :left event once underlying connection is closed](./spec/acceptance/realtime/presence_spec.rb#L1695)
|
1175
|
+
* [expect :left event with client data from enter event](./spec/acceptance/realtime/presence_spec.rb#L1705)
|
1174
1176
|
* connection failure mid-way through a large member sync
|
1175
|
-
* [resumes the SYNC operation](./spec/acceptance/realtime/presence_spec.rb#
|
1177
|
+
* [resumes the SYNC operation](./spec/acceptance/realtime/presence_spec.rb#L1724)
|
1176
1178
|
|
1177
1179
|
### Ably::Realtime::Client#stats
|
1178
1180
|
_(see [spec/acceptance/realtime/stats_spec.rb](./spec/acceptance/realtime/stats_spec.rb))_
|
@@ -1866,6 +1868,45 @@ _(see [spec/unit/models/channel_state_change_spec.rb](./spec/unit/models/channel
|
|
1866
1868
|
* invalid attributes
|
1867
1869
|
* [raises an argument error](./spec/unit/models/channel_state_change_spec.rb#L40)
|
1868
1870
|
|
1871
|
+
### Ably::Models::CipherParams
|
1872
|
+
_(see [spec/unit/models/cipher_params_spec.rb](./spec/unit/models/cipher_params_spec.rb))_
|
1873
|
+
* :key missing from constructor
|
1874
|
+
* [raises an exception](./spec/unit/models/cipher_params_spec.rb#L8)
|
1875
|
+
* #key
|
1876
|
+
* with :key in constructor
|
1877
|
+
* as nil
|
1878
|
+
* [raises an exception](./spec/unit/models/cipher_params_spec.rb#L20)
|
1879
|
+
* as a base64 encoded string
|
1880
|
+
* [is a binary representation of the base64 encoded string](./spec/unit/models/cipher_params_spec.rb#L29)
|
1881
|
+
* as a URL safe base64 encoded string
|
1882
|
+
* [is a binary representation of the URL safe base64 encoded string](./spec/unit/models/cipher_params_spec.rb#L40)
|
1883
|
+
* as a binary encoded string
|
1884
|
+
* [contains the binary string](./spec/unit/models/cipher_params_spec.rb#L48)
|
1885
|
+
* with an incompatible :key_length constructor param
|
1886
|
+
* [raises an exception](./spec/unit/models/cipher_params_spec.rb#L58)
|
1887
|
+
* with an unsupported :key_length for aes-cbc encryption
|
1888
|
+
* [raises an exception](./spec/unit/models/cipher_params_spec.rb#L67)
|
1889
|
+
* with an invalid type
|
1890
|
+
* [raises an exception](./spec/unit/models/cipher_params_spec.rb#L76)
|
1891
|
+
* with specified params in the constructor
|
1892
|
+
* #cipher_type
|
1893
|
+
* [contains the complete algorithm string as an upper case string](./spec/unit/models/cipher_params_spec.rb#L88)
|
1894
|
+
* #mode
|
1895
|
+
* [contains the mode](./spec/unit/models/cipher_params_spec.rb#L94)
|
1896
|
+
* #algorithm
|
1897
|
+
* [contains the algorithm](./spec/unit/models/cipher_params_spec.rb#L100)
|
1898
|
+
* #key_length
|
1899
|
+
* [contains the key_length](./spec/unit/models/cipher_params_spec.rb#L106)
|
1900
|
+
* with combined param in the constructor
|
1901
|
+
* #cipher_type
|
1902
|
+
* [contains the complete algorithm string as an upper case string](./spec/unit/models/cipher_params_spec.rb#L117)
|
1903
|
+
* #mode
|
1904
|
+
* [contains the mode](./spec/unit/models/cipher_params_spec.rb#L123)
|
1905
|
+
* #algorithm
|
1906
|
+
* [contains the algorithm](./spec/unit/models/cipher_params_spec.rb#L129)
|
1907
|
+
* #key_length
|
1908
|
+
* [contains the key_length](./spec/unit/models/cipher_params_spec.rb#L135)
|
1909
|
+
|
1869
1910
|
### Ably::Models::ConnectionDetails
|
1870
1911
|
_(see [spec/unit/models/connection_details_spec.rb](./spec/unit/models/connection_details_spec.rb))_
|
1871
1912
|
* behaves like a model
|
@@ -1993,46 +2034,47 @@ _(see [spec/unit/models/message_encoders/cipher_spec.rb](./spec/unit/models/mess
|
|
1993
2034
|
* message with another payload
|
1994
2035
|
* [leaves the message data intact](./spec/unit/models/message_encoders/cipher_spec.rb#L72)
|
1995
2036
|
* [leaves the encoding intact](./spec/unit/models/message_encoders/cipher_spec.rb#L76)
|
1996
|
-
*
|
1997
|
-
*
|
1998
|
-
|
1999
|
-
*
|
2037
|
+
* 256 bit key
|
2038
|
+
* with invalid channel_option cipher params
|
2039
|
+
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#L90)
|
2040
|
+
* without any configured encryption
|
2041
|
+
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#L100)
|
2000
2042
|
* with invalid cipher data
|
2001
|
-
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2043
|
+
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#L110)
|
2002
2044
|
* with AES-256-CBC
|
2003
2045
|
* message with cipher payload
|
2004
|
-
* [decodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2005
|
-
* [strips the encoding](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2046
|
+
* [decodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#L127)
|
2047
|
+
* [strips the encoding](./spec/unit/models/message_encoders/cipher_spec.rb#L131)
|
2006
2048
|
* #encode
|
2007
2049
|
* with channel set up for AES-128-CBC
|
2008
2050
|
* with encrypted set to true
|
2009
2051
|
* message with string payload
|
2010
|
-
* [encodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2011
|
-
* [adds the encoding with utf-8](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2052
|
+
* [encodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#L151)
|
2053
|
+
* [adds the encoding with utf-8](./spec/unit/models/message_encoders/cipher_spec.rb#L156)
|
2012
2054
|
* message with binary payload
|
2013
|
-
* [encodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2014
|
-
* [adds the encoding without utf-8 prefixed](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2015
|
-
* [returns ASCII_8BIT encoded binary data](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2055
|
+
* [encodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#L164)
|
2056
|
+
* [adds the encoding without utf-8 prefixed](./spec/unit/models/message_encoders/cipher_spec.rb#L169)
|
2057
|
+
* [returns ASCII_8BIT encoded binary data](./spec/unit/models/message_encoders/cipher_spec.rb#L173)
|
2016
2058
|
* message with json payload
|
2017
|
-
* [encodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2018
|
-
* [adds the encoding with utf-8](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2059
|
+
* [encodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#L181)
|
2060
|
+
* [adds the encoding with utf-8](./spec/unit/models/message_encoders/cipher_spec.rb#L186)
|
2019
2061
|
* message with existing cipher encoding before
|
2020
|
-
* [leaves message intact as it is already encrypted](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2021
|
-
* [leaves encoding intact](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2062
|
+
* [leaves message intact as it is already encrypted](./spec/unit/models/message_encoders/cipher_spec.rb#L194)
|
2063
|
+
* [leaves encoding intact](./spec/unit/models/message_encoders/cipher_spec.rb#L198)
|
2022
2064
|
* with encryption set to to false
|
2023
|
-
* [leaves message intact as encryption is not enable](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2024
|
-
* [leaves encoding intact](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2065
|
+
* [leaves message intact as encryption is not enable](./spec/unit/models/message_encoders/cipher_spec.rb#L207)
|
2066
|
+
* [leaves encoding intact](./spec/unit/models/message_encoders/cipher_spec.rb#L211)
|
2025
2067
|
* channel_option cipher params
|
2026
2068
|
* have invalid key length
|
2027
|
-
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2069
|
+
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#L223)
|
2028
2070
|
* have invalid algorithm
|
2029
|
-
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2071
|
+
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#L230)
|
2030
2072
|
* have missing key
|
2031
|
-
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2073
|
+
* [raise an exception](./spec/unit/models/message_encoders/cipher_spec.rb#L237)
|
2032
2074
|
* with AES-256-CBC
|
2033
2075
|
* message with cipher payload
|
2034
|
-
* [decodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2035
|
-
* [strips the encoding](./spec/unit/models/message_encoders/cipher_spec.rb#
|
2076
|
+
* [decodes cipher](./spec/unit/models/message_encoders/cipher_spec.rb#L255)
|
2077
|
+
* [strips the encoding](./spec/unit/models/message_encoders/cipher_spec.rb#L260)
|
2036
2078
|
|
2037
2079
|
### Ably::Models::MessageEncoders::Json
|
2038
2080
|
_(see [spec/unit/models/message_encoders/json_spec.rb](./spec/unit/models/message_encoders/json_spec.rb))_
|
@@ -2040,31 +2082,37 @@ _(see [spec/unit/models/message_encoders/json_spec.rb](./spec/unit/models/messag
|
|
2040
2082
|
* message with json payload
|
2041
2083
|
* [decodes json](./spec/unit/models/message_encoders/json_spec.rb#L24)
|
2042
2084
|
* [strips the encoding](./spec/unit/models/message_encoders/json_spec.rb#L28)
|
2043
|
-
* message with json payload
|
2085
|
+
* message with json payload in camelCase
|
2044
2086
|
* [decodes json](./spec/unit/models/message_encoders/json_spec.rb#L36)
|
2045
2087
|
* [strips the encoding](./spec/unit/models/message_encoders/json_spec.rb#L40)
|
2088
|
+
* message with json payload before other payloads
|
2089
|
+
* [decodes json](./spec/unit/models/message_encoders/json_spec.rb#L48)
|
2090
|
+
* [strips the encoding](./spec/unit/models/message_encoders/json_spec.rb#L52)
|
2046
2091
|
* message with another payload
|
2047
|
-
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#
|
2048
|
-
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#
|
2092
|
+
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#L60)
|
2093
|
+
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#L64)
|
2049
2094
|
* #encode
|
2050
2095
|
* message with hash payload
|
2051
|
-
* [encodes hash payload data as json](./spec/unit/models/message_encoders/json_spec.rb#L66)
|
2052
|
-
* [adds the encoding](./spec/unit/models/message_encoders/json_spec.rb#L70)
|
2053
|
-
* already encoded message with hash payload
|
2054
2096
|
* [encodes hash payload data as json](./spec/unit/models/message_encoders/json_spec.rb#L78)
|
2055
2097
|
* [adds the encoding](./spec/unit/models/message_encoders/json_spec.rb#L82)
|
2056
|
-
* message with
|
2057
|
-
* [encodes
|
2098
|
+
* message with hash payload and underscore case keys
|
2099
|
+
* [encodes hash payload data as json and leaves underscore case in tact](./spec/unit/models/message_encoders/json_spec.rb#L90)
|
2058
2100
|
* [adds the encoding](./spec/unit/models/message_encoders/json_spec.rb#L94)
|
2101
|
+
* already encoded message with hash payload
|
2102
|
+
* [encodes hash payload data as json](./spec/unit/models/message_encoders/json_spec.rb#L102)
|
2103
|
+
* [adds the encoding](./spec/unit/models/message_encoders/json_spec.rb#L106)
|
2104
|
+
* message with Array payload
|
2105
|
+
* [encodes Array payload data as json](./spec/unit/models/message_encoders/json_spec.rb#L114)
|
2106
|
+
* [adds the encoding](./spec/unit/models/message_encoders/json_spec.rb#L118)
|
2059
2107
|
* message with UTF-8 payload
|
2060
|
-
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#L102)
|
2061
|
-
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#L106)
|
2062
|
-
* message with nil payload
|
2063
|
-
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#L114)
|
2064
|
-
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#L118)
|
2065
|
-
* message with no data payload
|
2066
2108
|
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#L126)
|
2067
2109
|
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#L130)
|
2110
|
+
* message with nil payload
|
2111
|
+
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#L138)
|
2112
|
+
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#L142)
|
2113
|
+
* message with no data payload
|
2114
|
+
* [leaves the message data intact](./spec/unit/models/message_encoders/json_spec.rb#L150)
|
2115
|
+
* [leaves the encoding intact](./spec/unit/models/message_encoders/json_spec.rb#L154)
|
2068
2116
|
|
2069
2117
|
### Ably::Models::MessageEncoders::Utf8
|
2070
2118
|
_(see [spec/unit/models/message_encoders/utf8_spec.rb](./spec/unit/models/message_encoders/utf8_spec.rb))_
|
@@ -2512,29 +2560,30 @@ _(see [spec/unit/models/token_details_spec.rb](./spec/unit/models/token_details_
|
|
2512
2560
|
* attributes
|
2513
2561
|
* #capability
|
2514
2562
|
* [retrieves attribute :capability as parsed JSON](./spec/unit/models/token_details_spec.rb#L21)
|
2515
|
-
*
|
2516
|
-
*
|
2517
|
-
|
2518
|
-
*
|
2519
|
-
|
2520
|
-
*
|
2521
|
-
|
2522
|
-
*
|
2523
|
-
|
2524
|
-
*
|
2525
|
-
|
2526
|
-
*
|
2563
|
+
*
|
2564
|
+
* #issued with :issued option as milliseconds in constructor
|
2565
|
+
* [retrieves attribute :issued as Time](./spec/unit/models/token_details_spec.rb#L32)
|
2566
|
+
* #issued with :issued option as a Time in constructor
|
2567
|
+
* [retrieves attribute :issued as Time](./spec/unit/models/token_details_spec.rb#L41)
|
2568
|
+
* #issued when converted to JSON
|
2569
|
+
* [is in milliseconds](./spec/unit/models/token_details_spec.rb#L50)
|
2570
|
+
* #expires with :expires option as milliseconds in constructor
|
2571
|
+
* [retrieves attribute :expires as Time](./spec/unit/models/token_details_spec.rb#L32)
|
2572
|
+
* #expires with :expires option as a Time in constructor
|
2573
|
+
* [retrieves attribute :expires as Time](./spec/unit/models/token_details_spec.rb#L41)
|
2574
|
+
* #expires when converted to JSON
|
2575
|
+
* [is in milliseconds](./spec/unit/models/token_details_spec.rb#L50)
|
2527
2576
|
* #expired?
|
2528
2577
|
* once grace period buffer has passed
|
2529
|
-
* [is true](./spec/unit/models/token_details_spec.rb#
|
2578
|
+
* [is true](./spec/unit/models/token_details_spec.rb#L63)
|
2530
2579
|
* within grace period buffer
|
2531
|
-
* [is false](./spec/unit/models/token_details_spec.rb#
|
2580
|
+
* [is false](./spec/unit/models/token_details_spec.rb#L71)
|
2532
2581
|
* when expires is not available (i.e. string tokens)
|
2533
|
-
* [is always false](./spec/unit/models/token_details_spec.rb#
|
2582
|
+
* [is always false](./spec/unit/models/token_details_spec.rb#L79)
|
2534
2583
|
* ==
|
2535
|
-
* [is true when attributes are the same](./spec/unit/models/token_details_spec.rb#
|
2536
|
-
* [is false when attributes are not the same](./spec/unit/models/token_details_spec.rb#
|
2537
|
-
* [is false when class type differs](./spec/unit/models/token_details_spec.rb#
|
2584
|
+
* [is true when attributes are the same](./spec/unit/models/token_details_spec.rb#L89)
|
2585
|
+
* [is false when attributes are not the same](./spec/unit/models/token_details_spec.rb#L94)
|
2586
|
+
* [is false when class type differs](./spec/unit/models/token_details_spec.rb#L98)
|
2538
2587
|
|
2539
2588
|
### Ably::Models::TokenRequest
|
2540
2589
|
_(see [spec/unit/models/token_request_spec.rb](./spec/unit/models/token_request_spec.rb))_
|
@@ -2960,26 +3009,34 @@ _(see [spec/unit/rest/rest_spec.rb](./spec/unit/rest/rest_spec.rb))_
|
|
2960
3009
|
### Ably::Util::Crypto
|
2961
3010
|
_(see [spec/unit/util/crypto_spec.rb](./spec/unit/util/crypto_spec.rb))_
|
2962
3011
|
* defaults
|
2963
|
-
* [match other client libraries](./spec/unit/util/crypto_spec.rb#
|
3012
|
+
* [match other client libraries](./spec/unit/util/crypto_spec.rb#L19)
|
2964
3013
|
* get_default_params
|
2965
|
-
*
|
2966
|
-
|
3014
|
+
* with just a :key param
|
3015
|
+
* [uses the defaults](./spec/unit/util/crypto_spec.rb#L29)
|
3016
|
+
* [contains the provided key](./spec/unit/util/crypto_spec.rb#L35)
|
3017
|
+
* [returns a CipherParams object](./spec/unit/util/crypto_spec.rb#L39)
|
3018
|
+
* without a :key param
|
3019
|
+
* [raises an exception](./spec/unit/util/crypto_spec.rb#L47)
|
3020
|
+
* with a base64-encoded :key param
|
3021
|
+
* [converts the key to binary](./spec/unit/util/crypto_spec.rb#L55)
|
3022
|
+
* with provided params
|
3023
|
+
* [overrides the defaults](./spec/unit/util/crypto_spec.rb#L67)
|
2967
3024
|
* encrypts & decrypt
|
2968
|
-
* [#encrypt encrypts a string](./spec/unit/util/crypto_spec.rb#
|
2969
|
-
* [#decrypt decrypts a string](./spec/unit/util/crypto_spec.rb#
|
3025
|
+
* [#encrypt encrypts a string](./spec/unit/util/crypto_spec.rb#L79)
|
3026
|
+
* [#decrypt decrypts a string](./spec/unit/util/crypto_spec.rb#L84)
|
2970
3027
|
* encrypting an empty string
|
2971
|
-
* [raises an ArgumentError](./spec/unit/util/crypto_spec.rb#
|
3028
|
+
* [raises an ArgumentError](./spec/unit/util/crypto_spec.rb#L93)
|
2972
3029
|
* using shared client lib fixture data
|
2973
3030
|
* with AES-128-CBC
|
2974
3031
|
* behaves like an Ably encrypter and decrypter
|
2975
3032
|
* text payload
|
2976
|
-
* [encrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#
|
2977
|
-
* [decrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#
|
3033
|
+
* [encrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#L116)
|
3034
|
+
* [decrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#L120)
|
2978
3035
|
* with AES-256-CBC
|
2979
3036
|
* behaves like an Ably encrypter and decrypter
|
2980
3037
|
* text payload
|
2981
|
-
* [encrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#
|
2982
|
-
* [decrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#
|
3038
|
+
* [encrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#L116)
|
3039
|
+
* [decrypts exactly the same binary data as other client libraries](./spec/unit/util/crypto_spec.rb#L120)
|
2983
3040
|
|
2984
3041
|
### Ably::Util::PubSub
|
2985
3042
|
_(see [spec/unit/util/pub_sub_spec.rb](./spec/unit/util/pub_sub_spec.rb))_
|
@@ -2995,6 +3052,6 @@ _(see [spec/unit/util/pub_sub_spec.rb](./spec/unit/util/pub_sub_spec.rb))_
|
|
2995
3052
|
|
2996
3053
|
## Test summary
|
2997
3054
|
|
2998
|
-
* Passing tests:
|
3055
|
+
* Passing tests: 1492
|
2999
3056
|
* Pending tests: 6
|
3000
3057
|
* Failing tests: 0
|