ably-rest 1.1.2 → 1.2.2

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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -0
  3. data/CHANGELOG.md +1 -1
  4. data/MAINTAINERS.md +1 -0
  5. data/README.md +4 -2
  6. data/ably-rest.gemspec +15 -18
  7. data/lib/ably-rest.rb +2 -0
  8. data/lib/submodules/ably-ruby/.github/workflows/check.yml +50 -0
  9. data/lib/submodules/ably-ruby/CHANGELOG.md +200 -0
  10. data/lib/submodules/ably-ruby/COPYRIGHT +1 -0
  11. data/lib/submodules/ably-ruby/LICENSE +172 -11
  12. data/lib/submodules/ably-ruby/MAINTAINERS.md +1 -0
  13. data/lib/submodules/ably-ruby/README.md +24 -22
  14. data/lib/submodules/ably-ruby/SPEC.md +1020 -929
  15. data/lib/submodules/ably-ruby/UPDATING.md +30 -0
  16. data/lib/submodules/ably-ruby/ably.gemspec +16 -23
  17. data/lib/submodules/ably-ruby/lib/ably/agent.rb +3 -0
  18. data/lib/submodules/ably-ruby/lib/ably/auth.rb +20 -10
  19. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +8 -2
  20. data/lib/submodules/ably-ruby/lib/ably/logger.rb +4 -4
  21. data/lib/submodules/ably-ruby/lib/ably/models/channel_details.rb +59 -0
  22. data/lib/submodules/ably-ruby/lib/ably/models/channel_metrics.rb +84 -0
  23. data/lib/submodules/ably-ruby/lib/ably/models/channel_occupancy.rb +43 -0
  24. data/lib/submodules/ably-ruby/lib/ably/models/channel_options.rb +97 -0
  25. data/lib/submodules/ably-ruby/lib/ably/models/channel_status.rb +53 -0
  26. data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +8 -0
  27. data/lib/submodules/ably-ruby/lib/ably/models/delta_extras.rb +29 -0
  28. data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +1 -1
  29. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +6 -2
  30. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
  31. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +28 -3
  32. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +14 -0
  33. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +31 -14
  34. data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +7 -2
  35. data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -1
  36. data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +11 -1
  37. data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +22 -2
  38. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +34 -0
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +2 -2
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +19 -7
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_properties.rb +24 -0
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +6 -0
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +56 -28
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/channels.rb +1 -1
  46. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
  47. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +9 -0
  48. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +13 -4
  49. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
  50. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +67 -1
  51. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +6 -5
  52. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +0 -14
  53. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +44 -29
  54. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +60 -29
  55. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/encoder.rb +1 -1
  56. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +1 -1
  57. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/external_exceptions.rb +1 -1
  58. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +5 -2
  59. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/logger.rb +1 -1
  60. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_json.rb +1 -1
  61. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +1 -1
  62. data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +1 -1
  63. data/lib/submodules/ably-ruby/lib/ably/version.rb +2 -14
  64. data/lib/submodules/ably-ruby/lib/ably.rb +1 -0
  65. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +4 -4
  66. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +25 -0
  67. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +476 -21
  68. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channels_spec.rb +59 -7
  69. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +72 -16
  70. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +85 -13
  71. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +301 -34
  72. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +77 -0
  73. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +3 -59
  74. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +84 -158
  75. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +3 -19
  76. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +24 -75
  77. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +8 -4
  78. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +141 -10
  79. data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +23 -6
  80. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +146 -47
  81. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +61 -3
  82. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +3 -19
  83. data/lib/submodules/ably-ruby/spec/lib/unit/models/channel_options_spec.rb +52 -0
  84. data/lib/submodules/ably-ruby/spec/run_parallel_tests +2 -7
  85. data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +131 -8
  86. data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +1 -1
  87. data/lib/submodules/ably-ruby/spec/spec_helper.rb +12 -2
  88. data/lib/submodules/ably-ruby/spec/support/serialization_helper.rb +21 -0
  89. data/lib/submodules/ably-ruby/spec/support/test_app.rb +3 -3
  90. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +6 -14
  91. data/lib/submodules/ably-ruby/spec/unit/models/channel_details_spec.rb +30 -0
  92. data/lib/submodules/ably-ruby/spec/unit/models/channel_metrics_spec.rb +42 -0
  93. data/lib/submodules/ably-ruby/spec/unit/models/channel_occupancy_spec.rb +17 -0
  94. data/lib/submodules/ably-ruby/spec/unit/models/channel_status_spec.rb +36 -0
  95. data/lib/submodules/ably-ruby/spec/unit/models/delta_extras_spec.rb +14 -0
  96. data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +17 -1
  97. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +97 -0
  98. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +49 -0
  99. data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +125 -27
  100. data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +14 -0
  101. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +3 -2
  102. data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +53 -15
  103. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +19 -6
  104. data/lib/submodules/ably-ruby/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
  105. data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +44 -1
  106. data/lib/submodules/ably-ruby/spec/unit/rest/channels_spec.rb +81 -14
  107. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +47 -0
  108. data/spec/spec_helper.rb +5 -0
  109. data/spec/unit/client_spec.rb +30 -0
  110. metadata +88 -25
  111. data/lib/submodules/ably-ruby/.travis.yml +0 -19
