ably-rest 0.8.14 → 0.8.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/lib/submodules/ably-ruby/CHANGELOG.md +48 -61
  3. data/lib/submodules/ably-ruby/README.md +6 -0
  4. data/lib/submodules/ably-ruby/ably.gemspec +1 -1
  5. data/lib/submodules/ably-ruby/lib/ably/models/http_paginated_response.rb +90 -0
  6. data/lib/submodules/ably-ruby/lib/ably/models/paginated_result.rb +5 -0
  7. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +30 -15
  8. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +25 -0
  9. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +3 -3
  10. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +13 -0
  11. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +2 -2
  12. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +3 -3
  13. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +60 -3
  14. data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
  15. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +29 -0
  16. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +8 -6
  17. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +52 -0
  18. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +44 -8
  19. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +79 -38
  20. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +2 -4
  21. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +69 -21
  22. data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +10 -12
  23. data/lib/submodules/ably-ruby/spec/unit/models/http_paginated_result_spec.rb +380 -0
  24. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +109 -51
  25. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +3 -3
  26. metadata +5 -4
@@ -615,16 +615,23 @@ describe Ably::Realtime::Connection, :event_machine do
615
615
  end
616
616
  end
617
617
 
618
- it 'is set to 0 when a message sent ACK is received' do
619
- channel.publish('event', 'data') do
618
+ it 'is set to 0 when a message is received back' do
619
+ channel.publish('event', 'data')
620
+ channel.subscribe do
620
621
  expect(connection.serial).to eql(0)
621
622
  stop_reactor
622
623
  end
623
624
  end
624
625
 
625
- it 'is set to 1 when the second message sent ACK is received' do
626
+ it 'is set to 1 when the second message is received' do
626
627
  channel.publish('event', 'data') do
627
- channel.publish('event', 'data') do
628
+ channel.publish('event', 'data')
629
+ end
630
+
631
+ messages = []
632
+ channel.subscribe do |message|
633
+ messages << message
634
+ if messages.length == 2
628
635
  expect(connection.serial).to eql(1)
629
636
  stop_reactor
630
637
  end
@@ -884,11 +891,16 @@ describe Ably::Realtime::Connection, :event_machine do
884
891
  expect(connection.serial).to eql(expected_serial)
885
892
 
886
893
  channel.attach do
887
- channel.publish('event', 'data') do
894
+ channel.publish('event', 'data')
895
+ channel.subscribe do
896
+ channel.unsubscribe
897
+
888
898
  expected_serial += 1 # attach message received
889
899
  expect(connection.serial).to eql(expected_serial)
890
900
 
891
- channel.publish('event', 'data') do
901
+ channel.publish('event', 'data')
902
+ channel.subscribe do
903
+ channel.unsubscribe
892
904
  expected_serial += 1 # attach message received
893
905
  expect(connection.serial).to eql(expected_serial)
894
906
 
@@ -1278,6 +1290,22 @@ describe Ably::Realtime::Connection, :event_machine do
1278
1290
  end
1279
1291
 
1280
1292
  context 'connection state change' do
1293
+ # See https://github.com/ably/ably-ruby/issues/103
1294
+ it 'emits event to all and single subscribers' do
1295
+ connected_emitted = []
1296
+ block = Proc.new do |state_change|
1297
+ if state_change.current == :connected
1298
+ connected_emitted << state_change
1299
+ EventMachine.add_timer(0.5) do
1300
+ expect(connected_emitted.length).to eql(2)
1301
+ stop_reactor
1302
+ end
1303
+ end
1304
+ end
1305
+ connection.on(&block)
1306
+ connection.on(:connected, &block)
1307
+ end
1308
+
1281
1309
  it 'emits a ConnectionStateChange object' do
1282
1310
  connection.on(:connected) do |connection_state_change|
1283
1311
  expect(connection_state_change).to be_a(Ably::Models::ConnectionStateChange)
@@ -1286,6 +1314,14 @@ describe Ably::Realtime::Connection, :event_machine do
1286
1314
  end
