ably-rest 1.0.6 → 1.1.4.rc

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/README.md +23 -15
  4. data/ably-rest.gemspec +6 -6
  5. data/lib/submodules/ably-ruby/.editorconfig +14 -0
  6. data/lib/submodules/ably-ruby/.travis.yml +10 -8
  7. data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
  8. data/lib/submodules/ably-ruby/LICENSE +1 -3
  9. data/lib/submodules/ably-ruby/README.md +12 -7
  10. data/lib/submodules/ably-ruby/Rakefile +32 -0
  11. data/lib/submodules/ably-ruby/SPEC.md +1277 -835
  12. data/lib/submodules/ably-ruby/ably.gemspec +15 -10
  13. data/lib/submodules/ably-ruby/lib/ably/auth.rb +30 -4
  14. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
  15. data/lib/submodules/ably-ruby/lib/ably/logger.rb +7 -1
  16. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
  17. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
  18. data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
  19. data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
  20. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
  21. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -4
  22. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
  23. data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
  24. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +1 -1
  25. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +1 -1
  26. data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
  27. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
  28. data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
  29. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  30. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +1 -1
  31. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +24 -102
  32. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -6
  33. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
  34. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
  35. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
  36. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
  37. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +6 -2
  38. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +34 -20
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +1 -1
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +4 -4
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +3 -3
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
  46. data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  47. data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
  48. data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
  49. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +53 -17
  50. data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
  51. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +162 -35
  52. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -1
  53. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
  54. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
  55. data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
  56. data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
  57. data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  58. data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
  59. data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
  60. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +245 -17
  61. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +26 -20
  62. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +177 -59
  63. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +153 -0
  64. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +72 -6
  65. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +129 -18
  66. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +36 -34
  67. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +201 -167
  68. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
  69. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
  70. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +41 -3
  71. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
  72. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
  73. data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
  74. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -10
  75. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
  76. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
  77. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
  78. data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
  79. data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
  80. data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -1
  81. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
  82. data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
  83. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +10 -3
  84. data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
  85. data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
  86. data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
  87. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
  88. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
  89. data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
  90. data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
  91. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
  92. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
  93. data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
  94. data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +8 -1
  95. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
  96. data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
  97. metadata +46 -21
@@ -112,22 +112,26 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
112
112
 
113
113
  context 'in multiple ProtocolMessages', em_timeout: (30 / 10) + 5 do
114
114
  it 'retrieves limited history forwards with pagination' do
115
- messages_sent.times do |index|
116
- EventMachine.add_timer(index.to_f / rate_per_second) do
117
- channel.publish('event', "history#{index}") do
118
- next unless index == messages_sent - 1
119
- ensure_message_history_direction_and_paging_is_correct :forwards
115
+ channel.attach do
116
+ messages_sent.times do |index|
117
+ EventMachine.add_timer(index.to_f / rate_per_second) do
118
+ channel.publish('event', "history#{index}") do
119
+ next unless index == messages_sent - 1
120
+ ensure_message_history_direction_and_paging_is_correct :forwards
121
+ end
120
122
  end
121
123
  end
122
124
  end
123
125
  end
124
126
 
125
127
  it 'retrieves limited history backwards with pagination' do
126
- messages_sent.times.to_a.reverse.each do |index|
127
- EventMachine.add_timer((messages_sent - index).to_f / rate_per_second) do
128
- channel.publish('event', "history#{index}") do
129
- next unless index == 0
130
- ensure_message_history_direction_and_paging_is_correct :backwards if index == 0
128
+ channel.attach do
129
+ messages_sent.times.to_a.reverse.each do |index|
130
+ EventMachine.add_timer((messages_sent - index).to_f / rate_per_second) do
131
+ channel.publish('event', "history#{index}") do
132
+ next unless index == 0
133
+ ensure_message_history_direction_and_paging_is_correct :backwards if index == 0
134
+ end
131
135
  end
132
136
  end
133
137
  end
@@ -139,18 +143,20 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
139
143
  let(:messages_per_batch) { 10 }
140
144
 
141
145
  it 'return the same results with unique matching message IDs' do