@@ -77,18 +77,6 @@ describe Ably::Realtime::Connection, :event_machine do
77
77
  end
78
78
  end
79
79
  end
80
-
81
- context 'with implicit authorisation' do
82
- let(:client_options) { default_options.merge(client_id: 'force_token_auth') }
83
-
84
- it 'uses the token created by the implicit authorisation' do
85
- expect(client.rest_client.auth).to receive(:request_token).once.and_call_original
86
-
87
- connection.once(:connected) do
88
- stop_reactor
89
- end
90
- end
91
- end
92
80
  end
93
81
 
94
82
  context 'that expire' do
@@ -134,7 +122,7 @@ describe Ably::Realtime::Connection, :event_machine do
134
122
  end
135
123
  end
136
124
 
137
- context 'with immediately expired token' do
125
+ context 'with immediately expired token and no fallback hosts' do
138
126
  let(:ttl) { 0.001 }
139
127
  let(:auth_requests) { [] }
140
128
  let(:token_callback) do
@@ -143,7 +131,7 @@ describe Ably::Realtime::Connection, :event_machine do
143
131
  Ably::Rest::Client.new(default_options).auth.request_token(ttl: ttl).token
144
132
  end
145
133
  end
146
- let(:client_options) { default_options.merge(auth_callback: token_callback) }
134
+ let(:client_options) { default_options.merge(auth_callback: token_callback, fallback_hosts: []) }
147
135
 
148
136
  it 'renews the token on connect, and makes one immediate subsequent attempt to obtain a new token (#RSA4b)' do
149
137
  started_at = Time.now.to_f
@@ -158,7 +146,7 @@ describe Ably::Realtime::Connection, :event_machine do
158
146
  end
159
147
 
160
148
  context 'when disconnected_retry_timeout is 0.5 seconds' do
161
- let(:client_options) { default_options.merge(disconnected_retry_timeout: 0.5, auth_callback: token_callback) }
149
+ let(:client_options) { default_options.merge(disconnected_retry_timeout: 0.5, auth_callback: token_callback, fallback_hosts: []) }
162
150
 
163
151
  it 'renews the token on connect, and continues to attempt renew based on the retry schedule' do
164
152
  disconnect_count = 0
@@ -184,7 +172,7 @@ describe Ably::Realtime::Connection, :event_machine do
184
172
  end
185
173
 
186
174
  context 'using implicit token auth' do
187
- let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { ttl: ttl }) }
175
+ let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { ttl: ttl }, fallback_hosts: []) }
188
176
 
189
177
  before do
190
178
  stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', -10 # ensure client lib thinks token is still valid
@@ -453,7 +441,9 @@ describe Ably::Realtime::Connection, :event_machine do
453
441
  end
454
442
  end
455
443
 
456
- context '#connect' do
444
+ context '#connect with no fallbacks' do
445
+ let(:client_options) { default_options.merge(fallback_hosts: []) }
446
+
457
447
  it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
458
448
  expect(connection.connect).to be_a(Ably::Util::SafeDeferrable)
459
449
  stop_reactor
@@ -492,6 +482,138 @@ describe Ably::Realtime::Connection, :event_machine do
492
482
  end
493
483
  end
494
484
 
