ably 1.1.0 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
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