142
- batches.times do |batch|
143
- EventMachine.add_timer(batch.to_f / batches.to_f) do
144
- messages_per_batch.times { channel.publish('event', 'data') }
146
+ channel.attach do
147
+ batches.times do |batch|
148
+ EventMachine.add_timer(batch.to_f / batches.to_f) do
149
+ messages_per_batch.times { |index| channel.publish('event') }
150
+ end
145
151
  end
146
- end
147
152
 
148
- channel.subscribe('event') do |message|
149
- messages << message
150
- if messages.count == batches * messages_per_batch
151
- channel.history do |page|
152
- expect(page.items.map(&:id).sort).to eql(messages.map(&:id).sort)
153
- stop_reactor
153
+ channel.subscribe('event') do |message|
154
+ messages << message
155
+ if messages.count == batches * messages_per_batch
156
+ channel.history do |page|
157
+ expect(page.items.map(&:id).sort).to eql(messages.map(&:id).sort)
158
+ stop_reactor
159
+ end
154
160
  end
155
161
  end
156
162
  end
@@ -13,6 +13,9 @@ describe Ably::Realtime::Channel, :event_machine do
13
13
  let(:channel) { client.channel(channel_name) }
14
14
  let(:messages) { [] }
15
15
 
16
+ let(:sub_client) { auto_close Ably::Realtime::Client.new(client_options) }
17
+ let(:sub_channel) { sub_client.channel(channel_name) }
18
+
16
19
  def disconnect_transport
17
20
  connection.transport.unbind
18
21
  end
@@ -276,8 +279,7 @@ describe Ably::Realtime::Channel, :event_machine do
276
279
  key: restricted_api_key,
277
280
  log_level: :fatal,
278
281
  use_token_auth: true,
279
- # TODO: Use wildcard / default when intersection issue resolved, realtime#780
280
- default_token_params: { capability: { "canpublish:foo" => ["publish"] } }
282
+ default_token_params: { capability: { "canpublish:foo" => ["*"] } }
281
283
  )
282
284
  end
283
285
  let(:restricted_client) do
@@ -726,7 +728,7 @@ describe Ably::Realtime::Channel, :event_machine do
726
728
  let(:name) { random_str }
727
729
  let(:data) { random_str }
728
730
 
729
- context 'when attached' do
731
+ context 'when channel is attached (#RTL6c1)' do
730
732
  it 'publishes messages' do
731
733
  channel.attach do
732
734
  3.times { channel.publish('event', payload) }
@@ -738,81 +740,173 @@ describe Ably::Realtime::Channel, :event_machine do
738
740
  end
739
741
  end
740
742
 
741
- context 'when not yet attached' do
742
- it 'publishes queued messages once attached' do
743
- 3.times { channel.publish('event', random_str) }
744
- channel.subscribe do |message|
745
- messages << message if message.name == 'event'
746
- stop_reactor if messages.count == 3
743
+ context 'when channel is not attached in state Initializing (#RTL6c1)' do
744
+ it 'publishes messages immediately and does not implicitly attach (#RTL6c1)' do
745
+ sub_channel.attach do
746
+ sub_channel.subscribe do |message|
747
+ messages << message if message.name == 'event'
748
+ if messages.count == 3
749
+ EventMachine.add_timer(1) do
750
+ expect(channel.state).to eq(:initialized)
751
+ stop_reactor
752
+ end
753
+ end
754
+ end
755
+ 3.times { channel.publish('event', random_str) }
747
756
  end
748
757
  end
758
+ end
749
759
 
