ably 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check.yml +1 -1
  3. data/CHANGELOG.md +17 -0
  4. data/README.md +24 -7
  5. data/SPEC.md +1722 -853
  6. data/ably.gemspec +1 -1
  7. data/lib/ably/auth.rb +19 -11
  8. data/lib/ably/models/protocol_message.rb +5 -26
  9. data/lib/ably/modules/safe_deferrable.rb +2 -2
  10. data/lib/ably/modules/state_emitter.rb +1 -1
  11. data/lib/ably/realtime/auth.rb +4 -0
  12. data/lib/ably/realtime/channel/channel_manager.rb +51 -48
  13. data/lib/ably/realtime/channel/channel_properties.rb +9 -0
  14. data/lib/ably/realtime/channel/channel_state_machine.rb +2 -0
  15. data/lib/ably/realtime/channel.rb +4 -3
  16. data/lib/ably/realtime/channels.rb +20 -0
  17. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -13
  18. data/lib/ably/realtime/client.rb +14 -6
  19. data/lib/ably/realtime/connection/connection_manager.rb +21 -22
  20. data/lib/ably/realtime/connection.rb +77 -109
  21. data/lib/ably/realtime/presence/members_map.rb +41 -92
  22. data/lib/ably/realtime/presence/presence_manager.rb +12 -17
  23. data/lib/ably/realtime/presence.rb +15 -6
  24. data/lib/ably/realtime/push.rb +0 -27
  25. data/lib/ably/realtime/recovery_key_context.rb +36 -0
  26. data/lib/ably/rest/client.rb +4 -6
  27. data/lib/ably/rest/push/admin.rb +1 -1
  28. data/lib/ably/rest/push.rb +0 -19
  29. data/lib/ably/util/ably_extensions.rb +29 -0
  30. data/lib/ably/util/crypto.rb +2 -2
  31. data/lib/ably/util/safe_deferrable.rb +1 -1
  32. data/lib/ably/version.rb +5 -7
  33. data/spec/acceptance/realtime/channel_history_spec.rb +8 -12
  34. data/spec/acceptance/realtime/channel_spec.rb +474 -300
  35. data/spec/acceptance/realtime/client_spec.rb +1 -1
  36. data/spec/acceptance/realtime/connection_failures_spec.rb +8 -25
  37. data/spec/acceptance/realtime/connection_spec.rb +28 -120
  38. data/spec/acceptance/realtime/message_spec.rb +23 -52
  39. data/spec/acceptance/realtime/presence_spec.rb +123 -92
  40. data/spec/acceptance/rest/channel_spec.rb +2 -2
  41. data/spec/acceptance/rest/client_spec.rb +9 -2
  42. data/spec/acceptance/rest/message_spec.rb +8 -11
  43. data/spec/acceptance/rest/push_admin_spec.rb +20 -15
  44. data/spec/shared/client_initializer_behaviour.rb +1 -1
  45. data/spec/support/markdown_spec_formatter.rb +1 -1
  46. data/spec/unit/models/protocol_message_spec.rb +0 -78
  47. data/spec/unit/models/token_details_spec.rb +4 -2
  48. data/spec/unit/realtime/channels_spec.rb +1 -1
  49. data/spec/unit/realtime/connection_spec.rb +0 -30
  50. data/spec/unit/realtime/recovery_key_context_spec.rb +36 -0
  51. data/spec/unit/util/crypto_spec.rb +15 -15
  52. metadata +9 -9
  53. data/spec/acceptance/realtime/push_spec.rb +0 -27
  54. data/spec/acceptance/rest/push_spec.rb +0 -25
@@ -127,14 +127,6 @@ describe Ably::Models::ProtocolMessage do
127
127
  end
128
128
  end
129
129
 
130
- context '#connection_serial' do
131
- let(:protocol_message) { new_protocol_message(connection_serial: "55") }
132
- it 'converts :connection_serial to an Integer' do
133
- expect(protocol_message.connection_serial).to be_a(Integer)
134
- expect(protocol_message.connection_serial).to eql(55)
135
- end
136
- end
137
-
138
130
  context '#flags (#TR4i)' do
