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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check.yml +15 -1
  3. data/CHANGELOG.md +131 -0
  4. data/COPYRIGHT +1 -1
  5. data/README.md +14 -2
  6. data/SPEC.md +0 -7
  7. data/UPDATING.md +30 -0
  8. data/ably.gemspec +12 -7
  9. data/lib/ably/agent.rb +3 -0
  10. data/lib/ably/auth.rb +3 -3
  11. data/lib/ably/exceptions.rb +6 -0
  12. data/lib/ably/models/channel_options.rb +97 -0
  13. data/lib/ably/models/connection_details.rb +8 -0
  14. data/lib/ably/models/delta_extras.rb +29 -0
  15. data/lib/ably/models/error_info.rb +6 -2
  16. data/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
  17. data/lib/ably/models/message.rb +28 -3
  18. data/lib/ably/models/presence_message.rb +14 -0
  19. data/lib/ably/models/protocol_message.rb +29 -12
  20. data/lib/ably/models/token_details.rb +7 -2
  21. data/lib/ably/modules/channels_collection.rb +22 -2
  22. data/lib/ably/modules/conversions.rb +34 -0
  23. data/lib/ably/realtime/channel/channel_manager.rb +18 -6
  24. data/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
  25. data/lib/ably/realtime/channel/publisher.rb +6 -0
  26. data/lib/ably/realtime/channel.rb +54 -22
  27. data/lib/ably/realtime/channels.rb +1 -1
  28. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
  29. data/lib/ably/realtime/connection/connection_manager.rb +13 -4
  30. data/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
  31. data/lib/ably/realtime/connection.rb +2 -2
  32. data/lib/ably/rest/channel.rb +31 -31
  33. data/lib/ably/rest/client.rb +27 -12
  34. data/lib/ably/util/crypto.rb +1 -1
  35. data/lib/ably/version.rb +2 -14
  36. data/lib/ably.rb +1 -0
  37. data/spec/acceptance/realtime/auth_spec.rb +1 -1
  38. data/spec/acceptance/realtime/channel_history_spec.rb +25 -0
  39. data/spec/acceptance/realtime/channel_spec.rb +466 -21
  40. data/spec/acceptance/realtime/channels_spec.rb +59 -7
  41. data/spec/acceptance/realtime/connection_failures_spec.rb +59 -2
  42. data/spec/acceptance/realtime/connection_spec.rb +256 -28
  43. data/spec/acceptance/realtime/message_spec.rb +77 -0
  44. data/spec/acceptance/realtime/presence_history_spec.rb +3 -1
  45. data/spec/acceptance/realtime/presence_spec.rb +31 -159
  46. data/spec/acceptance/rest/auth_spec.rb +18 -0
  47. data/spec/acceptance/rest/channel_spec.rb +84 -9
  48. data/spec/acceptance/rest/channels_spec.rb +23 -6
  49. data/spec/acceptance/rest/client_spec.rb +25 -21
  50. data/spec/acceptance/rest/message_spec.rb +61 -3
  51. data/spec/lib/unit/models/channel_options_spec.rb +52 -0
  52. data/spec/shared/model_behaviour.rb +1 -1
  53. data/spec/spec_helper.rb +11 -2
  54. data/spec/support/test_app.rb +1 -1
  55. data/spec/unit/models/delta_extras_spec.rb +14 -0
  56. data/spec/unit/models/error_info_spec.rb +17 -1
  57. data/spec/unit/models/message_spec.rb +97 -0
  58. data/spec/unit/models/presence_message_spec.rb +49 -0
  59. data/spec/unit/models/protocol_message_spec.rb +125 -27
  60. data/spec/unit/models/token_details_spec.rb +14 -0
  61. data/spec/unit/realtime/channel_spec.rb +3 -2
  62. data/spec/unit/realtime/channels_spec.rb +53 -15
  63. data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
  64. data/spec/unit/rest/channel_spec.rb +44 -1
  65. data/spec/unit/rest/channels_spec.rb +81 -14
  66. data/spec/unit/rest/client_spec.rb +47 -0
  67. metadata +60 -24
