ably 1.1.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +15 -1
- data/CHANGELOG.md +131 -0
- data/COPYRIGHT +1 -1
- data/README.md +14 -2
- data/SPEC.md +0 -7
- data/UPDATING.md +30 -0
- data/ably.gemspec +12 -7
- data/lib/ably/agent.rb +3 -0
- data/lib/ably/auth.rb +3 -3
- data/lib/ably/exceptions.rb +6 -0
- data/lib/ably/models/channel_options.rb +97 -0
- data/lib/ably/models/connection_details.rb +8 -0
- data/lib/ably/models/delta_extras.rb +29 -0
- data/lib/ably/models/error_info.rb +6 -2
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
- data/lib/ably/models/message.rb +28 -3
- data/lib/ably/models/presence_message.rb +14 -0
- data/lib/ably/models/protocol_message.rb +29 -12
- data/lib/ably/models/token_details.rb +7 -2
- data/lib/ably/modules/channels_collection.rb +22 -2
- data/lib/ably/modules/conversions.rb +34 -0
- data/lib/ably/realtime/channel/channel_manager.rb +18 -6
- data/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
- data/lib/ably/realtime/channel/publisher.rb +6 -0
- data/lib/ably/realtime/channel.rb +54 -22
- data/lib/ably/realtime/channels.rb +1 -1
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
- data/lib/ably/realtime/connection/connection_manager.rb +13 -4
- data/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
- data/lib/ably/realtime/connection.rb +2 -2
- data/lib/ably/rest/channel.rb +31 -31
- data/lib/ably/rest/client.rb +27 -12
- data/lib/ably/util/crypto.rb +1 -1
- data/lib/ably/version.rb +2 -14
- data/lib/ably.rb +1 -0
- data/spec/acceptance/realtime/auth_spec.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +25 -0
- data/spec/acceptance/realtime/channel_spec.rb +466 -21
- data/spec/acceptance/realtime/channels_spec.rb +59 -7
- data/spec/acceptance/realtime/connection_failures_spec.rb +59 -2
- data/spec/acceptance/realtime/connection_spec.rb +256 -28
- data/spec/acceptance/realtime/message_spec.rb +77 -0
- data/spec/acceptance/realtime/presence_history_spec.rb +3 -1
- data/spec/acceptance/realtime/presence_spec.rb +31 -159
- data/spec/acceptance/rest/auth_spec.rb +18 -0
- data/spec/acceptance/rest/channel_spec.rb +84 -9
- data/spec/acceptance/rest/channels_spec.rb +23 -6
- data/spec/acceptance/rest/client_spec.rb +25 -21
- data/spec/acceptance/rest/message_spec.rb +61 -3
- data/spec/lib/unit/models/channel_options_spec.rb +52 -0
- data/spec/shared/model_behaviour.rb +1 -1
- data/spec/spec_helper.rb +11 -2
- data/spec/support/test_app.rb +1 -1
- data/spec/unit/models/delta_extras_spec.rb +14 -0
- data/spec/unit/models/error_info_spec.rb +17 -1
- data/spec/unit/models/message_spec.rb +97 -0
- data/spec/unit/models/presence_message_spec.rb +49 -0
- data/spec/unit/models/protocol_message_spec.rb +125 -27
- data/spec/unit/models/token_details_spec.rb +14 -0
- data/spec/unit/realtime/channel_spec.rb +3 -2
- data/spec/unit/realtime/channels_spec.rb +53 -15
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
- data/spec/unit/rest/channel_spec.rb +44 -1
- data/spec/unit/rest/channels_spec.rb +81 -14
- data/spec/unit/rest/client_spec.rb +47 -0
- metadata +60 -24
@@ -19,7 +19,7 @@ shared_examples 'a model' do |shared_options = {}|
|
|
19
19
|
end
|
20
20
|
|
21
21
|
context '#attributes', :api_private do
|
22
|
-
let(:model_options) { { action: 5 } }
|
22
|
+
let(:model_options) { { action: 5, max_message_size: 65536, max_frame_size: 524288 } }
|
23
23
|
|
24
24
|
it 'provides access to #attributes' do
|
25
25
|
expect(model.attributes).to eq(model_options)
|
data/spec/spec_helper.rb
CHANGED
@@ -5,8 +5,17 @@ def console(message)
|
|
5
5
|
end
|
6
6
|
|
7
7
|
unless RUBY_VERSION.match(/^1\./)
|
8
|
-
require '
|
9
|
-
|
8
|
+
require 'simplecov'
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
require 'simplecov-lcov'
|
12
|
+
SimpleCov::Formatter::LcovFormatter.config do |c|
|
13
|
+
c.report_with_single_file = true
|
14
|
+
c.single_report_path = 'coverage/lcov.info'
|
15
|
+
end
|
16
|
+
formatter SimpleCov::Formatter::LcovFormatter
|
17
|
+
add_filter %w[vendor spec]
|
18
|
+
end
|
10
19
|
end
|
11
20
|
|
12
21
|
require 'webmock/rspec'
|
data/spec/support/test_app.rb
CHANGED
@@ -59,7 +59,7 @@ class TestApp
|
|
59
59
|
|
60
60
|
url = "#{sandbox_client.endpoint}/apps/#{app_id}"
|
61
61
|
|
62
|
-
basic_auth = Base64.
|
62
|
+
basic_auth = Base64.urlsafe_encode64(api_key).chomp
|
63
63
|
headers = { "Authorization" => "Basic #{basic_auth}" }
|
64
64
|
|
65
65
|
Faraday.delete(url, nil, headers)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Ably::Models::DeltaExtras do
|
5
|
+
subject { described_class.new({ format: 'vcdiff', from: '1234-4567-8910-1001-1111'}) }
|
6
|
+
|
7
|
+
it 'should have `from` attribute' do
|
8
|
+
expect(subject.from).to eq('1234-4567-8910-1001-1111')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should have `format` attribute' do
|
12
|
+
expect(subject.format).to eq('vcdiff')
|
13
|
+
end
|
14
|
+
end
|
@@ -5,7 +5,7 @@ describe Ably::Models::ErrorInfo do
|
|
5
5
|
subject { Ably::Models::ErrorInfo }
|
6
6
|
|
7
7
|
context '#TI1, #TI4' do
|
8
|
-
it_behaves_like 'a model', with_simple_attributes: %w(code status_code href message) do
|
8
|
+
it_behaves_like 'a model', with_simple_attributes: %w(code status_code href message request_id cause) do
|
9
9
|
let(:model_args) { [] }
|
10
10
|
end
|
11
11
|
end
|
@@ -18,6 +18,22 @@ describe Ably::Models::ErrorInfo do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
context '#request_id #RSC7c' do
|
22
|
+
subject { Ably::Models::ErrorInfo.new('request_id' => '123-456-789-001') }
|
23
|
+
|
24
|
+
it 'should return request ID' do
|
25
|
+
expect(subject.request_id).to eql('123-456-789-001')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#cause #TI1' do
|
30
|
+
subject { Ably::Models::ErrorInfo.new('cause' => Ably::Models::ErrorInfo.new({})) }
|
31
|
+
|
32
|
+
it 'should return cause attribute' do
|
33
|
+
expect(subject.cause).to be_kind_of(Ably::Models::ErrorInfo)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
21
37
|
context 'log entries container help link #TI5' do
|
22
38
|
context 'without an error code' do
|
23
39
|
subject { Ably::Models::ErrorInfo.new('statusCode' => 401) }
|
@@ -211,6 +211,79 @@ describe Ably::Models::Message do
|
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
214
|
+
describe '#size' do
|
215
|
+
let(:model) { subject.new({ name: name, data: data, client_id: client_id, extras: extras }, protocol_message: protocol_message) }
|
216
|
+
|
217
|
+
context 'String (#TO3l8a)' do
|
218
|
+
let(:data) { 'example string data' }
|
219
|
+
let(:client_id) { '1' }
|
220
|
+
let(:name) { 'My Name' }
|
221
|
+
let(:extras) { 'extras' }
|
222
|
+
|
223
|
+
it 'should return 33 bytes' do
|
224
|
+
expect(model.size).to eq(33)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'Object (#TO3l8b)' do
|
229
|
+
let(:data) { Object.new }
|
230
|
+
let(:client_id) { String('10') }
|
231
|
+
let(:name) { 'John' }
|
232
|
+
let(:extras) { Hash.new }
|
233
|
+
|
234
|
+
it 'should return 38 bytes' do
|
235
|
+
expect(model.size).to eq(38)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'Array (#TO3l8b)' do
|
240
|
+
let(:data) { [1, 'two', :three] }
|
241
|
+
let(:client_id) { '2' }
|
242
|
+
let(:name) { 'Kate' }
|
243
|
+
let(:extras) { [] }
|
244
|
+
|
245
|
+
it 'should return 24 bytes' do
|
246
|
+
expect(model.size).to eq(24)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context 'extras (#TO3l8d)' do
|
251
|
+
let(:data) { { example: 'value', score: 1, hash: { test: true } } }
|
252
|
+
let(:client_id) { '3' }
|
253
|
+
let(:name) { 'John' }
|
254
|
+
let(:extras) { {} }
|
255
|
+
|
256
|
+
it 'should return 57 bytes' do
|
257
|
+
expect(model.size).to eq(57)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context 'nil (#TO3l8e)' do
|
262
|
+
let(:data) { nil }
|
263
|
+
let(:client_id) { '' }
|
264
|
+
let(:name) { '' }
|
265
|
+
let(:extras) { nil}
|
266
|
+
|
267
|
+
it 'should return 19 bytes' do
|
268
|
+
expect(model.size).to eq(0)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe '#protocol_message_index (#RTL21)' do
|
274
|
+
let(:messages) { [{ name: 'test1' }, { name: 'test2' }, { name: 'test3' }] }
|
275
|
+
|
276
|
+
let(:protocol_message) do
|
277
|
+
Ably::Models::ProtocolMessage.new({ action: 1 }.merge(messages: messages))
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'should return correct protocol_message_index' do
|
281
|
+
expect(protocol_message.messages[0].protocol_message_index).to eq(0)
|
282
|
+
expect(protocol_message.messages[1].protocol_message_index).to eq(1)
|
283
|
+
expect(protocol_message.messages[2].protocol_message_index).to eq(2)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
214
287
|
context 'from REST request with embedded fields', :api_private do
|
215
288
|
let(:id) { random_str }
|
216
289
|
let(:protocol_message_id) { random_str }
|
@@ -547,4 +620,28 @@ describe Ably::Models::Message do
|
|
547
620
|
end
|
548
621
|
end
|
549
622
|
end
|
623
|
+
|
624
|
+
context '#delta_extras (TM2i)' do
|
625
|
+
let(:delta_extras) { message.delta_extras }
|
626
|
+
|
627
|
+
context 'when delta' do
|
628
|
+
let(:message) { subject.new({ extras: { delta: { from: '1234-1234-5678-9009', format: 'vcdiff' } } }) }
|
629
|
+
|
630
|
+
it 'should return vcdiff format' do
|
631
|
+
expect(delta_extras.format).to eq('vcdiff')
|
632
|
+
end
|
633
|
+
|
634
|
+
it 'should return 1234-1234-5678-9009 message id' do
|
635
|
+
expect(delta_extras.from).to eq('1234-1234-5678-9009')
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
context 'when no delta' do
|
640
|
+
let(:message) { subject.new({ extras: {} }) }
|
641
|
+
|
642
|
+
it 'should return nil' do
|
643
|
+
expect(delta_extras).to eq(nil)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
550
647
|
end
|
@@ -220,6 +220,55 @@ describe Ably::Models::PresenceMessage do
|
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
223
|
+
describe '#size' do
|
224
|
+
let(:model) { subject.new({ action: 'enter', data: data, client_id: client_id }, protocol_message: protocol_message) }
|
225
|
+
|
226
|
+
context 'String (#TO3l8a)' do
|
227
|
+
let(:data) { 'example string data' }
|
228
|
+
let(:client_id) { '1' }
|
229
|
+
|
230
|
+
it 'should return 20 bytes' do
|
231
|
+
expect(model.size).to eq(20)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'Object (#TO3l8b)' do
|
236
|
+
let(:data) { Object.new }
|
237
|
+
let(:client_id) { '10' }
|
238
|
+
|
239
|
+
it 'should return 32 bytes' do
|
240
|
+
expect(model.size).to eq(32)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context 'Array (#TO3l8b)' do
|
245
|
+
let(:data) { [1, 'two', :three] }
|
246
|
+
let(:client_id) { '2' }
|
247
|
+
|
248
|
+
it 'should return 18 bytes' do
|
249
|
+
expect(model.size).to eq(18)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'extras (#TO3l8d)' do
|
254
|
+
let(:data) { { example: 'value', score: 1, hash: { test: true } } }
|
255
|
+
let(:client_id) { '3' }
|
256
|
+
|
257
|
+
it 'should return 51 bytes' do
|
258
|
+
expect(model.size).to eq(51)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
context 'nil (#TO3l8e)' do
|
263
|
+
let(:data) { nil }
|
264
|
+
let(:client_id) { '4' }
|
265
|
+
|
266
|
+
it 'should return 1 bytes' do
|
267
|
+
expect(model.size).to eq(1)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
223
272
|
context 'from REST request with embedded fields', :api_private do
|
224
273
|
let(:id) { random_str }
|
225
274
|
let(:message_time) { Time.now + 60 }
|
@@ -10,9 +10,9 @@ describe Ably::Models::ProtocolMessage do
|
|
10
10
|
subject.new({ action: 1 }.merge(options))
|
11
11
|
end
|
12
12
|
|
13
|
-
# TR4n, TR4b, TR4c, TR4d
|
13
|
+
# TR4n, TR4b, TR4c, TR4d
|
14
14
|
it_behaves_like 'a model',
|
15
|
-
with_simple_attributes: %w(id channel channel_serial connection_id
|
15
|
+
with_simple_attributes: %w(id channel channel_serial connection_id),
|
16
16
|
base_model_options: { action: 1 } do
|
17
17
|
|
18
18
|
let(:model_args) { [] }
|
@@ -176,6 +176,28 @@ describe Ably::Models::ProtocolMessage do
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
context 'when attach resumed flag' do
|
180
|
+
context 'flags is 34' do
|
181
|
+
let(:protocol_message) { new_protocol_message(flags: 34) }
|
182
|
+
|
183
|
+
it '#has_attach_resume_flag? is true' do
|
184
|
+
expect(protocol_message.has_attach_resume_flag?).to be_truthy
|
185
|
+
end
|
186
|
+
|
187
|
+
it '#has_attach_presence_flag? is false' do
|
188
|
+
expect(protocol_message.has_attach_presence_flag?).to be_falsey
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'flags is 0' do
|
193
|
+
let(:protocol_message) { new_protocol_message(flags: 0) }
|
194
|
+
|
195
|
+
it 'should raise an exception if flags is a float number' do
|
196
|
+
expect(protocol_message.has_attach_resume_flag?).to be_falsy
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
179
201
|
context 'when channel resumed and presence flags present' do
|
180
202
|
let(:protocol_message) { new_protocol_message(flags: 5) }
|
181
203
|
|
@@ -201,6 +223,24 @@ describe Ably::Models::ProtocolMessage do
|
|
201
223
|
end
|
202
224
|
end
|
203
225
|
|
226
|
+
context '#params (#RTL4k1)' do
|
227
|
+
let(:params) do
|
228
|
+
{ foo: :bar }
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'when present' do
|
232
|
+
specify do
|
233
|
+
expect(new_protocol_message({ params: params }).params).to eq(params)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context 'when empty' do
|
238
|
+
specify do
|
239
|
+
expect(new_protocol_message({}).params).to eq({})
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
204
244
|
context '#has_connection_serial?' do
|
205
245
|
context 'without connection_serial' do
|
206
246
|
let(:protocol_message) { new_protocol_message({}) }
|
@@ -308,6 +348,26 @@ describe Ably::Models::ProtocolMessage do
|
|
308
348
|
end
|
309
349
|
end
|
310
350
|
|
351
|
+
context '#messages (#RTL21)' do
|
352
|
+
let(:protocol_message) do
|
353
|
+
new_protocol_message(messages: [{ name: 'test1' }, { name: 'test2' }, { name: 'test3' }])
|
354
|
+
end
|
355
|
+
|
356
|
+
before do
|
357
|
+
message = Ably::Models::Message(name: 'test4')
|
358
|
+
message.assign_to_protocol_message(protocol_message)
|
359
|
+
protocol_message.add_message(message)
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'contains Message objects in ascending order' do
|
363
|
+
expect(protocol_message.messages.count).to eql(4)
|
364
|
+
protocol_message.messages.each_with_index do |message, index|
|
365
|
+
expect(message.protocol_message_index).to eql(index)
|
366
|
+
expect(message.name).to include('test')
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
311
371
|
context '#presence (#TR4l)' do
|
312
372
|
let(:protocol_message) { new_protocol_message(presence: [{ action: 1, data: 'test' }]) }
|
313
373
|
|
@@ -318,6 +378,54 @@ describe Ably::Models::ProtocolMessage do
|
|
318
378
|
end
|
319
379
|
end
|
320
380
|
|
381
|
+
context '#message_size (#TO3l8)' do
|
382
|
+
context 'on presence' do
|
383
|
+
let(:protocol_message) do
|
384
|
+
new_protocol_message(presence: [{ action: 1, data: 'test342343', client_id: 'sdf' }])
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'should return 13 bytes (sum in bytes: data and client_id)' do
|
388
|
+
expect(protocol_message.message_size).to eq(13)
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
context 'on message' do
|
393
|
+
let(:protocol_message) do
|
394
|
+
new_protocol_message(messages: [{ action: 1, unknown: 'test', data: 'test342343', client_id: 'sdf', name: 'sf23ewrew', extras: { time: Time.now, time_zone: 'UTC' } }])
|
395
|
+
end
|
396
|
+
|
397
|
+
it 'should return 76 bytes (sum in bytes: data, client_id, name, extras)' do
|
398
|
+
expect(protocol_message.message_size).to eq(76)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
context '#has_correct_message_size? (#TO3l8)' do
|
404
|
+
context 'on presence' do
|
405
|
+
it 'should return true when a message has correct size' do
|
406
|
+
protocol_message = new_protocol_message(presence: [{ action: 1, data: 'x' * 100 }])
|
407
|
+
expect(protocol_message.has_correct_message_size?).to eq(true)
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'should return false when a message has not correct size' do
|
411
|
+
protocol_message = new_protocol_message(presence: [{ action: 1, data: 'x' * 65537 }])
|
412
|
+
expect(protocol_message.has_correct_message_size?).to eq(false)
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
context 'on message' do
|
417
|
+
it 'should return true when a message has correct size' do
|
418
|
+
protocol_message = new_protocol_message(messages: [{ name: 'x' * 100 }])
|
419
|
+
expect(protocol_message.has_correct_message_size?).to eq(true)
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'should return false when a message has not correct size' do
|
423
|
+
protocol_message = new_protocol_message(messages: [{ name: 'x' * 65537 }])
|
424
|
+
expect(protocol_message.has_correct_message_size?).to eq(false)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
321
429
|
context '#connection_details (#TR4o)' do
|
322
430
|
let(:connection_details) { protocol_message.connection_details }
|
323
431
|
|
@@ -369,41 +477,27 @@ describe Ably::Models::ProtocolMessage do
|
|
369
477
|
end
|
370
478
|
end
|
371
479
|
end
|
372
|
-
|
373
|
-
context '#connection_key (#TR4e)' do
|
374
|
-
context 'existing only in #connection_details.connection_key' do
|
375
|
-
let(:protocol_message) { new_protocol_message(connectionDetails: { connectionKey: 'key' }) }
|
376
|
-
|
377
|
-
it 'is returned' do
|
378
|
-
expect(protocol_message.connection_key).to eql('key')
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
|
-
context 'existing in both #connection_key and #connection_details.connection_key' do
|
383
|
-
let(:protocol_message) { new_protocol_message(connectionKey: 'deprecated', connectionDetails: { connectionKey: 'key' }) }
|
384
|
-
|
385
|
-
it 'returns #connection_details.connection_key as #connection_key will be deprecated > 0.8' do
|
386
|
-
expect(protocol_message.connection_key).to eql('key')
|
387
|
-
end
|
388
|
-
end
|
389
|
-
end
|
390
480
|
end
|
391
481
|
|
392
482
|
context '#to_json', :api_private do
|
393
483
|
let(:json_object) { JSON.parse(model.to_json) }
|
394
|
-
let(:
|
484
|
+
let(:message1) { { 'name' => 'event1', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
485
|
+
let(:message2) { { 'name' => 'event2', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
486
|
+
let(:message3) { { 'name' => 'event3', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
395
487
|
let(:attached_action) { Ably::Models::ProtocolMessage::ACTION.Attached }
|
396
488
|
let(:message_action) { Ably::Models::ProtocolMessage::ACTION.Message }
|
397
489
|
|
398
490
|
context 'with valid data' do
|
399
|
-
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [
|
491
|
+
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [message1, message2, message3] }) }
|
400
492
|
|
401
493
|
it 'converts the attribute back to Java mixedCase notation using string keys' do
|
402
494
|
expect(json_object["channelSerial"]).to eql('unique')
|
403
495
|
end
|
404
496
|
|
405
497
|
it 'populates the messages' do
|
406
|
-
expect(json_object["messages"]
|
498
|
+
expect(json_object["messages"][0]).to include(message1)
|
499
|
+
expect(json_object["messages"][1]).to include(message2)
|
500
|
+
expect(json_object["messages"][2]).to include(message3)
|
407
501
|
end
|
408
502
|
end
|
409
503
|
|
@@ -416,7 +510,7 @@ describe Ably::Models::ProtocolMessage do
|
|
416
510
|
end
|
417
511
|
|
418
512
|
context 'is aliased by #to_s' do
|
419
|
-
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [
|
513
|
+
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [message1, message2, message3], :timestamp => as_since_epoch(Time.now) }) }
|
420
514
|
|
421
515
|
specify do
|
422
516
|
expect(json_object).to eql(JSON.parse("#{model}"))
|
@@ -425,14 +519,18 @@ describe Ably::Models::ProtocolMessage do
|
|
425
519
|
end
|
426
520
|
|
427
521
|
context '#to_msgpack', :api_private do
|
428
|
-
let(:model) { new_protocol_message({ :connectionSerial => 'unique', messages: [
|
429
|
-
let(:
|
522
|
+
let(:model) { new_protocol_message({ :connectionSerial => 'unique', messages: [message1, message2, message3] }) }
|
523
|
+
let(:message1) { { 'name' => 'event1', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
524
|
+
let(:message2) { { 'name' => 'event2', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
525
|
+
let(:message3) { { 'name' => 'event3', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
430
526
|
let(:packed) { model.to_msgpack }
|
431
527
|
let(:unpacked) { MessagePack.unpack(packed) }
|
432
528
|
|
433
529
|
it 'returns a unpackable msgpack object' do
|
434
530
|
expect(unpacked['connectionSerial']).to eq('unique')
|
435
|
-
expect(unpacked['messages'][0]['name']).to eq('
|
531
|
+
expect(unpacked['messages'][0]['name']).to eq('event1')
|
532
|
+
expect(unpacked['messages'][1]['name']).to eq('event2')
|
533
|
+
expect(unpacked['messages'][2]['name']).to eq('event3')
|
436
534
|
end
|
437
535
|
end
|
438
536
|
end
|
@@ -80,6 +80,20 @@ describe Ably::Models::TokenDetails do
|
|
80
80
|
expect(subject.expired?).to eql(false)
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
context 'with :from attribute' do
|
85
|
+
subject { Ably::Models::TokenDetails.new(expires: expire_time) }
|
86
|
+
|
87
|
+
let(:server_offset_time) { 2 * 60 * 60 } # 2 hours
|
88
|
+
|
89
|
+
it 'is false' do
|
90
|
+
expect(subject.expired?(from: (Time.now - server_offset_time))).to eql(false)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'is true' do
|
94
|
+
expect(subject.expired?(from: Time.now)).to eql(true)
|
95
|
+
end
|
96
|
+
end
|
83
97
|
end
|
84
98
|
end
|
85
99
|
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
require 'shared/protocol_msgbus_behaviour'
|
4
4
|
|
5
5
|
describe Ably::Realtime::Channel do
|
6
|
-
let(:client) {
|
6
|
+
let(:client) { Ably::Realtime::Client.new(token: 'valid') }
|
7
7
|
let(:channel_name) { 'test' }
|
8
8
|
|
9
9
|
subject do
|
@@ -68,9 +68,10 @@ describe Ably::Realtime::Channel do
|
|
68
68
|
|
69
69
|
describe '#publish name argument' do
|
70
70
|
let(:encoded_value) { random_str.encode(encoding) }
|
71
|
-
let(:message) { instance_double('Ably::Models::Message', client_id: nil) }
|
71
|
+
let(:message) { instance_double('Ably::Models::Message', client_id: nil, size: 0) }
|
72
72
|
|
73
73
|
before do
|
74
|
+
allow(subject).to receive(:enqueue_messages_on_connection).and_return(message)
|
74
75
|
allow(subject).to receive(:create_message).and_return(message)
|
75
76
|
allow(subject).to receive(:attach).and_return(:true)
|
76
77
|
end
|
@@ -3,39 +3,77 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe Ably::Realtime::Channels do
|
5
5
|
let(:connection) { instance_double('Ably::Realtime::Connection', unsafe_on: true, on_resume: true) }
|
6
|
-
let(:client)
|
6
|
+
let(:client) do
|
7
|
+
instance_double('Ably::Realtime::Client', connection: connection, client_id: 'clientId', logger: double('logger').as_null_object)
|
8
|
+
end
|
7
9
|
let(:channel_name) { 'unique' }
|
8
|
-
let(:options)
|
10
|
+
let(:options) do
|
11
|
+
{ params: { bizarre: 'value' } }
|
12
|
+
end
|
9
13
|
|
10
14
|
subject { Ably::Realtime::Channels.new(client) }
|
11
15
|
|
12
16
|
context 'creating channels' do
|
13
17
|
context '#get' do
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
context "when channel doesn't exist" do
|
19
|
+
shared_examples 'creates a channel' do
|
20
|
+
it 'creates a channel (RTS3a)' do
|
21
|
+
expect(Ably::Realtime::Channel).to receive(:new).with(client, channel_name, channel_options)
|
22
|
+
subject.get(channel_name, channel_options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'hash' do
|
27
|
+
let(:channel_options) { options }
|
28
|
+
it { expect(channel_options).to be_a(Hash) }
|
29
|
+
|
30
|
+
include_examples 'creates a channel'
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'ChannelOptions object' do
|
34
|
+
let(:channel_options) { Ably::Models::ChannelOptions.new(options) }
|
35
|
+
it { expect(channel_options).to be_a(Ably::Models::ChannelOptions) }
|
36
|
+
|
37
|
+
include_examples 'creates a channel'
|
38
|
+
end
|
17
39
|
end
|
18
40
|
|
19
41
|
context 'when an existing channel exists' do
|
20
|
-
|
21
|
-
channel
|
22
|
-
|
23
|
-
|
42
|
+
shared_examples 'reuse a channel object if it exists' do
|
43
|
+
it 'will reuse a channel object if it exists (RTS3a)' do
|
44
|
+
channel = subject.get(channel_name, channel_options)
|
45
|
+
expect(channel).to be_a(Ably::Realtime::Channel)
|
46
|
+
expect(subject.get(channel_name, channel_options).object_id).to eql(channel.object_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'hash' do
|
51
|
+
let(:channel_options) { options }
|
52
|
+
it { expect(channel_options).to be_a(Hash) }
|
53
|
+
|
54
|
+
include_examples 'reuse a channel object if it exists'
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'ChannelOptions object' do
|
58
|
+
let(:channel_options) { Ably::Models::ChannelOptions.new(options) }
|
59
|
+
it { expect(channel_options).to be_a(Ably::Models::ChannelOptions) }
|
60
|
+
|
61
|
+
include_examples 'reuse a channel object if it exists'
|
24
62
|
end
|
25
63
|
|
26
|
-
it 'will update the options on the channel if provided' do
|
64
|
+
it 'will update the options on the channel if provided (RSN3c)' do
|
27
65
|
channel = subject.get(channel_name, options)
|
28
|
-
expect(channel.options).to
|
29
|
-
expect(channel.options).to_not include(:encrypted)
|
66
|
+
expect(channel.options.to_h).to eq(options)
|
67
|
+
expect(channel.options.to_h).to_not include(:encrypted)
|
30
68
|
subject.get(channel_name, encrypted: true)
|
31
|
-
expect(channel.options[:encrypted]).to
|
69
|
+
expect(channel.options[:encrypted]).to eq(true)
|
32
70
|
end
|
33
71
|
|
34
72
|
it 'will leave the options intact on the channel if not provided' do
|
35
73
|
channel = subject.get(channel_name, options)
|
36
|
-
expect(channel.options).to
|
74
|
+
expect(channel.options.to_h).to eq(options)
|
37
75
|
subject.get(channel_name)
|
38
|
-
expect(channel.options).to
|
76
|
+
expect(channel.options.to_h).to eq(options)
|
39
77
|
end
|
40
78
|
end
|
41
79
|
end
|
@@ -32,5 +32,43 @@ describe Ably::Realtime::Client::IncomingMessageDispatcher, :api_private do
|
|
32
32
|
expect(subject).to receive_message_chain(:logger, :warn)
|
33
33
|
msgbus.publish :protocol_message, Ably::Models::ProtocolMessage.new(:action => :attached, channel: 'unknown')
|
34
34
|
end
|
35
|
+
|
36
|
+
context 'TO3l8' do
|
37
|
+
context 'on action presence' do
|
38
|
+
let(:presence) { 101.times.map { { data: 'x' * 655 } } }
|
39
|
+
|
40
|
+
let(:protocol_message) do
|
41
|
+
Ably::Models::ProtocolMessage.new(action: :presence, channel: 'default', presence: presence, connection_serial: 123123123)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should raise a protocol error when message size exceeded 65536 bytes' do
|
45
|
+
allow(connection).to receive(:serial).and_return(12312312)
|
46
|
+
allow(subject).to receive(:update_connection_recovery_info)
|
47
|
+
allow(subject).to receive_message_chain(:logger, :debug)
|
48
|
+
allow(subject).to receive_message_chain(:logger, :warn)
|
49
|
+
expect(subject).to receive_message_chain(:logger, :fatal)
|
50
|
+
|
51
|
+
msgbus.publish :protocol_message, protocol_message
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'on action message' do
|
56
|
+
let(:messages) { 101.times.map { { data: 'x' * 655 } } }
|
57
|
+
|
58
|
+
let(:protocol_message) do
|
59
|
+
Ably::Models::ProtocolMessage.new(action: :message, channel: 'default', messages: messages, connection_serial: 123123123)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should raise a protocol error when message size exceeded 65536 bytes' do
|
63
|
+
allow(connection).to receive(:serial).and_return(12312312)
|
64
|
+
allow(subject).to receive(:update_connection_recovery_info)
|
65
|
+
allow(subject).to receive_message_chain(:logger, :debug)
|
66
|
+
allow(subject).to receive_message_chain(:logger, :warn)
|
67
|
+
expect(subject).to receive_message_chain(:logger, :fatal)
|
68
|
+
|
69
|
+
msgbus.publish :protocol_message, protocol_message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
35
73
|
end
|
36
74
|
end
|