139
131
  context 'when nil' do
140
132
  let(:protocol_message) { new_protocol_message({}) }
@@ -241,76 +233,6 @@ describe Ably::Models::ProtocolMessage do
241
233
  end
242
234
  end
243
235
 
244
- context '#has_connection_serial?' do
245
- context 'without connection_serial' do
246
- let(:protocol_message) { new_protocol_message({}) }
247
-
248
- it 'returns false' do
249
- expect(protocol_message.has_connection_serial?).to eql(false)
250
- end
251
- end
252
-
253
- context 'with connection_serial' do
254
- let(:protocol_message) { new_protocol_message(connection_serial: "55") }
255
-
256
- it 'returns true' do
257
- expect(protocol_message.has_connection_serial?).to eql(true)
258
- end
259
- end
260
- end
261
-
262
- context '#serial' do
263
- context 'with underlying msg_serial' do
264
- let(:protocol_message) { new_protocol_message(msg_serial: "55") }
265
- it 'converts :msg_serial to an Integer' do
266
- expect(protocol_message.serial).to be_a(Integer)
267
- expect(protocol_message.serial).to eql(55)
268
- end
269
- end
270
-
271
- context 'with underlying connection_serial' do
272
- let(:protocol_message) { new_protocol_message(connection_serial: "55") }
273
- it 'converts :connection_serial to an Integer' do
274
- expect(protocol_message.serial).to be_a(Integer)
275
- expect(protocol_message.serial).to eql(55)
276
- end
277
- end
278
-
279
- context 'with underlying connection_serial and msg_serial' do
280
- let(:protocol_message) { new_protocol_message(connection_serial: "99", msg_serial: "11") }
281
- it 'prefers connection_serial and converts :connection_serial to an Integer' do
282
- expect(protocol_message.serial).to be_a(Integer)
283
- expect(protocol_message.serial).to eql(99)
284
- end
285
- end
286
- end
287
-
288
- context '#has_serial?' do
289
- context 'without msg_serial or connection_serial' do
290
- let(:protocol_message) { new_protocol_message({}) }
291
-
292
- it 'returns false' do
293
- expect(protocol_message.has_serial?).to eql(false)
294
- end
295
- end
296
-
297
- context 'with msg_serial' do
298
- let(:protocol_message) { new_protocol_message(msg_serial: "55") }
299
-
300
- it 'returns true' do
301
- expect(protocol_message.has_serial?).to eql(true)
302
- end
303
- end
304
-
305
- context 'with connection_serial' do
306
- let(:protocol_message) { new_protocol_message(connection_serial: "55") }
307
-
308
- it 'returns true' do
309
- expect(protocol_message.has_serial?).to eql(true)
310
- end
311
- end
312
- end
313
-
314
236
  context '#error' do
315
237
  context 'with no error attribute' do
316
238
  let(:protocol_message) { new_protocol_message(action: 1) }
@@ -56,6 +56,7 @@ describe Ably::Models::TokenDetails do
56
56
 
57
57
  context '#expired?' do
58
58
  let(:expire_time) { Time.now + Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER }
59
+ let(:clock_skew) { 1 } # clock skew of 1 second
59
60
 
60
61
  context 'once grace period buffer has passed' do
61
62
  subject { Ably::Models::TokenDetails.new(expires: expire_time - 1) }
@@ -74,7 +75,7 @@ describe Ably::Models::TokenDetails do
74
75
  end
75
76
 
76
77
  context 'when expires is not available (i.e. string tokens)' do
77
- subject { Ably::Models::TokenDetails.new() }
78
+ subject { Ably::Models::TokenDetails.new }
78
79
 
79
80
  it 'is always false' do
80
81
  expect(subject.expired?).to eql(false)
@@ -90,8 +91,9 @@ describe Ably::Models::TokenDetails do
90
91
  expect(subject.expired?(from: (Time.now - server_offset_time))).to eql(false)
91
92
  end
92
93
 
94
+ # Test is flaky and fails on CI, so adding a bit of extra tolerance (clock_skew) to make it work
93
95
  it 'is true' do