485
+ context "when can't connect to host" do
486
+ let(:client_options) { super().merge(realtime_host: 'non-existent.ably.io') }
487
+
488
+ it 'logs error on failed connection attempt' do
489
+ logger_expectation = lambda do |*args, &block|
490
+ error_message = "Connection to non-existent.ably.io:443 failed"
491
+ expect(args.concat([block ? block.call : nil]).join(',')).to include(error_message)
492
+ stop_reactor
493
+ end
494
+
495
+ expect(connection.logger).to receive(:warn, &logger_expectation).at_least(:once)
496
+
497
+ connection.on(:connected) do
498
+ raise "Connection should not succeed"
499
+ end
500
+
501
+ connection.connect
502
+ end
503
+ end
504
+
505
+ context 'when explicitly reconnecting disconnected/suspended connection in retry (#RTN11c)' do
506
+ let(:close_connection_proc) do
507
+ lambda do
508
+ EventMachine.add_timer(0.001) do
509
+ if connection.transport.nil?
510
+ close_connection_proc.call
511
+ else
512
+ connection.transport.close_connection_after_writing
513
+ end
514
+ end
515
+ end
516
+ end
517
+
518
+ context 'when suspended' do
519
+ let(:suspended_retry_timeout) { 60 }
520
+ let(:client_options) do
521
+ default_options.merge(
522
+ disconnected_retry_timeout: 0.02,
523
+ suspended_retry_timeout: suspended_retry_timeout,
524
+ connection_state_ttl: 0
525
+ )
526
+ end
527
+
528
+ it 'reconnects immediately' do
529
+ connection.once(:connecting) { close_connection_proc.call }
530
+
531
+ connection.on(:suspended) do |connection_state_change|
532
+ if connection_state_change.retry_in.zero?
533
+ # Exhausting immediate retries
534
+ connection.once(:connecting) { close_connection_proc.call }
535
+ else
536
+ suspended_at = Time.now.to_f
537
+ connection.on(:connected) do
538
+ expect(connection_state_change.retry_in).to eq(suspended_retry_timeout)
539
+ expect(connection.state).to eq(:connected)
540
+ expect(Time.now.to_f).to be_within(4).of(suspended_at)
541
+ stop_reactor
542
+ end
543
+ end
544
+
545
+ connection.connect
546
+ end
547
+
548
+ connection.connect
549
+ end
550
+ end
551
+
552
+ context 'when disconnected' do
553
+ let(:retry_timeout) { 60 }
554
+ let(:client_options) do
555
+ default_options.merge(
556
+ disconnected_retry_timeout: retry_timeout,
557
+ suspended_retry_timeout: retry_timeout,
558
+ connection_state_ttl: 0
559
+ )
560
+ end
561
+
562
+ it 'reconnects immediately' do
563
+ connection.once(:connected) do
564
+ connection.on(:disconnected) do |connection_state_change|
565
+ disconnected_at = Time.now.to_f
566
+ connection.on(:connected) do
567
+ if connection_state_change.retry_in.zero?
568
+ # Exhausting immediate retries
569
+ close_connection_proc.call
570
+ else
571
+ expect(connection_state_change.retry_in).to eq(retry_timeout)
572
+ expect(connection.state).to eq(:connected)
573
+ expect(Time.now.to_f).to be_within(4).of(disconnected_at)
574
+ stop_reactor
575
+ end
576
+ end
577
+ connection.connect
578
+ end
579
+
580
+ close_connection_proc.call
581
+ end
582
+
583
+ connection.connect
584
+ end
585
+ end
586
+ end
587
+
588
+ context 'when reconnecting a failed connection' do
589
+ let(:channel) { client.channel(random_str) }
590
+ let(:client_options) { default_options.merge(log_level: :none) }
591
+
592
+ it 'transitions all channels state to initialized and cleares error_reason' do
593
+ connection.on(:failed) do |connection_state_change|
594
+ expect(connection.error_reason).to be_a(Ably::Exceptions::BaseAblyException)
595
+ expect(channel.error_reason).to be_a(Ably::Exceptions::BaseAblyException)
596
+ expect(channel).to be_failed
597
+
598
+ connection.on(:connected) do
599
+ expect(connection.error_reason).to eq(nil)
600
+ expect(channel).to be_initialized
601
+ expect(channel.error_reason).to eq(nil)
602
+ stop_reactor
603
+ end
604
+
605
+ connection.connect
606
+ end
607
+
608
+ connection.connect do
609
+ channel.attach do
610
+ error = Ably::Exceptions::ConnectionFailed.new('forced failure', 500, 50000)
611
+ client.connection.manager.error_received_from_server error
612
+ end
613
+ end
614
+ end
615
+ end
616
+
495
617
  context 'with invalid auth details' do
