ably 1.0.7 → 1.1.4.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +14 -0
  3. data/.travis.yml +10 -8
  4. data/CHANGELOG.md +58 -4
  5. data/LICENSE +1 -3
  6. data/README.md +9 -5
  7. data/Rakefile +32 -0
  8. data/SPEC.md +920 -565
  9. data/ably.gemspec +16 -11
  10. data/lib/ably/auth.rb +28 -2
  11. data/lib/ably/exceptions.rb +10 -4
  12. data/lib/ably/logger.rb +7 -1
  13. data/lib/ably/models/channel_state_change.rb +1 -1
  14. data/lib/ably/models/connection_state_change.rb +1 -1
  15. data/lib/ably/models/device_details.rb +87 -0
  16. data/lib/ably/models/device_push_details.rb +86 -0
  17. data/lib/ably/models/error_info.rb +23 -2
  18. data/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -4
  19. data/lib/ably/models/protocol_message.rb +32 -2
  20. data/lib/ably/models/push_channel_subscription.rb +89 -0
  21. data/lib/ably/modules/conversions.rb +1 -1
  22. data/lib/ably/modules/encodeable.rb +1 -1
  23. data/lib/ably/modules/exception_codes.rb +128 -0
  24. data/lib/ably/modules/model_common.rb +15 -2
  25. data/lib/ably/modules/state_machine.rb +2 -2
  26. data/lib/ably/realtime.rb +1 -0
  27. data/lib/ably/realtime/auth.rb +1 -1
  28. data/lib/ably/realtime/channel.rb +24 -102
  29. data/lib/ably/realtime/channel/channel_manager.rb +2 -6
  30. data/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
  31. data/lib/ably/realtime/channel/publisher.rb +74 -0
  32. data/lib/ably/realtime/channel/push_channel.rb +62 -0
  33. data/lib/ably/realtime/client.rb +91 -3
  34. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +6 -2
  35. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  36. data/lib/ably/realtime/connection.rb +34 -20
  37. data/lib/ably/realtime/connection/connection_manager.rb +25 -9
  38. data/lib/ably/realtime/connection/websocket_transport.rb +1 -1
  39. data/lib/ably/realtime/presence.rb +4 -4
  40. data/lib/ably/realtime/presence/members_map.rb +3 -3
  41. data/lib/ably/realtime/push.rb +40 -0
  42. data/lib/ably/realtime/push/admin.rb +61 -0
  43. data/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  44. data/lib/ably/realtime/push/device_registrations.rb +105 -0
  45. data/lib/ably/rest.rb +1 -0
  46. data/lib/ably/rest/channel.rb +53 -17
  47. data/lib/ably/rest/channel/push_channel.rb +62 -0
  48. data/lib/ably/rest/client.rb +161 -35
  49. data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -1
  50. data/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
  51. data/lib/ably/rest/presence.rb +1 -0
  52. data/lib/ably/rest/push.rb +42 -0
  53. data/lib/ably/rest/push/admin.rb +54 -0
  54. data/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  55. data/lib/ably/rest/push/device_registrations.rb +103 -0
  56. data/lib/ably/version.rb +7 -2
  57. data/spec/acceptance/realtime/auth_spec.rb +22 -21
  58. data/spec/acceptance/realtime/channel_history_spec.rb +26 -20
  59. data/spec/acceptance/realtime/channel_spec.rb +177 -59
  60. data/spec/acceptance/realtime/client_spec.rb +153 -0
  61. data/spec/acceptance/realtime/connection_failures_spec.rb +72 -6
  62. data/spec/acceptance/realtime/connection_spec.rb +129 -18
  63. data/spec/acceptance/realtime/message_spec.rb +36 -34
  64. data/spec/acceptance/realtime/presence_spec.rb +201 -167
  65. data/spec/acceptance/realtime/push_admin_spec.rb +736 -0
  66. data/spec/acceptance/realtime/push_spec.rb +27 -0
  67. data/spec/acceptance/rest/auth_spec.rb +4 -3
  68. data/spec/acceptance/rest/base_spec.rb +2 -2
  69. data/spec/acceptance/rest/channel_spec.rb +79 -4
  70. data/spec/acceptance/rest/channels_spec.rb +6 -0
  71. data/spec/acceptance/rest/client_spec.rb +129 -10
  72. data/spec/acceptance/rest/message_spec.rb +158 -6
  73. data/spec/acceptance/rest/push_admin_spec.rb +952 -0
  74. data/spec/acceptance/rest/push_spec.rb +25 -0
  75. data/spec/acceptance/rest/time_spec.rb +1 -1
  76. data/spec/run_parallel_tests +33 -0
  77. data/spec/spec_helper.rb +1 -1
  78. data/spec/support/debug_failure_helper.rb +9 -5
  79. data/spec/support/test_app.rb +2 -2
  80. data/spec/unit/logger_spec.rb +10 -3
  81. data/spec/unit/models/device_details_spec.rb +102 -0
  82. data/spec/unit/models/device_push_details_spec.rb +101 -0
  83. data/spec/unit/models/error_info_spec.rb +51 -3
  84. data/spec/unit/models/message_spec.rb +17 -2
  85. data/spec/unit/models/presence_message_spec.rb +1 -1
  86. data/spec/unit/models/push_channel_subscription_spec.rb +86 -0
  87. data/spec/unit/modules/enum_spec.rb +1 -1
  88. data/spec/unit/realtime/client_spec.rb +13 -1
  89. data/spec/unit/realtime/connection_spec.rb +1 -1
  90. data/spec/unit/realtime/push_channel_spec.rb +36 -0
  91. data/spec/unit/rest/channel_spec.rb +8 -1
  92. data/spec/unit/rest/client_spec.rb +30 -0
  93. data/spec/unit/rest/push_channel_spec.rb +36 -0
  94. metadata +94 -31
