ably 1.1.0 → 1.1.4

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check.yml +27 -0
  3. data/CHANGELOG.md +68 -2
  4. data/COPYRIGHT +1 -0
  5. data/LICENSE +172 -11
  6. data/MAINTAINERS.md +1 -0
  7. data/README.md +3 -7
  8. data/SPEC.md +944 -914
  9. data/ably.gemspec +7 -7
  10. data/lib/ably/auth.rb +12 -2
  11. data/lib/ably/exceptions.rb +2 -2
  12. data/lib/ably/logger.rb +7 -1
  13. data/lib/ably/modules/state_machine.rb +1 -1
  14. data/lib/ably/realtime/channel.rb +7 -11
  15. data/lib/ably/realtime/channel/channel_manager.rb +2 -2
  16. data/lib/ably/realtime/channel/channel_properties.rb +24 -0
  17. data/lib/ably/realtime/client.rb +12 -3
  18. data/lib/ably/realtime/connection.rb +31 -19
  19. data/lib/ably/realtime/connection/connection_manager.rb +19 -3
  20. data/lib/ably/realtime/connection/websocket_transport.rb +67 -1
  21. data/lib/ably/realtime/presence.rb +0 -14
  22. data/lib/ably/rest/channel.rb +25 -17
  23. data/lib/ably/rest/client.rb +22 -11
  24. data/lib/ably/version.rb +1 -1
  25. data/spec/acceptance/realtime/auth_spec.rb +16 -13
  26. data/spec/acceptance/realtime/channel_history_spec.rb +26 -20
  27. data/spec/acceptance/realtime/channel_spec.rb +21 -8
  28. data/spec/acceptance/realtime/client_spec.rb +80 -20
  29. data/spec/acceptance/realtime/connection_failures_spec.rb +71 -5
  30. data/spec/acceptance/realtime/connection_spec.rb +153 -26
  31. data/spec/acceptance/realtime/message_spec.rb +17 -17
  32. data/spec/acceptance/realtime/presence_history_spec.rb +0 -58
  33. data/spec/acceptance/realtime/presence_spec.rb +250 -162
  34. data/spec/acceptance/realtime/push_admin_spec.rb +49 -25
  35. data/spec/acceptance/rest/auth_spec.rb +6 -75
  36. data/spec/acceptance/rest/channel_spec.rb +79 -4
  37. data/spec/acceptance/rest/channels_spec.rb +6 -0
  38. data/spec/acceptance/rest/client_spec.rb +72 -12
  39. data/spec/acceptance/rest/message_spec.rb +8 -27
  40. data/spec/acceptance/rest/push_admin_spec.rb +67 -27
  41. data/spec/shared/client_initializer_behaviour.rb +0 -8
  42. data/spec/spec_helper.rb +2 -1
  43. data/spec/support/debug_failure_helper.rb +9 -5
  44. data/spec/support/serialization_helper.rb +21 -0
  45. data/spec/support/test_app.rb +2 -2
  46. data/spec/unit/modules/enum_spec.rb +1 -1
  47. data/spec/unit/realtime/client_spec.rb +20 -7
  48. data/spec/unit/realtime/connection_spec.rb +1 -1
  49. metadata +40 -29
  50. data/.travis.yml +0 -16
@@ -87,22 +87,6 @@ describe Ably::Realtime::Client, :event_machine do
87
87
  end
88
88
  end
89
89
  end
90
-
91
- context 'with client_id' do
92
- let(:client_options) do
93
- default_options.merge(client_id: random_str)
94
- end
95
- it 'connects using token auth' do
96
- run_reactor do
97
- connection.on(:connected) do
98
- expect(connection.state).to eq(:connected)
99
- expect(auth_params[:access_token]).to_not be_nil
100
- expect(auth_params[:key]).to be_nil
101
- stop_reactor
102
- end
103
- end
104
- end
105
- end
106
90
  end
107
91
  end
108
92
 
@@ -249,6 +233,8 @@ describe Ably::Realtime::Client, :event_machine do
249
233
 
250
234
  context '#request (#RSC19*)' do
251
235
  let(:client_options) { default_options.merge(key: api_key) }
236
+ let(:device_id) { random_str }
237
+ let(:endpoint) { subject.rest_client.endpoint }
252
238
 
253
239
  context 'get' do
254
240
  it 'returns an HttpPaginatedResponse object' do
@@ -297,6 +283,76 @@ describe Ably::Realtime::Client, :event_machine do
297
283
  end
298
284
  end
299
285
  end
