ably-rest 0.9.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/ably-rest.gemspec +2 -1
  3. data/lib/submodules/ably-ruby/.travis.yml +6 -4
  4. data/lib/submodules/ably-ruby/CHANGELOG.md +52 -61
  5. data/lib/submodules/ably-ruby/README.md +10 -0
  6. data/lib/submodules/ably-ruby/SPEC.md +1473 -852
  7. data/lib/submodules/ably-ruby/ably.gemspec +2 -1
  8. data/lib/submodules/ably-ruby/lib/ably/auth.rb +57 -25
  9. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +34 -8
  10. data/lib/submodules/ably-ruby/lib/ably/logger.rb +10 -1
  11. data/lib/submodules/ably-ruby/lib/ably/models/auth_details.rb +42 -0
  12. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +18 -4
  13. data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +6 -3
  14. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +4 -3
  15. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +1 -1
  16. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +12 -1
  17. data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/base.rb +101 -97
  18. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +13 -1
  19. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +20 -3
  20. data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +7 -3
  21. data/lib/submodules/ably-ruby/lib/ably/modules/enum.rb +17 -7
  22. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +29 -14
  23. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +7 -4
  24. data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -4
  25. data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +7 -3
  26. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +2 -0
  27. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +79 -31
  28. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +62 -26
  29. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +154 -65
  30. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +14 -15
  31. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +16 -3
  32. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +38 -29
  33. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +6 -1
  34. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +108 -49
  35. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +165 -59
  36. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +22 -3
  37. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +19 -10
  38. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +67 -45
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +198 -36
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/presence_manager.rb +30 -6
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/presence_state_machine.rb +5 -12
  42. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +3 -3
  43. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +21 -8
  44. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +1 -3
  45. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/logger.rb +2 -2
  46. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
  47. data/lib/submodules/ably-ruby/lib/ably/util/pub_sub.rb +1 -1
  48. data/lib/submodules/ably-ruby/lib/ably/util/safe_deferrable.rb +26 -0
  49. data/lib/submodules/ably-ruby/lib/ably/version.rb +2 -2
  50. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +416 -99
  51. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +5 -3
  52. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +1011 -160
  53. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +2 -2
  54. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +458 -27
  55. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +436 -97
  56. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +52 -23
  57. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +5 -3
  58. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +1160 -105
  59. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +151 -22
  60. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +1 -1
  61. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +88 -27
  62. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +42 -15
  63. data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +4 -4
  64. data/lib/submodules/ably-ruby/spec/rspec_config.rb +2 -1
  65. data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +2 -2
  66. data/lib/submodules/ably-ruby/spec/shared/safe_deferrable_behaviour.rb +6 -2
  67. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +20 -4
  68. data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +32 -1
  69. data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +4 -11
  70. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +28 -2
  71. data/lib/submodules/ably-ruby/spec/unit/models/auth_details_spec.rb +49 -0
  72. data/lib/submodules/ably-ruby/spec/unit/models/channel_state_change_spec.rb +23 -3
  73. data/lib/submodules/ably-ruby/spec/unit/models/connection_details_spec.rb +12 -1
  74. data/lib/submodules/ably-ruby/spec/unit/models/connection_state_change_spec.rb +15 -4
  75. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +34 -2
  76. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +73 -2
  77. data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +64 -6
  78. data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +1 -1
  79. data/lib/submodules/ably-ruby/spec/unit/models/token_request_spec.rb +1 -1
  80. data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +2 -1
  81. data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +69 -0
  82. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +149 -22
  83. data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +9 -3
  84. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +1 -1
  85. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +8 -5
  86. data/lib/submodules/ably-ruby/spec/unit/realtime/incoming_message_dispatcher_spec.rb +1 -1
  87. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +4 -3
  88. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +1 -1
  89. data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +3 -3
  90. metadata +7 -5
@@ -6,6 +6,7 @@ describe Ably::Models::ConnectionDetails do
6
6
 
7
7
  subject { Ably::Models::ConnectionDetails }
8
8
 