@@ -45,7 +45,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
45
45
  connection.on(:failed) do |connection_state_change|
46
46
  error = connection_state_change.reason
47
47
  expect(connection.state).to eq(:failed)
48
- # TODO: Check error type is a TokenNotFOund exception
48
+ # TODO: Check error type is a TokenNotFound exception
49
49
  expect(error.status).to eq(401)
50
50
  expect(error.code).to eq(40400) # not found
51
51
  stop_reactor
@@ -110,6 +110,72 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
110
110
  end
111
111
  end
112
112
  end
113
+
114
+ context 'request fails due to slow response and subsequent timeout', :webmock, em_timeout: (Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout) + 5) * 2 do
115
+ let(:auth_url) { "http://#{random_str}.domain.will.be.stubbed/path" }
116
+ let(:client_options) { default_options.reject { |k, v| k == :key }.merge(auth_url: auth_url, log_level: :fatal) }
117
+
118
+ # Timeout +5 seconds, beyond default allowed timeout
119
+ before do
120
+ stub_request(:get, auth_url).
121
+ to_return do |request|
122
+ sleep Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout) + 5
123
+ { status: [500, "Internal Server Error"] }
124
+ end
125
+ end
126
+
127
+ specify 'the connection moves to the disconnected state and tries again, returning again to the disconnected state (#RSA4c, #RSA4c1, #RSA4c2)' do
128
+ states = Hash.new { |hash, key| hash[key] = [] }
129
+
130
+ connection.once(:connected) { raise "Connection can never move to connected because of auth failures" }
131
+
132
+ connection.on do |connection_state|
133
+ states[connection_state.current.to_sym] << Time.now
134
+ if states[:disconnected].count == 2 && connection_state.current == :disconnected
135
+ expect(connection.error_reason).to be_a(Ably::Exceptions::ConnectionError)
136
+ expect(connection.error_reason.message).to match(/auth_url/)
137
+ EventMachine.add_timer(2) do
138
+ expect(states.keys).to include(:connecting, :disconnected)
139
+ expect(states[:connecting].count).to eql(2)
140
+ expect(states[:connected].count).to eql(0)
141
+ stop_reactor
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ context 'request fails once due to slow response but succeeds the second time' do
149
+ let(:auth_url) { "http://#{random_str}.domain.will.be.stubbed/path" }
150
+ let(:client_options) { default_options.reject { |k, v| k == :key }.merge(auth_url: auth_url, log_level: :fatal) }
151
+
152
+ # Timeout +5 seconds, beyond default allowed timeout
153
+ before do
154
+ token_response = Ably::Rest::Client.new(default_options).auth.request_token
155
+ WebMock.enable!
156
+
157
+ stub_request(:get, auth_url).
158
+ to_return do |request|
159
+ sleep Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout)
160
+ { status: [500, "Internal Server Error"] }
161
+ end.then.
162
+ to_return(:status => 201, :body => token_response.to_json, :headers => { 'Content-Type' => 'application/json' })
163
+ end
164
+
165
+ specify 'the connection moves to the disconnected state and tries again, returning again to the disconnected state (#RSA4c, #RSA4c1, #RSA4c2)' do
166
+ states = Hash.new { |hash, key| hash[key] = [] }
167
+
168
+ connection.once(:connected) do
169
+ expect(states[:disconnected].count).to eql(1)
170
+ expect(states[:connecting].count).to eql(2)
171
+ stop_reactor
172
+ end
173
+
174
+ connection.on do |connection_state|
175
+ states[connection_state.current.to_sym] << Time.now
176
+ end
177
+ end
178
+ end
113
179
  end