496
618
  let(:client_options) { default_options.merge(key: 'this.is:invalid', log_level: :none) }
497
619
 
@@ -703,6 +825,18 @@ describe Ably::Realtime::Connection, :event_machine do
703
825
  end
704
826
 
705
827
  context '#close' do
828
+ let(:close_connection_proc) do
829
+ lambda do
830
+ EventMachine.add_timer(0.001) do
831
+ if connection.transport.nil?
832
+ close_connection_proc.call
833
+ else
834
+ connection.transport.close_connection_after_writing
835
+ end
836
+ end
837
+ end
838
+ end
839
+
706
840
  it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
707
841
  connection.connect do
708
842
  expect(connection.close).to be_a(Ably::Util::SafeDeferrable)
@@ -764,6 +898,56 @@ describe Ably::Realtime::Connection, :event_machine do
764
898
  end
765
899
  end
766
900
 
901
+ context ':connecting RTN12f' do
902
+ context ":connected does not arrive when trying to close" do
903
+ it 'moves to closed' do
904
+ connection.on(:closed) do |state_change|
905
+ state_changes = connection.state_history.map { |t| t[:state].to_sym }
906
+
907
+ expect(state_changes).to eq([:connecting, :closing, :closed])
908
+ stop_reactor
909
+ end
910
+
911
+ connection.on(:connecting) do
912
+ connection.close
913
+ connection.__outgoing_protocol_msgbus__.unsubscribe
914
+ end
915
+
916
+ connection.connect
917
+ end
918
+ end
919
+
920
+ context ":connected arrive when trying to close" do
921
+ let(:protocol_message_attributes) do
922
+ {
923
+ action: Ably::Models::ProtocolMessage::ACTION.Connected.to_i,
924
+ connection_serial: 55,
925
+ connection_details: {
926
+ max_idle_interval: 2 * 1000
927
+ }
928
+ }
929
+ end
930
+
931
+ it 'moves to connected and then to closed' do
932
+ connection.on(:closed) do |state_change|
933
+ state_changes = connection.state_history.map { |t| t[:state].to_sym }
934
+
935
+ expect(state_changes).to eq([:connecting, :connected, :closing, :closed])
936
+ stop_reactor
937
+ end
938
+
939
+ connection.on(:connecting) do
940
+ connection.__outgoing_protocol_msgbus__.unsubscribe
941
+
942
+ connection.__incoming_protocol_msgbus__.publish :protocol_message, Ably::Models::ProtocolMessage.new(protocol_message_attributes)
943
+ connection.close
944
+ end
945
+
946
+ connection.connect
947
+ end
948
+ end
949
+ end
950
+
767
951
  context ':connected' do
768
952
  it 'changes the connection state to :closing and waits for the server to confirm connection is :closed with a ProtocolMessage' do
769
953
  connection.on(:connected) do
@@ -810,6 +994,81 @@ describe Ably::Realtime::Connection, :event_machine do
810
994
  end
811
995
  end
812
996
  end
997
+
998
+ context ':suspended RTN12d' do
999
+ let(:suspended_retry_timeout) { 60 }
1000
+ let(:client_options) do
1001
+ default_options.merge(
1002
+ disconnected_retry_timeout: 0.02,
1003
+ suspended_retry_timeout: suspended_retry_timeout,
1004
+ connection_state_ttl: 0
1005
+ )
1006
+ end
1007
+
1008
+ it 'immediatly closes connection' do
1009
+ connection.on(:connecting) { close_connection_proc.call }
1010
+ connection.on(:suspended) do |connection_state_change|
1011
+ if connection_state_change.retry_in.zero?
1012
+ # Exhausting immediate retries
1013
+ connection.once(:connecting) { close_connection_proc.call }
1014
+ else
1015
+ suspended_at = Time.now.to_f
1016
+ connection.on(:closed) do
1017
+ expect(connection_state_change.retry_in).to eq(suspended_retry_timeout)
1018
+ expect(connection.state).to eq(:closed)
1019
+ expect(Time.now.to_f).to be_within(4).of(suspended_at)
1020
+ stop_reactor
1021
+ end
1022
+
1023
+ connection.close
1024
+ end
1025
+
1026
+ connection.connect
1027
+ end
1028
+
1029
+ connection.connect
1030
+ end
1031
+ end
1032
+
1033
+ context ':disconnected RTN12d' do
1034
+ let(:retry_timeout) { 60 }
1035
+ let(:client_options) do
1036
+ default_options.merge(
1037
+ disconnected_retry_timeout: retry_timeout,
1038
+ suspended_retry_timeout: retry_timeout,
1039
+ connection_state_ttl: 0
1040
+ )
1041
+ end
1042
+
1043
+ it 'immediatly closes connection' do
1044
+ connection.once(:connected) do
1045
+ connection.on(:disconnected) do |connection_state_change|
1046
+ disconnected_at = Time.now.to_f
1047
+ connection.on(:connected) do
1048
+ if connection_state_change.retry_in.zero?
1049
+ # Exhausting immediate retries
1050
+ close_connection_proc.call
1051
+ else
1052
+ connection.once(:closed) do
1053
+ expect(connection_state_change.retry_in).to eq(retry_timeout)
1054
+ expect(connection.state).to eq(:closed)
1055
+ expect(Time.now.to_f).to be_within(4).of(disconnected_at)
1056
+ stop_reactor
1057
+ end
1058
+
1059
+ connection.close
1060
+ end
1061
+ end
1062
+
1063
+ connection.connect
1064
+ end
1065
+
1066
+ close_connection_proc.call
1067
+ end
1068
+
1069
+ connection.connect
1070
+ end
1071
+ end
813
1072
  end