9
+ # Spec model items CD2*
9
10
  it_behaves_like 'a model', with_simple_attributes: %w(client_id connection_key max_message_size max_frame_size max_inbound_rate) do
10
11
  let(:model_args) { [] }
11
12
  end
@@ -13,13 +14,23 @@ describe Ably::Models::ConnectionDetails do
13
14
  context 'attributes' do
14
15
  let(:connection_state_ttl_ms) { 5_000 }
15
16
 
16
- context '#connection_state_ttl' do
17
+ context '#connection_state_ttl (#CD2f)' do
17
18
  subject { Ably::Models::ConnectionDetails.new({ connection_state_ttl: connection_state_ttl_ms }) }
18
19
 
19
20
  it 'retrieves attribute :connection_state_ttl and converts it from ms to s' do
20
21
  expect(subject.connection_state_ttl).to eql(connection_state_ttl_ms / 1000)
21
22
  end
22
23
  end
24
+
25
+ let(:max_idle_interval) { 6_000 }
26
+
27
+ context '#max_idle_interval (#CD2h)' do
28
+ subject { Ably::Models::ConnectionDetails.new({ max_idle_interval: max_idle_interval }) }
29
+
30
+ it 'retrieves attribute :max_idle_interval and converts it from ms to s' do
31
+ expect(subject.max_idle_interval).to eql(max_idle_interval / 1000)
32
+ end
33
+ end
23
34
  end
24
35
 
25
36
  context '==' do
@@ -6,7 +6,7 @@ describe Ably::Models::ConnectionStateChange do
6
6
 
7
7
  subject { Ably::Models::ConnectionStateChange }
8
8
 
9
- context '#current' do
9
+ context '#current (#TA2)' do
10
10
  it 'is required' do
11
11
  expect { subject.new(previous: true) }.to raise_error ArgumentError
12
12
  end
@@ -16,7 +16,7 @@ describe Ably::Models::ConnectionStateChange do
16
16
  end
17
17
  end
18
18
 
19
- context '#previous' do
19
+ context '#previous(#TA2)' do
20
20
  it 'is required' do
21
21
  expect { subject.new(current: true) }.to raise_error ArgumentError
22
22
  end
@@ -26,7 +26,18 @@ describe Ably::Models::ConnectionStateChange do
26
26
  end
27
27
  end
28
28
 
29
- context '#retry_in' do
29
+ context '#event(#TA5)' do
30
+ it 'is not required' do
31
+ expect { subject.new(previous: true, current: true) }.to_not raise_error
32
+ end
33
+
34
+ it 'is an attribute' do
35
+ expect(subject.new(event: unique, current: true, previous: true).event).to eql(unique)
36
+ end
37
+ end
38
+
39
+
40
+ context '#retry_in (#TA2)' do
30
41
  it 'is not required' do
31
42
  expect { subject.new(previous: true, current: true) }.to_not raise_error
32
43
  end
@@ -36,7 +47,7 @@ describe Ably::Models::ConnectionStateChange do
36
47
  end
37
48
  end
38
49
 
39
- context '#reason' do
50
+ context '#reason (#TA3)' do
40
51
  it 'is not required' do
41
52
  expect { subject.new(previous: true, current: true) }.to_not raise_error
42
53
  end
@@ -25,6 +25,38 @@ describe Ably::Models::Message do
25
25
  end
26
26
  end
27
27
 
28
+ context '#extras (#TM2i)' do
29
+ let(:model) { subject.new({ extras: extras }, protocol_message: protocol_message) }
30
+
31
+ context 'when missing' do
32
+ let(:model) { subject.new({}, protocol_message: protocol_message) }
33
+ it 'is nil' do
34
+ expect(model.extras).to be_nil
35
+ end
36
+ end
37
+
38
+ context 'when a string' do
39
+ let(:extras) { 'string' }
40
+ it 'raises an exception' do
41
+ expect { model.extras }.to raise_error ArgumentError, /extras contains an unsupported type/
42
+ end
43
+ end
44
+
45
+ context 'when a Hash' do
46
+ let(:extras) { { key: 'value' } }
47
+ it 'contains a Hash Json object' do
48
+ expect(model.extras).to eq(extras)
49
+ end
50
+ end
51
+
52
+ context 'when a Json Array' do
53
+ let(:extras) { [{ 'key' => 'value' }] }
54
+ it 'contains a Json Array object' do
55
+ expect(model.extras).to eq(extras)
56
+ end
57
+ end
58
+ end
59
+
28
60
  context '#connection_id attribute' do