114
180
 
115
181
  context 'existing CONNECTED connection' do
@@ -425,7 +491,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
425
491
  let(:client_options) do
426
492
  default_options.merge(
427
493
  log_level: :none,
428
- realtime_request_timeout: timeout
494
+ realtime_request_timeout: timeout,
429
495
  )
430
496
  end
431
497
 
@@ -921,11 +987,11 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
921
987
  end
922
988
  end
923
989
 
924
- it 'retains the client_serial (#RTN15c2, #RTN15c3)' do
990
+ it 'retains the client_msg_serial (#RTN15c2, #RTN15c3)' do
925
991
  last_message = nil
926
992
  channel = client.channels.get("foo")
927
993
 
928
- connection.once(:connected) do
994
+ channel.attach do
929
995
  connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
930
996
  if protocol_message.action == :message
931
997
  last_message = protocol_message
@@ -1103,7 +1169,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
1103
1169
  end
1104
1170
  end
1105
1171
 
1106
- it 'resets the client_serial (#RTN15c3)' do
1172
+ it 'continues to use the client_msg_serial (#RTN15c3)' do
1107
1173
  last_message = nil
1108
1174
  channel = client.channels.get("foo")
1109
1175
 
@@ -1121,7 +1187,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
1121
1187
  connection.once(:connected) do
1122
1188
  channel.publish("first on new connection") do
1123
1189
  # Message serial reset after failed resume
1124
- expect(last_message.message_serial).to eql(0)
1190
+ expect(last_message.message_serial).to eql(2)
1125
1191
  stop_reactor
1126
1192
  end
1127
1193
  end
@@ -27,6 +27,13 @@ describe Ably::Realtime::Connection, :event_machine do
27
27
  end
28
28
  end
29
29
 
30
+ context 'current_host' do
31
+ it 'is available immediately after the client is instanced' do
32
+ expect(connection.current_host.to_s).to match(/\.ably\.io$/)
33
+ stop_reactor
34
+ end
35
+ end
36
+
30
37
  context 'with :auto_connect option set to false' do
31
38
  let(:client) do
32
39
  auto_close Ably::Realtime::Client.new(default_options.merge(auto_connect: false))
@@ -264,7 +271,7 @@ describe Ably::Realtime::Connection, :event_machine do
264
271
  channel.subscribe('event') do |message|
265
272
  messages_received << message.data.to_i
266
273
  if messages_received.count == total_expected
267
- expect(messages_received).to match(total_expected.times)
274
+ expect(messages_received).to match(total_expected.times.to_a)
268
275
  expect(auth_requests.count).to eql(iteration + 1)