750
- it 'publishes queued messages within a single protocol message' do
751
- 3.times { channel.publish('event', random_str) }
752
- channel.subscribe do |message|
753
- messages << message if message.name == 'event'
754
- next unless messages.length == 3
755
-
756
- # All 3 messages should be batched into a single Protocol Message by the client library
757
- # message.id = "{protocol_message.id}:{protocol_message_index}"
758
- # Check that all messages share the same protocol_message.id
759
- message_id = messages.map { |msg| msg.id.split(':')[0...-1].join(':') }
760
- expect(message_id.uniq.count).to eql(1)
761
-
762
- # Check that messages use index 0,1,2 in the ID
763
- message_indexes = messages.map { |msg| msg.id.split(':').last }
764
- expect(message_indexes).to include("0", "1", "2")
765
- stop_reactor
760
+ context 'when channel is Attaching (#RTL6c1)' do
761
+ it 'publishes messages immediately (#RTL6c1)' do
762
+ sub_channel.attach do
763
+ channel.once(:attaching) do
764
+ outgoing_message_count = 0
765
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
766
+ if protocol_message.action == :message
767
+ raise "Expected channel state to be attaching when publishing messages, not #{channel.state}" unless channel.attaching?
768
+ outgoing_message_count += protocol_message.messages.count
769
+ end
770
+ end
771
+ sub_channel.subscribe do |message|
772
+ messages << message if message.name == 'event'
773
+ if messages.count == 3
774
+ expect(outgoing_message_count).to eql(3)
775
+ stop_reactor
776
+ end
777
+ end
778
+ 3.times { channel.publish('event', random_str) }
779
+ end
780
+ channel.attach
766
781
  end
767
782
  end
783
+ end
768
784
 
769
- context 'with :queue_messages client option set to false' do
770
- let(:client_options) { default_options.merge(queue_messages: false) }
771
-
772
- context 'and connection state initialized' do
773
- it 'fails the deferrable' do
774
- expect(client.connection).to be_initialized
775
- channel.publish('event').errback do |error|
776
- expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled)
777
- stop_reactor
785
+ context 'when channel is Detaching (#RTL6c1)' do
786
+ it 'publishes messages immediately (#RTL6c1)' do
787
+ sub_channel.attach do
788
+ channel.attach do
789
+ channel.once(:detaching) do
790
+ outgoing_message_count = 0
791
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
792
+ if protocol_message.action == :message
793
+ raise "Expected channel state to be attaching when publishing messages, not #{channel.state}" unless channel.detaching?
794
+ outgoing_message_count += protocol_message.messages.count
795
+ end
796
+ end
797
+ sub_channel.subscribe do |message|
798
+ messages << message if message.name == 'event'
799
+ if messages.count == 3
800
+ expect(outgoing_message_count).to eql(3)
801
+ stop_reactor
802
+ end
803
+ end
804
+ 3.times { channel.publish('event', random_str) }
778
805
  end
806
+ channel.detach
779
807
  end
780
808
  end
809
+ end
810
+ end
781
811
 
782
- context 'and connection state connecting' do
783
- it 'fails the deferrable' do
784
- client.connect
785
- EventMachine.next_tick do
786
- expect(client.connection).to be_connecting
787
- channel.publish('event').errback do |error|
788
- expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled)
789
- stop_reactor
812
+ context 'when channel is Detached (#RTL6c1)' do
813
+ it 'publishes messages immediately (#RTL6c1)' do
814
+ sub_channel.attach do
815
+ channel.attach
816
+ channel.once(:attached) do
817
+ channel.once(:detached) do
818
+ outgoing_message_count = 0
819
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
820
+ if protocol_message.action == :message
821
+ raise "Expected channel state to be attaching when publishing messages, not #{channel.state}" unless channel.detached?
822
+ outgoing_message_count += protocol_message.messages.count
823
+ end
824
+ end
825
+ sub_channel.subscribe do |message|
826
+ messages << message if message.name == 'event'
827
+ if messages.count == 3
828
+ expect(outgoing_message_count).to eql(3)
829
+ stop_reactor
830
+ end
790
831
  end
832
+ 3.times { channel.publish('event', random_str) }
833
+ end
834
+ channel.detach
835
+ end
836
+ end
837
+ end
838
+ end
839
+
840
+ context 'with :queue_messages client option set to false (#RTL6c4)' do
841
+ let(:client_options) { default_options.merge(queue_messages: false) }
842
+
843
+ context 'and connection state connected (#RTL6c4)' do
844
+ it 'publishes the message' do
845
+ client.connection.once(:connected) do
846
+ channel.publish('event')
847
+ stop_reactor
848
+ end
849
+ end
850
+ end
851
+
852
+ context 'and connection state initialized (#RTL6c4)' do
853
+ it 'fails the deferrable' do
854
+ expect(client.connection).to be_initialized
855
+ channel.publish('event').errback do |error|
856
+ expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled)
857
+ stop_reactor
858
+ end
859
+ end
860
+ end
861
+
862
+ context 'and connection state connecting (#RTL6c4)' do
863
+ it 'fails the deferrable' do
864
+ client.connect
865
+ EventMachine.next_tick do
866
+ expect(client.connection).to be_connecting
867
+ channel.publish('event').errback do |error|
868
+ expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled)
869
+ stop_reactor
791
870
  end