29
61
  let(:protocol_connection_id) { random_str }
30
62
  let(:protocol_message) { Ably::Models::ProtocolMessage.new('connectionId' => protocol_connection_id, action: 1, timestamp: protocol_message_timestamp) }
@@ -380,7 +412,7 @@ describe Ably::Models::Message do
380
412
  end
381
413
  end
382
414
 
383
- context '#from_encoded (TM3)' do
415
+ context '#from_encoded (#TM3)' do
384
416
  context 'with no encoding' do
385
417
  let(:message_data) do
386
418
  { name: 'name', data: 'data-string' }
@@ -482,7 +514,7 @@ describe Ably::Models::Message do
482
514
  end
483
515
  end
484
516
 
485
- context '#from_encoded_array (TM3)' do
517
+ context '#from_encoded_array (#TM3)' do
486
518
  context 'with no encoding' do
487
519
  let(:message_data) do
488
520
  [{ name: 'name1', data: 'data-string' }, { name: 'name2', data: 'data-string' }]
@@ -385,7 +385,7 @@ describe Ably::Models::PresenceMessage do
385
385
  end
386
386
 
387
387
 
388
- context '#from_encoded (TP4)' do
388
+ context '#from_encoded (#TP4)' do
389
389
  context 'with no encoding' do
390
390
  let(:message_data) do
391
391
  { action: 2, data: 'data-string' }
@@ -486,7 +486,7 @@ describe Ably::Models::PresenceMessage do
486
486
  end
487
487
  end
488
488
 
489
- context '#from_encoded_array (TP4)' do
489
+ context '#from_encoded_array (#TP4)' do
490
490
  context 'with no encoding' do
491
491
  let(:message_data) do
492
492
  [{ action: 1, data: 'data-string' }, { action: 2, data: 'data-string' }]
@@ -504,4 +504,75 @@ describe Ably::Models::PresenceMessage do
504
504
  end
505
505
  end
506
506
  end