269
276
  EventMachine.add_timer(1) do
270
277
  channel.unsubscribe 'event'
@@ -649,16 +656,47 @@ describe Ably::Realtime::Connection, :event_machine do
649
656
  end
650
657
 
651
658
  it 'is set to 1 when the second message is received' do
652
- channel.publish('event', 'data') do
653
- channel.publish('event', 'data')
659
+ channel.attach do
660
+ messages = []
661
+ channel.subscribe do |message|
662
+ messages << message
663
+ if messages.length == 2
664
+ expect(connection.serial).to eql(1)
665
+ stop_reactor
666
+ end
667
+ end
668
+
669
+ channel.publish('event', 'data') do
670
+ channel.publish('event', 'data')
671
+ end
654
672
  end
673
+ end
674
+ end
655
675
 
656
- messages = []
657
- channel.subscribe do |message|
658
- messages << message
659
- if messages.length == 2
660
- expect(connection.serial).to eql(1)
661
- stop_reactor
676
+ describe '#msgSerial' do
677
+ context 'when messages are queued for publish before a connection is established' do
678
+ let(:batches) { 6 }
679
+ let(:messages_per_batch) { 10 }
680
+
681
+ let(:publishing_client) { auto_close Ably::Realtime::Client.new(default_options) }
682
+ let(:channel_name) { random_str }
683
+ let(:publishing_channel) { publishing_client.channels.get(channel_name) }
684
+ let(:receiving_channel) { client.channels.get(channel_name) }
685
+
686
+ it 'the msgSerial is always incrementing (and not reset when the new connection is established) ensuring messages are never de-duped by the realtime service' do
687
+ messages = []
688
+
689
+ receiving_channel.attach do
690
+ receiving_channel.subscribe('event') do |message|
691
+ messages << message
692
+ stop_reactor if messages.count == batches * messages_per_batch
693
+ end
694
+
695
+ batches.times do |batch|
696
+ EventMachine.add_timer(batch.to_f / batches.to_f) do
697
+ messages_per_batch.times { |index| publishing_channel.publish('event') }
698
+ end
699
+ end
662
700
  end
663
701
  end
664
702
  end
@@ -1005,10 +1043,9 @@ describe Ably::Realtime::Connection, :event_machine do
1005
1043
  let(:client_options) { default_options.merge(websocket_heartbeats_disabled: true) }
1006
1044
 
1007
1045
  it 'does not provide the heartbeats argument in the websocket connection params (#RTN23b)' do
1008
- skip 'Native heartbeats not yet supported in the WS driver https://github.com/ably/ably-ruby/issues/116'
1009
1046
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1010
1047
  uri = URI.parse(url)
1011
- expect(CGI::parse(uri.query)['heartbeats'][0]).to be_nil
1048
+ expect(CGI::parse(uri.query)['heartbeats'][0]).to eql('true')
1012
1049
  stop_reactor
1013
1050
  end
1014
1051
  client
@@ -1126,7 +1163,7 @@ describe Ably::Realtime::Connection, :event_machine do
1126
1163
  expected_serial += 1 # attach message received
1127
1164
  expect(connection.serial).to eql(expected_serial)
1128
1165
 
1129
- expect(connection.recovery_key).to eql("#{connection.key}:#{connection.serial}")
1166
+ expect(connection.recovery_key).to eql("#{connection.key}:#{connection.serial}:#{connection.send(:client_msg_serial)}")
1130
1167
  stop_reactor
1131
1168
  end
1132
1169
  end
@@ -1237,6 +1274,80 @@ describe Ably::Realtime::Connection, :event_machine do
1237
1274
  end
1238
1275
  end
1239
1276
  end