1287
1315
 
1288
1316
  context 'ConnectionStateChange object' do
1317
+ def unbind
1318
+ if connection.transport
1319
+ connection.transport.unbind
1320
+ else
1321
+ EventMachine.add_timer(0.005) { unbind }
1322
+ end
1323
+ end
1324
+
1289
1325
  it 'has current state' do
1290
1326
  connection.on(:connected) do |connection_state_change|
1291
1327
  expect(connection_state_change.current).to eq(:connected)
@@ -1349,7 +1385,7 @@ describe Ably::Realtime::Connection, :event_machine do
1349
1385
  expect(connection_state_change.retry_in).to eql(0)
1350
1386
  stop_reactor
1351
1387
  end
1352
- EventMachine.add_timer(0.005) { connection.transport.unbind }
1388
+ unbind
1353
1389
  end
1354
1390
  end
1355
1391
 
@@ -1370,7 +1406,7 @@ describe Ably::Realtime::Connection, :event_machine do
1370
1406
  expect(connection_state_change.retry_in).to be > 0
1371
1407
  stop_reactor
1372
1408
  end
1373
- EventMachine.add_timer(0.005) { connection.transport.unbind }
1409
+ unbind
1374
1410
  end
1375
1411
  connection.transport.unbind
1376
1412
  end
@@ -42,9 +42,11 @@ describe Ably::Realtime::Presence, :event_machine do
42
42
 
43
43
  def setup_test(method_name, args, options)
44
44
  if options[:enter_first]
45
- presence_client_one.public_send(method_name.to_s.gsub(/leave|update/, 'enter'), args) do
45
+ presence_client_one.subscribe do
46
+ presence_client_one.unsubscribe
46
47
  yield
47
48
  end
49
+ presence_client_one.public_send(method_name.to_s.gsub(/leave|update/, 'enter'), args)
48
50
  else
49
51
  yield
50
52
  end
@@ -468,7 +470,14 @@ describe Ably::Realtime::Presence, :event_machine do
468
470
 
469
471
  context 'once server sync is complete' do
470
472
  it 'behaves like an Enumerable allowing direct access to current members' do
471
- when_all(presence_client_one.enter, presence_client_two.enter) do
473
+ presence_client_one.enter
474
+ presence_client_two.enter
475
+
476
+ entered = 0
477
+ presence_client_one.subscribe(:enter) do
478
+ entered += 1
479
+ next unless entered == 2
480
+
472
481
  presence_anonymous_client.members.once(:in_sync) do
473
482
  expect(presence_anonymous_client.members.count).to eql(2)
474
483
  member_ids = presence_anonymous_client.members.map(&:member_key)
@@ -495,7 +504,10 @@ describe Ably::Realtime::Presence, :event_machine do
495
504
 
496
505
  context 'when attaching to a channel with members present' do
497
506
  it 'is false and the presence channel will subsequently be synced' do
498
- presence_client_one.enter do
507
+ presence_client_one.enter
508
+ presence_client_one.subscribe(:enter) do
509
+ presence_client_one.unsubscribe :enter
510
+
499
511
  channel_anonymous_client.attach do
500
512
  expect(channel_anonymous_client.presence).to_not be_sync_complete
501
513
  channel_anonymous_client.presence.get(wait_for_sync: true) do
@@ -680,16 +692,18 @@ describe Ably::Realtime::Presence, :event_machine do
680
692
  it 'waits until sync is complete', em_timeout: 30 do # allow for slow connections and lots of messages
681
693
  enter_expected_count.times do |index|
682
694
  EventMachine.add_timer(index / 10) do
683
- presence_client_one.enter_client("client:#{index}") do |message|
684
- entered << message
685
- next unless entered.count == enter_expected_count
695
+ presence_client_one.enter_client("client:#{index}")
696
+ end
697
+ end
686
698
 