507
+
508
+ context '#shallow_clone' do
509
+ context 'with inherited attributes from ProtocolMessage' do
510
+ let(:protocol_message) {
511
+ Ably::Models::ProtocolMessage.new('id' => 'fooId', 'connectionId' => protocol_connection_id, 'action' => 1, 'timestamp' => protocol_message_timestamp)
512
+ }
513
+ let(:protocol_connection_id) { random_str }
514
+ let(:model) { subject.new({ 'action' => 2 }, protocol_message: protocol_message) }
515
+
516
+ it 'creates a duplicate of the message without any ProtocolMessage dependency' do
517
+ clone = model.shallow_clone
518
+ expect(clone.id).to match(/fooId/)
519
+ expect(clone.connection_id).to eql(protocol_connection_id)
520
+ expect(as_since_epoch(clone.timestamp)).to eq(protocol_message_timestamp)
521
+ expect(clone.action).to eq(2)
522
+ end
523
+ end
524
+
525
+ context 'with embedded attributes for all fields' do
526
+ let(:message_timestamp) { as_since_epoch(Time.now) + 100 }
527
+ let(:connection_id) { random_str }
528
+ let(:model) { subject.new({ 'action' => 3, 'id' => 'fooId', 'connectionId' => connection_id, 'timestamp' => message_timestamp }) }
529
+
530
+ it 'creates a duplicate of the message without any ProtocolMessage dependency' do
531
+ clone = model.shallow_clone
532
+ expect(clone.id).to eql('fooId')
533
+ expect(clone.connection_id).to eql(connection_id)
534
+ expect(as_since_epoch(clone.timestamp)).to eq(message_timestamp)
535
+ expect(clone.action).to eq(3)
536
+ end
537
+ end
538
+
539
+ context 'with new attributes passed in to the method' do
540
+ let(:protocol_message) {
541
+ Ably::Models::ProtocolMessage.new('id' => 'fooId', 'connectionId' => protocol_connection_id, 'action' => 1, 'timestamp' => protocol_message_timestamp)
542
+ }
543
+ let(:protocol_connection_id) { random_str }
544
+ let(:model) { subject.new({ 'action' => 2 }, protocol_message: protocol_message) }
545
+
546
+ it 'creates a duplicate of the message without any ProtocolMessage dependency' do
547
+ clone = model.shallow_clone(id: 'newId', action: 1, timestamp: protocol_message_timestamp + 1000)
548
+ expect(clone.id).to match(/newId/)
549
+ expect(clone.connection_id).to eql(protocol_connection_id)
550
+ expect(as_since_epoch(clone.timestamp)).to eq(protocol_message_timestamp + 1000)
551
+ expect(clone.action).to eq(1)
552
+ end
553
+
554
+ context 'with an invalid ProtocolMessage (missing an ID)' do
555
+ let(:protocol_message) {
556
+ Ably::Models::ProtocolMessage.new('connectionId' => protocol_connection_id, 'action' => 1, 'timestamp' => protocol_message_timestamp)
557
+ }
558
+ it 'allows an ID to be passed in to the shallow clone that takes precedence' do
559
+ clone = model.shallow_clone(id: 'newId', action: 1, timestamp: protocol_message_timestamp + 1000)
560
+ expect(clone.id).to match(/newId/)
561
+ end
562
+ end
563
+
564
+ context 'with mixing of cases' do
565
+ it 'resolves case issues and can use camelCase or snake_case' do
566
+ clone = model.shallow_clone(connectionId: 'camelCaseSym')
567
+ expect(clone.connection_id).to match(/camelCaseSym/)
568
+
569
+ clone = model.shallow_clone('connectionId' => 'camelCaseStr')
570
+ expect(clone.connection_id).to match(/camelCaseStr/)
571
+
572
+ clone = model.shallow_clone(connection_id: 'snake_case_sym')
573
+ expect(clone.connection_id).to match(/snake_case_sym/)
574
+ end
575
+ end
576
+ end
577
+ end
507
578
  end
@@ -10,6 +10,7 @@ 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
14
  it_behaves_like 'a model',
14
15
  with_simple_attributes: %w(id channel channel_serial connection_id connection_key),
15
16
  base_model_options: { action: 1 } do
@@ -134,7 +135,7 @@ describe Ably::Models::ProtocolMessage do
134
135
  end
135
136
  end
136
137
 
137
- context '#flags' do
138
+ context '#flags (#TR4i)' do
138
139
  context 'when nil' do
139
140
  let(:protocol_message) { new_protocol_message({}) }
140
141
 
@@ -151,12 +152,40 @@ describe Ably::Models::ProtocolMessage do
151
152
  end
152
153
  end
153
154
 
154
- context 'when has_presence' do
155
+ context 'when presence flag present' do
155
156
  let(:protocol_message) { new_protocol_message(flags: 1) }
156
157
 
157
158
  it '#has_presence_flag? is true' do
158
159
  expect(protocol_message.has_presence_flag?).to be_truthy
159
160
  end
161
+
162
+ it '#has_channel_resumed_flag? is false' do
163
+ expect(protocol_message.has_channel_resumed_flag?).to be_falsey
164
+ end
165
+ end
166
+
167
+ context 'when channel resumed flag present' do
168
+ let(:protocol_message) { new_protocol_message(flags: 4) }
169
+
170
+ it '#has_channel_resumed_flag? is true' do
171
+ expect(protocol_message.has_channel_resumed_flag?).to be_truthy
172
+ end
173
+
174
+ it '#has_presence_flag? is false' do
175
+ expect(protocol_message.has_presence_flag?).to be_falsey
176
+ end
177
+ end
178
+
179
+ context 'when channel resumed and presence flags present' do
180
+ let(:protocol_message) { new_protocol_message(flags: 5) }
181
+
182
+ it '#has_channel_resumed_flag? is true' do
183
+ expect(protocol_message.has_channel_resumed_flag?).to be_truthy
184
+ end
185
+
186
+ it '#has_presence_flag? is true' do
187
+ expect(protocol_message.has_presence_flag?).to be_truthy
188
+ end
160
189
  end