1277
+
1278
+ context 'when messages have been published' do
1279
+ describe 'the new connection' do
1280
+ it 'uses the correct msgSerial from the old connection' do
1281
+ msg_serial, recovery_key, connection_id = nil, nil, nil
1282
+
1283
+ channel.attach do
1284
+ expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
1285
+ connection_id = client.connection.id
1286
+ connection.transport.__incoming_protocol_msgbus__
1287
+ channel.publish('event', 'message') do
1288
+ msg_serial = connection.send(:client_msg_serial)
1289
+ expect(msg_serial).to eql(0)
1290
+ recovery_key = client.connection.recovery_key
1291
+ connection.transition_state_machine! :failed
1292
+ end
1293
+ end
1294
+
1295
+ connection.on(:failed) do
1296
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: recovery_key))
1297
+ recover_client_channel = recover_client.channel(channel_name)
1298
+ recover_client_channel.attach do
1299
+ expect(recover_client.connection.id).to eql(connection_id)
1300
+ expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial)
1301
+ stop_reactor
1302
+ end
1303
+ end
1304
+ end
1305
+ end
1306
+ end
1307
+
1308
+ context 'when messages are published before the new connection is recovered' do
1309
+ describe 'the new connection' do
1310
+ it 'uses the correct msgSerial from the old connection for the queued messages' do
1311
+ msg_serial, recovery_key, connection_id = nil, nil, nil
1312
+
1313
+ channel.attach do
1314
+ expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
1315
+ connection_id = client.connection.id
1316
+ connection.transport.__incoming_protocol_msgbus__
1317
+ channel.subscribe('event') do |message|
1318
+ expect(message.data).to eql('message-1')
1319
+ msg_serial = connection.send(:client_msg_serial)
1320
+ expect(msg_serial).to eql(0)
1321
+ recovery_key = client.connection.recovery_key
1322
+ connection.transition_state_machine! :failed
1323
+ end
1324
+ channel.publish('event', 'message-1')
1325
+ end
1326
+
1327
+ connection.on(:failed) do
1328
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: recovery_key))
1329
+ recover_client_channel = recover_client.channel(channel_name)
1330
+ expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial)
1331
+
1332
+ recover_client.connection.once(:connecting) do
1333
+ recover_client_channel.publish('event', 'message-2')
1334
+ expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial + 1)
1335
+ end
1336
+
1337
+ recover_client_channel.attach do
1338
+ expect(recover_client.connection.id).to eql(connection_id)
1339
+
1340
+ recover_client_channel.subscribe do |message|
1341
+ expect(message.data).to eql('message-2')
1342
+ EventMachine.add_timer(2) do
1343
+ stop_reactor
1344
+ end
1345
+ end
1346
+ end
1347
+ end
1348
+ end
1349
+ end
1350
+ end
1240
1351
  end
1241
1352
 
1242
1353
  context 'with :recover option' do
@@ -1250,7 +1361,7 @@ describe Ably::Realtime::Connection, :event_machine do
1250
1361
  end
1251
1362
 
1252
1363
  context 'with invalid formatted value sent to server' do
1253
- let(:client_options) { default_options.merge(recover: 'not-a-valid-connection-key:1', log_level: :none) }
1364
+ let(:client_options) { default_options.merge(recover: 'not-a-valid-connection-key:1:0', log_level: :none) }
1254
1365
 
1255
1366
  it 'sets the #error_reason and moves the connection to FAILED' do
1256
1367
  connection.once(:failed) do |state_change|
@@ -1265,7 +1376,7 @@ describe Ably::Realtime::Connection, :event_machine do
1265
1376
  end
1266
1377
 
1267
1378
  context 'with expired (missing) value sent to server' do
1268
- let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0', log_level: :fatal) }
1379
+ let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0:0', log_level: :fatal) }
1269
1380
 
1270
1381
  it 'connects but sets the error reason and includes the reason in the state change' do
1271
1382
  connection.once(:connected) do |state_change|
@@ -1472,7 +1583,7 @@ describe Ably::Realtime::Connection, :event_machine do
1472
1583
  channel.attach do
1473
1584
  channel.once(:suspended) do
1474
1585
  channel.publish('test').errback do |error|
1475
- expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled)
1586
+ expect(error).to be_a(Ably::Exceptions::ChannelInactive)
1476
1587
  stop_reactor
1477
1588
  end
1478
1589
  end