@@ -117,6 +117,94 @@ describe Ably::Realtime::Channel, :event_machine do
117
117
  end
118
118
  end
119
119
 
120
+ context 'context when channel options contain modes' do
121
+ before do
122
+ channel.options = { modes: %i[publish] }
123
+ end
124
+
125
+ it 'sends an ATTACH with options as flags (#RTL4l)' do
126
+ connection.once(:connected) do
127
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
128
+ next if protocol_message.action != :attach
129
+
130
+ expect(protocol_message.has_attach_publish_flag?).to eq(true)
131
+ stop_reactor
132
+ end
133
+
134
+ channel.attach
135
+ end
136
+ end
137
+
138
+ context 'when channel is reattaching' do
139
+ it 'sends ATTACH_RESUME flag along with other modes (RTL4j)' do
140
+ channel.attach do
141
+ channel.on(:suspended) do
142
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
143
+ next if protocol_message.action != :attach
144
+
145
+ expect(protocol_message.has_attach_resume_flag?).to eq(true)
146
+ expect(protocol_message.has_attach_publish_flag?).to eq(true)
147
+ stop_reactor
148
+ end
149
+
150
+ client.connection.connect
151
+ end
152
+ client.connection.transition_state_machine :suspended
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ context 'context when channel options contain params' do
159
+ let(:params) do
160
+ { foo: 'foo', bar: 'bar'}
161
+ end
162
+
163
+ before do
164
+ channel.options = { params: params }
165
+ end
166
+
167
+ it 'sends an ATTACH with params (#RTL4k)' do
168
+ connection.once(:connected) do
169
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
170
+ next if protocol_message.action != :attach
171
+
172
+ expect(protocol_message.params).to eq(params)
173
+ stop_reactor
174
+ end
175
+
176
+ channel.attach
177
+ end
178
+ end
179
+ end
180
+
181
+ context 'when received attached' do
182
+ it 'decodes flags and sets it as modes on channel options (#RTL4m)'do
183
+ channel.on(:attached) do
184
+ expect(channel.options.modes.map(&:to_sym)).to eq(%i[subscribe])
185
+ stop_reactor
186
+ end
187
+
188
+ channel.transition_state_machine(:attaching)
189
+ attached_message = Ably::Models::ProtocolMessage.new(action: 11, channel: channel_name, flags: 262144)
190
+ client.connection.__incoming_protocol_msgbus__.publish :protocol_message, attached_message
191
+ end
192
+
193
+ it 'set params as channel options params (#RTL4k1)' do
194
+ params = { param: :something }
195
+
196
+ channel.on(:attached) do
197
+ expect(channel.params).to eq(channel.options.params)
198
+ expect(channel.params).to eq(params)
199
+ stop_reactor
200
+ end
201
+
202
+ channel.transition_state_machine(:attaching)
203
+ attached_message = Ably::Models::ProtocolMessage.new(action: 11, channel: channel_name, params: params)
204
+ client.connection.__incoming_protocol_msgbus__.publish :protocol_message, attached_message
205
+ end
206
+ end
207
+
120
208
  it 'implicitly attaches the channel (#RTL7c)' do
121
209
  expect(channel).to be_initialized
122
210
  channel.subscribe { |message| }
@@ -368,6 +456,42 @@ describe Ably::Realtime::Channel, :event_machine do
368
456
  end
369
457
  end
370
458
  end
459
+
460
+ describe 'clean attach (RTL4j)' do
461
+ context "when channel wasn't previously attached" do
462
+ it "doesn't send ATTACH_RESUME" do
463
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
464
+ next if protocol_message.action != :attach
465
+
466
+ expect(protocol_message.has_attach_resume_flag?).to eq(false)
467
+ stop_reactor
468
+ end
469
+
470
+ channel.attach
471
+ end
472
+ end
473
+
474
+ context "when channel was explicitly detached" do
475
+ it "doesn't send ATTACH_RESUME" do
476
+ channel.once(:detached) do
477
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
478
+ next if protocol_message.action != :attach
479
+
480
+ expect(protocol_message.has_attach_resume_flag?).to eq(false)
481
+ stop_reactor
482
+ end
483
+
484
+ channel.attach
485
+ end
486
+
487
+ channel.once(:attached) do
488
+ channel.detach
489
+ end
490
+
491
+ channel.attach
492
+ end
493
+ end
494
+ end
371
495
  end