161
190
 
162
191
  context 'when has another future flag' do
@@ -165,6 +194,10 @@ describe Ably::Models::ProtocolMessage do
165
194
  it '#has_presence_flag? is false' do
166
195
  expect(protocol_message.has_presence_flag?).to be_falsey
167
196
  end
197
+
198
+ it '#has_backlog_flag? is true' do
199
+ expect(protocol_message.has_backlog_flag?).to be_truthy
200
+ end
168
201
  end
169
202
  end
170
203
 
@@ -265,7 +298,7 @@ describe Ably::Models::ProtocolMessage do
265
298
  end
266
299
  end
267
300
 
268
- context '#messages' do
301
+ context '#messages (#TR4k)' do
269
302
  let(:protocol_message) { new_protocol_message(messages: [{ name: 'test' }]) }
270
303
 
271
304
  it 'contains Message objects' do
@@ -275,7 +308,7 @@ describe Ably::Models::ProtocolMessage do
275
308
  end
276
309
  end
277
310
 
278
- context '#presence' do
311
+ context '#presence (#TR4l)' do
279
312
  let(:protocol_message) { new_protocol_message(presence: [{ action: 1, data: 'test' }]) }
280
313
 
281
314
  it 'contains PresenceMessage objects' do
@@ -285,7 +318,7 @@ describe Ably::Models::ProtocolMessage do
285
318
  end
286
319
  end
287
320
 
288
- context '#connection_details' do
321
+ context '#connection_details (#TR4o)' do
289
322
  let(:connection_details) { protocol_message.connection_details }
290
323
 
291
324
  context 'with a JSON value' do
@@ -312,7 +345,32 @@ describe Ably::Models::ProtocolMessage do
312
345
  end
313
346
  end
314
347
 
315
- context '#connection_key' do
348
+ context '#auth (#TR4p)' do
349
+ let(:auth) { protocol_message.auth }
350
+
351
+ context 'with a JSON value' do
352
+ let(:protocol_message) { new_protocol_message(auth: { accesstoken: 'foo' }) }
353
+
354
+ it 'contains a AuthDetails object' do
355
+ expect(auth).to be_a(Ably::Models::AuthDetails)
356
+ end
357
+
358
+ it 'contains the attributes from the JSON auth details' do
359
+ expect(auth.access_token).to eql('foo')
360
+ end
361
+ end
362
+
363
+ context 'without a JSON value' do
364
+ let(:protocol_message) { new_protocol_message({}) }
365
+
366
+ it 'contains an empty AuthDetails object' do
367
+ expect(auth).to be_a(Ably::Models::AuthDetails)
368
+ expect(auth.access_token).to eql(nil)
369
+ end
370
+ end
371
+ end
372
+
373
+ context '#connection_key (#TR4e)' do
316
374
  context 'existing only in #connection_details.connection_key' do
317
375
  let(:protocol_message) { new_protocol_message(connectionDetails: { connectionKey: 'key' }) }
318
376
 
@@ -147,7 +147,7 @@ describe Ably::Models::TokenDetails do
147
147
  end
148
148
  end
149
149
 
150
- context 'from_json (TD7)' do
150
+ context 'from_json (#TD7)' do
151
151
  let(:issued_time) { Time.now }
152
152
  let(:expires_time) { Time.now + 24*60*60 }
153
153
  let(:capabilities) { { '*' => ['publish'] } }
@@ -108,7 +108,7 @@ describe Ably::Models::TokenRequest do
108
108
  end
109
109
  end
110
110
 
111
- context 'from_json (TE6)' do
111
+ context 'from_json (#TE6)' do
112
112
  let(:timestamp) { Time.now }