@@ -1732,7 +1843,7 @@ describe Ably::Realtime::Connection, :event_machine do
1732
1843
  it 'sends the protocol version param v (#G4, #RTN2f)' do
1733
1844
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1734
1845
  uri = URI.parse(url)
1735
- expect(CGI::parse(uri.query)['v'][0]).to eql('1.0')
1846
+ expect(CGI::parse(uri.query)['v'][0]).to eql('1.1')
1736
1847
  stop_reactor
1737
1848
  end
1738
1849
  client
@@ -1741,7 +1852,7 @@ describe Ably::Realtime::Connection, :event_machine do
1741
1852
  it 'sends the lib version param lib (#RTN2g)' do
1742
1853
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1743
1854
  uri = URI.parse(url)
1744
- expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-1\.0\.\d+(-[\w\.]+)?+$/)
1855
+ expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-1\.1\.\d+(-[\w\.]+)?+$/)
1745
1856
  stop_reactor
1746
1857
  end
1747
1858
  client
@@ -1761,7 +1872,7 @@ describe Ably::Realtime::Connection, :event_machine do
1761
1872
  it 'sends the lib version param lib with the variant (#RTN2g + #RSC7b)' do
1762
1873
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1763
1874
  uri = URI.parse(url)
1764
- expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-#{variant}-1\.0\.\d+(-[\w\.]+)?$/)
1875
+ expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-#{variant}-1\.1\.\d+(-[\w\.]+)?$/)
1765
1876
  stop_reactor
1766
1877
  end
1767
1878
  client
@@ -96,8 +96,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
96
96
  end
97
97
 
98
98
  context 'JSON Array' do
99
- # TODO: Add nil type back in
100
- let(:data) { { 'push' => { 'data' => { 'key' => [ true, false, 55, 'string', { 'Hash' => true }, ['array'] ] } } } }
99
+ let(:data) { { 'push' => { 'data' => { 'key' => [ true, false, 55, nil, 'string', { 'Hash' => true }, ['array'] ] } } } }
101
100
 
102
101
  it 'is encoded and decoded to the same Array' do
103
102
  publish_and_check_extras data
@@ -116,7 +115,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
116
115
  context 'Integer' do
117
116
  let(:data) { 1 }
118
117
 
119
- it 'is raises an UnsupportedDataType 40011 exception' do
118
+ it 'is raises an UnsupportedDataType 40013 exception' do
120
119
  expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
121
120
  stop_reactor
122
121
  end
@@ -125,7 +124,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
125
124
  context 'Float' do
126
125
  let(:data) { 1.1 }
127
126
 
128
- it 'is raises an UnsupportedDataType 40011 exception' do
127
+ it 'is raises an UnsupportedDataType 40013 exception' do
129
128
  expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
130
129
  stop_reactor
131
130
  end
@@ -134,7 +133,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
134
133
  context 'Boolean' do
135
134
  let(:data) { true }
136
135
 
137
- it 'is raises an UnsupportedDataType 40011 exception' do
136
+ it 'is raises an UnsupportedDataType 40013 exception' do
138
137
  expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
139
138
  stop_reactor
140
139
  end
@@ -143,7 +142,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
143
142
  context 'False' do
144
143
  let(:data) { false }
145
144
 
146
- it 'is raises an UnsupportedDataType 40011 exception' do
145
+ it 'is raises an UnsupportedDataType 40013 exception' do
147
146
  expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
148
147
  stop_reactor
149
148
  end
@@ -353,23 +352,25 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
353
352
  first_message_protocol_message ||= protocol_message unless protocol_message.messages.empty?
354
353
  end
355
354
 
356
- channel.subscribe do |message|
357
- messages_received << message
358
- if messages_received.count == 2
359
- # simulate a duplicate protocol message being received
360
- EventMachine.next_tick do
361
- connection.__incoming_protocol_msgbus__.publish :protocol_message, first_message_protocol_message
355
+ channel.attach do
356
+ channel.subscribe do |message|
357
+ messages_received << message
358
+ if messages_received.count == 2
359
+ # simulate a duplicate protocol message being received
360
+ EventMachine.next_tick do
361
+ connection.__incoming_protocol_msgbus__.publish :protocol_message, first_message_protocol_message
362
+ end
362
363
  end