372
496
 
373
497
  describe '#detach' do
@@ -750,6 +874,107 @@ describe Ably::Realtime::Channel, :event_machine do
750
874
  end
751
875
  end
752
876
 
877
+ describe '#(RTL17)' do
878
+ context 'when channel is initialized' do
879
+ it 'sends messages only on attach' do
880
+ expect(channel).to be_initialized
881
+ channel.publish('event', payload)
882
+
883
+ channel.subscribe do |message|
884
+ stop_reactor if message.data == payload && channel.attached?
885
+ end
886
+
887
+ channel.attach
888
+ end
889
+ end
890
+
891
+ context 'when channel is attaching' do
892
+ it 'sends messages only on attach' do
893
+ channel.publish('event', payload)
894
+
895
+ sent_message = nil
896
+ channel.subscribe do |message|
897
+ return if message.data != payload
898
+ sent_message = message
899
+
900
+ stop_reactor if channel.attached?
901
+ end
902
+
903
+ channel.on(:attaching) do
904
+ expect(channel).to be_attaching
905
+ expect(sent_message).to be_nil
906
+ end
907
+
908
+ channel.attach
909
+ end
910
+ end
911
+
912
+ context 'when channel is detaching' do
913
+ it 'stops sending message' do
914
+ sent_message = nil
915
+ event_published = false
916
+ channel.subscribe do |message|
917
+ sent_message = message if message.data == payload
918
+ end
919
+
920
+ channel.on(:detaching) do
921
+ channel.publish('event', payload)
922
+ event_published = true
923
+ end
924
+
925
+ channel.on(:detaching) do
926
+ EventMachine.next_tick do
927
+ expect(sent_message).to be_nil
928
+ stop_reactor if event_published
929
+ end
930
+ end
931
+
932
+ channel.attach do
933
+ channel.detach
934
+ end
935
+ end
936
+ end
937
+
938
+ context 'when channel is detached' do
939
+ it 'stops sending message' do
940
+ sent_message = nil
941
+ event_published = false
942
+ channel.subscribe do |message|
943
+ sent_message = message if message.data == payload
944
+ end
945
+
946
+ channel.on(:detaching) do
947
+ channel.publish('event', payload)
948
+ event_published = true
949
+ end
950
+
951
+ channel.on(:detached) do
952
+ expect(sent_message).to be_nil
953
+ stop_reactor if event_published
954
+ end
955
+
956
+ channel.attach do
957
+ channel.detach
958
+ end
959
+ end
960
+ end
961
+
962
+ context 'when channel is failed' do
963
+ it 'errors when trying to send a message' do
964
+ channel.once(:failed) do
965
+ channel.publish('event', payload).errback do |error|
966
+ expect(error).to be_a(Ably::Exceptions::ChannelInactive)
967
+ stop_reactor
968
+ end
969
+ end
970
+
971
+ channel.attach do
972
+ channel.transition_state_machine(:failed)
973
+ end
974
+ end
975
+ end
976
+ end
977
+
753
978
  context 'when channel is not attached in state Initializing (#RTL6c1)' do
754
979
  it 'publishes messages immediately and does not implicitly attach (#RTL6c1)' do
755
980
  sub_channel.attach do
@@ -1181,7 +1406,7 @@ describe Ably::Realtime::Channel, :event_machine do
1181
1406
  end
1182
1407
 
1183
1408
  context 'with more than allowed messages in a single publish' do
1184
- let(:channel_name) { random_str }
1409
+ 65536
1185
1410
 
1186
1411
  it 'rejects the publish' do
1187
1412
  messages = (Ably::Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE + 1).times.map do
@@ -1403,6 +1628,103 @@ describe Ably::Realtime::Channel, :event_machine do
1403
1628
  end
1404
1629
  end
1405
1630
  end