792
871
  end
793
872
  end
873
+ end
794
874
 
795
- context 'and connection state disconnected' do
875
+ [:disconnected, :suspended, :closing, :closed].each do |invalid_connection_state|
876
+ context "and connection state #{invalid_connection_state} (#RTL6c4)" do
796
877
  let(:client_options) { default_options.merge(queue_messages: false) }
797
878
  it 'fails the deferrable' do
798
879
  client.connection.once(:connected) do
799
- client.connection.once(:disconnected) do
800
- expect(client.connection).to be_disconnected
880
+ client.connection.once(invalid_connection_state) do
881
+ expect(client.connection.state).to eq(invalid_connection_state)
801
882
  channel.publish('event').errback do |error|
802
883
  expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled)
803
884
  stop_reactor
804
885
  end
805
886
  end
806
- client.connection.transition_state_machine :disconnected
887
+ if invalid_connection_state == :closed
888
+ connection.close
889
+ else
890
+ client.connection.transition_state_machine invalid_connection_state
891
+ end
807
892
  end
808
893
  end
809
894
  end
895
+ end
810
896
 
811
- context 'and connection state connected' do
812
- it 'publishes the message' do
813
- client.connection.once(:connected) do
814
- channel.publish('event')
815
- stop_reactor
897
+ context 'and the channel state is failed (#RTL6c4)' do
898
+ let(:client_options) { default_options.merge(queue_messages: false) }
899
+ it 'fails the deferrable' do
900
+ client.connection.once(:connected) do
901
+ channel.attach
902
+ channel.once(:attached) do
903
+ channel.once(:failed) do
904
+ channel.publish('event').errback do |error|
905
+ expect(error).to be_a(Ably::Exceptions::ChannelInactive)
906
+ stop_reactor
907
+ end
908
+ end
909
+ channel.transition_state_machine(:failed)
816
910
  end
817
911
  end
818
912
  end
@@ -914,9 +1008,6 @@ describe Ably::Realtime::Channel, :event_machine do
914
1008
 
915
1009
  it 'publishes the message without a name attribute in the payload' do
916
1010
  published = false
917
- channel.publish(nil, data) do
918
- published = true
919
- end
920
1011
 
921
1012
  channel.subscribe do |message|
922
1013
  expect(message.name).to be_nil
@@ -929,6 +1020,10 @@ describe Ably::Realtime::Channel, :event_machine do
929
1020
  end
930
1021
  end
931
1022
  end
1023
+
1024
+ channel.publish(nil, data) do
1025
+ published = true
1026
+ end
932
1027
  end
933
1028
  end
934
1029
 
@@ -937,9 +1032,6 @@ describe Ably::Realtime::Channel, :event_machine do
937
1032
 
938
1033
  it 'publishes the message without a data attribute in the payload' do
939
1034
  published = false
940
- channel.publish(name, nil) do
941
- published = true
942
- end
943
1035
 
944
1036
  channel.subscribe do |message|
945
1037
  expect(message.data).to be_nil
@@ -952,6 +1044,10 @@ describe Ably::Realtime::Channel, :event_machine do
952
1044
  end
953
1045
  end
954
1046
  end
1047
+
1048
+ channel.publish(name, nil) do
1049
+ published = true
1050
+ end
955
1051
  end
956
1052
  end
957
1053
 
@@ -1074,6 +1170,21 @@ describe Ably::Realtime::Channel, :event_machine do
1074
1170
  end
1075
1171
  end
1076
1172
 
1173
+ context 'with more than allowed messages in a single publish' do
1174
+ let(:channel_name) { random_str }
1175
+
1176
+ it 'rejects the publish' do
1177
+ messages = (Ably::Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE + 1).times.map do
1178
+ { name: 'foo' }
1179
+ end
1180
+
1181
+ channel.publish(messages).errback do |error|
1182
+ expect(error).to be_kind_of(Ably::Exceptions::InvalidRequest)
1183
+ stop_reactor
1184
+ end
1185
+ end
1186
+ end
1187
+
1077
1188
  context 'identified clients' do