286
+
287
+
288
+ context 'post', :webmock do
289
+ before do
290
+ stub_request(:delete, "#{endpoint}/push/deviceRegistrations/#{device_id}/resetUpdateToken").
291
+ to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
292
+ end
293
+
294
+ it 'supports post' do
295
+ subject.request(:delete, "push/deviceRegistrations/#{device_id}/resetUpdateToken").callback do |response|
296
+ expect(response).to be_success
297
+ stop_reactor
298
+ end
299
+ end
300
+ end
301
+
302
+ context 'delete', :webmock do
303
+ before do
304
+ stub_request(:delete, "#{endpoint}/push/channelSubscriptions?deviceId=#{device_id}").
305
+ to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
306
+ end
307
+
308
+ it 'supports delete' do
309
+ subject.request(:delete, "/push/channelSubscriptions", { deviceId: device_id}).callback do |response|
310
+ expect(response).to be_success
311
+ stop_reactor
312
+ end
313
+ end
314
+ end
315
+
316
+ context 'patch', :webmock do
317
+ let(:body_params) { { 'metadata' => { 'key' => 'value' } } }
318
+
319
+ before do
320
+ stub_request(:patch, "#{endpoint}/push/deviceRegistrations/#{device_id}")
321
+ .with(body: serialize_body(body_params, protocol))
322
+ .to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
323
+ end
324
+
325
+ it 'supports patch' do
326
+ subject.request(:patch, "/push/deviceRegistrations/#{device_id}", {}, body_params).callback do |response|
327
+ expect(response).to be_success
328
+ stop_reactor
329
+ end
330
+ end
331
+ end
332
+
333
+ context 'put', :webmock do
334
+ let(:body_params) do
335
+ {
336
+ 'id' => random_str,
337
+ 'platform' => 'ios',
338
+ 'formFactor' => 'phone',
339
+ 'metadata' => { 'key' => 'value' }
340
+ }
341
+ end
342
+
343
+ before do
344
+ stub_request(:put, "#{endpoint}/push/deviceRegistrations/#{device_id}")
345
+ .with(body: serialize_body(body_params, protocol))
346
+ .to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
347
+ end
348
+
349
+ it 'supports put' do
350
+ subject.request(:put, "/push/deviceRegistrations/#{device_id}", {}, body_params).callback do |response|
351
+ expect(response).to be_success
352
+ stop_reactor
353
+ end
354
+ end
355
+ end
300
356
  end
301
357
 
302
358
  context '#publish (#TBC)' do
@@ -315,8 +371,9 @@ describe Ably::Realtime::Client, :event_machine do
315
371
  expect(msg.data).to eql(data)
316
372
  stop_reactor
317
373
  end
374
+
375
+ subject.publish channel_name, event_name, data
318
376
  end
319
- subject.publish channel_name, event_name, data
320
377
  end
321
378
 
322
379
  specify 'publishing does not result in a channel being created' do
@@ -341,8 +398,9 @@ describe Ably::Realtime::Client, :event_machine do
341
398
  expect(msg.extras).to eql(extras)
342
399
  stop_reactor
343
400
  end
401
+
402
+ subject.publish channel_name, event_name, {}, extras: extras
344
403
  end
345
- subject.publish channel_name, event_name, {}, extras: extras
346
404
  end
347
405
  end
348
406
 
@@ -353,8 +411,9 @@ describe Ably::Realtime::Client, :event_machine do
353
411
  expect(msg.data).to eql(data)
354
412
  stop_reactor
355
413
  end
414
+
415
+ subject.publish channel_name, [message]
356
416
  end
357
- subject.publish channel_name, [message]
358
417
  end
359
418
 
360
419
  specify 'publishing supports an array of Hash objects' do
@@ -364,8 +423,9 @@ describe Ably::Realtime::Client, :event_machine do
364
423
  expect(msg.data).to eql(data)
365
424
  stop_reactor
366
425
  end
426
+
427
+ subject.publish channel_name, [name: event_name, data: data]
367
428
  end
368
- subject.publish channel_name, [name: event_name, data: data]
369
429
  end
370
430
 
371
431
  specify 'publishing on a closed connection fails' do
@@ -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,7 +987,7 @@ 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
 
@@ -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))
@@ -70,18 +77,6 @@ describe Ably::Realtime::Connection, :event_machine do
70
77
  end
71
78
  end
72
79
  end
