ably-rest 1.0.6 → 1.1.4.rc

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/README.md +23 -15
  4. data/ably-rest.gemspec +6 -6
  5. data/lib/submodules/ably-ruby/.editorconfig +14 -0
  6. data/lib/submodules/ably-ruby/.travis.yml +10 -8
  7. data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
  8. data/lib/submodules/ably-ruby/LICENSE +1 -3
  9. data/lib/submodules/ably-ruby/README.md +12 -7
  10. data/lib/submodules/ably-ruby/Rakefile +32 -0
  11. data/lib/submodules/ably-ruby/SPEC.md +1277 -835
  12. data/lib/submodules/ably-ruby/ably.gemspec +15 -10
  13. data/lib/submodules/ably-ruby/lib/ably/auth.rb +30 -4
  14. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
  15. data/lib/submodules/ably-ruby/lib/ably/logger.rb +7 -1
  16. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
  17. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
  18. data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
  19. data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
  20. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
  21. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -4
  22. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
  23. data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
  24. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +1 -1
  25. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +1 -1
  26. data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
  27. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
  28. data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
  29. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  30. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +1 -1
  31. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +24 -102
  32. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -6
  33. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
  34. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
  35. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
  36. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
  37. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +6 -2
  38. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +34 -20
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +1 -1
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +4 -4
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +3 -3
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
  46. data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  47. data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
  48. data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
  49. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +53 -17
  50. data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
  51. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +162 -35
  52. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -1
  53. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
  54. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
  55. data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
  56. data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
  57. data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  58. data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
  59. data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
  60. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +245 -17
  61. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +26 -20
  62. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +177 -59
  63. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +153 -0
  64. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +72 -6
  65. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +129 -18
  66. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +36 -34
  67. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +201 -167
  68. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
  69. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
  70. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +41 -3
  71. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
  72. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
  73. data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
  74. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -10
  75. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
  76. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
  77. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
  78. data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
  79. data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
  80. data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -1
  81. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
  82. data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
  83. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +10 -3
  84. data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
  85. data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
  86. data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
  87. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
  88. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
  89. data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
  90. data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
  91. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
  92. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
  93. data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
  94. data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +8 -1
  95. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
  96. data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
  97. metadata +46 -21
@@ -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