1631
+
1632
+ context 'message size exceeded (#TO3l8)' do
1633
+ let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
1634
+ let(:channel) { client.channels.get(channel_name) }
1635
+
1636
+ context 'and max_message_size is default (65536 bytes)' do
1637
+ let(:channel_name) { random_str }
1638
+ let(:max_message_size) { 65536 }
1639
+
1640
+ it 'should allow to send a message (32 bytes)' do
1641
+ client.connection.once(:connected) do
1642
+ channel.subscribe('event') do |msg|
1643
+ expect(msg.data).to eq('x' * 32)
1644
+ stop_reactor
1645
+ end
1646
+ channel.publish('event', 'x' * 32)
1647
+ end
1648
+ end
1649
+
1650
+ it 'should not allow to send a message (700000 bytes)' do
1651
+ client.connection.once(:connected) do
1652
+ connection_details = Ably::Models::ConnectionDetails.new(
1653
+ client.connection.details.attributes.attributes.merge('maxMessageSize' => max_message_size)
1654
+ )
1655
+ client.connection.set_connection_details(connection_details)
1656
+ expect(client.connection.details.max_message_size).to eq(65536)
1657
+ channel.publish('event', 'x' * 700000).errback do |error|
1658
+ expect(error).to be_instance_of(Ably::Exceptions::MaxMessageSizeExceeded)
1659
+ stop_reactor
1660
+ end
1661
+ end
1662
+ end
1663
+ end
1664
+
1665
+ context 'and max_message_size is customized (11 bytes)' do
1666
+ let(:max_message_size) { 11 }
1667
+
1668
+ context 'and the message size is 30 bytes' do
1669
+ let(:channel_name) { random_str }
1670
+
1671
+ it 'should not allow to send a message' do
1672
+ client.connection.once(:connected) do
1673
+ connection_details = Ably::Models::ConnectionDetails.new(
1674
+ client.connection.details.attributes.attributes.merge('maxMessageSize' => max_message_size)
1675
+ )
1676
+ client.connection.set_connection_details(connection_details)
1677
+ expect(client.connection.details.max_message_size).to eq(11)
1678
+ channel.publish('event', 'x' * 30).errback do |error|
1679
+ expect(error).to be_instance_of(Ably::Exceptions::MaxMessageSizeExceeded)
1680
+ stop_reactor
1681
+ end
1682
+ end
1683
+ end
1684
+ end
1685
+ end
1686
+
1687
+ context 'and max_message_size is nil' do
1688
+ let(:max_message_size) { nil }
1689
+
1690
+ context 'and the message size is 30 bytes' do
1691
+ let(:channel_name) { random_str }
1692
+
1693
+ it 'should allow to send a message' do
1694
+ client.connection.once(:connected) do
1695
+ connection_details = Ably::Models::ConnectionDetails.new(
1696
+ client.connection.details.attributes.attributes.merge('maxMessageSize' => max_message_size)
1697
+ )
1698
+ client.connection.set_connection_details(connection_details)
1699
+ expect(client.connection.details.max_message_size).to eq(65536)
1700
+ channel.subscribe('event') do |msg|
1701
+ expect(msg.data).to eq('x' * 30)
1702
+ stop_reactor
1703
+ end
1704
+ channel.publish('event', 'x' * 30)
1705
+ end
1706
+ end
1707
+ end
1708
+
1709
+ context 'and the message size is 65537 bytes' do
1710
+ let(:channel_name) { random_str }
1711
+
1712
+ it 'should not allow to send a message' do
1713
+ client.connection.once(:connected) do
1714
+ connection_details = Ably::Models::ConnectionDetails.new(
1715
+ client.connection.details.attributes.attributes.merge('maxMessageSize' => max_message_size)
1716
+ )
1717
+ client.connection.set_connection_details(connection_details)
1718
+ expect(client.connection.details.max_message_size).to eq(65536)
1719
+ channel.publish('event', 'x' * 65537).errback do |error|
1720
+ expect(error).to be_instance_of(Ably::Exceptions::MaxMessageSizeExceeded)
1721
+ stop_reactor
1722
+ end
1723
+ end
1724
+ end
1725
+ end
1726
+ end
1727
+ end
1406
1728
  end
1407
1729
 
1408
1730
  describe '#subscribe' do