113
113
  let(:capabilities) { { '*' => ['publish'] } }
114
114
  let(:ttl_seconds) { 60 * 1000 }
@@ -59,7 +59,8 @@ describe Ably::Modules::AsyncWrapper, :api_private do
59
59
  subject.operation do |result|
60
60
  raise 'Intentional exception'
61
61
  end
62
- expect(subject.logger).to receive(:error).with(/Intentional exception/) do
62
+ expect(subject.logger).to receive(:error) do |*args, &block|
63
+ expect(args.concat([block ? block.call : nil]).join(',')).to match(/Intentional exception/)
63
64
  stop_reactor
64
65
  end
65
66
  end
@@ -41,6 +41,41 @@ describe Ably::Modules::Enum, :api_private do
41
41
  end
42
42
  end
43
43
 
44
+ context 'using include? to compare Enum values' do
45
+ subject { enum }
46
+
47
+ it 'allows same type comparison' do
48
+ expect([subject.ValueZero].include?(subject.ValueZero)).to eql(true)
49
+ end
50
+
51
+ it 'allows different type comparison 1' do
52
+ expect([subject.ValueZero].include?(:value_zero)).to eql(true)
53
+ end
54
+
55
+ it 'allows different type comparison 2' do
56
+ skip 'Unless we monkeypath Symbols, the == operator is never invoked'
57
+ expect([:value_zero].include?(subject.ValueZero)).to eql(true)
58
+ end
59
+
60
+ context '#match_any? replacement for include?' do
61
+ it 'matches any value in the arguments provided' do
62
+ expect(subject.ValueZero.match_any?(:value_foo, :value_zero)).to eql(true)
63
+ end
64
+
65
+ it 'returns false if there are no matches in any value in the arguments provided' do
66
+ expect(subject.ValueZero.match_any?(:value_x, :value_y)).to eql(false)
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'class method #to_sym_arr' do
72
+ subject { enum }
73
+
74
+ it 'returns all keys as symbols' do
75
+ expect(enum.to_sym_arr).to contain_exactly(:value_zero, :value_1, :value_snake_case_2, :sentence_case)
76
+ end
77
+ end
78
+
44
79
  context 'defined Enum from Array class' do
45
80
  subject { enum }
46
81
 
@@ -212,6 +247,40 @@ describe Ably::Modules::Enum, :api_private do
212
247
  end
213
248
  end
214
249
 
250
+ context 'two similar Enums with shared symbol values' do
251
+ class ExampleEnumOne
252
+ extend Ably::Modules::Enum
253
+ ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', :pear, :orange, :litchi, :apple)
254
+ end
255
+
256
+ class ExampleEnumTwo
257
+ extend Ably::Modules::Enum
258
+ ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', :pear, :grape, :apple)
259
+ end
260
+
261
+ let(:enum_one) { ExampleEnumOne::ENUMEXAMPLE }
262
+ let(:enum_two) { ExampleEnumTwo::ENUMEXAMPLE }
263
+
264
+ it 'provides compatability for the equivalent symbol values' do
265
+ expect(enum_one.Pear).to eq(enum_two.Pear)
266
+ expect(enum_two.Pear).to eq(enum_one.Pear)
267
+ expect(enum_one.Apple).to eq(enum_two.Apple)
268
+ expect(enum_two.Apple).to eq(enum_one.Apple)
269
+ end
270
+
271
+ it 'does not consider different symbol values the same' do
272
+ expect(enum_one.Orange).to_not eq(enum_two.Grape)
273
+ end
274
+
275
+ it 'matches symbols when used with a converter method' do
276
+ expect(ExampleEnumOne::ENUMEXAMPLE(enum_two.Pear)).to eq(:pear)
277
+ end
278
+
279
+ it 'fails to match when using an incompatible method with a converter method' do
280
+ expect { ExampleEnumOne::ENUMEXAMPLE(enum_two.Grape) }.to raise_error KeyError
281
+ end
282
+ end
283
+
215
284
  context 'Enum instance' do
216
285
  context '#==' do
217
286
  subject { enum.get(:value_snake_case_2) }