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
@@ -14,8 +14,8 @@ describe Ably::Realtime::Client, '#stats', :event_machine do
14
14
  end
15
15
  end
16
16
 
17
- it 'should return a Deferrable object' do
18
- expect(client.stats).to be_a(EventMachine::Deferrable)
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 'should return a deferrable object' do
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(EventMachine::Deferrable)
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(:token_request) { { id: key_id } }
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 => token_request.to_json,
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
- before { auth.request_token options }
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!(:token) do
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,66 @@ 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(token.client_id).to eql(client_id)
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)
329
+ end
330
+ end
331
+
332
+ context 'persisted option', api_private: true do
333
+ context 'when set to true', api_private: true do
334
+ let(:options) { { persisted: true } }
335
+ let(:token) { auth.request_token(options) }
336
+
337
+ it 'returns a token with a short token ID that is used to look up the token details' do
338
+ expect(token.id.length).to be < 64
339
+ expect(token.id).to match(/^#{app_id}\.A/)
340
+ end
341
+ end
342
+
343
+ context 'when omitted', api_private: true do
344
+ let(:options) { { } }
345
+ let(:token) { auth.request_token(options) }
346
+
347
+ it 'returns a literal token' do
348
+ expect(token.id.length).to be > 64
349
+ end
261
350
  end
262
351
  end
263
352
  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
@@ -44,7 +44,7 @@ RSpec.configure do |config|
44
44
 
45
45
  config.after(:suite) do
46
46
  WebMock.disable!
47
- TestApp.instance.delete
47
+ TestApp.instance.delete if TestApp.instance_variable_get('@singleton__instance__')
48
48
  end
49
49
  end
50
50
 
@@ -6,7 +6,7 @@ module RSpec
6
6
  module EventMachine
7
7
  extend self
8
8
 
9
- DEFAULT_TIMEOUT = 10
9
+ DEFAULT_TIMEOUT = 15
10
10
 
11
11
  def run_reactor(timeout = DEFAULT_TIMEOUT)
12
12
  Timeout::timeout(timeout + 0.5) do
@@ -15,10 +15,10 @@ class TestApp
15
15
  {
16
16
  'name' => 'persisted:presence_fixtures',
17
17
  'presence' => [
18
- { 'clientId' => 'client_bool', 'clientData' => 'true' },
19
- { 'clientId' => 'client_int', 'clientData' => '24' },
20
- { 'clientId' => 'client_string', 'clientData' => 'This is a string clientData payload' },
21
- { 'clientId' => 'client_json', 'clientData' => '{ "test" => \'This is a JSONObject clientData payload\'}' }
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
- @attributes = JSON.parse(Faraday.post(url, APP_SPEC.to_json, headers).body)
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 deferrable object' do
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(EventMachine::Deferrable)
142
+ expect(subject.next_page).to be_a(Ably::Util::SafeDeferrable)
143
143
  stop_reactor
144
144
  end
145
145
  end