@@ -1738,15 +2060,33 @@ describe Ably::Realtime::Channel, :event_machine do
1738
2060
  end
1739
2061
  end
1740
2062
 
1741
- it 'transitions state automatically to :attaching once the connection is re-established (#RTN15c3)' do
1742
- channel.attach do
1743
- channel.on(:suspended) do
1744
- client.connection.connect
1745
- channel.once(:attached) do
1746
- stop_reactor
2063
+ describe 'reattaching (#RTN15c3)' do
2064
+ it 'transitions state automatically to :attaching once the connection is re-established ' do
2065
+ channel.attach do
2066
+ channel.on(:suspended) do
2067
+ client.connection.connect
2068
+ channel.once(:attached) do
2069
+ stop_reactor
2070
+ end
1747
2071
  end
2072
+ client.connection.transition_state_machine :suspended
2073
+ end
2074
+ end
2075
+
2076
+ it 'sends ATTACH_RESUME flag when reattaching (RTL4j)' do
2077
+ channel.attach do
2078
+ channel.on(:suspended) do
2079
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
2080
+ next if protocol_message.action != :attach
2081
+
2082
+ expect(protocol_message.has_attach_resume_flag?).to eq(true)
2083
+ stop_reactor
2084
+ end
2085
+
2086
+ client.connection.connect
2087
+ end
2088
+ client.connection.transition_state_machine :suspended
1748
2089
  end
1749
- client.connection.transition_state_machine :suspended
1750
2090
  end
1751
2091
  end
1752
2092
  end
@@ -1936,6 +2276,68 @@ describe Ably::Realtime::Channel, :event_machine do
1936
2276
  end
1937
2277
  end
1938
2278
 
2279
+ describe '#set_options (#RTL16a)' do
2280
+ let(:modes) { %i[subscribe] }
2281
+ let(:channel_options) do
2282
+ { modes: modes }
2283
+ end
2284
+
2285
+ def self.build_flags(flags)
2286
+ flags.map { |flag| Ably::Models::ProtocolMessage::ATTACH_FLAGS_MAPPING[flag] }.reduce(:|)
2287
+ end
2288
+
2289
+ shared_examples 'an update that sends ATTACH message' do |state, flags|
2290
+ it 'sends an ATTACH message on options change' do
2291
+ attach_sent = nil
2292
+
2293
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
2294
+ if protocol_message.action == :attach && protocol_message.flags.nonzero?
2295
+ attach_sent = true
2296
+ expect(protocol_message.flags).to eq(flags)
2297
+ end
2298
+ end
2299
+
2300
+ channel.once(state) do
2301
+ channel.options = channel_options
2302
+ end
2303
+
2304
+ channel.on(:attached) do
2305
+ client.connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
2306
+ next if protocol_message.action != :attached
2307
+
2308
+ expect(attach_sent).to eq(true)
2309
+ stop_reactor
2310
+ end
2311
+ end
2312
+
2313
+ channel.attach
2314
+ end
2315
+ end
2316
+
2317
+ context 'when channel is attaching' do
2318
+ it_behaves_like 'an update that sends ATTACH message', :attaching, build_flags(%i[subscribe])
2319
+ end
2320
+
2321
+ context 'when channel is attaching' do
2322
+ it_behaves_like 'an update that sends ATTACH message', :attached, build_flags(%i[resume subscribe])
2323
+ end
2324
+
2325
+ context 'when channel is initialized' do
2326
+ it "doesn't send ATTACH message" do
2327
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
2328
+ raise "Unexpected message" if protocol_message.action == :attach
2329
+ end
2330
+
2331
+ channel.options = channel_options
2332
+ expect(channel.options.modes.map(&:to_sym)).to eq(modes)
2333
+
2334
+ EventMachine.next_tick do
2335
+ stop_reactor
2336
+ end
2337
+ end
2338
+ end
2339
+ end
2340
+
1939
2341
  context 'channel state change' do
1940
2342
  it 'emits a ChannelStateChange object' do
1941
2343
  channel.on(:attached) do |channel_state_change|
