ably 0.7.2 → 0.7.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +1 -1
- data/README.md +107 -24
- data/SPEC.md +531 -398
- data/lib/ably/auth.rb +23 -15
- data/lib/ably/exceptions.rb +9 -0
- data/lib/ably/models/message.rb +17 -9
- data/lib/ably/models/paginated_resource.rb +12 -8
- data/lib/ably/models/presence_message.rb +18 -10
- data/lib/ably/models/protocol_message.rb +15 -4
- data/lib/ably/modules/async_wrapper.rb +4 -3
- data/lib/ably/modules/event_emitter.rb +31 -2
- data/lib/ably/modules/message_emitter.rb +77 -0
- data/lib/ably/modules/safe_deferrable.rb +71 -0
- data/lib/ably/modules/safe_yield.rb +41 -0
- data/lib/ably/modules/state_emitter.rb +28 -8
- data/lib/ably/realtime.rb +0 -5
- data/lib/ably/realtime/channel.rb +24 -29
- data/lib/ably/realtime/channel/channel_manager.rb +54 -11
- data/lib/ably/realtime/channel/channel_state_machine.rb +21 -6
- data/lib/ably/realtime/client.rb +7 -2
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +29 -26
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +4 -4
- data/lib/ably/realtime/connection.rb +41 -9
- data/lib/ably/realtime/connection/connection_manager.rb +72 -24
- data/lib/ably/realtime/connection/connection_state_machine.rb +26 -4
- data/lib/ably/realtime/connection/websocket_transport.rb +19 -6
- data/lib/ably/realtime/presence.rb +74 -208
- data/lib/ably/realtime/presence/members_map.rb +264 -0
- data/lib/ably/realtime/presence/presence_manager.rb +59 -0
- data/lib/ably/realtime/presence/presence_state_machine.rb +64 -0
- data/lib/ably/rest/channel.rb +1 -1
- data/lib/ably/rest/client.rb +6 -2
- data/lib/ably/rest/presence.rb +1 -1
- data/lib/ably/util/pub_sub.rb +3 -1
- data/lib/ably/util/safe_deferrable.rb +18 -0
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +2 -2
- data/spec/acceptance/realtime/channel_spec.rb +28 -6
- data/spec/acceptance/realtime/connection_failures_spec.rb +116 -46
- data/spec/acceptance/realtime/connection_spec.rb +55 -10
- data/spec/acceptance/realtime/message_spec.rb +32 -0
- data/spec/acceptance/realtime/presence_spec.rb +456 -96
- data/spec/acceptance/realtime/stats_spec.rb +2 -2
- data/spec/acceptance/realtime/time_spec.rb +2 -2
- data/spec/acceptance/rest/auth_spec.rb +75 -7
- data/spec/shared/client_initializer_behaviour.rb +8 -0
- data/spec/shared/safe_deferrable_behaviour.rb +71 -0
- data/spec/support/api_helper.rb +1 -1
- data/spec/support/event_machine_helper.rb +1 -1
- data/spec/support/test_app.rb +13 -7
- data/spec/unit/models/message_spec.rb +15 -14
- data/spec/unit/models/paginated_resource_spec.rb +4 -4
- data/spec/unit/models/presence_message_spec.rb +17 -17
- data/spec/unit/models/stat_spec.rb +4 -4
- data/spec/unit/modules/async_wrapper_spec.rb +28 -9
- data/spec/unit/modules/event_emitter_spec.rb +50 -0
- data/spec/unit/modules/state_emitter_spec.rb +76 -2
- data/spec/unit/realtime/channel_spec.rb +51 -20
- data/spec/unit/realtime/channels_spec.rb +3 -3
- data/spec/unit/realtime/connection_spec.rb +30 -0
- data/spec/unit/realtime/presence_spec.rb +52 -26
- data/spec/unit/realtime/safe_deferrable_spec.rb +12 -0
- metadata +85 -39
- checksums.yaml +0 -7
- data/.ruby-version.old +0 -1
@@ -14,8 +14,8 @@ describe Ably::Realtime::Client, '#stats', :event_machine do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
it '
|
18
|
-
expect(client.stats).to be_a(
|
17
|
+
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
18
|
+
expect(client.stats).to be_a(Ably::Util::SafeDeferrable)
|
19
19
|
stop_reactor
|
20
20
|
end
|
21
21
|
end
|
@@ -16,9 +16,9 @@ describe Ably::Realtime::Client, '#time', :event_machine do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
it '
|
19
|
+
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
20
20
|
run_reactor do
|
21
|
-
expect(client.time).to be_a(
|
21
|
+
expect(client.time).to be_a(Ably::Util::SafeDeferrable)
|
22
22
|
stop_reactor
|
23
23
|
end
|
24
24
|
end
|
@@ -146,7 +146,7 @@ describe Ably::Auth do
|
|
146
146
|
|
147
147
|
context 'with :auth_url option', :webmock do
|
148
148
|
let(:auth_url) { 'https://www.fictitious.com/get_token' }
|
149
|
-
let(:
|
149
|
+
let(:auth_url_response) { { id: key_id } }
|
150
150
|
let(:token_response) { { access_token: { } } }
|
151
151
|
let(:query_params) { nil }
|
152
152
|
let(:headers) { nil }
|
@@ -166,7 +166,7 @@ describe Ably::Auth do
|
|
166
166
|
stub.with(:headers => headers) unless headers.nil?
|
167
167
|
stub.to_return(
|
168
168
|
:status => 201,
|
169
|
-
:body =>
|
169
|
+
:body => auth_url_response.to_json,
|
170
170
|
:headers => { 'Content-Type' => 'application/json' }
|
171
171
|
)
|
172
172
|
end
|
@@ -182,14 +182,18 @@ describe Ably::Auth do
|
|
182
182
|
)
|
183
183
|
end
|
184
184
|
|
185
|
-
context 'when response is valid' do
|
186
|
-
|
185
|
+
context 'when response from :auth_url is a valid token request' do
|
186
|
+
let!(:token) { auth.request_token(options) }
|
187
187
|
|
188
188
|
it 'requests a token from :auth_url using an HTTP GET request' do
|
189
189
|
expect(request_token_stub).to have_been_requested
|
190
190
|
expect(auth_url_request_stub).to have_been_requested
|
191
191
|
end
|
192
192
|
|
193
|
+
it 'returns a valid token generated from the token request' do
|
194
|
+
expect(token).to be_a(Ably::Models::Token)
|
195
|
+
end
|
196
|
+
|
193
197
|
context 'with :query_params' do
|
194
198
|
let(:query_params) { { 'key' => random_str } }
|
195
199
|
|
@@ -216,6 +220,32 @@ describe Ably::Auth do
|
|
216
220
|
end
|
217
221
|
end
|
218
222
|
|
223
|
+
context 'when response from :auth_url is a token' do
|
224
|
+
let(:token_id) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' }
|
225
|
+
let(:issued_at) { Time.now }
|
226
|
+
let(:expires) { Time.now + 60}
|
227
|
+
let(:capability) { {'foo'=>['publish']} }
|
228
|
+
let(:auth_url_response) do
|
229
|
+
{
|
230
|
+
'id' => token_id,
|
231
|
+
'key' => 'J_0Tlg.NxCRig',
|
232
|
+
'issued_at' => issued_at.to_i,
|
233
|
+
'expires' => expires.to_i,
|
234
|
+
'capability'=> capability
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
let!(:token) { auth.request_token(options) }
|
239
|
+
|
240
|
+
it 'returns a Token created from the token JSON' do
|
241
|
+
expect(request_token_stub).to_not have_been_requested
|
242
|
+
expect(token.id).to eql(token_id)
|
243
|
+
expect(token.expires_at).to be_within(1).of(expires)
|
244
|
+
expect(token.issued_at).to be_within(1).of(issued_at)
|
245
|
+
expect(token.capability.to_json).to eql(capability.to_json)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
219
249
|
context 'when response is invalid' do
|
220
250
|
context '500' do
|
221
251
|
let!(:auth_url_request_stub) do
|
@@ -240,10 +270,10 @@ describe Ably::Auth do
|
|
240
270
|
end
|
241
271
|
end
|
242
272
|
|
243
|
-
context 'with token_request_block' do
|
273
|
+
context 'with token_request_block that returns a token request' do
|
244
274
|
let(:client_id) { random_str }
|
245
275
|
let(:options) { { client_id: client_id } }
|
246
|
-
let!(:
|
276
|
+
let!(:request_token) do
|
247
277
|
auth.request_token(options) do |block_options|
|
248
278
|
@block_called = true
|
249
279
|
@block_options = block_options
|
@@ -257,7 +287,45 @@ describe Ably::Auth do
|
|
257
287
|
end
|
258
288
|
|
259
289
|
it 'uses the token request from the block when requesting a new token' do
|
260
|
-
expect(
|
290
|
+
expect(request_token.client_id).to eql(client_id)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context 'with token_request_block that returns a token' do
|
295
|
+
let(:client_id) { random_str }
|
296
|
+
let(:options) { { client_id: client_id } }
|
297
|
+
let(:token_id) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' }
|
298
|
+
let(:issued_at) { Time.now }
|
299
|
+
let(:expires) { Time.now + 60}
|
300
|
+
let(:capability) { {'foo'=>['publish']} }
|
301
|
+
|
302
|
+
let!(:request_token) do
|
303
|
+
auth.request_token(options) do |block_options|
|
304
|
+
@block_called = true
|
305
|
+
@block_options = block_options
|
306
|
+
{
|
307
|
+
'id' => token_id,
|
308
|
+
'key' => 'J_0Tlg.NxCRig',
|
309
|
+
'client_id' => client_id,
|
310
|
+
'issued_at' => issued_at.to_i,
|
311
|
+
'expires' => expires.to_i,
|
312
|
+
'capability'=> capability
|
313
|
+
}
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
it 'calls the block when authenticating to obtain the request token' do
|
318
|
+
expect(@block_called).to eql(true)
|
319
|
+
expect(@block_options).to include(options)
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'uses the token request from the block when requesting a new token' do
|
323
|
+
expect(request_token).to be_a(Ably::Models::Token)
|
324
|
+
expect(request_token.id).to eql(token_id)
|
325
|
+
expect(request_token.client_id).to eql(client_id)
|
326
|
+
expect(request_token.expires_at).to be_within(1).of(expires)
|
327
|
+
expect(request_token.issued_at).to be_within(1).of(issued_at)
|
328
|
+
expect(request_token.capability.to_json).to eql(capability.to_json)
|
261
329
|
end
|
262
330
|
end
|
263
331
|
end
|
@@ -113,6 +113,14 @@ shared_examples 'a client initializer' do
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
context 'with a string token key instead of options hash' do
|
117
|
+
let(:client_options) { 'app.kjhkasjhdsakdh127g7g1271' }
|
118
|
+
|
119
|
+
it 'sets the token_id' do
|
120
|
+
expect(subject.auth.token_id).to eql(client_options)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
116
124
|
context 'with token' do
|
117
125
|
let(:client_options) { { token_id: 'token' } }
|
118
126
|
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_examples 'a safe Deferrable' do
|
4
|
+
let(:logger) { instance_double('Logger') }
|
5
|
+
let(:arguments) { [random_str] }
|
6
|
+
let(:errback_calls) { [] }
|
7
|
+
let(:success_calls) { [] }
|
8
|
+
let(:exception) { StandardError.new("Intentional error") }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(subject).to receive(:logger).and_return(logger)
|
12
|
+
end
|
13
|
+
|
14
|
+
context '#errback' do
|
15
|
+
it 'adds a callback that is called when #fail is called' do
|
16
|
+
subject.errback do |*args|
|
17
|
+
expect(args).to eql(arguments)
|
18
|
+
end
|
19
|
+
subject.fail *arguments
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'catches exceptions in the callback and logs the error to the logger' do
|
23
|
+
expect(subject.send(:logger)).to receive(:error).with(/#{exception.message}/)
|
24
|
+
subject.errback do
|
25
|
+
raise exception
|
26
|
+
end
|
27
|
+
subject.fail
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context '#fail' do
|
32
|
+
it 'calls the callbacks defined with #errback, but not the ones added for success #callback' do
|
33
|
+
3.times do
|
34
|
+
subject.errback { errback_calls << true }
|
35
|
+
subject.callback { success_calls << true }
|
36
|
+
end
|
37
|
+
subject.fail *arguments
|
38
|
+
expect(errback_calls.count).to eql(3)
|
39
|
+
expect(success_calls.count).to eql(0)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context '#callback' do
|
44
|
+
it 'adds a callback that is called when #succed is called' do
|
45
|
+
subject.callback do |*args|
|
46
|
+
expect(args).to eql(arguments)
|
47
|
+
end
|
48
|
+
subject.succeed *arguments
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'catches exceptions in the callback and logs the error to the logger' do
|
52
|
+
expect(subject.send(:logger)).to receive(:error).with(/#{exception.message}/)
|
53
|
+
subject.callback do
|
54
|
+
raise exception
|
55
|
+
end
|
56
|
+
subject.succeed
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context '#succeed' do
|
61
|
+
it 'calls the callbacks defined with #callback, but not the ones added for #errback' do
|
62
|
+
3.times do
|
63
|
+
subject.errback { errback_calls << true }
|
64
|
+
subject.callback { success_calls << true }
|
65
|
+
end
|
66
|
+
subject.succeed *arguments
|
67
|
+
expect(success_calls.count).to eql(3)
|
68
|
+
expect(errback_calls.count).to eql(0)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/support/api_helper.rb
CHANGED
data/spec/support/test_app.rb
CHANGED
@@ -15,10 +15,10 @@ class TestApp
|
|
15
15
|
{
|
16
16
|
'name' => 'persisted:presence_fixtures',
|
17
17
|
'presence' => [
|
18
|
-
{ 'clientId' => 'client_bool', '
|
19
|
-
{ 'clientId' => 'client_int', '
|
20
|
-
{ 'clientId' => 'client_string', '
|
21
|
-
{ 'clientId' => 'client_json', '
|
18
|
+
{ 'clientId' => 'client_bool', 'data' => 'true' },
|
19
|
+
{ 'clientId' => 'client_int', 'data' => '24' },
|
20
|
+
{ 'clientId' => 'client_string', 'data' => 'This is a string clientData payload' },
|
21
|
+
{ 'clientId' => 'client_json', 'data' => '{ "test" => \'This is a JSONObject clientData payload\'}' }
|
22
22
|
]
|
23
23
|
}
|
24
24
|
]
|
@@ -79,7 +79,7 @@ class TestApp
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def environment
|
82
|
-
'sandbox'
|
82
|
+
ENV['ABLY_ENV'] || 'sandbox'
|
83
83
|
end
|
84
84
|
|
85
85
|
def create_test_app
|
@@ -90,7 +90,12 @@ class TestApp
|
|
90
90
|
'Content-Type' => 'application/json'
|
91
91
|
}
|
92
92
|
|
93
|
-
|
93
|
+
response = Faraday.post(url, APP_SPEC.to_json, headers)
|
94
|
+
raise "Could not create test app. Ably responded with status #{response.status}\n#{response.body}" unless (200..299).include?(response.status)
|
95
|
+
|
96
|
+
@attributes = JSON.parse(response.body)
|
97
|
+
|
98
|
+
puts "Test app '#{app_id}' created in #{environment} environment"
|
94
99
|
end
|
95
100
|
|
96
101
|
def host
|
@@ -103,7 +108,8 @@ class TestApp
|
|
103
108
|
|
104
109
|
def create_test_stats(stats)
|
105
110
|
client = Ably::Rest::Client.new(api_key: api_key, environment: environment)
|
106
|
-
client.post('/stats', stats)
|
111
|
+
response = client.post('/stats', stats)
|
112
|
+
raise "Could not create stats fixtures. Ably responded with status #{response.status}\n#{response.body}" unless (200..299).include?(response.status)
|
107
113
|
end
|
108
114
|
|
109
115
|
private
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'shared/model_behaviour'
|
4
2
|
require 'base64'
|
5
3
|
require 'msgpack'
|
6
4
|
|
5
|
+
require 'spec_helper'
|
6
|
+
require 'shared/model_behaviour'
|
7
|
+
|
7
8
|
describe Ably::Models::Message do
|
8
9
|
include Ably::Modules::Conversions
|
9
10
|
|
@@ -12,11 +13,11 @@ describe Ably::Models::Message do
|
|
12
13
|
let(:protocol_message) { Ably::Models::ProtocolMessage.new(action: 1, timestamp: protocol_message_timestamp) }
|
13
14
|
|
14
15
|
it_behaves_like 'a model', with_simple_attributes: %w(name client_id data encoding) do
|
15
|
-
let(:model_args) { [protocol_message] }
|
16
|
+
let(:model_args) { [protocol_message: protocol_message] }
|
16
17
|
end
|
17
18
|
|
18
19
|
context '#timestamp' do
|
19
|
-
let(:model) { subject.new({}, protocol_message) }
|
20
|
+
let(:model) { subject.new({}, protocol_message: protocol_message) }
|
20
21
|
|
21
22
|
it 'retrieves attribute :timestamp as Time object from ProtocolMessage' do
|
22
23
|
expect(model.timestamp).to be_a(Time)
|
@@ -39,7 +40,7 @@ describe Ably::Models::Message do
|
|
39
40
|
end
|
40
41
|
|
41
42
|
context 'with a protocol message with a different connectionId' do
|
42
|
-
let(:model) { subject.new({ 'connectionId' => model_connection_id }, protocol_message) }
|
43
|
+
let(:model) { subject.new({ 'connectionId' => model_connection_id }, protocol_message: protocol_message) }
|
43
44
|
|
44
45
|
it 'uses the model value' do
|
45
46
|
expect(model.connection_id).to eql(model_connection_id)
|
@@ -57,7 +58,7 @@ describe Ably::Models::Message do
|
|
57
58
|
end
|
58
59
|
|
59
60
|
context 'with a protocol message with a connectionId' do
|
60
|
-
let(:model) { subject.new({ }, protocol_message) }
|
61
|
+
let(:model) { subject.new({ }, protocol_message: protocol_message) }
|
61
62
|
|
62
63
|
it 'uses the model value' do
|
63
64
|
expect(model.connection_id).to eql(protocol_connection_id)
|
@@ -67,7 +68,7 @@ describe Ably::Models::Message do
|
|
67
68
|
end
|
68
69
|
|
69
70
|
context 'Java naming', :api_private do
|
70
|
-
let(:model) { subject.new({ clientId: 'joe' }, protocol_message) }
|
71
|
+
let(:model) { subject.new({ clientId: 'joe' }, protocol_message: protocol_message) }
|
71
72
|
|
72
73
|
it 'converts the attribute to ruby symbol naming convention' do
|
73
74
|
expect(model.client_id).to eql('joe')
|
@@ -80,7 +81,7 @@ describe Ably::Models::Message do
|
|
80
81
|
let(:encoded_value) { value.encode(encoding) }
|
81
82
|
let(:value) { random_str }
|
82
83
|
let(:options) { { attribute.to_sym => encoded_value } }
|
83
|
-
let(:model) { subject.new(options, protocol_message) }
|
84
|
+
let(:model) { subject.new(options, protocol_message: protocol_message) }
|
84
85
|
let(:model_attribute) { model.public_send(attribute) }
|
85
86
|
|
86
87
|
context 'as UTF_8 string' do
|
@@ -142,7 +143,7 @@ describe Ably::Models::Message do
|
|
142
143
|
let(:json_object) { JSON.parse(model.to_json) }
|
143
144
|
|
144
145
|
context 'with valid data' do
|
145
|
-
let(:model) { subject.new({ name: 'test', clientId: 'joe' }, protocol_message) }
|
146
|
+
let(:model) { subject.new({ name: 'test', clientId: 'joe' }, protocol_message: protocol_message) }
|
146
147
|
|
147
148
|
it 'converts the attribute back to Java mixedCase notation using string keys' do
|
148
149
|
expect(json_object["clientId"]).to eql('joe')
|
@@ -150,7 +151,7 @@ describe Ably::Models::Message do
|
|
150
151
|
end
|
151
152
|
|
152
153
|
context 'with invalid data' do
|
153
|
-
let(:model) { subject.new({ clientId: 'joe' }, protocol_message) }
|
154
|
+
let(:model) { subject.new({ clientId: 'joe' }, protocol_message: protocol_message) }
|
154
155
|
|
155
156
|
it 'raises an exception' do
|
156
157
|
expect { model.to_json }.to raise_error RuntimeError, /cannot generate a valid Hash/
|
@@ -159,7 +160,7 @@ describe Ably::Models::Message do
|
|
159
160
|
|
160
161
|
context 'with binary data' do
|
161
162
|
let(:data) { MessagePack.pack(random_str(32)) }
|
162
|
-
let(:model) { subject.new({ name: 'test', data: data }, protocol_message) }
|
163
|
+
let(:model) { subject.new({ name: 'test', data: data }, protocol_message: protocol_message) }
|
163
164
|
|
164
165
|
it 'encodes as Base64 so that it can be converted to UTF-8 automatically by JSON#dump' do
|
165
166
|
expect(json_object["data"]).to eql(::Base64.encode64(data))
|
@@ -188,7 +189,7 @@ describe Ably::Models::Message do
|
|
188
189
|
end
|
189
190
|
|
190
191
|
context 'with protocol message' do
|
191
|
-
let(:model) { subject.new({ id: id, timestamp: message_timestamp }, protocol_message) }
|
192
|
+
let(:model) { subject.new({ id: id, timestamp: message_timestamp }, protocol_message: protocol_message) }
|
192
193
|
|
193
194
|
specify '#id prefers embedded ID' do
|
194
195
|
expect(model.id).to eql(id)
|
@@ -322,7 +323,7 @@ describe Ably::Models::Message do
|
|
322
323
|
end
|
323
324
|
|
324
325
|
context 'with ProtocolMessage' do
|
325
|
-
subject { Ably::Models.Message(json, protocol_message) }
|
326
|
+
subject { Ably::Models.Message(json, protocol_message: protocol_message) }
|
326
327
|
|
327
328
|
it 'returns a Message object' do
|
328
329
|
expect(subject).to be_a(Ably::Models::Message)
|
@@ -366,7 +367,7 @@ describe Ably::Models::Message do
|
|
366
367
|
end
|
367
368
|
|
368
369
|
context 'with ProtocolMessage' do
|
369
|
-
subject { Ably::Models.Message(message, protocol_message) }
|
370
|
+
subject { Ably::Models.Message(message, protocol_message: protocol_message) }
|
370
371
|
|
371
372
|
it 'returns a Message object' do
|
372
373
|
expect(subject).to be_a(Ably::Models::Message)
|
@@ -5,7 +5,7 @@ describe Ably::Models::PaginatedResource do
|
|
5
5
|
let(:paginated_resource_class) { Ably::Models::PaginatedResource }
|
6
6
|
let(:headers) { Hash.new }
|
7
7
|
let(:client) do
|
8
|
-
instance_double('Ably::Rest::Client').tap do |client|
|
8
|
+
instance_double('Ably::Rest::Client', logger: true).tap do |client|
|
9
9
|
allow(client).to receive(:get).and_return(http_response)
|
10
10
|
end
|
11
11
|
end
|
@@ -90,7 +90,7 @@ describe Ably::Models::PaginatedResource do
|
|
90
90
|
}
|
91
91
|
end
|
92
92
|
let(:paged_client) do
|
93
|
-
instance_double('Ably::Rest::Client').tap do |client|
|
93
|
+
instance_double('Ably::Rest::Client', logger: true).tap do |client|
|
94
94
|
allow(client).to receive(:get).and_return(http_response_page2)
|
95
95
|
end
|
96
96
|
end
|
@@ -137,9 +137,9 @@ describe Ably::Models::PaginatedResource do
|
|
137
137
|
end
|
138
138
|
|
139
139
|
context '#next_page' do
|
140
|
-
it 'returns a
|
140
|
+
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
141
141
|
run_reactor do
|
142
|
-
expect(subject.next_page).to be_a(
|
142
|
+
expect(subject.next_page).to be_a(Ably::Util::SafeDeferrable)
|
143
143
|
stop_reactor
|
144
144
|
end
|
145
145
|
end
|