1078
1189
  context 'when authenticated with a wildcard client_id' do
1079
1190
  let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') }
@@ -1887,6 +1998,8 @@ describe Ably::Realtime::Channel, :event_machine do
1887
1998
  end
1888
1999
 
1889
2000
  context '#resume (#RTL2f)' do
2001
+ let(:client_options) { default_options.merge(log_level: :fatal) }
2002
+
1890
2003
  it 'is false when a channel first attaches' do
1891
2004
  channel.attach
1892
2005
  channel.on(:attached) do |channel_state_change|
@@ -1953,8 +2066,12 @@ describe Ably::Realtime::Channel, :event_machine do
1953
2066
  end
1954
2067
 
1955
2068
  context 'moves to' do
1956
- %w(suspended detached failed).each do |channel_state|
2069
+ %w(suspended failed).each do |channel_state|
1957
2070
  context(channel_state) do
2071
+ let(:client) do
2072
+ auto_close Ably::Realtime::Client.new(default_options.merge(log_level: :error))
2073
+ end
2074
+
1958
2075
  specify 'all queued messages fail with NACK (#RTL11)' do
1959
2076
  channel.attach do
1960
2077
  # Move to disconnected
@@ -1981,7 +2098,8 @@ describe Ably::Realtime::Channel, :event_machine do
1981
2098
  specify 'all published messages awaiting an ACK do nothing (#RTL11a)' do
1982
2099
  connection_been_disconnected = false
1983
2100
 
1984
- channel.attach do
2101
+ channel.attach
2102
+ channel.once(:attached) do
1985
2103
  deferrable = channel.publish("foo")
1986
2104
  deferrable.errback do |error|
1987
2105
  fail "Message publish should not fail"
@@ -12,6 +12,7 @@ describe Ably::Realtime::Client, :event_machine do
12
12
  let(:auth_params) { subject.auth.auth_params_sync }
13
13
 
14
14
  subject { auto_close Ably::Realtime::Client.new(client_options) }
15
+ let(:sub_client) { auto_close Ably::Realtime::Client.new(client_options) }
15
16
 
16
17
  context 'initialization' do
17
18
  context 'basic auth' do
@@ -24,6 +25,22 @@ describe Ably::Realtime::Client, :event_machine do
24
25
  end
25
26
  end
26
27
 
