ably 1.1.6 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +15 -1
- data/CHANGELOG.md +131 -0
- data/COPYRIGHT +1 -1
- data/README.md +14 -2
- data/SPEC.md +0 -7
- data/UPDATING.md +30 -0
- data/ably.gemspec +12 -7
- data/lib/ably/agent.rb +3 -0
- data/lib/ably/auth.rb +3 -3
- data/lib/ably/exceptions.rb +6 -0
- data/lib/ably/models/channel_options.rb +97 -0
- data/lib/ably/models/connection_details.rb +8 -0
- data/lib/ably/models/delta_extras.rb +29 -0
- data/lib/ably/models/error_info.rb +6 -2
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
- data/lib/ably/models/message.rb +28 -3
- data/lib/ably/models/presence_message.rb +14 -0
- data/lib/ably/models/protocol_message.rb +29 -12
- data/lib/ably/models/token_details.rb +7 -2
- data/lib/ably/modules/channels_collection.rb +22 -2
- data/lib/ably/modules/conversions.rb +34 -0
- data/lib/ably/realtime/channel/channel_manager.rb +18 -6
- data/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
- data/lib/ably/realtime/channel/publisher.rb +6 -0
- data/lib/ably/realtime/channel.rb +54 -22
- data/lib/ably/realtime/channels.rb +1 -1
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
- data/lib/ably/realtime/connection/connection_manager.rb +13 -4
- data/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
- data/lib/ably/realtime/connection.rb +2 -2
- data/lib/ably/rest/channel.rb +31 -31
- data/lib/ably/rest/client.rb +27 -12
- data/lib/ably/util/crypto.rb +1 -1
- data/lib/ably/version.rb +2 -14
- data/lib/ably.rb +1 -0
- data/spec/acceptance/realtime/auth_spec.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +25 -0
- data/spec/acceptance/realtime/channel_spec.rb +466 -21
- data/spec/acceptance/realtime/channels_spec.rb +59 -7
- data/spec/acceptance/realtime/connection_failures_spec.rb +59 -2
- data/spec/acceptance/realtime/connection_spec.rb +256 -28
- data/spec/acceptance/realtime/message_spec.rb +77 -0
- data/spec/acceptance/realtime/presence_history_spec.rb +3 -1
- data/spec/acceptance/realtime/presence_spec.rb +31 -159
- data/spec/acceptance/rest/auth_spec.rb +18 -0
- data/spec/acceptance/rest/channel_spec.rb +84 -9
- data/spec/acceptance/rest/channels_spec.rb +23 -6
- data/spec/acceptance/rest/client_spec.rb +25 -21
- data/spec/acceptance/rest/message_spec.rb +61 -3
- data/spec/lib/unit/models/channel_options_spec.rb +52 -0
- data/spec/shared/model_behaviour.rb +1 -1
- data/spec/spec_helper.rb +11 -2
- data/spec/support/test_app.rb +1 -1
- data/spec/unit/models/delta_extras_spec.rb +14 -0
- data/spec/unit/models/error_info_spec.rb +17 -1
- data/spec/unit/models/message_spec.rb +97 -0
- data/spec/unit/models/presence_message_spec.rb +49 -0
- data/spec/unit/models/protocol_message_spec.rb +125 -27
- data/spec/unit/models/token_details_spec.rb +14 -0
- data/spec/unit/realtime/channel_spec.rb +3 -2
- data/spec/unit/realtime/channels_spec.rb +53 -15
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
- data/spec/unit/rest/channel_spec.rb +44 -1
- data/spec/unit/rest/channels_spec.rb +81 -14
- data/spec/unit/rest/client_spec.rb +47 -0
- metadata +60 -24
@@ -570,7 +570,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
570
570
|
end
|
571
571
|
|
572
572
|
context 'when DISCONNECTED ProtocolMessage received from the server' do
|
573
|
-
it 'reconnects automatically and immediately' do
|
573
|
+
it 'reconnects automatically and immediately (#RTN15a)' do
|
574
574
|
fail_if_suspended_or_failed
|
575
575
|
|
576
576
|
connection.once(:connected) do
|
@@ -590,6 +590,61 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
590
590
|
end
|
591
591
|
end
|
592
592
|
|
593
|
+
context 'when protocolMessage contains token error' do
|
594
|
+
context "library does not have a means to renew the token (#RTN15h1)" do
|
595
|
+
let(:auth_url) { 'https://echo.ably.io/createJWT' }
|
596
|
+
let(:token) { Faraday.get("#{auth_url}?keyName=#{key_name}&keySecret=#{key_secret}").body }
|
597
|
+
let(:client_options) { default_options.merge(token: token, log_level: :none) }
|
598
|
+
|
599
|
+
let(:error_message) { 'error_message' }
|
600
|
+
|
601
|
+
it 'moves connection state to failed' do
|
602
|
+
connection.on(:failed) do |connection_state_change|
|
603
|
+
expect(connection.error_reason.message).to eq(error_message)
|
604
|
+
stop_reactor
|
605
|
+
end
|
606
|
+
|
607
|
+
connection.on(:connected) do
|
608
|
+
protocol_message = Ably::Models::ProtocolMessage.new(action: Ably::Models::ProtocolMessage::ACTION.Disconnected.to_i, error: { code: 40140, message: error_message })
|
609
|
+
connection.__incoming_protocol_msgbus__.publish :protocol_message, protocol_message
|
610
|
+
end
|
611
|
+
|
612
|
+
connection.connect
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
context "library have a means to renew the token (#RTN15h2)" do
|
617
|
+
let(:client_options) { default_options.merge(log_level: :none) }
|
618
|
+
let(:error_message) { 'error_message' }
|
619
|
+
|
620
|
+
def send_disconnect_message
|
621
|
+
protocol_message = Ably::Models::ProtocolMessage.new(action: Ably::Models::ProtocolMessage::ACTION.Disconnected.to_i, error: { code: 40140, message: error_message })
|
622
|
+
connection.__incoming_protocol_msgbus__.publish :protocol_message, protocol_message
|
623
|
+
end
|
624
|
+
|
625
|
+
it 'attempts to reconnect' do
|
626
|
+
connection.on(:failed) do |connection_state_change|
|
627
|
+
raise "Connection shouldn't be failed"
|
628
|
+
end
|
629
|
+
|
630
|
+
connection.on(:connected) do
|
631
|
+
connection.once(:connecting) do
|
632
|
+
connection.once(:disconnected) do
|
633
|
+
expect(connection.error_reason.message).to eq(error_message)
|
634
|
+
stop_reactor
|
635
|
+
end
|
636
|
+
|
637
|
+
send_disconnect_message
|
638
|
+
end
|
639
|
+
|
640
|
+
send_disconnect_message
|
641
|
+
end
|
642
|
+
|
643
|
+
connection.connect
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
593
648
|
context 'connection state freshness is monitored' do
|
594
649
|
it 'resumes connections when disconnected within the connection_state_ttl period (#RTN15g)' do
|
595
650
|
connection.once(:connected) do
|
@@ -1320,7 +1375,9 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
1320
1375
|
end)
|
1321
1376
|
end
|
1322
1377
|
|
1323
|
-
|
1378
|
+
xit 'triggers a re-authentication and then resumes the connection' do
|
1379
|
+
# [PENDING] After sandbox env update connection isn't found and a new connection is created. Spec fails
|
1380
|
+
#
|
1324
1381
|
connection.once(:connected) do
|
1325
1382
|
connection_id = connection.id
|
1326
1383
|
|
@@ -482,6 +482,118 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
482
482
|
end
|
483
483
|
end
|
484
484
|
|
485
|
+
context 'when explicitly reconnecting disconnected/suspended connection in retry (#RTN11c)' do
|
486
|
+
let(:close_connection_proc) do
|
487
|
+
lambda do
|
488
|
+
EventMachine.add_timer(0.001) do
|
489
|
+
if connection.transport.nil?
|
490
|
+
close_connection_proc.call
|
491
|
+
else
|
492
|
+
connection.transport.close_connection_after_writing
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
context 'when suspended' do
|
499
|
+
let(:suspended_retry_timeout) { 60 }
|
500
|
+
let(:client_options) do
|
501
|
+
default_options.merge(
|
502
|
+
disconnected_retry_timeout: 0.02,
|
503
|
+
suspended_retry_timeout: suspended_retry_timeout,
|
504
|
+
connection_state_ttl: 0
|
505
|
+
)
|
506
|
+
end
|
507
|
+
|
508
|
+
it 'reconnects immediately' do
|
509
|
+
connection.once(:connecting) { close_connection_proc.call }
|
510
|
+
|
511
|
+
connection.on(:suspended) do |connection_state_change|
|
512
|
+
if connection_state_change.retry_in.zero?
|
513
|
+
# Exhausting immediate retries
|
514
|
+
connection.once(:connecting) { close_connection_proc.call }
|
515
|
+
else
|
516
|
+
suspended_at = Time.now.to_f
|
517
|
+
connection.on(:connected) do
|
518
|
+
expect(connection_state_change.retry_in).to eq(suspended_retry_timeout)
|
519
|
+
expect(connection.state).to eq(:connected)
|
520
|
+
expect(Time.now.to_f).to be_within(4).of(suspended_at)
|
521
|
+
stop_reactor
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
connection.connect
|
526
|
+
end
|
527
|
+
|
528
|
+
connection.connect
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
context 'when disconnected' do
|
533
|
+
let(:retry_timeout) { 60 }
|
534
|
+
let(:client_options) do
|
535
|
+
default_options.merge(
|
536
|
+
disconnected_retry_timeout: retry_timeout,
|
537
|
+
suspended_retry_timeout: retry_timeout,
|
538
|
+
connection_state_ttl: 0
|
539
|
+
)
|
540
|
+
end
|
541
|
+
|
542
|
+
it 'reconnects immediately' do
|
543
|
+
connection.once(:connected) do
|
544
|
+
connection.on(:disconnected) do |connection_state_change|
|
545
|
+
disconnected_at = Time.now.to_f
|
546
|
+
connection.on(:connected) do
|
547
|
+
if connection_state_change.retry_in.zero?
|
548
|
+
# Exhausting immediate retries
|
549
|
+
close_connection_proc.call
|
550
|
+
else
|
551
|
+
expect(connection_state_change.retry_in).to eq(retry_timeout)
|
552
|
+
expect(connection.state).to eq(:connected)
|
553
|
+
expect(Time.now.to_f).to be_within(4).of(disconnected_at)
|
554
|
+
stop_reactor
|
555
|
+
end
|
556
|
+
end
|
557
|
+
connection.connect
|
558
|
+
end
|
559
|
+
|
560
|
+
close_connection_proc.call
|
561
|
+
end
|
562
|
+
|
563
|
+
connection.connect
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
context 'when reconnecting a failed connection' do
|
569
|
+
let(:channel) { client.channel(random_str) }
|
570
|
+
let(:client_options) { default_options.merge(log_level: :none) }
|
571
|
+
|
572
|
+
it 'transitions all channels state to initialized and cleares error_reason' do
|
573
|
+
connection.on(:failed) do |connection_state_change|
|
574
|
+
expect(connection.error_reason).to be_a(Ably::Exceptions::BaseAblyException)
|
575
|
+
expect(channel.error_reason).to be_a(Ably::Exceptions::BaseAblyException)
|
576
|
+
expect(channel).to be_failed
|
577
|
+
|
578
|
+
connection.on(:connected) do
|
579
|
+
expect(connection.error_reason).to eq(nil)
|
580
|
+
expect(channel).to be_initialized
|
581
|
+
expect(channel.error_reason).to eq(nil)
|
582
|
+
stop_reactor
|
583
|
+
end
|
584
|
+
|
585
|
+
connection.connect
|
586
|
+
end
|
587
|
+
|
588
|
+
connection.connect do
|
589
|
+
channel.attach do
|
590
|
+
error = Ably::Exceptions::ConnectionFailed.new('forced failure', 500, 50000)
|
591
|
+
client.connection.manager.error_received_from_server error
|
592
|
+
end
|
593
|
+
end
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
485
597
|
context 'with invalid auth details' do
|
486
598
|
let(:client_options) { default_options.merge(key: 'this.is:invalid', log_level: :none) }
|
487
599
|
|
@@ -693,6 +805,18 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
693
805
|
end
|
694
806
|
|
695
807
|
context '#close' do
|
808
|
+
let(:close_connection_proc) do
|
809
|
+
lambda do
|
810
|
+
EventMachine.add_timer(0.001) do
|
811
|
+
if connection.transport.nil?
|
812
|
+
close_connection_proc.call
|
813
|
+
else
|
814
|
+
connection.transport.close_connection_after_writing
|
815
|
+
end
|
816
|
+
end
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
696
820
|
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
697
821
|
connection.connect do
|
698
822
|
expect(connection.close).to be_a(Ably::Util::SafeDeferrable)
|
@@ -754,6 +878,56 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
754
878
|
end
|
755
879
|
end
|
756
880
|
|
881
|
+
context ':connecting RTN12f' do
|
882
|
+
context ":connected does not arrive when trying to close" do
|
883
|
+
it 'moves to closed' do
|
884
|
+
connection.on(:closed) do |state_change|
|
885
|
+
state_changes = connection.state_history.map { |t| t[:state].to_sym }
|
886
|
+
|
887
|
+
expect(state_changes).to eq([:connecting, :closing, :closed])
|
888
|
+
stop_reactor
|
889
|
+
end
|
890
|
+
|
891
|
+
connection.on(:connecting) do
|
892
|
+
connection.close
|
893
|
+
connection.__outgoing_protocol_msgbus__.unsubscribe
|
894
|
+
end
|
895
|
+
|
896
|
+
connection.connect
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
900
|
+
context ":connected arrive when trying to close" do
|
901
|
+
let(:protocol_message_attributes) do
|
902
|
+
{
|
903
|
+
action: Ably::Models::ProtocolMessage::ACTION.Connected.to_i,
|
904
|
+
connection_serial: 55,
|
905
|
+
connection_details: {
|
906
|
+
max_idle_interval: 2 * 1000
|
907
|
+
}
|
908
|
+
}
|
909
|
+
end
|
910
|
+
|
911
|
+
it 'moves to connected and then to closed' do
|
912
|
+
connection.on(:closed) do |state_change|
|
913
|
+
state_changes = connection.state_history.map { |t| t[:state].to_sym }
|
914
|
+
|
915
|
+
expect(state_changes).to eq([:connecting, :connected, :closing, :closed])
|
916
|
+
stop_reactor
|
917
|
+
end
|
918
|
+
|
919
|
+
connection.on(:connecting) do
|
920
|
+
connection.__outgoing_protocol_msgbus__.unsubscribe
|
921
|
+
|
922
|
+
connection.__incoming_protocol_msgbus__.publish :protocol_message, Ably::Models::ProtocolMessage.new(protocol_message_attributes)
|
923
|
+
connection.close
|
924
|
+
end
|
925
|
+
|
926
|
+
connection.connect
|
927
|
+
end
|
928
|
+
end
|
929
|
+
end
|
930
|
+
|
757
931
|
context ':connected' do
|
758
932
|
it 'changes the connection state to :closing and waits for the server to confirm connection is :closed with a ProtocolMessage' do
|
759
933
|
connection.on(:connected) do
|
@@ -800,6 +974,81 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
800
974
|
end
|
801
975
|
end
|
802
976
|
end
|
977
|
+
|
978
|
+
context ':suspended RTN12d' do
|
979
|
+
let(:suspended_retry_timeout) { 60 }
|
980
|
+
let(:client_options) do
|
981
|
+
default_options.merge(
|
982
|
+
disconnected_retry_timeout: 0.02,
|
983
|
+
suspended_retry_timeout: suspended_retry_timeout,
|
984
|
+
connection_state_ttl: 0
|
985
|
+
)
|
986
|
+
end
|
987
|
+
|
988
|
+
it 'immediatly closes connection' do
|
989
|
+
connection.on(:connecting) { close_connection_proc.call }
|
990
|
+
connection.on(:suspended) do |connection_state_change|
|
991
|
+
if connection_state_change.retry_in.zero?
|
992
|
+
# Exhausting immediate retries
|
993
|
+
connection.once(:connecting) { close_connection_proc.call }
|
994
|
+
else
|
995
|
+
suspended_at = Time.now.to_f
|
996
|
+
connection.on(:closed) do
|
997
|
+
expect(connection_state_change.retry_in).to eq(suspended_retry_timeout)
|
998
|
+
expect(connection.state).to eq(:closed)
|
999
|
+
expect(Time.now.to_f).to be_within(4).of(suspended_at)
|
1000
|
+
stop_reactor
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
connection.close
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
connection.connect
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
connection.connect
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
context ':disconnected RTN12d' do
|
1014
|
+
let(:retry_timeout) { 60 }
|
1015
|
+
let(:client_options) do
|
1016
|
+
default_options.merge(
|
1017
|
+
disconnected_retry_timeout: retry_timeout,
|
1018
|
+
suspended_retry_timeout: retry_timeout,
|
1019
|
+
connection_state_ttl: 0
|
1020
|
+
)
|
1021
|
+
end
|
1022
|
+
|
1023
|
+
it 'immediatly closes connection' do
|
1024
|
+
connection.once(:connected) do
|
1025
|
+
connection.on(:disconnected) do |connection_state_change|
|
1026
|
+
disconnected_at = Time.now.to_f
|
1027
|
+
connection.on(:connected) do
|
1028
|
+
if connection_state_change.retry_in.zero?
|
1029
|
+
# Exhausting immediate retries
|
1030
|
+
close_connection_proc.call
|
1031
|
+
else
|
1032
|
+
connection.once(:closed) do
|
1033
|
+
expect(connection_state_change.retry_in).to eq(retry_timeout)
|
1034
|
+
expect(connection.state).to eq(:closed)
|
1035
|
+
expect(Time.now.to_f).to be_within(4).of(disconnected_at)
|
1036
|
+
stop_reactor
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
connection.close
|
1040
|
+
end
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
connection.connect
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
close_connection_proc.call
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
connection.connect
|
1050
|
+
end
|
1051
|
+
end
|
803
1052
|
end
|
804
1053
|
end
|
805
1054
|
|
@@ -1454,7 +1703,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1454
1703
|
let(:client_options) { default_options.merge(tls: true) }
|
1455
1704
|
|
1456
1705
|
it 'uses TLS for the Internet check to https://internet-up.ably-realtime.com/is-the-internet-up.txt' do
|
1457
|
-
expect(EventMachine::HttpRequest).to receive(:new).with('https://internet-up.ably-realtime.com/is-the-internet-up.txt').and_return(http_request)
|
1706
|
+
expect(EventMachine::HttpRequest).to receive(:new).with('https://internet-up.ably-realtime.com/is-the-internet-up.txt', { tls: { verify_peer: true } }).and_return(http_request)
|
1458
1707
|
connection.internet_up?
|
1459
1708
|
stop_reactor
|
1460
1709
|
end
|
@@ -1464,7 +1713,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1464
1713
|
let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
|
1465
1714
|
|
1466
1715
|
it 'uses TLS for the Internet check to http://internet-up.ably-realtime.com/is-the-internet-up.txt' do
|
1467
|
-
expect(EventMachine::HttpRequest).to receive(:new).with('http://internet-up.ably-realtime.com/is-the-internet-up.txt').and_return(http_request)
|
1716
|
+
expect(EventMachine::HttpRequest).to receive(:new).with('http://internet-up.ably-realtime.com/is-the-internet-up.txt', { tls: { verify_peer: true } }).and_return(http_request)
|
1468
1717
|
connection.internet_up?
|
1469
1718
|
stop_reactor
|
1470
1719
|
end
|
@@ -1478,7 +1727,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1478
1727
|
let(:client_options) { default_options.merge(tls: true) }
|
1479
1728
|
|
1480
1729
|
it 'checks the Internet up URL over TLS' do
|
1481
|
-
expect(EventMachine::HttpRequest).to receive(:new).with("https:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
1730
|
+
expect(EventMachine::HttpRequest).to receive(:new).with("https:#{Ably::INTERNET_CHECK.fetch(:url)}", { tls: { verify_peer: true } }).and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
1482
1731
|
connection.internet_up?
|
1483
1732
|
stop_reactor
|
1484
1733
|
end
|
@@ -1488,7 +1737,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1488
1737
|
let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
|
1489
1738
|
|
1490
1739
|
it 'checks the Internet up URL over TLS' do
|
1491
|
-
expect(EventMachine::HttpRequest).to receive(:new).with("http:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
1740
|
+
expect(EventMachine::HttpRequest).to receive(:new).with("http:#{Ably::INTERNET_CHECK.fetch(:url)}", { tls: { verify_peer: true } }).and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
1492
1741
|
connection.internet_up?
|
1493
1742
|
stop_reactor
|
1494
1743
|
end
|
@@ -1834,41 +2083,20 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1834
2083
|
it 'sends the protocol version param v (#G4, #RTN2f)' do
|
1835
2084
|
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
1836
2085
|
uri = URI.parse(url)
|
1837
|
-
expect(CGI::parse(uri.query)['v'][0]).to eql('1.
|
2086
|
+
expect(CGI::parse(uri.query)['v'][0]).to eql('1.2')
|
1838
2087
|
stop_reactor
|
1839
2088
|
end
|
1840
2089
|
client
|
1841
2090
|
end
|
1842
2091
|
|
1843
|
-
it 'sends the lib version param
|
2092
|
+
it 'sends the lib version param agent (#RCS7d)' do
|
1844
2093
|
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
1845
2094
|
uri = URI.parse(url)
|
1846
|
-
expect(CGI::parse(uri.query)['
|
2095
|
+
expect(CGI::parse(uri.query)['agent'][0]).to match(/^ably-ruby\/\d\.\d\.\d ruby\/\d\.\d\.\d$/)
|
1847
2096
|
stop_reactor
|
1848
2097
|
end
|
1849
2098
|
client
|
1850
2099
|
end
|
1851
|
-
|
1852
|
-
context 'with variant' do
|
1853
|
-
let(:variant) { 'foo' }
|
1854
|
-
|
1855
|
-
before do
|
1856
|
-
Ably.lib_variant = variant
|
1857
|
-
end
|
1858
|
-
|
1859
|
-
after do
|
1860
|
-
Ably.lib_variant = nil
|
1861
|
-
end
|
1862
|
-
|
1863
|
-
it 'sends the lib version param lib with the variant (#RTN2g + #RSC7b)' do
|
1864
|
-
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
1865
|
-
uri = URI.parse(url)
|
1866
|
-
expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-#{variant}-1\.1\.\d+(-[\w\.]+)?$/)
|
1867
|
-
stop_reactor
|
1868
|
-
end
|
1869
|
-
client
|
1870
|
-
end
|
1871
|
-
end
|
1872
2100
|
end
|
1873
2101
|
|
1874
2102
|
context 'transport_params (#RTC1f)' do
|
@@ -75,6 +75,83 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
context 'a single Message object (#RSL1a)' do
|
79
|
+
let(:name) { random_str }
|
80
|
+
let(:data) { random_str }
|
81
|
+
let(:message) { Ably::Models::Message.new(name: name, data: data) }
|
82
|
+
|
83
|
+
it 'publishes the message' do
|
84
|
+
channel.attach
|
85
|
+
channel.publish(message)
|
86
|
+
channel.subscribe do |msg|
|
87
|
+
expect(msg.name).to eq(message.name)
|
88
|
+
expect(msg.data).to eq(message.data)
|
89
|
+
stop_reactor
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'an array of Message objects (#RSL1a)' do
|
95
|
+
let(:data) { random_str }
|
96
|
+
let(:message1) { Ably::Models::Message.new(name: random_str, data: data) }
|
97
|
+
let(:message2) { Ably::Models::Message.new(name: random_str, data: data) }
|
98
|
+
let(:message3) { Ably::Models::Message.new(name: random_str, data: data) }
|
99
|
+
|
100
|
+
it 'publishes three messages' do
|
101
|
+
channel.attach
|
102
|
+
channel.publish([message1, message2, message3])
|
103
|
+
counter = 0
|
104
|
+
channel.subscribe do |message|
|
105
|
+
counter += 1
|
106
|
+
expect(message.data).to eq(data)
|
107
|
+
expect(message.name).to eq(message1.name) if counter == 1
|
108
|
+
expect(message.name).to eq(message2.name) if counter == 2
|
109
|
+
if counter == 3
|
110
|
+
expect(message.name).to eq(message3.name)
|
111
|
+
stop_reactor
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'an array of hashes (#RSL1a)' do
|
118
|
+
let(:data) { random_str }
|
119
|
+
let(:message1) { { name: random_str, data: data } }
|
120
|
+
let(:message2) { { name: random_str, data: data } }
|
121
|
+
let(:message3) { { name: random_str, data: data } }
|
122
|
+
|
123
|
+
it 'publishes three messages' do
|
124
|
+
channel.attach
|
125
|
+
channel.publish([message1, message2, message3])
|
126
|
+
counter = 0
|
127
|
+
channel.subscribe do |message|
|
128
|
+
counter += 1
|
129
|
+
expect(message.data).to eq(data)
|
130
|
+
expect(message.name).to eq(message1[:name]) if counter == 1
|
131
|
+
expect(message.name).to eq(message2[:name]) if counter == 2
|
132
|
+
if counter == 3
|
133
|
+
expect(message.name).to eq(message3[:name])
|
134
|
+
stop_reactor
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'a name with data payload (#RSL1a, #RSL1b)' do
|
141
|
+
let(:name) { random_str }
|
142
|
+
let(:data) { random_str }
|
143
|
+
|
144
|
+
it 'publishes a message' do
|
145
|
+
channel.attach
|
146
|
+
channel.publish(name, data)
|
147
|
+
channel.subscribe do |message|
|
148
|
+
expect(message.name).to eql(name)
|
149
|
+
expect(message.data).to eq(data)
|
150
|
+
stop_reactor
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
78
155
|
context 'with supported extra payload content type (#RTL6h, #RSL6a2)' do
|
79
156
|
let(:channel) { client.channel("pushenabled:#{random_str}") }
|
80
157
|
|
@@ -20,7 +20,7 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
20
20
|
|
21
21
|
it 'provides up to the moment presence history' do
|
22
22
|
presence_client_one.enter(data) do
|
23
|
-
presence_client_one.leave
|
23
|
+
presence_client_one.subscribe(:leave) do
|
24
24
|
presence_client_one.history do |history_page|
|
25
25
|
expect(history_page).to be_a(Ably::Models::PaginatedResult)
|
26
26
|
expect(history_page.items.count).to eql(2)
|
@@ -36,6 +36,8 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
36
36
|
stop_reactor
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
presence_client_one.leave(leave_data)
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|