ably-rest 0.8.5 → 0.8.6
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/SPEC.md +1380 -631
- data/ably-rest.gemspec +11 -5
- data/lib/submodules/ably-ruby/.travis.yml +1 -1
- data/lib/submodules/ably-ruby/CHANGELOG.md +42 -48
- data/lib/submodules/ably-ruby/ably.gemspec +7 -1
- data/lib/submodules/ably-ruby/lib/ably.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +155 -47
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +2 -3
- data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +54 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +14 -4
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +13 -7
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +3 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +1 -3
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +15 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +10 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +62 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +58 -54
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +18 -5
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +32 -14
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +251 -11
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +12 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +316 -24
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +93 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +177 -86
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +284 -60
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +45 -6
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +4 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +181 -49
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +13 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +222 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +132 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -28
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +7 -7
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +10 -0
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +41 -17
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -0
- data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +16 -0
- data/lib/submodules/ably-ruby/spec/unit/models/connection_details_spec.rb +60 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +45 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +6 -5
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +5 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +5 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +5 -1
- metadata +57 -13
@@ -70,15 +70,6 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
context '#token' do
|
74
|
-
let(:client_options) { default_options.merge(token: random_str) }
|
75
|
-
|
76
|
-
it 'contains the current token after auth' do
|
77
|
-
expect(auth.token).to_not be_nil
|
78
|
-
stop_reactor
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
73
|
context '#current_token_details' do
|
83
74
|
it 'contains the current token after auth' do
|
84
75
|
expect(auth.current_token_details).to be_nil
|
@@ -99,6 +90,7 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
99
90
|
context '#options (auth_options)' do
|
100
91
|
let(:auth_url) { "https://echo.ably.io/?type=text" }
|
101
92
|
let(:auth_params) { { :body => random_str } }
|
93
|
+
let(:client_options) { default_options.merge(auto_connect: false) }
|
102
94
|
|
103
95
|
it 'contains the configured auth options' do
|
104
96
|
auth.authorise({}, auth_url: auth_url, auth_params: auth_params) do
|
@@ -193,6 +185,75 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
193
185
|
stop_reactor
|
194
186
|
end
|
195
187
|
end
|
188
|
+
|
189
|
+
context 'when implicitly called, with an explicit ClientOptions client_id' do
|
190
|
+
let(:client_id) { random_str }
|
191
|
+
let(:client_options) { default_options.merge(auth_callback: Proc.new { auth_token_object }, client_id: client_id, log_level: :none) }
|
192
|
+
let(:rest_auth_client) { Ably::Rest::Client.new(default_options.merge(key: api_key, client_id: 'invalid')) }
|
193
|
+
|
194
|
+
context 'and an incompatible client_id in a TokenDetails object passed to the auth callback' do
|
195
|
+
let(:auth_token_object) { rest_auth_client.auth.request_token }
|
196
|
+
|
197
|
+
it 'rejects a TokenDetails object with an incompatible client_id and raises an exception' do
|
198
|
+
client.connect
|
199
|
+
client.connection.on(:error) do |error|
|
200
|
+
expect(error).to be_a(Ably::Exceptions::IncompatibleClientId)
|
201
|
+
EventMachine.add_timer(0.1) do
|
202
|
+
expect(client.connection).to be_failed
|
203
|
+
stop_reactor
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context 'and an incompatible client_id in a TokenRequest object passed to the auth callback and raises an exception' do
|
210
|
+
let(:auth_token_object) { rest_auth_client.auth.create_token_request }
|
211
|
+
|
212
|
+
it 'rejects a TokenRequests object with an incompatible client_id and raises an exception' do
|
213
|
+
client.connect
|
214
|
+
client.connection.on(:error) do |error|
|
215
|
+
expect(error).to be_a(Ably::Exceptions::IncompatibleClientId)
|
216
|
+
EventMachine.add_timer(0.1) do
|
217
|
+
expect(client.connection).to be_failed
|
218
|
+
stop_reactor
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'when explicitly called, with an explicit ClientOptions client_id' do
|
226
|
+
let(:auth_proc) do
|
227
|
+
Proc.new do
|
228
|
+
if !@requested
|
229
|
+
@requested = true
|
230
|
+
valid_auth_token
|
231
|
+
else
|
232
|
+
invalid_auth_token
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
let(:client_id) { random_str }
|
238
|
+
let(:client_options) { default_options.merge(auth_callback: auth_proc, client_id: client_id, log_level: :none) }
|
239
|
+
let(:valid_auth_token) { Ably::Rest::Client.new(default_options.merge(key: api_key, client_id: client_id)).auth.request_token }
|
240
|
+
let(:invalid_auth_token) { Ably::Rest::Client.new(default_options.merge(key: api_key, client_id: 'invalid')).auth.request_token }
|
241
|
+
|
242
|
+
context 'and an incompatible client_id in a TokenDetails object passed to the auth callback' do
|
243
|
+
it 'rejects a TokenDetails object with an incompatible client_id and raises an exception' do
|
244
|
+
client.connection.once(:connected) do
|
245
|
+
client.auth.authorise({}, force: true)
|
246
|
+
client.connection.on(:error) do |error|
|
247
|
+
expect(error).to be_a(Ably::Exceptions::IncompatibleClientId)
|
248
|
+
EventMachine.add_timer(0.1) do
|
249
|
+
expect(client.connection).to be_failed
|
250
|
+
stop_reactor
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
196
257
|
end
|
197
258
|
|
198
259
|
context '#authorise_async' do
|
@@ -216,7 +277,7 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
216
277
|
end
|
217
278
|
end
|
218
279
|
|
219
|
-
context '#
|
280
|
+
context '#auth_params_sync' do
|
220
281
|
it 'returns the auth params synchronously' do
|
221
282
|
expect(auth.auth_params_sync).to be_a(Hash)
|
222
283
|
stop_reactor
|
@@ -232,11 +293,190 @@ describe Ably::Realtime::Auth, :event_machine do
|
|
232
293
|
end
|
233
294
|
end
|
234
295
|
|
235
|
-
context '#
|
296
|
+
context '#auth_header_sync' do
|
236
297
|
it 'returns an auth header synchronously' do
|
237
298
|
expect(auth.auth_header_sync).to be_a(String)
|
238
299
|
stop_reactor
|
239
300
|
end
|
240
301
|
end
|
302
|
+
|
303
|
+
describe '#client_id_validated?' do
|
304
|
+
let(:auth) { Ably::Rest::Client.new(default_options.merge(key: api_key)).auth }
|
305
|
+
|
306
|
+
context 'when using basic auth' do
|
307
|
+
let(:client_options) { default_options.merge(key: api_key) }
|
308
|
+
|
309
|
+
context 'before connected' do
|
310
|
+
it 'is false as basic auth users do not have an identity' do
|
311
|
+
expect(client.auth).to_not be_client_id_validated
|
312
|
+
stop_reactor
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context 'once connected' do
|
317
|
+
it 'is true' do
|
318
|
+
client.connection.once(:connected) do
|
319
|
+
expect(client.auth).to be_client_id_validated
|
320
|
+
stop_reactor
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'contains a validated wildcard client_id' do
|
325
|
+
client.connection.once(:connected) do
|
326
|
+
expect(client.auth.client_id).to eql('*')
|
327
|
+
stop_reactor
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
context 'when using a token string' do
|
334
|
+
context 'with a valid client_id' do
|
335
|
+
let(:client_options) { default_options.merge(token: auth.request_token(client_id: 'present').token) }
|
336
|
+
|
337
|
+
context 'before connected' do
|
338
|
+
it 'is false as identification is not possible from an opaque token string' do
|
339
|
+
expect(client.auth).to_not be_client_id_validated
|
340
|
+
stop_reactor
|
341
|
+
end
|
342
|
+
|
343
|
+
specify '#client_id is nil' do
|
344
|
+
expect(client.auth.client_id).to be_nil
|
345
|
+
stop_reactor
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context 'once connected' do
|
350
|
+
it 'is true' do
|
351
|
+
client.connection.once(:connected) do
|
352
|
+
expect(client.auth).to be_client_id_validated
|
353
|
+
stop_reactor
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
specify '#client_id is populated' do
|
358
|
+
client.connection.once(:connected) do
|
359
|
+
expect(client.auth.client_id).to eql('present')
|
360
|
+
stop_reactor
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
context 'with no client_id (anonymous)' do
|
367
|
+
let(:client_options) { default_options.merge(token: auth.request_token(client_id: nil).token) }
|
368
|
+
|
369
|
+
context 'before connected' do
|
370
|
+
it 'is false as identification is not possible from an opaque token string' do
|
371
|
+
expect(client.auth).to_not be_client_id_validated
|
372
|
+
stop_reactor
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
context 'once connected' do
|
377
|
+
it 'is true' do
|
378
|
+
client.connection.once(:connected) do
|
379
|
+
expect(client.auth).to be_client_id_validated
|
380
|
+
stop_reactor
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
context 'with a wildcard client_id (anonymous)' do
|
387
|
+
let(:client_options) { default_options.merge(token: auth.request_token(client_id: '*').token) }
|
388
|
+
|
389
|
+
context 'before connected' do
|
390
|
+
it 'is false as identification is not possible from an opaque token string' do
|
391
|
+
expect(client.auth).to_not be_client_id_validated
|
392
|
+
stop_reactor
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context 'once connected' do
|
397
|
+
it 'is true' do
|
398
|
+
client.connection.once(:connected) do
|
399
|
+
expect(client.auth).to be_client_id_validated
|
400
|
+
stop_reactor
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
context 'when using a token' do
|
408
|
+
context 'with a client_id' do
|
409
|
+
let(:client_options) { default_options.merge(token: auth.request_token(client_id: 'present')) }
|
410
|
+
|
411
|
+
it 'is true' do
|
412
|
+
expect(client.auth).to be_client_id_validated
|
413
|
+
stop_reactor
|
414
|
+
end
|
415
|
+
|
416
|
+
context 'once connected' do
|
417
|
+
it 'is true' do
|
418
|
+
client.connection.once(:connected) do
|
419
|
+
expect(client.auth).to be_client_id_validated
|
420
|
+
stop_reactor
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
context 'with no client_id (anonymous)' do
|
427
|
+
let(:client_options) { default_options.merge(token: auth.request_token(client_id: nil)) }
|
428
|
+
|
429
|
+
it 'is true' do
|
430
|
+
expect(client.auth).to be_client_id_validated
|
431
|
+
stop_reactor
|
432
|
+
end
|
433
|
+
|
434
|
+
context 'once connected' do
|
435
|
+
it 'is true' do
|
436
|
+
client.connection.once(:connected) do
|
437
|
+
expect(client.auth).to be_client_id_validated
|
438
|
+
stop_reactor
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
context 'with a wildcard client_id (anonymous)' do
|
445
|
+
let(:client_options) { default_options.merge(token: auth.request_token(client_id: '*')) }
|
446
|
+
|
447
|
+
it 'is true' do
|
448
|
+
expect(client.auth).to be_client_id_validated
|
449
|
+
stop_reactor
|
450
|
+
end
|
451
|
+
|
452
|
+
context 'once connected' do
|
453
|
+
it 'is true' do
|
454
|
+
client.connection.once(:connected) do
|
455
|
+
expect(client.auth).to be_client_id_validated
|
456
|
+
stop_reactor
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
context 'when using a token request with a client_id' do
|
464
|
+
let(:client_options) { default_options.merge(token: auth.create_token_request(client_id: 'present')) }
|
465
|
+
|
466
|
+
it 'is not true as identification is not confirmed until authenticated' do
|
467
|
+
expect(client.auth).to_not be_client_id_validated
|
468
|
+
stop_reactor
|
469
|
+
end
|
470
|
+
|
471
|
+
context 'once connected' do
|
472
|
+
it 'is true as identification is completed following CONNECTED ProtocolMessage' do
|
473
|
+
client.channel('test').publish('a') do
|
474
|
+
expect(client.auth).to be_client_id_validated
|
475
|
+
stop_reactor
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
241
481
|
end
|
242
482
|
end
|
@@ -186,9 +186,19 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
186
186
|
messages.next do |next_page_messages|
|
187
187
|
expect(next_page_messages.items.count).to eql(5)
|
188
188
|
expect(next_page_messages.items.map(&:data).uniq.first).to eql(message_before_attach)
|
189
|
-
expect(next_page_messages).to be_last
|
190
189
|
|
191
|
-
|
190
|
+
if next_page_messages.last?
|
191
|
+
expect(next_page_messages).to be_last
|
192
|
+
stop_reactor
|
193
|
+
else
|
194
|
+
# If previous page said there is another page it is plausible and correct that
|
195
|
+
# the next page is empty and then the last, if the limit was satisfied
|
196
|
+
next_page_messages.next do |empty_page|
|
197
|
+
expect(empty_page.items.count).to eql(0)
|
198
|
+
expect(empty_page).to be_last
|
199
|
+
stop_reactor
|
200
|
+
end
|
201
|
+
end
|
192
202
|
end
|
193
203
|
end
|
194
204
|
end
|
@@ -504,55 +504,143 @@ describe Ably::Realtime::Channel, :event_machine do
|
|
504
504
|
end
|
505
505
|
end
|
506
506
|
|
507
|
+
context 'nil attributes' do
|
508
|
+
context 'when name is nil' do
|
509
|
+
let(:data) { random_str }
|
510
|
+
|
511
|
+
it 'publishes the message without a name attribute in the payload' do
|
512
|
+
published = false
|
513
|
+
channel.publish(nil, data) do
|
514
|
+
published = true
|
515
|
+
end
|
516
|
+
|
517
|
+
channel.subscribe do |message|
|
518
|
+
expect(message.name).to be_nil
|
519
|
+
channel.history do |page|
|
520
|
+
expect(page.items.first.name).to be_nil
|
521
|
+
expect(page.items.first.data).to eql(data)
|
522
|
+
EM.add_timer(0.5) do
|
523
|
+
expect(published).to eql(true)
|
524
|
+
stop_reactor
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
context 'when data is nil' do
|
532
|
+
let(:name) { random_str }
|
533
|
+
|
534
|
+
it 'publishes the message without a data attribute in the payload' do
|
535
|
+
published = false
|
536
|
+
channel.publish(name, nil) do
|
537
|
+
published = true
|
538
|
+
end
|
539
|
+
|
540
|
+
channel.subscribe do |message|
|
541
|
+
expect(message.data).to be_nil
|
542
|
+
channel.history do |page|
|
543
|
+
expect(page.items.first.name).to eql(name)
|
544
|
+
expect(page.items.first.data).to be_nil
|
545
|
+
EM.add_timer(0.5) do
|
546
|
+
expect(published).to eql(true)
|
547
|
+
stop_reactor
|
548
|
+
end
|
549
|
+
end
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
context 'with neither name or data attributes' do
|
555
|
+
let(:name) { random_str }
|
556
|
+
|
557
|
+
it 'publishes the message without any attributes in the payload' do
|
558
|
+
channel.publish(nil) do
|
559
|
+
channel.history do |page|
|
560
|
+
expect(page.items.first.name).to be_nil
|
561
|
+
expect(page.items.first.data).to be_nil
|
562
|
+
stop_reactor
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
507
569
|
context 'with two invalid message out of 12' do
|
508
|
-
let(:
|
570
|
+
let(:rest_client) { Ably::Rest::Client.new(default_options.merge(client_id: 'valid')) }
|
571
|
+
|
509
572
|
let(:invalid_messages) do
|
510
573
|
2.times.map do |index|
|
511
574
|
Ably::Models::Message(name: index.to_s, data: { "index" => index + 10 }, client_id: 'prohibited')
|
512
575
|
end
|
513
576
|
end
|
514
577
|
|
515
|
-
|
516
|
-
|
517
|
-
channel.publish(messages + invalid_messages).tap do |deferrable|
|
518
|
-
deferrable.callback do
|
519
|
-
raise 'Publish should have failed'
|
520
|
-
end
|
578
|
+
context 'before client_id is known (validated)' do
|
579
|
+
let(:client_options) { default_options.merge(token: rest_client.auth.request_token.token, log_level: :error) }
|
521
580
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
581
|
+
it 'calls the errback once' do
|
582
|
+
channel.publish(messages + invalid_messages).tap do |deferrable|
|
583
|
+
deferrable.callback do
|
584
|
+
raise 'Publish should have failed'
|
585
|
+
end
|
586
|
+
|
587
|
+
deferrable.errback do |error, message|
|
588
|
+
# TODO: Review whether we should fail once or multiple times
|
589
|
+
channel.history do |page|
|
590
|
+
expect(page.items.count).to eql(0)
|
591
|
+
stop_reactor
|
592
|
+
end
|
527
593
|
end
|
528
594
|
end
|
529
595
|
end
|
530
596
|
end
|
597
|
+
|
598
|
+
context 'when client_id is known (validated)' do
|
599
|
+
let(:client_options) { default_options.merge(client_id: 'valid') }
|
600
|
+
|
601
|
+
it 'raises an exception' do
|
602
|
+
expect { channel.publish(messages + invalid_messages) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
603
|
+
stop_reactor
|
604
|
+
end
|
605
|
+
end
|
531
606
|
end
|
532
607
|
|
533
608
|
context 'only invalid messages' do
|
534
|
-
let(:
|
609
|
+
let(:rest_client) { Ably::Rest::Client.new(default_options.merge(client_id: 'valid')) }
|
610
|
+
|
535
611
|
let(:invalid_messages) do
|
536
612
|
10.times.map do |index|
|
537
613
|
Ably::Models::Message(name: index.to_s, data: { "index" => index + 10 }, client_id: 'prohibited')
|
538
614
|
end
|
539
615
|
end
|
540
616
|
|
541
|
-
|
542
|
-
|
543
|
-
channel.publish(invalid_messages).tap do |deferrable|
|
544
|
-
deferrable.callback do
|
545
|
-
raise 'Publish should have failed'
|
546
|
-
end
|
617
|
+
context 'before client_id is known (validated)' do
|
618
|
+
let(:client_options) { default_options.merge(token: rest_client.auth.request_token.token, log_level: :error) }
|
547
619
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
620
|
+
it 'calls the errback once' do
|
621
|
+
channel.publish(invalid_messages).tap do |deferrable|
|
622
|
+
deferrable.callback do
|
623
|
+
raise 'Publish should have failed'
|
624
|
+
end
|
625
|
+
|
626
|
+
deferrable.errback do |error, message|
|
627
|
+
channel.history do |page|
|
628
|
+
expect(page.items.count).to eql(0)
|
629
|
+
stop_reactor
|
630
|
+
end
|
552
631
|
end
|
553
632
|
end
|
554
633
|
end
|
555
634
|
end
|
635
|
+
|
636
|
+
context 'when client_id is known (validated)' do
|
637
|
+
let(:client_options) { default_options.merge(client_id: 'valid') }
|
638
|
+
|
639
|
+
it 'raises an exception' do
|
640
|
+
expect { channel.publish(invalid_messages) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
641
|
+
stop_reactor
|
642
|
+
end
|
643
|
+
end
|
556
644
|
end
|
557
645
|
end
|
558
646
|
|
@@ -581,6 +669,208 @@ describe Ably::Realtime::Channel, :event_machine do
|
|
581
669
|
end
|
582
670
|
end
|
583
671
|
end
|
672
|
+
|
673
|
+
context 'identified clients' do
|
674
|
+
context 'when authenticated with a wildcard client_id' do
|
675
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') }
|
676
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
677
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
|
678
|
+
let(:channel) { client.channels.get(channel_name) }
|
679
|
+
|
680
|
+
context 'with a valid client_id in the message' do
|
681
|
+
it 'succeeds' do
|
682
|
+
channel.publish([name: 'event', client_id: 'validClient']).tap do |deferrable|
|
683
|
+
deferrable.errback { raise 'Should have succeeded' }
|
684
|
+
end
|
685
|
+
channel.subscribe('event') do |message|
|
686
|
+
expect(message.client_id).to eql('validClient')
|
687
|
+
EM.add_timer(0.5) { stop_reactor }
|
688
|
+
end
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
context 'with a wildcard client_id in the message' do
|
693
|
+
it 'throws an exception' do
|
694
|
+
expect { channel.publish([name: 'event', client_id: '*']) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
695
|
+
stop_reactor
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
context 'with an empty client_id in the message' do
|
700
|
+
it 'succeeds and publishes without a client_id' do
|
701
|
+
channel.publish([name: 'event', client_id: nil]).tap do |deferrable|
|
702
|
+
deferrable.errback { raise 'Should have succeeded' }
|
703
|
+
end
|
704
|
+
channel.subscribe('event') do |message|
|
705
|
+
expect(message.client_id).to be_nil
|
706
|
+
EM.add_timer(0.5) { stop_reactor }
|
707
|
+
end
|
708
|
+
end
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
context 'when authenticated with a Token string with an implicit client_id' do
|
713
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: 'valid').token }
|
714
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
715
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
|
716
|
+
let(:channel) { client.channels.get(channel_name) }
|
717
|
+
|
718
|
+
context 'before the client is CONNECTED and the client\'s identity has been obtained' do
|
719
|
+
context 'with a valid client_id in the message' do
|
720
|
+
it 'succeeds' do
|
721
|
+
channel.publish([name: 'event', client_id: 'valid']).tap do |deferrable|
|
722
|
+
deferrable.errback { raise 'Should have succeeded' }
|
723
|
+
end
|
724
|
+
channel.subscribe('event') do |message|
|
725
|
+
expect(message.client_id).to eql('valid')
|
726
|
+
EM.add_timer(0.5) { stop_reactor }
|
727
|
+
end
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
context 'with an invalid client_id in the message' do
|
732
|
+
let(:client_options) { default_options.merge(key: nil, token: token, log_level: :error) }
|
733
|
+
it 'succeeds in the client library but then fails when delivered to Ably' do
|
734
|
+
channel.publish([name: 'event', client_id: 'invalid']).tap do |deferrable|
|
735
|
+
EM.add_timer(0.5) { stop_reactor }
|
736
|
+
end
|
737
|
+
channel.subscribe('event') do |message|
|
738
|
+
raise 'Message should not have been published'
|
739
|
+
end
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
context 'with an empty client_id in the message' do
|
744
|
+
it 'succeeds and publishes with an implicit client_id' do
|
745
|
+
channel.publish([name: 'event', client_id: nil]).tap do |deferrable|
|
746
|
+
deferrable.errback { raise 'Should have succeeded' }
|
747
|
+
end
|
748
|
+
channel.subscribe('event') do |message|
|
749
|
+
expect(message.client_id).to eql('valid')
|
750
|
+
EM.add_timer(0.5) { stop_reactor }
|
751
|
+
end
|
752
|
+
end
|
753
|
+
end
|
754
|
+
end
|
755
|
+
|
756
|
+
context 'after the client is CONNECTED and the client\'s identity is known' do
|
757
|
+
context 'with a valid client_id in the message' do
|
758
|
+
it 'succeeds' do
|
759
|
+
client.connection.once(:connected) do
|
760
|
+
channel.publish([name: 'event', client_id: 'valid']).tap do |deferrable|
|
761
|
+
deferrable.errback { raise 'Should have succeeded' }
|
762
|
+
end
|
763
|
+
channel.subscribe('event') do |message|
|
764
|
+
expect(message.client_id).to eql('valid')
|
765
|
+
EM.add_timer(0.5) { stop_reactor }
|
766
|
+
end
|
767
|
+
end
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
context 'with an invalid client_id in the message' do
|
772
|
+
it 'throws an exception' do
|
773
|
+
client.connection.once(:connected) do
|
774
|
+
expect { channel.publish([name: 'event', client_id: 'invalid']) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
775
|
+
stop_reactor
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
context 'with an empty client_id in the message' do
|
781
|
+
it 'succeeds and publishes with an implicit client_id' do
|
782
|
+
client.connection.once(:connected) do
|
783
|
+
channel.publish([name: 'event', client_id: nil]).tap do |deferrable|
|
784
|
+
deferrable.errback { raise 'Should have succeeded' }
|
785
|
+
end
|
786
|
+
channel.subscribe('event') do |message|
|
787
|
+
expect(message.client_id).to eql('valid')
|
788
|
+
EM.add_timer(0.5) { stop_reactor }
|
789
|
+
end
|
790
|
+
end
|
791
|
+
end
|
792
|
+
end
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
context 'when authenticated with a valid client_id' do
|
797
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: 'valid') }
|
798
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
799
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
|
800
|
+
let(:channel) { client.channels.get(channel_name) }
|
801
|
+
|
802
|
+
context 'with a valid client_id' do
|
803
|
+
it 'succeeds' do
|
804
|
+
channel.publish([name: 'event', client_id: 'valid']).tap do |deferrable|
|
805
|
+
deferrable.errback { raise 'Should have succeeded' }
|
806
|
+
end
|
807
|
+
channel.subscribe('event') do |message|
|
808
|
+
expect(message.client_id).to eql('valid')
|
809
|
+
EM.add_timer(0.5) { stop_reactor }
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
context 'with a wildcard client_id in the message' do
|
815
|
+
it 'throws an exception' do
|
816
|
+
expect { channel.publish([name: 'event', client_id: '*']) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
817
|
+
stop_reactor
|
818
|
+
end
|
819
|
+
end
|
820
|
+
|
821
|
+
context 'with an invalid client_id in the message' do
|
822
|
+
it 'throws an exception' do
|
823
|
+
expect { channel.publish([name: 'event', client_id: 'invalid']) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
824
|
+
stop_reactor
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
context 'with an empty client_id in the message' do
|
829
|
+
it 'succeeds and publishes with an implicit client_id' do
|
830
|
+
channel.publish([name: 'event', client_id: nil]).tap do |deferrable|
|
831
|
+
deferrable.errback { raise 'Should have succeeded' }
|
832
|
+
end
|
833
|
+
channel.subscribe('event') do |message|
|
834
|
+
expect(message.client_id).to eql('valid')
|
835
|
+
EM.add_timer(0.5) { stop_reactor }
|
836
|
+
end
|
837
|
+
end
|
838
|
+
end
|
839
|
+
end
|
840
|
+
|
841
|
+
context 'when anonymous and no client_id' do
|
842
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: nil) }
|
843
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
844
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
|
845
|
+
let(:channel) { client.channels.get(channel_name) }
|
846
|
+
|
847
|
+
context 'with a client_id in the message' do
|
848
|
+
it 'throws an exception' do
|
849
|
+
expect { channel.publish([name: 'event', client_id: 'invalid']) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
850
|
+
stop_reactor
|
851
|
+
end
|
852
|
+
end
|
853
|
+
|
854
|
+
context 'with a wildcard client_id in the message' do
|
855
|
+
it 'throws an exception' do
|
856
|
+
expect { channel.publish([name: 'event', client_id: '*']) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
857
|
+
stop_reactor
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
861
|
+
context 'with an empty client_id in the message' do
|
862
|
+
it 'succeeds and publishes with an implicit client_id' do
|
863
|
+
channel.publish([name: 'event', client_id: nil]).tap do |deferrable|
|
864
|
+
deferrable.errback { raise 'Should have succeeded' }
|
865
|
+
end
|
866
|
+
channel.subscribe('event') do |message|
|
867
|
+
expect(message.client_id).to be_nil
|
868
|
+
EM.add_timer(0.5) { stop_reactor }
|
869
|
+
end
|
870
|
+
end
|
871
|
+
end
|
872
|
+
end
|
873
|
+
end
|
584
874
|
end
|
585
875
|
|
586
876
|
describe '#subscribe' do
|
@@ -881,7 +1171,7 @@ describe Ably::Realtime::Channel, :event_machine do
|
|
881
1171
|
|
882
1172
|
context 'a :failed channel' do
|
883
1173
|
let(:original_error) { RuntimeError.new }
|
884
|
-
let(:client_options)
|
1174
|
+
let(:client_options) { default_options.merge(log_level: :fatal) }
|
885
1175
|
|
886
1176
|
it 'remains in the :failed state and retains the error_reason' do
|
887
1177
|
channel.attach do
|
@@ -904,6 +1194,8 @@ describe Ably::Realtime::Channel, :event_machine do
|
|
904
1194
|
end
|
905
1195
|
|
906
1196
|
context 'a channel ATTACH request when connection SUSPENDED' do
|
1197
|
+
let(:client_options) { default_options.merge(log_level: :fatal) }
|
1198
|
+
|
907
1199
|
it 'raises an exception' do
|
908
1200
|
client.connect do
|
909
1201
|
client.connection.once(:suspended) do
|