28
+ context 'with an invalid API key' do
29
+ let(:custom_logger_object) { TestLogger.new }
30
+ let(:client) { Ably::Realtime::Client.new(client_options.merge(key: 'app.key:secret', logger: custom_logger_object)) }
31
+
32
+ it 'logs an entry with a help href url matching the code #TI5' do
33
+ client.connect
34
+ client.connection.once(:failed) do
35
+ expect(custom_logger_object.logs.find do |severity, message|
36
+ next unless %w(fatal error).include?(severity.to_s)
37
+ message.match(%r{https://help.ably.io/error/40400})
38
+ end).to_not be_nil
39
+ stop_reactor
40
+ end
41
+ end
42
+ end
43
+
27
44
  context ':tls option' do
28
45
  context 'set to false to force a plain-text connection' do
29
46
  let(:client_options) { default_options.merge(tls: false, log_level: :none) }
@@ -281,5 +298,141 @@ describe Ably::Realtime::Client, :event_machine do
281
298
  end
282
299
  end
283
300
  end
301
+
302
+ context '#publish (#TBC)' do
303
+ let(:channel_name) { random_str }
304
+ let(:channel) { subject.channel(channel_name) }
305
+ let(:sub_channel) { sub_client.channel(channel_name) }
306
+ let(:event_name) { random_str }
307
+ let(:data) { random_str }
308
+ let(:extras) { { 'push' => { 'notification' => { 'title' => 'Testing' } } } }
309
+ let(:message) { Ably::Models::Message.new(name: event_name, data: data) }
310
+
311
+ specify 'publishing a message implicity connects and publishes the message successfully on the provided channel' do
312
+ sub_channel.attach do
313
+ sub_channel.subscribe do |msg|
314
+ expect(msg.name).to eql(event_name)
315
+ expect(msg.data).to eql(data)
316
+ stop_reactor
317
+ end
318
+
319
+ subject.publish channel_name, event_name, data
320
+ end
321
+ end
322
+
323
+ specify 'publishing does not result in a channel being created' do
324
+ subject.publish channel_name, event_name, data
325
+ subject.channels.fetch(channel_name) do
326
+ # Block called if channel does not exist
327
+ EventMachine.add_timer(1) do
328
+ subject.channels.fetch(channel_name) do
329
+ # Block called if channel does not exist
330
+ stop_reactor
331
+ end
332
+ end
333
+ end
334
+ end
335
+
336
+ context 'with extras' do
337
+ let(:channel_name) { "pushenabled:#{random_str}" }
338
+
339
+ specify 'publishing supports extras' do
340
+ sub_channel.attach do
341
+ sub_channel.subscribe do |msg|
342
+ expect(msg.extras).to eql(extras)
343
+ stop_reactor
344
+ end
345
+
346
+ subject.publish channel_name, event_name, {}, extras: extras
347
+ end
348
+ end
349
+ end
350
+
351
+ specify 'publishing supports an array of Message objects' do
352
+ sub_channel.attach do
353
+ sub_channel.subscribe do |msg|
354
+ expect(msg.name).to eql(event_name)
355
+ expect(msg.data).to eql(data)
356
+ stop_reactor
357
+ end
358
+
359
+ subject.publish channel_name, [message]
360
+ end
361
+ end
362
+
363
+ specify 'publishing supports an array of Hash objects' do
364
+ sub_channel.attach do
365
+ sub_channel.subscribe do |msg|
366
+ expect(msg.name).to eql(event_name)
367
+ expect(msg.data).to eql(data)
368
+ stop_reactor
369
+ end
370
+
371
+ subject.publish channel_name, [name: event_name, data: data]
372
+ end
373
+ end
374
+
375
+ specify 'publishing on a closed connection fails' do
376
+ subject.connection.once(:connected) do
377
+ subject.connection.once(:closed) do
378
+ subject.publish(channel_name, name: event_name).errback do |error|
379
+ expect(error).to be_kind_of(Ably::Exceptions::MessageQueueingDisabled)
380
+ stop_reactor
381
+ end
382
+ end
383
+ connection.close
384
+ end
385
+ end
386
+
387
+ context 'queue_messages ClientOption' do
388
+ context 'when true' do
389
+ subject { auto_close Ably::Realtime::Client.new(client_options.merge(auto_connect: false)) }
390
+
391
+ it 'will queue messages whilst connecting and publish once connected' do
392
+ sub_channel.attach do
393
+ sub_channel.subscribe do |msg|
394
+ expect(msg.name).to eql(event_name)
395
+ stop_reactor
396
+ end
397
+ subject.connection.once(:connecting) do
398
+ subject.publish channel_name, event_name
399
+ end
400
+ subject.connection.connect
401
+ end
402
+ end
403
+ end
404
+
405
+ context 'when false' do
406
+ subject { auto_close Ably::Realtime::Client.new(client_options.merge(auto_connect: false, queue_messages: false)) }
407
+
408
+ it 'will reject messages on an initializing connection' do
409
+ sub_channel.attach do
410
+ subject.connection.once(:connecting) do
411
+ subject.publish(channel_name, event_name).errback do |error|
412
+ expect(error).to be_kind_of(Ably::Exceptions::MessageQueueingDisabled)
413
+ stop_reactor
414
+ end
415
+ end
416
+ subject.connection.connect
417
+ end
418
+ end
419
+ end
420
+ end
421
+
422
+ context 'with more than allowed messages in a single publish' do
423
+ let(:channel_name) { random_str }
424
+
425
+ it 'rejects the publish' do
426
+ messages = (Ably::Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE + 1).times.map do
427
+ { name: 'foo' }
428
+ end
429
+
430
+ subject.publish(channel_name, messages).errback do |error|
431
+ expect(error).to be_kind_of(Ably::Exceptions::InvalidRequest)
432
+ stop_reactor
433
+ end
434
+ end
435
+ end
436
+ end
284
437
  end
285
438
  end