@@ -2177,11 +2579,20 @@ describe Ably::Realtime::Channel, :event_machine do
2177
2579
  end
2178
2580
 
2179
2581
  context 'and channel is attached' do
2180
- it 'reattaches immediately (#RTL13a)' do
2181
- channel.attach do
2582
+ it 'reattaches immediately (#RTL13a) with ATTACH_RESUME flag(RTL4j)' do
2583
+ resume_flag = false
2584
+
2585
+ channel.once(:attached) do
2586
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
2587
+ next if protocol_message.action != :attach
2588
+
2589
+ resume_flag = protocol_message.has_attach_resume_flag?
2590
+ end
2591
+
2182
2592
  channel.once(:attaching) do |state_change|
2183
2593
  expect(state_change.reason.code).to eql(50505)
2184
2594
  channel.once(:attached) do
2595
+ expect(resume_flag).to eq(true)
2185
2596
  stop_reactor
2186
2597
  end
2187
2598
  end
@@ -2189,25 +2600,59 @@ describe Ably::Realtime::Channel, :event_machine do
2189
2600
  detach_message = Ably::Models::ProtocolMessage.new(action: detached_action, channel: channel_name, error: { code: 50505 })
2190
2601
  client.connection.__incoming_protocol_msgbus__.publish :protocol_message, detach_message
2191
2602
  end
2603
+
2604
+ channel.attach
2192
2605
  end
2193
2606
  end
2194
2607
 
2195
2608
  context 'and channel is suspended' do
2196
- it 'reattaches immediately (#RTL13a)' do
2197
- channel.attach do
2198
- channel.once(:suspended) do
2199
- channel.once(:attaching) do |state_change|
2200
- expect(state_change.reason.code).to eql(50505)
2201
- channel.once(:attached) do
2202
- stop_reactor
2609
+ it 'reattaches immediately (#RTL13a) with ATTACH_RESUME flag(RTL4j)' do
2610
+ resume_flag = false
2611
+
2612
+ channel.once(:attached) do
2613
+ channel.transition_state_machine! :suspended
2614
+ end
2615
+
2616
+ channel.once(:suspended) do
2617
+ client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
2618
+ next if protocol_message.action != :attach
2619
+
2620
+ resume_flag = protocol_message.has_attach_resume_flag?
2621
+ end
2622
+
2623
+ channel.once(:attaching) do |state_change|
2624
+ expect(state_change.reason.code).to eql(50505)
2625
+ channel.once(:attached) do
2626
+ expect(resume_flag).to eq(true)
2627
+ stop_reactor
2628
+ end
2629
+ end
2630
+
2631
+ detach_message = Ably::Models::ProtocolMessage.new(action: detached_action, channel: channel_name, error: { code: 50505 })
2632
+ client.connection.__incoming_protocol_msgbus__.publish :protocol_message, detach_message
2633
+ end
2634
+
2635
+ channel.attach
2636
+ end
2637
+
2638
+ context 'when connection is no longer connected' do
2639
+ it 'will not attempt to reattach (#RTL13c)' do
2640
+ channel.attach do
2641
+ connection.once(:closing) do
2642
+ channel.once(:attaching) do |state_change|
2643
+ raise 'Channel should not attempt to reattach'
2203
2644
  end
2645
+
2646
+ channel.transition_state_machine! :suspended
2204
2647
  end
2205
2648
 
2206
- detach_message = Ably::Models::ProtocolMessage.new(action: detached_action, channel: channel_name, error: { code: 50505 })
2207
- client.connection.__incoming_protocol_msgbus__.publish :protocol_message, detach_message
2208
- end
2649
+ connection.once(:closed) do
2650
+ expect(channel).to be_suspended
2651
+ stop_reactor
2652
+ end
2209
2653
 
2210
- channel.transition_state_machine! :suspended
2654
+ connection.close
2655
+ end
2211
2656
  end
2212
2657
  end
2213
2658
  end
@@ -10,17 +10,56 @@ describe Ably::Realtime::Channels, :event_machine do
10
10
  end
11
11
 
12
12
  it 'returns channel object and passes the provided options' do
