ably-rest 0.9.3 → 1.0.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.
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) }