94
- expect(subject.expired?(from: Time.now)).to eql(true)
96
+ expect(subject.expired?(from: Time.now + clock_skew)).to eql(true)
95
97
  end
96
98
  end
97
99
  end
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Ably::Realtime::Channels do
5
- let(:connection) { instance_double('Ably::Realtime::Connection', unsafe_on: true, on_resume: true) }
5
+ let(:connection) { instance_double('Ably::Realtime::Connection', unsafe_on: true) }
6
6
  let(:client) do
7
7
  instance_double('Ably::Realtime::Client', connection: connection, client_id: 'clientId', logger: double('logger').as_null_object)
8
8
  end
@@ -34,36 +34,6 @@ describe Ably::Realtime::Connection do
34
34
  it_behaves_like 'an incoming protocol message bus'
35
35
  it_behaves_like 'an outgoing protocol message bus'
36
36
 
37
- describe 'connection resume callbacks', api_private: true do
38
- let(:callbacks) { [] }
39
-
40
- describe '#trigger_resumed' do
41
- it 'executes the callbacks' do
42
- subject.on_resume { callbacks << true }
43
- subject.trigger_resumed
44
- expect(callbacks.count).to eql(1)
45
- end
46
- end
47
-
48
- describe '#on_resume' do
49
- it 'registers a callback' do
50
- subject.on_resume { callbacks << true }
51
- subject.trigger_resumed
52
- expect(callbacks.count).to eql(1)
53
- end
54
- end
55
-
56
- describe '#off_resume' do
57
- it 'registers a callback' do
58
- subject.on_resume { callbacks << true }
59
- additional_proc = lambda { raise 'This should not be called' }
60
- subject.off_resume(&additional_proc)
61
- subject.trigger_resumed
62
- expect(callbacks.count).to eql(1)
63
- end
64
- end
65
- end
66
-
67
37
  after(:all) do
68
38
  sleep 1 # let realtime library shut down any open clients
69
39
  end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'ably/realtime/recovery_key_context'
3
+
4
+ describe Ably::Realtime::RecoveryKeyContext do
5
+
6
+ context 'connection recovery key' do
7
+
8
+ it 'should encode recovery key - RTN16i, RTN16f, RTN16j' do
9
+ connection_key = 'key'
10
+ msg_serial = 123
11
+ channel_serials = {
12
+ 'channel1' => 'serial1',
13
+ 'channel2' => 'serial2'
14
+ }
15
+ recovery_context = Ably::Realtime::RecoveryKeyContext.new(connection_key, msg_serial, channel_serials)
16
+ encoded_recovery_key = recovery_context.to_json
17
+ expect(encoded_recovery_key).to eq "{\"connection_key\":\"key\",\"msg_serial\":123," <<
18
+ "\"channel_serials\":{\"channel1\":\"serial1\",\"channel2\":\"serial2\"}}"
19
+ end
20
+
21
+ it 'should decode recovery key - RTN16i, RTN16f, RTN16j' do
22
+ encoded_recovery_key = "{\"connection_key\":\"key\",\"msg_serial\":123," <<
23
+ "\"channel_serials\":{\"channel1\":\"serial1\",\"channel2\":\"serial2\"}}"
24
+ decoded_recovery_key = Ably::Realtime::RecoveryKeyContext.from_json(encoded_recovery_key)
25
+ expect(decoded_recovery_key.connection_key).to eq("key")
26
+ expect(decoded_recovery_key.msg_serial).to eq(123)
27
+ end
28
+
29
+ it 'should return nil for invalid recovery key - RTN16i, RTN16f, RTN16j' do
30
+ encoded_recovery_key = "{\"invalid key\"}"
31
+ decoded_recovery_key = Ably::Realtime::RecoveryKeyContext.from_json(encoded_recovery_key)
32
+ expect(decoded_recovery_key).to be_nil
33
+ end
34
+
35
+ end
36
+ end
@@ -72,26 +72,26 @@ describe Ably::Util::Crypto do
72
72
  end
73
73
  end
74
74
 
75
- context 'encrypts & decrypt' do
75
+ context '#encrypt & #decrypt' do
76
76
  let(:string) { random_str }