363
364
  end
364
- end
365
- 2.times { |i| EventMachine.add_timer(i.to_f / 5) { channel.publish('event', 'data') } }
365
+ 2.times { |i| EventMachine.add_timer(i.to_f / 5) { channel.publish('event', 'data') } }
366
366
 
367
- expect(client.logger).to receive(:error) do |*args, &block|
368
- expect(args.concat([block ? block.call : nil]).join(',')).to match(/duplicate/)
367
+ expect(client.logger).to receive(:error) do |*args, &block|
368
+ expect(args.concat([block ? block.call : nil]).join(',')).to match(/duplicate/)
369
369
 
370
- EventMachine.add_timer(0.5) do
371
- expect(messages_received.count).to eql(2)
372
- stop_reactor
370
+ EventMachine.add_timer(0.5) do
371
+ expect(messages_received.count).to eql(2)
372
+ stop_reactor
373
+ end
373
374
  end
374
375
  end
375
376
  end
@@ -413,30 +414,32 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
413
414
  let(:encrypted_channel) { client.channel(channel_name, cipher: cipher_options) }
414
415
 
415
416
  it 'encrypts message automatically before they are pushed to the server (#RTL7d)' do
416
- encrypted_channel.__incoming_msgbus__.unsubscribe # remove all subscribe callbacks that could decrypt the message
417
+ encrypted_channel.attach do
418
+ encrypted_channel.__incoming_msgbus__.unsubscribe # remove all subscribe callbacks that could decrypt the message
417
419
 
418
- encrypted_channel.__incoming_msgbus__.subscribe(:message) do |message|
419
- if protocol == :json
420
- expect(message['encoding']).to eql(encrypted_encoding)
421
- expect(message['data']).to eql(encrypted_data)
422
- else
423
- # Messages received over binary protocol will not have Base64 encoded data
424
- expect(message['encoding']).to eql(encrypted_encoding.gsub(%r{/base64$}, ''))
425
- expect(message['data']).to eql(encrypted_data_decoded)
420
+ encrypted_channel.__incoming_msgbus__.subscribe(:message) do |message|
421
+ if protocol == :json
422
+ expect(message['encoding']).to eql(encrypted_encoding)
423
+ expect(message['data']).to eql(encrypted_data)
424
+ else
425
+ # Messages received over binary protocol will not have Base64 encoded data
426
+ expect(message['encoding']).to eql(encrypted_encoding.gsub(%r{/base64$}, ''))
427
+ expect(message['data']).to eql(encrypted_data_decoded)
428
+ end
429
+ stop_reactor
426
430
  end
427
- stop_reactor
428
- end
429
431
 
430
- encrypted_channel.publish 'example', encoded_data_decoded
432
+ encrypted_channel.publish 'example', encoded_data_decoded
433
+ end
431
434
  end
432
435
 
433
436
  it 'sends and receives messages that are encrypted & decrypted by the Ably library (#RTL7d)' do
434
- encrypted_channel.publish 'example', encoded_data_decoded
435
437
  encrypted_channel.subscribe do |message|
436
438
  expect(message.data).to eql(encoded_data_decoded)
437
439
  expect(message.encoding).to be_nil
438
440
  stop_reactor
439
441
  end
442
+ encrypted_channel.publish 'example', encoded_data_decoded
440
443
  end
441
444
  end
442
445
  end
@@ -654,8 +657,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
654
657
  expect(message_state).to be_empty
655
658
  EventMachine.add_timer(2) do
656
659
  expect(message_state).to contain_exactly(:delivered)
657
- # TODO: Uncomment once issue realtime#42 is resolved
658
- # expect(msgs_received.length).to eql(1)
660
+ expect(msgs_received.length).to eql(1)
659
661
  stop_reactor
660
662
  end
661
663
  end