ably 1.1.6 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check.yml +15 -1
  3. data/CHANGELOG.md +131 -0
  4. data/COPYRIGHT +1 -1
  5. data/README.md +14 -2
  6. data/SPEC.md +0 -7
  7. data/UPDATING.md +30 -0
  8. data/ably.gemspec +12 -7
  9. data/lib/ably/agent.rb +3 -0
  10. data/lib/ably/auth.rb +3 -3
  11. data/lib/ably/exceptions.rb +6 -0
  12. data/lib/ably/models/channel_options.rb +97 -0
  13. data/lib/ably/models/connection_details.rb +8 -0
  14. data/lib/ably/models/delta_extras.rb +29 -0
  15. data/lib/ably/models/error_info.rb +6 -2
  16. data/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
  17. data/lib/ably/models/message.rb +28 -3
  18. data/lib/ably/models/presence_message.rb +14 -0
  19. data/lib/ably/models/protocol_message.rb +29 -12
  20. data/lib/ably/models/token_details.rb +7 -2
  21. data/lib/ably/modules/channels_collection.rb +22 -2
  22. data/lib/ably/modules/conversions.rb +34 -0
  23. data/lib/ably/realtime/channel/channel_manager.rb +18 -6
  24. data/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
  25. data/lib/ably/realtime/channel/publisher.rb +6 -0
  26. data/lib/ably/realtime/channel.rb +54 -22
  27. data/lib/ably/realtime/channels.rb +1 -1
  28. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
  29. data/lib/ably/realtime/connection/connection_manager.rb +13 -4
  30. data/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
  31. data/lib/ably/realtime/connection.rb +2 -2
  32. data/lib/ably/rest/channel.rb +31 -31
  33. data/lib/ably/rest/client.rb +27 -12
  34. data/lib/ably/util/crypto.rb +1 -1
  35. data/lib/ably/version.rb +2 -14
  36. data/lib/ably.rb +1 -0
  37. data/spec/acceptance/realtime/auth_spec.rb +1 -1
  38. data/spec/acceptance/realtime/channel_history_spec.rb +25 -0
  39. data/spec/acceptance/realtime/channel_spec.rb +466 -21
  40. data/spec/acceptance/realtime/channels_spec.rb +59 -7
  41. data/spec/acceptance/realtime/connection_failures_spec.rb +59 -2
  42. data/spec/acceptance/realtime/connection_spec.rb +256 -28
  43. data/spec/acceptance/realtime/message_spec.rb +77 -0
  44. data/spec/acceptance/realtime/presence_history_spec.rb +3 -1
  45. data/spec/acceptance/realtime/presence_spec.rb +31 -159
  46. data/spec/acceptance/rest/auth_spec.rb +18 -0
  47. data/spec/acceptance/rest/channel_spec.rb +84 -9
  48. data/spec/acceptance/rest/channels_spec.rb +23 -6
  49. data/spec/acceptance/rest/client_spec.rb +25 -21
  50. data/spec/acceptance/rest/message_spec.rb +61 -3
  51. data/spec/lib/unit/models/channel_options_spec.rb +52 -0
  52. data/spec/shared/model_behaviour.rb +1 -1
  53. data/spec/spec_helper.rb +11 -2
  54. data/spec/support/test_app.rb +1 -1
  55. data/spec/unit/models/delta_extras_spec.rb +14 -0
  56. data/spec/unit/models/error_info_spec.rb +17 -1
  57. data/spec/unit/models/message_spec.rb +97 -0
  58. data/spec/unit/models/presence_message_spec.rb +49 -0
  59. data/spec/unit/models/protocol_message_spec.rb +125 -27
  60. data/spec/unit/models/token_details_spec.rb +14 -0
  61. data/spec/unit/realtime/channel_spec.rb +3 -2
  62. data/spec/unit/realtime/channels_spec.rb +53 -15
  63. data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
  64. data/spec/unit/rest/channel_spec.rb +44 -1
  65. data/spec/unit/rest/channels_spec.rb +81 -14
  66. data/spec/unit/rest/client_spec.rb +47 -0
  67. 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 'coveralls'
9
- Coveralls.wear!
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'
@@ -59,7 +59,7 @@ class TestApp
59
59
 
60
60
  url = "#{sandbox_client.endpoint}/apps/#{app_id}"
61
61
 
62
- basic_auth = Base64.encode64(api_key).chomp
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, TR4e
13
+ # TR4n, TR4b, TR4c, TR4d
14
14
  it_behaves_like 'a model',
15
- with_simple_attributes: %w(id channel channel_serial connection_id connection_key),
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(:message) { { 'name' => 'event', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
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: [message] }) }
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"].first).to include(message)
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: [message], :timestamp => as_since_epoch(Time.now) }) }
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: [message] }) }
429
- let(:message) { { 'name' => 'event', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
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('event')
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) { double('client').as_null_object }
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) { instance_double('Ably::Realtime::Client', connection: connection, client_id: 'clientId') }
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) { { 'bizarre' => 'value' } }
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
- it 'creates a channel if it does not exist' do
15
- expect(Ably::Realtime::Channel).to receive(:new).with(client, channel_name, options)
16
- subject.get(channel_name, options)
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
- it 'will reuse a channel object if it exists' do
21
- channel = subject.get(channel_name, options)
22
- expect(channel).to be_a(Ably::Realtime::Channel)
23
- expect(subject.get(channel_name, options).object_id).to eql(channel.object_id)
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 eql(options)
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 eql(true)
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 eql(options)
74
+ expect(channel.options.to_h).to eq(options)
37
75
  subject.get(channel_name)
38
- expect(channel.options).to eql(options)
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