ably 1.1.6 → 1.2.0
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/.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
|
|