13
- expect(channel_with_options.options).to eql(options)
13
+ expect(channel_options).to be_a(Ably::Models::ChannelOptions)
14
+ expect(channel_options.to_h).to eq(options)
14
15
  stop_reactor
15
16
  end
16
17
  end
17
18
 
18
19
  vary_by_protocol do
20
+ let(:client_options) do
21
+ { key: api_key, environment: environment, protocol: protocol }
22
+ end
19
23
  let(:client) do
20
- auto_close Ably::Realtime::Client.new(key: api_key, environment: environment, protocol: protocol)
24
+ auto_close Ably::Realtime::Client.new(client_options)
21
25
  end
22
26
  let(:channel_name) { random_str }
23
- let(:options) { { key: 'value' } }
27
+ let(:options) do
28
+ { params: { key: 'value' } }
29
+ end
30
+
31
+ subject(:channel_options) { channel_with_options.options }
32
+
33
+ context 'when channel supposed to trigger reattachment per RTL16a (#RTS3c1)' do
34
+ it 'will raise an error' do
35
+ channel = client.channels.get(channel_name, options)
36
+
37
+ channel.on(:attached) do
38
+ expect { client.channels.get(channel_name, { modes: [] }) }.to raise_error ArgumentError, /use Channel#set_options directly/
39
+ stop_reactor
40
+ end
41
+
42
+ channel.attach
43
+ end
44
+
45
+ context 'params keys are the same but values are different' do
46
+ let(:options) do
47
+ { params: { x: '1' } }
48
+ end
49
+
50
+ it 'will raise an error' do
51
+ channel = client.channels.get(channel_name, options)
52
+
53
+ channel.on(:attached) do
54
+ expect { client.channels.get(channel_name, { params: { x: '2' } }) }.to raise_error ArgumentError, /use Channel#set_options directly/
55
+
56
+ stop_reactor
57
+ end
58
+
59
+ channel.attach
60
+ end
61
+ end
62
+ end
24
63
 
25
64
  describe 'using shortcut method #channel on the client object' do
26
65
  let(:channel) { client.channel(channel_name) }
@@ -35,26 +74,39 @@ describe Ably::Realtime::Channels, :event_machine do
35
74
  end
36
75
 
37
76
  describe 'accessing an existing channel object with different options' do
77
+ let(:client_options) { super().merge(logger: custom_logger_object) }
78
+ let(:custom_logger_object) { TestLogger.new }
38
79
  let(:new_channel_options) { { encrypted: true } }
39
- let(:original_channel) { client.channels.get(channel_name, options) }
80
+ let!(:original_channel) { client.channels.get(channel_name, options) }
40
81
 
41
82
  it 'overrides the existing channel options and returns the channel object' do
42
- expect(original_channel.options).to_not include(:encrypted)
83
+ expect(original_channel.options.to_h).to_not include(:encrypted)
43
84
  new_channel = client.channels.get(channel_name, new_channel_options)
44
85
  expect(new_channel).to be_a(Ably::Realtime::Channel)
45
86
  expect(new_channel.options[:encrypted]).to eql(true)
46
87
  stop_reactor
47
88
  end
89
+
90
+ it 'shows deprecation warning' do
91
+ client.channels.get(channel_name, new_channel_options)
92
+
93
+ warning = custom_logger_object.logs.find do |severity, message|
94
+ message.match(/Using this method to update channel options is deprecated and may be removed/)
95
+ end
96
+
97
+ expect(warning).to_not be_nil
98
+ stop_reactor
99
+ end
48
100
  end
49
101
 
50
102
  describe 'accessing an existing channel object without specifying any channel options' do
51
103
  let(:original_channel) { client.channels.get(channel_name, options) }
52
104
 
53
105
  it 'returns the existing channel without modifying the channel options' do
54
- expect(original_channel.options).to eql(options)
106
+ expect(original_channel.options.to_h).to eq(options)
55
107
  new_channel = client.channels.get(channel_name)
56
108
  expect(new_channel).to be_a(Ably::Realtime::Channel)
57
- expect(original_channel.options).to eql(options)
109
+ expect(original_channel.options.to_h).to eq(options)
58
110
  stop_reactor
59
111
  end
60
112
  end