687
- presence_anonymous_client.get(wait_for_sync: true) do |members|
688
- expect(members.map(&:client_id).uniq.count).to eql(enter_expected_count)
689
- expect(members.count).to eql(enter_expected_count)
690
- stop_reactor
691
- end
692
- end
699
+ presence_client_one.subscribe(:enter) do |message|
700
+ entered << message
701
+ next unless entered.count == enter_expected_count
702
+
703
+ presence_anonymous_client.get(wait_for_sync: true) do |members|
704
+ expect(members.map(&:client_id).uniq.count).to eql(enter_expected_count)
705
+ expect(members.count).to eql(enter_expected_count)
706
+ stop_reactor
693
707
  end
694
708
  end
695
709
  end
@@ -697,19 +711,21 @@ describe Ably::Realtime::Presence, :event_machine do
697
711
 
698
712
  context 'by default' do
699
713
  it 'it does not wait for sync', em_timeout: 30 do # allow for slow connections and lots of messages
700
- enter_expected_count.times do |index|
701
- EventMachine.add_timer(index / 10) do
702
- presence_client_one.enter_client("client:#{index}") do |message|
703
- entered << message
704
- next unless entered.count == enter_expected_count
705
-
706
- channel_anonymous_client.attach do
707
- presence_anonymous_client.get do |members|
708
- expect(presence_anonymous_client.members).to_not be_in_sync
709
- expect(members.count).to eql(0)
710
- stop_reactor
711
- end
712
- end
714
+ enter_expected_count.times do |indx|
715
+ EventMachine.add_timer(indx / 10) do
716
+ presence_client_one.enter_client "client:#{indx}"
717
+ end
718
+ end
719
+
720
+ presence_client_one.subscribe(:enter) do |message|
721
+ entered << message
722
+ next unless entered.count == enter_expected_count
723
+
724
+ channel_anonymous_client.attach do
725
+ presence_anonymous_client.get do |members|
726
+ expect(presence_anonymous_client.members).to_not be_in_sync
727
+ expect(members.count).to eql(0)
728
+ stop_reactor
713
729
  end
714
730
  end
715
731
  end
@@ -896,15 +912,25 @@ describe Ably::Realtime::Presence, :event_machine do
896
912
 
897
913
  context 'and sync is complete' do
898
914
  it 'does not cache members that have left' do
899
- presence_client_one.enter enter_data do
915
+ enter_ack = false
916
+
917
+ presence_client_one.subscribe(:enter) do
918
+ presence_client_one.unsubscribe :enter
919
+
900
920
  expect(presence_client_one.members).to be_in_sync
901
921
  expect(presence_client_one.members.send(:members).count).to eql(1)
902
922
  presence_client_one.leave data
903
923
  end
904
924
 
925
+ presence_client_one.enter(enter_data) do
926
+ enter_ack = true
927
+ end
928
+
905
929
  presence_client_one.subscribe(:leave) do |presence_message|
930
+ presence_client_one.unsubscribe :leave
906
931
  expect(presence_message.data).to eql(data)
907
932
  expect(presence_client_one.members.send(:members).count).to eql(0)
933
+ expect(enter_ack).to eql(true)
908
934
  stop_reactor
909
935
  end
910
936
  end
@@ -1290,7 +1316,9 @@ describe Ably::Realtime::Presence, :event_machine do
1290
1316
  # skip 'it fails if the connection changes to failed state'
1291
1317
 
1292
1318
  it 'returns the current members on the channel' do
1293
- presence_client_one.enter do
1319
+ presence_client_one.enter
1320
+ presence_client_one.subscribe(:enter) do
1321
+ presence_client_one.unsubscribe :enter
1294
1322
  presence_client_one.get do |members|
1295
1323
  expect(members.count).to eq(1)
1296
1324
 
@@ -1351,7 +1379,10 @@ describe Ably::Realtime::Presence, :event_machine do
1351
1379
  end
1352
1380
 
1353
1381
  it 'does not wait for SYNC to complete if :wait_for_sync option is false' do