73
-
74
- context 'with implicit authorisation' do
75
- let(:client_options) { default_options.merge(client_id: 'force_token_auth') }
76
-
77
- it 'uses the token created by the implicit authorisation' do
78
- expect(client.rest_client.auth).to receive(:request_token).once.and_call_original
79
-
80
- connection.once(:connected) do
81
- stop_reactor
82
- end
83
- end
84
- end
85
80
  end
86
81
 
87
82
  context 'that expire' do
@@ -264,7 +259,7 @@ describe Ably::Realtime::Connection, :event_machine do
264
259
  channel.subscribe('event') do |message|
265
260
  messages_received << message.data.to_i
266
261
  if messages_received.count == total_expected
267
- expect(messages_received).to match(total_expected.times)
262
+ expect(messages_received).to match(total_expected.times.to_a)
268
263
  expect(auth_requests.count).to eql(iteration + 1)
269
264
  EventMachine.add_timer(1) do
270
265
  channel.unsubscribe 'event'
@@ -649,16 +644,47 @@ describe Ably::Realtime::Connection, :event_machine do
649
644
  end
650
645
 
651
646
  it 'is set to 1 when the second message is received' do
652
- channel.publish('event', 'data') do
653
- channel.publish('event', 'data')
647
+ channel.attach do
648
+ messages = []
649
+ channel.subscribe do |message|
650
+ messages << message
651
+ if messages.length == 2
652
+ expect(connection.serial).to eql(1)
653
+ stop_reactor
654
+ end
655
+ end
656
+
657
+ channel.publish('event', 'data') do
658
+ channel.publish('event', 'data')
659
+ end
654
660
  end
661
+ end
662
+ end
655
663
 
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
664
+ describe '#msgSerial' do
665
+ context 'when messages are queued for publish before a connection is established' do
666
+ let(:batches) { 6 }
667
+ let(:messages_per_batch) { 10 }
668
+
669
+ let(:publishing_client) { auto_close Ably::Realtime::Client.new(default_options) }
670
+ let(:channel_name) { random_str }
671
+ let(:publishing_channel) { publishing_client.channels.get(channel_name) }
672
+ let(:receiving_channel) { client.channels.get(channel_name) }
673
+
674
+ 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
675
+ messages = []
676
+
677
+ receiving_channel.attach do
678
+ receiving_channel.subscribe('event') do |message|
679
+ messages << message
680
+ stop_reactor if messages.count == batches * messages_per_batch
681
+ end
682
+
683
+ batches.times do |batch|
684
+ EventMachine.add_timer(batch.to_f / batches.to_f) do
685
+ messages_per_batch.times { |index| publishing_channel.publish('event') }
686
+ end
687
+ end
662
688
  end
663
689
  end
664
690
  end
@@ -1005,10 +1031,9 @@ describe Ably::Realtime::Connection, :event_machine do
1005
1031
  let(:client_options) { default_options.merge(websocket_heartbeats_disabled: true) }
1006
1032
 
1007
1033
  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
1034
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1010
1035
  uri = URI.parse(url)
1011
- expect(CGI::parse(uri.query)['heartbeats'][0]).to be_nil
1036
+ expect(CGI::parse(uri.query)['heartbeats'][0]).to eql('true')
1012
1037
  stop_reactor
1013
1038
  end
1014
1039
  client
@@ -1126,7 +1151,7 @@ describe Ably::Realtime::Connection, :event_machine do
1126
1151
  expected_serial += 1 # attach message received
1127
1152
  expect(connection.serial).to eql(expected_serial)
1128
1153
 
1129
- expect(connection.recovery_key).to eql("#{connection.key}:#{connection.serial}")
1154
+ expect(connection.recovery_key).to eql("#{connection.key}:#{connection.serial}:#{connection.send(:client_msg_serial)}")
1130
1155
  stop_reactor
1131
1156
  end
1132
1157
  end
@@ -1237,6 +1262,80 @@ describe Ably::Realtime::Connection, :event_machine do
1237
1262
  end
1238
1263
  end
1239
1264
  end