77
- let(:byte_array) { random_str.to_msgpack.unpack('C*') }
78
-
79
- specify '#encrypt encrypts a string' do
80
- encrypted = subject.encrypt(string)
81
- expect(subject.decrypt(encrypted)).to eql(string)
82
- end
77
+ let(:empty_string) { '' }
83
78
 
84
- specify '#decrypt decrypts a string' do
79
+ specify 'encrypts and decrypts a non-empty string' do
80
+ expect(string).to be_ascii_only
85
81
  encrypted = subject.encrypt(string)
86
- expect(subject.decrypt(encrypted)).to eql(string)
82
+ expect(encrypted).to be_truthy
83
+ decrypted = subject.decrypt(encrypted)
84
+ expect(decrypted).to eql(string)
85
+ expect(decrypted).to be_ascii_only
87
86
  end
88
- end
89
-
90
- context 'encrypting an empty string' do
91
- let(:empty_string) { '' }
92
87
 
93
- it 'raises an ArgumentError' do
94
- expect { subject.encrypt(empty_string) }.to raise_error ArgumentError, /data must not be empty/
88
+ specify 'encrypts and decrypts an empty string' do
89
+ expect(empty_string).to be_ascii_only
90
+ encrypted = subject.encrypt(empty_string)
91
+ expect(encrypted).to be_truthy
92
+ decrypted = subject.decrypt(encrypted)
93
+ expect(decrypted).to eql(empty_string)
94
+ expect(decrypted).to be_ascii_only
95
95
  end
96
96
  end
97
97
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ably
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lewis Marshall
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-05-16 00:00:00.000000000 Z
12
+ date: 2024-07-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -283,14 +283,14 @@ dependencies:
283
283
  requirements:
284
284
  - - "~>"
285
285
  - !ruby/object:Gem::Version
286
- version: 0.21.2
286
+ version: 0.22.0
287
287
  type: :development
288
288
  prerelease: false
289
289
  version_requirements: !ruby/object:Gem::Requirement
290
290
  requirements:
291
291
  - - "~>"
292
292
  - !ruby/object:Gem::Version
293
- version: 0.21.2
293
+ version: 0.22.0
294
294
  - !ruby/object:Gem::Dependency
295
295
  name: simplecov-lcov
296
296
  requirement: !ruby/object:Gem::Requirement
@@ -469,6 +469,7 @@ files:
469
469
  - lib/ably/realtime/push/admin.rb
470
470
  - lib/ably/realtime/push/channel_subscriptions.rb
471
471
  - lib/ably/realtime/push/device_registrations.rb
472
+ - lib/ably/realtime/recovery_key_context.rb
472
473
  - lib/ably/rest.rb
473
474
  - lib/ably/rest/channel.rb
474
475
  - lib/ably/rest/channel/push_channel.rb
@@ -486,6 +487,7 @@ files:
486
487
  - lib/ably/rest/push/admin.rb
487
488
  - lib/ably/rest/push/channel_subscriptions.rb
488
489
  - lib/ably/rest/push/device_registrations.rb
490
+ - lib/ably/util/ably_extensions.rb
489
491
  - lib/ably/util/crypto.rb
490
492
  - lib/ably/util/pub_sub.rb
491
493
  - lib/ably/util/safe_deferrable.rb
@@ -501,7 +503,6 @@ files:
501
503
  - spec/acceptance/realtime/presence_history_spec.rb
502
504
  - spec/acceptance/realtime/presence_spec.rb
503
505
  - spec/acceptance/realtime/push_admin_spec.rb
504
- - spec/acceptance/realtime/push_spec.rb
505
506
  - spec/acceptance/realtime/stats_spec.rb
506
507
  - spec/acceptance/realtime/time_spec.rb
507
508
  - spec/acceptance/rest/auth_spec.rb
@@ -513,7 +514,6 @@ files:
513
514
  - spec/acceptance/rest/message_spec.rb
514
515
  - spec/acceptance/rest/presence_spec.rb
515
516
  - spec/acceptance/rest/push_admin_spec.rb