814
1073
  end
815
1074
 
@@ -1179,6 +1438,7 @@ describe Ably::Realtime::Connection, :event_machine do
1179
1438
  host: 'this.host.does.not.exist.com'
1180
1439
  )
1181
1440
  )
1441
+ allow(client).to receive(:fallback_hosts).and_return([])
1182
1442
 
1183
1443
  connection.transition_state_machine! :disconnected
1184
1444
  end
@@ -1463,7 +1723,7 @@ describe Ably::Realtime::Connection, :event_machine do
1463
1723
  let(:client_options) { default_options.merge(tls: true) }
1464
1724
 
1465
1725
  it 'uses TLS for the Internet check to https://internet-up.ably-realtime.com/is-the-internet-up.txt' do
1466
- expect(EventMachine::HttpRequest).to receive(:new).with('https://internet-up.ably-realtime.com/is-the-internet-up.txt').and_return(http_request)
1726
+ 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)
1467
1727
  connection.internet_up?
1468
1728
  stop_reactor
1469
1729
  end
@@ -1473,7 +1733,7 @@ describe Ably::Realtime::Connection, :event_machine do
1473
1733
  let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
1474
1734
 
1475
1735
  it 'uses TLS for the Internet check to http://internet-up.ably-realtime.com/is-the-internet-up.txt' do
1476
- expect(EventMachine::HttpRequest).to receive(:new).with('http://internet-up.ably-realtime.com/is-the-internet-up.txt').and_return(http_request)
1736
+ 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)
1477
1737
  connection.internet_up?
1478
1738
  stop_reactor
1479
1739
  end
@@ -1487,7 +1747,7 @@ describe Ably::Realtime::Connection, :event_machine do
1487
1747
  let(:client_options) { default_options.merge(tls: true) }
1488
1748
 
1489
1749
  it 'checks the Internet up URL over TLS' do
1490
- expect(EventMachine::HttpRequest).to receive(:new).with("https:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
1750
+ 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))
1491
1751
  connection.internet_up?
1492
1752
  stop_reactor
1493
1753
  end
@@ -1497,7 +1757,7 @@ describe Ably::Realtime::Connection, :event_machine do
1497
1757
  let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
1498
1758
 
1499
1759
  it 'checks the Internet up URL over TLS' do
1500
- expect(EventMachine::HttpRequest).to receive(:new).with("http:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
1760
+ 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))
1501
1761
  connection.internet_up?
1502
1762
  stop_reactor
1503
1763
  end
@@ -1843,38 +2103,45 @@ describe Ably::Realtime::Connection, :event_machine do
1843
2103
  it 'sends the protocol version param v (#G4, #RTN2f)' do
1844
2104
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1845
2105
  uri = URI.parse(url)
1846
- expect(CGI::parse(uri.query)['v'][0]).to eql('1.1')
2106
+ expect(CGI::parse(uri.query)['v'][0]).to eql('1.2')
1847
2107
  stop_reactor
1848
2108
  end
1849
2109
  client
1850
2110
  end
1851
2111
 
1852
- it 'sends the lib version param lib (#RTN2g)' do
2112
+ it 'sends the lib version param agent (#RCS7d)' do
1853
2113
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1854
2114
  uri = URI.parse(url)