1265
+
1266
+ context 'when messages have been published' do
1267
+ describe 'the new connection' do
1268
+ it 'uses the correct msgSerial from the old connection' do
1269
+ msg_serial, recovery_key, connection_id = nil, nil, nil
1270
+
1271
+ channel.attach do
1272
+ expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
1273
+ connection_id = client.connection.id
1274
+ connection.transport.__incoming_protocol_msgbus__
1275
+ channel.publish('event', 'message') do
1276
+ msg_serial = connection.send(:client_msg_serial)
1277
+ expect(msg_serial).to eql(0)
1278
+ recovery_key = client.connection.recovery_key
1279
+ connection.transition_state_machine! :failed
1280
+ end
1281
+ end
1282
+
1283
+ connection.on(:failed) do
1284
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: recovery_key))
1285
+ recover_client_channel = recover_client.channel(channel_name)
1286
+ recover_client_channel.attach do
1287
+ expect(recover_client.connection.id).to eql(connection_id)
1288
+ expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial)
1289
+ stop_reactor
1290
+ end
1291
+ end
1292
+ end
1293
+ end
1294
+ end
1295
+
1296
+ context 'when messages are published before the new connection is recovered' do
1297
+ describe 'the new connection' do
1298
+ it 'uses the correct msgSerial from the old connection for the queued messages' do
1299
+ msg_serial, recovery_key, connection_id = nil, nil, nil
1300
+
1301
+ channel.attach do
1302
+ expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
1303
+ connection_id = client.connection.id
1304
+ connection.transport.__incoming_protocol_msgbus__
1305
+ channel.subscribe('event') do |message|
1306
+ expect(message.data).to eql('message-1')
1307
+ msg_serial = connection.send(:client_msg_serial)
1308
+ expect(msg_serial).to eql(0)
1309
+ recovery_key = client.connection.recovery_key
1310
+ connection.transition_state_machine! :failed
1311
+ end
1312
+ channel.publish('event', 'message-1')
1313
+ end
1314
+
1315
+ connection.on(:failed) do
1316
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: recovery_key))
1317
+ recover_client_channel = recover_client.channel(channel_name)
1318
+ expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial)
1319
+
1320
+ recover_client.connection.once(:connecting) do
1321
+ recover_client_channel.publish('event', 'message-2')
1322
+ expect(recover_client.connection.send(:client_msg_serial)).to eql(msg_serial + 1)
1323
+ end
1324
+
1325
+ recover_client_channel.attach do
1326
+ expect(recover_client.connection.id).to eql(connection_id)
1327
+
1328
+ recover_client_channel.subscribe do |message|
1329
+ expect(message.data).to eql('message-2')
1330
+ EventMachine.add_timer(2) do
1331
+ stop_reactor
1332
+ end
1333
+ end
1334
+ end
1335
+ end
1336
+ end
1337
+ end
1338
+ end
1240
1339
  end
1241
1340
 
1242
1341
  context 'with :recover option' do
@@ -1250,7 +1349,7 @@ describe Ably::Realtime::Connection, :event_machine do
1250
1349
  end
1251
1350
 
1252
1351
  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) }
1352
+ let(:client_options) { default_options.merge(recover: 'not-a-valid-connection-key:1:0', log_level: :none) }
1254
1353
 
1255
1354
  it 'sets the #error_reason and moves the connection to FAILED' do
1256
1355
  connection.once(:failed) do |state_change|
@@ -1265,7 +1364,7 @@ describe Ably::Realtime::Connection, :event_machine do
1265
1364
  end
1266
1365
 
1267
1366
  context 'with expired (missing) value sent to server' do
1268
- let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0', log_level: :fatal) }
1367
+ let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0:0', log_level: :fatal) }
1269
1368
 
1270
1369
  it 'connects but sets the error reason and includes the reason in the state change' do
1271
1370
  connection.once(:connected) do |state_change|
@@ -1768,5 +1867,33 @@ describe Ably::Realtime::Connection, :event_machine do
1768
1867
  end
1769
1868
  end
1770
1869
  end
1870
+
1871
+ context 'transport_params (#RTC1f)' do
1872
+ let(:client_options) { default_options.merge(transport_params: { 'extra_param' => 'extra_param' }) }
1873
+
1874
+ it 'pases transport_params to query' do
1875
+ expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1876
+ uri = URI.parse(url)
1877
+ expect(CGI::parse(uri.query)['extra_param'][0]).to eq('extra_param')
1878
+ stop_reactor
1879
+ end
1880
+
1881
+ client
1882
+ end
1883
+
1884
+ context 'when changing default param' do
1885
+ let(:client_options) { default_options.merge(transport_params: { v: '1.0' }) }
1886
+
1887
+ it 'overrides default param (#RTC1f1)' do
1888
+ expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1889
+ uri = URI.parse(url)
1890
+ expect(CGI::parse(uri.query)['v'][0]).to eq('1.0')
1891
+ stop_reactor
1892
+ end
1893
+
1894
+ client
1895
+ end
1896
+ end
1897
+ end
1771
1898
  end
1772
1899
  end