516
- - spec/acceptance/rest/push_spec.rb
517
517
  - spec/acceptance/rest/stats_spec.rb
518
518
  - spec/acceptance/rest/time_spec.rb
519
519
  - spec/lib/unit/models/channel_options_spec.rb
@@ -578,6 +578,7 @@ files:
578
578
  - spec/unit/realtime/presence_spec.rb
579
579
  - spec/unit/realtime/push_channel_spec.rb
580
580
  - spec/unit/realtime/realtime_spec.rb
581
+ - spec/unit/realtime/recovery_key_context_spec.rb
581
582
  - spec/unit/realtime/safe_deferrable_spec.rb
582
583
  - spec/unit/realtime/websocket_transport_spec.rb
583
584
  - spec/unit/rest/channel_spec.rb
@@ -606,7 +607,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
606
607
  - !ruby/object:Gem::Version
607
608
  version: '0'
608
609
  requirements: []
609
- rubygems_version: 3.3.7
610
+ rubygems_version: 3.5.4
610
611
  signing_key:
611
612
  specification_version: 4
612
613
  summary: A Ruby client library for ably.io realtime messaging implemented using EventMachine
@@ -622,7 +623,6 @@ test_files:
622
623
  - spec/acceptance/realtime/presence_history_spec.rb
623
624
  - spec/acceptance/realtime/presence_spec.rb
624
625
  - spec/acceptance/realtime/push_admin_spec.rb
625
- - spec/acceptance/realtime/push_spec.rb
626
626
  - spec/acceptance/realtime/stats_spec.rb
627
627
  - spec/acceptance/realtime/time_spec.rb
628
628
  - spec/acceptance/rest/auth_spec.rb
@@ -634,7 +634,6 @@ test_files:
634
634
  - spec/acceptance/rest/message_spec.rb
635
635
  - spec/acceptance/rest/presence_spec.rb
636
636
  - spec/acceptance/rest/push_admin_spec.rb
637
- - spec/acceptance/rest/push_spec.rb
638
637
  - spec/acceptance/rest/stats_spec.rb
639
638
  - spec/acceptance/rest/time_spec.rb
640
639
  - spec/lib/unit/models/channel_options_spec.rb
@@ -699,6 +698,7 @@ test_files:
699
698
  - spec/unit/realtime/presence_spec.rb
700
699
  - spec/unit/realtime/push_channel_spec.rb
701
700
  - spec/unit/realtime/realtime_spec.rb
701
+ - spec/unit/realtime/recovery_key_context_spec.rb
702
702
  - spec/unit/realtime/safe_deferrable_spec.rb
703
703
  - spec/unit/realtime/websocket_transport_spec.rb
704
704
  - spec/unit/rest/channel_spec.rb
@@ -1,27 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe Ably::Realtime::Push, :event_machine do
5
- vary_by_protocol do
6
- let(:default_options) { { key: api_key, environment: environment, protocol: protocol} }
7
- let(:client_options) { default_options }
8
- let(:client) do
9
- Ably::Realtime::Client.new(client_options)
10
- end
11
- subject { client.push }
12
-
13
- describe '#activate' do
14
- it 'raises an unsupported exception' do
15
- expect { subject.activate('foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
16
- stop_reactor
17
- end
18
- end
19
-
20
- describe '#deactivate' do
21
- it 'raises an unsupported exception' do
22
- expect { subject.deactivate('foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
23
- stop_reactor
24
- end
25
- end
26
- end
27
- end
@@ -1,25 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe Ably::Rest::Push do
5
- vary_by_protocol do
6
- let(:default_options) { { key: api_key, environment: environment, protocol: protocol} }
7
- let(:client_options) { default_options }
8
- let(:client) do
9
- Ably::Rest::Client.new(client_options)
10
- end
11
- subject { client.push }
12
-
13
- describe '#activate' do
14
- it 'raises an unsupported exception' do
15
- expect { subject.activate('foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
16
- end
17
- end
18
-
19
- describe '#deactivate' do
20
- it 'raises an unsupported exception' do
21
- expect { subject.deactivate('foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
22
- end
23
- end
24
- end
25
- end