1855
- expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-1\.1\.\d+(-[\w\.]+)?+$/)
2115
+ expect(CGI::parse(uri.query)['agent'][0]).to match(/^ably-ruby\/\d\.\d\.\d ruby\/\d\.\d\.\d$/)
1856
2116
  stop_reactor
1857
2117
  end
1858
2118
  client
1859
2119
  end
2120
+ end
1860
2121
 
1861
- context 'with variant' do
1862
- let(:variant) { 'foo' }
2122
+ context 'transport_params (#RTC1f)' do
2123
+ let(:client_options) { default_options.merge(transport_params: { 'extra_param' => 'extra_param' }) }
1863
2124
 
1864
- before do
1865
- Ably.lib_variant = variant
1866
- end
2125
+ it 'pases transport_params to query' do
2126
+ expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
2127
+ uri = URI.parse(url)
2128
+ expect(CGI::parse(uri.query)['extra_param'][0]).to eq('extra_param')
2129
+ stop_reactor
2130
+ end
1867
2131
 
1868
- after do
1869
- Ably.lib_variant = nil
1870
- end
2132
+ client
2133
+ end
1871
2134
 
1872
- it 'sends the lib version param lib with the variant (#RTN2g + #RSC7b)' do
2135
+ context 'when changing default param' do
2136
+ let(:client_options) { default_options.merge(transport_params: { v: '1.0' }) }
2137
+
2138
+ it 'overrides default param (#RTC1f1)' do
1873
2139
  expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
1874
2140
  uri = URI.parse(url)
1875
- expect(CGI::parse(uri.query)['lib'][0]).to match(/^ruby-#{variant}-1\.1\.\d+(-[\w\.]+)?$/)
2141
+ expect(CGI::parse(uri.query)['v'][0]).to eq('1.0')
1876
2142
  stop_reactor
1877
2143
  end
2144
+
1878
2145
  client
1879
2146
  end
1880
2147
  end
@@ -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(leave_data) do
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
 
@@ -52,63 +54,5 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
52
54
 
53
55
  presence_client_one.enter(data)
54
56
  end
55
-
56
- context 'with option until_attach: true' do
57
- let(:event) { random_str }
58
- let(:presence_data_before_attach) { random_str }
59
- let(:presence_data_after_attach) { random_str }
60
-
61
- it 'retrieves all presence messages before channel was attached' do
62
- presence_client_two.enter(presence_data_before_attach) do
63
- presence_client_one.enter(presence_data_after_attach) do
64
- presence_client_one.history(until_attach: true) do |presence_page|
65
- expect(presence_page.items.count).to eql(1)
66
- expect(presence_page.items.first.data).to eql(presence_data_before_attach)
67
- stop_reactor
68
- end
69
- end
70
- end
71
- end
72
-
73
- context 'and two pages of messages' do
74
- let(:wildcard_token) { lambda { |token_params| Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') } }
75
- let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
76
- let(:client_two) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
77
-
78
- # TODO: Remove retry logic when presence history regression fixed
79
- # https://github.com/ably/realtime/issues/1707
80
- #
81
- it 'retrieves two pages of messages before channel was attached', retry: 10, :retry_wait => 5 do
82
- when_all(*10.times.map { |i| presence_client_two.enter_client("client:#{i}", presence_data_before_attach) }) do
83
- when_all(*10.times.map { |i| presence_client_one.enter_client("client:#{i}", presence_data_after_attach) }) do
84
- presence_client_one.history(until_attach: true, limit: 5) do |presence_page|
85
- expect(presence_page.items.count).to eql(5)
86
- expect(presence_page.items.map(&:data).uniq.first).to eql(presence_data_before_attach)
87
-
88
- presence_page.next do |presence_next_page|
89
- expect(presence_next_page.items.count).to eql(5)
90
- expect(presence_next_page.items.map(&:data).uniq.first).to eql(presence_data_before_attach)
91
- if presence_next_page.has_next?
92
- presence_next_page.next do |last|
93
- expect(last.items.count).to eql(0)
94
- end
95
- else
96
- expect(presence_next_page).to be_last
97
- end
98
- stop_reactor
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
105
-
106
- it 'fails with an exception unless state is attached' do
107
- presence_client_one.history(until_attach: true).errback do |error|
108
- expect(error.message).to match(/not attached/)
109
- stop_reactor
110
- end
111
- end
112
- end
113
57
  end
114
58
  end