1354
- presence_client_one.enter do
1382
+ presence_client_one.enter
1383
+ presence_client_one.subscribe(:enter) do
1384
+ presence_client_one.unsubscribe :enter
1385
+
1355
1386
  presence_client_two.get(wait_for_sync: false) do |members|
1356
1387
  expect(members.count).to eql(0)
1357
1388
  stop_reactor
@@ -1362,11 +1393,13 @@ describe Ably::Realtime::Presence, :event_machine do
1362
1393
  context 'when a member enters and then leaves' do
1363
1394
  it 'has no members' do
1364
1395
  presence_client_one.enter do
1365
- presence_client_one.leave do
1366
- presence_client_one.get do |members|
1367
- expect(members.count).to eq(0)
1368
- stop_reactor
1369
- end
1396
+ presence_client_one.leave
1397
+ end
1398
+
1399
+ presence_client_one.subscribe(:leave) do
1400
+ presence_client_one.get do |members|
1401
+ expect(members.count).to eq(0)
1402
+ stop_reactor
1370
1403
  end
1371
1404
  end
1372
1405
  end
@@ -1524,7 +1557,10 @@ describe Ably::Realtime::Presence, :event_machine do
1524
1557
 
1525
1558
  context 'REST #get' do
1526
1559
  it 'returns current members' do
1527
- presence_client_one.enter(data_payload) do
1560
+ presence_client_one.enter data_payload
1561
+ presence_client_one.subscribe(:enter) do
1562
+ presence_client_one.unsubscribe :enter
1563
+
1528
1564
  members_page = channel_rest_client_one.presence.get
1529
1565
  this_member = members_page.items.first
1530
1566
 
@@ -1538,7 +1574,10 @@ describe Ably::Realtime::Presence, :event_machine do
1538
1574
 
1539
1575
  it 'returns no members once left' do
1540
1576
  presence_client_one.enter(data_payload) do
1541
- presence_client_one.leave do
1577
+ presence_client_one.leave
1578
+ presence_client_one.subscribe(:leave) do
1579
+ presence_client_one.unsubscribe :leave
1580
+
1542
1581
  members_page = channel_rest_client_one.presence.get
1543
1582
  expect(members_page.items.count).to eql(0)
1544
1583
  stop_reactor
@@ -1654,7 +1693,8 @@ describe Ably::Realtime::Presence, :event_machine do
1654
1693
 
1655
1694
  context '#get' do
1656
1695
  it 'returns a list of members with decrypted data' do
1657
- encrypted_channel.presence.enter(data) do
1696
+ encrypted_channel.presence.enter(data)
1697
+ encrypted_channel.presence.subscribe(:enter) do
1658
1698
  encrypted_channel.presence.get do |members|
1659
1699
  member = members.first
1660
1700
  expect(member.encoding).to be_nil
@@ -1667,7 +1707,8 @@ describe Ably::Realtime::Presence, :event_machine do
1667
1707
 
1668
1708
  context 'REST #get' do
1669
1709
  it 'returns a list of members with decrypted data' do
1670
- encrypted_channel.presence.enter(data) do
1710
+ encrypted_channel.presence.enter(data)
1711
+ encrypted_channel.presence.subscribe(:enter) do
1671
1712
  member = channel_rest_client_one.presence.get.items.first
1672
1713
  expect(member.encoding).to be_nil
1673
1714
  expect(member.data).to eql(data)
@@ -1738,7 +1779,7 @@ describe Ably::Realtime::Presence, :event_machine do
1738
1779
  context 'connection failure mid-way through a large member sync' do
1739
1780
  let(:members_count) { 250 }
1740
1781
  let(:sync_pages_received) { [] }
1741
- let(:client_options) { default_options.merge(log_level: :error) }
1782
+ let(:client_options) { default_options.merge(log_level: :fatal) }
1742
1783
 
1743
1784
  it 'resumes the SYNC operation', em_timeout: 15 do
1744
1785
  when_all(*members_count.times.map do |index|
@@ -360,10 +360,7 @@ describe Ably::Rest::Channel do
360
360
  let(:channel_name) { "persisted:#{random_str(4)}" }
361
361
  let(:channel) { client.channel(channel_name) }
362
362
  let(:endpoint) do
363
- client.endpoint.tap do |client_end_point|
364
- client_end_point.user = key_name
365
- client_end_point.password = key_secret
366
- end
363
+ client.endpoint
367
364
  end
368
365
  let(:default_history_options) do
369
366
  {
@@ -378,6 +375,7 @@ describe Ably::Rest::Channel do
378
375
  query_params = default_history_options
379
376
  .merge(option => milliseconds).map { |k, v| "#{k}=#{v}" }.join('&')
380
377
  stub_request(:get, "#{endpoint}/channels/#{Addressable::URI.encode(channel_name)}/messages?#{query_params}").
378
+ with(basic_auth: [key_name, key_secret]).
381
379
  to_return(:body => '{}', :headers => { 'Content-Type' => 'application/json' })
382
380
  }
383
381
 
@@ -111,7 +111,8 @@ describe Ably::Rest::Client do
111
111
  let(:client_options) { default_options.merge(key: api_key) }
112
112
 
113
113
  let!(:get_message_history_stub) do
114
- stub_request(:get, "https://#{api_key}@#{environment}-#{Ably::Rest::Client::DOMAIN}/channels/#{channel_name}/messages?#{history_querystring}").
114
+ stub_request(:get, "https://#{environment}-#{Ably::Rest::Client::DOMAIN}/channels/#{channel_name}/messages?#{history_querystring}").
115
+ with(basic_auth: [key_name, key_secret]).
115
116
  to_return(body: [], headers: { 'Content-Type' => 'application/json' })
116
117
  end
117
118
 
@@ -284,7 +285,9 @@ describe Ably::Rest::Client do
284
285
  context 'when environment is NOT production' do
285
286
  let(:client_options) { default_options.merge(environment: 'sandbox', key: api_key) }
286
287
  let!(:default_host_request_stub) do
287
- stub_request(:post, "https://#{api_key}@#{environment}-#{Ably::Rest::Client::DOMAIN}#{path}").to_return do
288
+ stub_request(:post, "https://#{environment}-#{Ably::Rest::Client::DOMAIN}#{path}").
289
+ with(basic_auth: [key_name, key_secret]).
290
+ to_return do
288
291
  raise Faraday::TimeoutError.new('timeout error message')
289
292
  end
290
293
  end
@@ -313,16 +316,16 @@ describe Ably::Rest::Client do
313
316
  end
314
317
 
315
318
  let!(:first_fallback_request_stub) do
316
- stub_request(:post, "https://#{api_key}@#{custom_hosts[0]}#{path}").to_return(&fallback_block)
319
+ stub_request(:post, "https://#{custom_hosts[0]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
317
320
  end
318
321
 
319
322
  let!(:second_fallback_request_stub) do
320
- stub_request(:post, "https://#{api_key}@#{custom_hosts[1]}#{path}").to_return(&fallback_block)
323
+ stub_request(:post, "https://#{custom_hosts[1]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
321
324
  end
322
325
 
323
326
  context 'and connection times out' do
324
327
  let!(:default_host_request_stub) do
325
- stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return do
328
+ stub_request(:post, "https://#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return do
326
329
  raise Faraday::TimeoutError.new('timeout error message')
327
330
  end
328
331
  end
@@ -336,7 +339,7 @@ describe Ably::Rest::Client do
336
339
 
337
340
  context "and the total request time exeeds #{http_defaults.fetch(:max_retry_duration)} seconds" do
338
341
  let!(:default_host_request_stub) do
339
- stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return do
342
+ stub_request(:post, "https://#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return do
340
343
  sleep max_retry_duration * 1.5
341
344
  raise Faraday::TimeoutError.new('timeout error message')
342
345
  end
@@ -353,7 +356,7 @@ describe Ably::Rest::Client do
353
356
 
354
357
  context 'and connection fails' do
355
358
  let!(:default_host_request_stub) do
356
- stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return do
359
+ stub_request(:post, "https://#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return do
357
360
  raise Faraday::ConnectionFailed.new('connection failure error message')
358
361
  end
359
362
  end
@@ -369,7 +372,7 @@ describe Ably::Rest::Client do
369
372
  context 'and basic authentication fails' do
370
373
  let(:status) { 401 }
371
374
  let!(:default_host_request_stub) do
372
- stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return(
375
+ stub_request(:post, "https://#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return(
373
376
  headers: { 'Content-Type' => 'application/json' },
374
377
  status: status,
375
378
  body: {
@@ -401,7 +404,7 @@ describe Ably::Rest::Client do
401
404
  end
402
405
  end
403
406
  let!(:default_host_request_stub) do
404
- stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return(&fallback_block)
407
+ stub_request(:post, "https://#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
405
408
  end
406
409
 
407
410
  it 'attempts the fallback hosts as this is an authentication failure' do
@@ -437,20 +440,20 @@ describe Ably::Rest::Client do
437
440
  end
438
441
  end
439
442
  let!(:default_host_request_stub) do
440
- stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return(&fallback_block)
443
+ stub_request(:post, "https://#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
441
444
  end
442
445
 
443
446
  context 'with custom fallback hosts provided' do
444
447
  let!(:first_fallback_request_stub) do
445
- stub_request(:post, "https://#{api_key}@#{custom_hosts[0]}#{path}").to_return(&fallback_block)
448
+ stub_request(:post, "https://#{custom_hosts[0]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
446
449
  end
447
450
 
448
451
  let!(:second_fallback_request_stub) do
449
- stub_request(:post, "https://#{api_key}@#{custom_hosts[1]}#{path}").to_return(&fallback_block)
452
+ stub_request(:post, "https://#{custom_hosts[1]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
450
453
  end
451
454
 
452
455
  let(:client_options) {
453
- production_options.merge(fallback_hosts: custom_hosts)
456
+ production_options.merge(fallback_hosts: custom_hosts, log_level: :error)
454
457
  }
455
458
 
456
459
  it 'attempts the fallback hosts as this is an authentication failure (#RSC15b, #TO3k6)' do
@@ -516,7 +519,8 @@ describe Ably::Rest::Client do
516
519
  port: port,
517
520
  tls: false,
518
521
  http_request_timeout: request_timeout,
519
- max_retry_duration: request_timeout * 3
522
+ max_retry_duration: request_timeout * 3,
523
+ log_level: :error
520
524
  )
521
525
  end
522
526
  let(:fail_fallback_request_count) { 1 }
@@ -619,16 +623,16 @@ describe Ably::Rest::Client do
619
623
  end
620
624
  end
621
625
  let!(:default_host_request_stub) do
622
- stub_request(:post, "https://#{api_key}@#{env}-#{Ably::Rest::Client::DOMAIN}#{path}").to_return(&fallback_block)
626
+ stub_request(:post, "https://#{env}-#{Ably::Rest::Client::DOMAIN}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
623
627
  end
624
628
 
625
629
  context 'with custom fallback hosts provided (#RSC15b, #TO3k6)' do
626
630
  let!(:first_fallback_request_stub) do
627
- stub_request(:post, "https://#{api_key}@#{custom_hosts[0]}#{path}").to_return(&fallback_block)
631
+ stub_request(:post, "https://#{custom_hosts[0]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
628
632
  end
629
633
 
630
634
  let!(:second_fallback_request_stub) do
631
- stub_request(:post, "https://#{api_key}@#{custom_hosts[1]}#{path}").to_return(&fallback_block)
635
+ stub_request(:post, "https://#{custom_hosts[1]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
632
636
  end
633
637
 
634
638
  let(:client_options) {
@@ -666,11 +670,11 @@ describe Ably::Rest::Client do
666
670
  }
667
671
 
668
672
  let!(:first_fallback_request_stub) do
669
- stub_request(:post, "https://#{api_key}@#{Ably::FALLBACK_HOSTS[0]}#{path}").to_return(&fallback_block)
673
+ stub_request(:post, "https://#{Ably::FALLBACK_HOSTS[0]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
670
674
  end
671
675
 
672
676
  let!(:second_fallback_request_stub) do
673
- stub_request(:post, "https://#{api_key}@#{Ably::FALLBACK_HOSTS[1]}#{path}").to_return(&fallback_block)
677
+ stub_request(:post, "https://#{Ably::FALLBACK_HOSTS[1]}#{path}").with(basic_auth: [key_name, key_secret]).to_return(&fallback_block)
674
678
  end
675
679
 
676
680
  let(:client_options) {
@@ -701,7 +705,7 @@ describe Ably::Rest::Client do
701
705
  let(:path) { '/channels/test/publish' }
702
706
 
703
707
  let!(:custom_host_request_stub) do
704
- stub_request(:post, "https://#{api_key}@#{custom_host}#{path}").to_return do
708
+ stub_request(:post, "https://#{custom_host}#{path}").with(basic_auth: [key_name, key_secret]).to_return do
705
709
  raise Faraday::ConnectionFailed.new('connection failure error message')
706
710
  end
707
711
  end
@@ -840,11 +844,12 @@ describe Ably::Rest::Client do
840
844
  lib << Ably::VERSION
841
845
 
842
846
 
843
- stub_request(:post, "#{client.endpoint.to_s.gsub('://', "://#{api_key}@")}/channels/foo/publish").
847
+ stub_request(:post, "#{client.endpoint.to_s.gsub('://', "://")}/channels/foo/publish").
844
848
  with(headers: {
845
849
  'X-Ably-Version' => Ably::PROTOCOL_VERSION,
846
850
  'X-Ably-Lib' => lib.join('-')
847
851
  }).
852
+ with(basic_auth: [key_name, key_secret]).
848
853
  to_return(status: 201, body: '{}', headers: { 'Content-Type' => 'application/json' })
849
854
  end
850
855
 
@@ -855,5 +860,48 @@ describe Ably::Rest::Client do
855
860
  end
856
861
  end
857
862
  end
863
+
864
+ context '#request (#RSC19*)' do
865
+ let(:client_options) { default_options.merge(key: api_key) }
866
+
867
+ context 'get' do
868
+ it 'returns an HttpPaginatedResponse object' do
869
+ response = client.request(:get, 'time')
870
+ expect(response).to be_a(Ably::Models::HttpPaginatedResponse)
871
+ expect(response.status_code).to eql(200)
872
+ end
873
+
874
+ context '404 request to invalid URL' do
875
+ it 'returns an object with 404 status code and error message' do
876
+ response = client.request(:get, 'does-not-exist')
877
+ expect(response).to be_a(Ably::Models::HttpPaginatedResponse)
878
+ expect(response.error_message).to match(/Could not find/)
879
+ expect(response.error_code).to eql(40400)
880
+ expect(response.status_code).to eql(404)
881
+ end
882
+ end
883
+
884
+ context 'paged results' do
885
+ let(:channel_name) { random_str }
886
+
887
+ it 'provides paging' do
888
+ 10.times do
889
+ client.request(:post, "/channels/#{channel_name}/publish", {}, { 'name': 'test' })
890
+ end
891
+ response = client.request(:get, "/channels/#{channel_name}/messages", { limit: 2 })
892
+ expect(response.items.length).to eql(2)
893
+ expect(response).to be_has_next
894
+ next_page = response.next
895
+ expect(next_page.items.length).to eql(2)
896
+ expect(next_page).to be_has_next
897
+ first_page_ids = response.items.map { |message| message['id'] }.uniq.sort
898
+ next_page_ids = next_page.items.map { |message| message['id'] }.uniq.sort
899
+ expect(first_page_ids).to_not eql(next_page_ids)
900
+ next_page = next_page.next
901
+ expect(next_page.items.length).to eql(2)
902
+ end
903
+ end
904
+ end
905
+ end
858
906
  end
859
907
  end