ably-rest 1.0.5 → 1.1.3

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 (118) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +6 -3
  3. data/CHANGELOG.md +1 -1
  4. data/LICENSE +1 -1
  5. data/README.md +26 -7
  6. data/SPEC.md +2003 -1605
  7. data/ably-rest.gemspec +4 -2
  8. data/lib/submodules/ably-ruby/.editorconfig +14 -0
  9. data/lib/submodules/ably-ruby/.travis.yml +10 -8
  10. data/lib/submodules/ably-ruby/CHANGELOG.md +97 -1
  11. data/lib/submodules/ably-ruby/LICENSE +1 -3
  12. data/lib/submodules/ably-ruby/README.md +12 -7
  13. data/lib/submodules/ably-ruby/Rakefile +32 -0
  14. data/lib/submodules/ably-ruby/SPEC.md +1277 -835
  15. data/lib/submodules/ably-ruby/ably.gemspec +17 -11
  16. data/lib/submodules/ably-ruby/lib/ably/auth.rb +34 -8
  17. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
  18. data/lib/submodules/ably-ruby/lib/ably/logger.rb +8 -2
  19. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
  20. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
  21. data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
  22. data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
  23. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
  24. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +12 -12
  25. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +6 -4
  26. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +6 -4
  27. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
  28. data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
  29. data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +2 -2
  30. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +2 -2
  31. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +2 -2
  32. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +2 -2
  33. data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
  34. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
  35. data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +1 -1
  36. data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +1 -1
  37. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +5 -5
  38. data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
  39. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +2 -2
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +27 -105
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +4 -8
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
  46. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
  47. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +9 -4
  48. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  49. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +45 -26
  50. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
  51. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +2 -2
  52. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +7 -7
  53. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +9 -9
  54. data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
  55. data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
  56. data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  57. data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
  58. data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
  59. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +54 -18
  60. data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
  61. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +171 -41
  62. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
  63. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
  64. data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
  65. data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
  66. data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  67. data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
  68. data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
  69. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +253 -49
  70. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +33 -21
  71. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +180 -62
  72. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +155 -2
  73. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +293 -13
  74. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +142 -39
  75. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +38 -36
  76. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +12 -3
  77. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +207 -173
  78. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
  79. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
  80. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +62 -51
  81. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
  82. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
  83. data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
  84. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +318 -74
  85. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
  86. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
  87. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
  88. data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
  89. data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
  90. data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +1 -9
  91. data/lib/submodules/ably-ruby/spec/spec_helper.rb +3 -1
  92. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
  93. data/lib/submodules/ably-ruby/spec/support/event_emitter_helper.rb +31 -0
  94. data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +1 -1
  95. data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
  96. data/lib/submodules/ably-ruby/spec/support/test_logger_helper.rb +42 -0
  97. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +11 -12
  98. data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
  99. data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
  100. data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
  101. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
  102. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
  103. data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
  104. data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +2 -2
  105. data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
  106. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -3
  107. data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +10 -10
  108. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +1 -1
  109. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
  110. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +2 -2
  111. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +1 -1
  112. data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
  113. data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +30 -1
  114. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
  115. data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
  116. data/lib/submodules/ably-ruby/spec/unit/util/pub_sub_spec.rb +3 -3
  117. data/spec/spec_helper.rb +1 -0
  118. metadata +51 -10
@@ -4,15 +4,63 @@ require 'shared/model_behaviour'
4
4
  describe Ably::Models::ErrorInfo do
5
5
  subject { Ably::Models::ErrorInfo }
6
6
 
7
- it_behaves_like 'a model', with_simple_attributes: %w(code status_code message) do
8
- let(:model_args) { [] }
7
+ context '#TI1, #TI4' do
8
+ it_behaves_like 'a model', with_simple_attributes: %w(code status_code href message) do
9
+ let(:model_args) { [] }
10
+ end
9
11
  end
10
12
 
11
- context '#status' do
13
+ context '#status #TI1, #TI2' do
12
14
  subject { Ably::Models::ErrorInfo.new('statusCode' => 401) }
13
15
  it 'is an alias for #status_code' do
14
16
  expect(subject.status).to eql(subject.status_code)
15
17
  expect(subject.status).to eql(401)
16
18
  end
17
19
  end
20
+
21
+ context 'log entries container help link #TI5' do
22
+ context 'without an error code' do
23
+ subject { Ably::Models::ErrorInfo.new('statusCode' => 401) }
24
+
25
+ it 'does not include the help URL' do
26
+ expect(subject.to_s.scan(/help\.ably\.io/)).to be_empty
27
+ end
28
+ end
29
+
30
+ context 'with a specified error code' do
31
+ subject { Ably::Models::ErrorInfo.new('code' => 44444) }
32
+
33
+ it 'includes https://help.ably.io/error/[CODE] in the stringified object' do
34
+ expect(subject.to_s).to include('https://help.ably.io/error/44444')
35
+ end
36
+ end
37
+
38
+ context 'with an error code and an href attribute' do
39
+ subject { Ably::Models::ErrorInfo.new('code' => 44444, 'href' => 'http://foo.bar.com/') }
40
+
41
+ it 'includes the specified href in the stringified object' do
42
+ expect(subject.to_s).to include('http://foo.bar.com/')
43
+ expect(subject.to_s).to_not include('https://help.ably.io/error/44444')
44
+ end
45
+ end
46
+
47
+ context 'with an error code and a message with the same error URL' do
48
+ subject { Ably::Models::ErrorInfo.new('message' => 'error https://help.ably.io/error/44444', 'code' => 44444) }
49
+
50
+ it 'includes the specified error URL only once in the stringified object' do
51
+ expect(subject.to_s.scan(/help.ably.io/).length).to eql(1)
52
+ end
53
+ end
54
+
55
+ context 'with an error code and a message with a different error URL' do
56
+ subject { Ably::Models::ErrorInfo.new('message' => 'error https://help.ably.io/error/123123', 'code' => 44444) }
57
+
58
+ it 'includes the specified error URL from the message and the error code URL in the stringified object' do
59
+ puts subject.to_s
60
+ expect(subject.to_s.scan(/help.ably.io/).length).to eql(2)
61
+ expect(subject.to_s.scan(%r{error/123123}).length).to eql(1)
62
+ expect(subject.to_s.scan(%r{error/44444}).length).to eql(1)
63
+ end
64
+ end
65
+ end
18
66
  end
@@ -12,8 +12,23 @@ describe Ably::Models::Message do
12
12
  let(:protocol_message_timestamp) { as_since_epoch(Time.now) }
13
13
  let(:protocol_message) { Ably::Models::ProtocolMessage.new(action: 1, timestamp: protocol_message_timestamp) }
14
14
 
15
- it_behaves_like 'a model', with_simple_attributes: %w(id name client_id data encoding) do
16
- let(:model_args) { [protocol_message: protocol_message] }
15
+ context 'serialization of the Message object (#RSL1j)' do
16
+ it_behaves_like 'a model', with_simple_attributes: %w(id name client_id data encoding) do
17
+ let(:model_args) { [protocol_message: protocol_message] }
18
+ end
19
+ end
20
+
21
+ context '#id (#RSL1j)' do
22
+ let(:id) { random_str }
23
+ let(:model) { subject.new(id: id) }
24
+
25
+ it 'exposes the #id attribute' do
26
+ expect(model.id).to eql(id)
27
+ end
28
+
29
+ specify '#as_json exposes the #id attribute' do
30
+ expect(model.as_json['id']).to eql(id)
31
+ end
17
32
  end
18
33
 
19
34
  context '#timestamp' do
@@ -547,7 +547,7 @@ describe Ably::Models::PresenceMessage do
547
547
  clone = model.shallow_clone(id: 'newId', action: 1, timestamp: protocol_message_timestamp + 1000)
548
548
  expect(clone.id).to match(/newId/)
549
549
  expect(clone.connection_id).to eql(protocol_connection_id)
550
- expect(as_since_epoch(clone.timestamp)).to eq(protocol_message_timestamp + 1000)
550
+ expect(as_since_epoch(clone.timestamp)).to be_within(5).of(protocol_message_timestamp + 1000)
551
551
  expect(clone.action).to eq(1)
552
552
  end
553
553
 
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'shared/model_behaviour'
4
+
5
+ describe Ably::Models::PushChannelSubscription do
6
+ include Ably::Modules::Conversions
7
+
8
+ subject { Ably::Models::PushChannelSubscription }
9
+
10
+ %w(channel client_id device_id).each do |string_attribute|
11
+ describe "##{string_attribute} and ##{string_attribute}=" do
12
+ let(:empty_device_details) do
13
+ if string_attribute == 'device_id'
14
+ subject.new(channel: 'default', device_id: 'default')
15
+ else
16
+ subject.new(channel: 'default', client_id: 'default')
17
+ end
18
+ end
19
+ let(:new_val) { random_str }
20
+
21
+ specify 'setter accepts a string value and getter returns the new value' do
22
+ expect(empty_device_details.public_send(string_attribute)).to eql('default')
23
+ empty_device_details.public_send("#{string_attribute}=", new_val)
24
+ expect(empty_device_details.public_send(string_attribute)).to eql(new_val)
25
+ end
26
+
27
+ specify 'setter accepts nil' do
28
+ empty_device_details.public_send("#{string_attribute}=", new_val)
29
+ expect(empty_device_details.public_send(string_attribute)).to eql(new_val)
30
+ empty_device_details.public_send("#{string_attribute}=", nil)
31
+ expect(empty_device_details.public_send(string_attribute)).to be_nil
32
+ end
33
+
34
+ specify 'rejects non string or nil values' do
35
+ expect { empty_device_details.public_send("#{string_attribute}=", {}) }.to raise_error(ArgumentError)
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'camelCase constructor attributes' do
41
+ let(:client_id) { random_str }
42
+ let(:device_details) { subject.new(channel: 'foo', 'clientId' => client_id ) }
43
+
44
+ specify 'are rubyfied and exposed as underscore case' do
45
+ expect(device_details.client_id).to eql(client_id)
46
+ end
47
+
48
+ specify 'are generated when the object is serialised to JSON' do
49
+ expect(JSON.parse(device_details.to_json)["clientId"]).to eql(client_id)
50
+ end
51
+ end
52
+
53
+ describe 'conversion method PushChannelSubscription' do
54
+ let(:channel) { 'foo' }
55
+ let(:device_id) { 'bar' }
56
+
57
+ it 'accepts a PushChannelSubscription object' do
58
+ push_channel_sub = PushChannelSubscription(channel: channel, device_id: device_id)
59
+ expect(push_channel_sub.channel).to eql('foo')
60
+ expect(push_channel_sub.client_id).to be_nil
61
+ expect(push_channel_sub.device_id).to eql('bar')
62
+ end
63
+ end
64
+
65
+ describe '#for_client_id constructor' do
66
+ context 'with a valid object' do
67
+ let(:channel) { 'foo' }
68
+ let(:client_id) { 'bob' }
69
+
70
+ it 'accepts a Hash object' do
71
+ push_channel_sub = Ably::Models::PushChannelSubscription.for_client_id(channel, client_id)
72
+ expect(push_channel_sub.channel).to eql('foo')
73
+ expect(push_channel_sub.client_id).to eql('bob')
74
+ expect(push_channel_sub.device_id).to be_nil
75
+ end
76
+ end
77
+
78
+ context 'with an invalid valid object' do
79
+ let(:subscription) { { channel: 'foo' } }
80
+
81
+ it 'accepts a Hash object' do
82
+ expect { Ably::Models::PushChannelSubscription.for_device(subscription) }.to raise_error(ArgumentError)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -31,7 +31,7 @@ describe Ably::Modules::AsyncWrapper, :api_private do
31
31
  context '#async_wrap blocking block' do
32
32
  context 'returns result' do
33
33
  let(:block) do
34
- proc do
34
+ lambda do
35
35
  sleep sleep_time
36
36
  result
37
37
  end
@@ -104,7 +104,7 @@ describe Ably::Modules::AsyncWrapper, :api_private do
104
104
 
105
105
  context 'raises an Exception' do
106
106
  let(:block) do
107
- proc do
107
+ lambda do
108
108
  sleep sleep_time
109
109
  raise RuntimeError, 'Intentional'
110
110
  end
@@ -53,7 +53,7 @@ describe Ably::Modules::Enum, :api_private do
53
53
  end
54
54
 
55
55
  it 'allows different type comparison 2' do
56
- skip 'Unless we monkeypath Symbols, the == operator is never invoked'
56
+ skip 'Unless we monkeypatch Symbols, the == operator is never invoked'
57
57
  expect([:value_zero].include?(subject.ValueZero)).to eql(true)
58
58
  end
59
59
 
@@ -38,7 +38,7 @@ describe Ably::Modules::EventEmitter do
38
38
 
39
39
  context 'with coercion', :api_private do
40
40
  let(:options) do
41
- { coerce_into: Proc.new { |event| String(event) } }
41
+ { coerce_into: lambda { |event| String(event) } }
42
42
  end
43
43
 
44
44
  it 'calls the provided proc to coerce the event name' do
@@ -244,7 +244,7 @@ describe Ably::Modules::EventEmitter do
244
244
  end
245
245
 
246
246
  context '#off' do
247
- let(:callback) { Proc.new { |msg| obj.received_message msg } }
247
+ let(:callback) { lambda { |msg| obj.received_message msg } }
248
248
 
249
249
  context 'with event specified in on handler' do
250
250
  before do
@@ -356,7 +356,7 @@ describe Ably::Modules::EventEmitter do
356
356
  end
357
357
 
358
358
  context '#unsafe_off' do
359
- let(:callback) { Proc.new { |msg| obj.received_message msg } }
359
+ let(:callback) { lambda { |msg| obj.received_message msg } }
360
360
 
361
361
  context 'with unsafe_on subscribers' do
362
362
  before do
@@ -85,7 +85,7 @@ describe Ably::Modules::StateEmitter do
85
85
  context 'without :else option block' do
86
86
  let(:block_calls) { [] }
87
87
  let(:block) do
88
- proc do
88
+ lambda do
89
89
  block_calls << Time.now
90
90
  end
91
91
  end
@@ -116,7 +116,7 @@ describe Ably::Modules::StateEmitter do
116
116
  context 'with an array of targets' do
117
117
  let(:block_calls) { [] }
118
118
  let(:block) do
119
- proc do
119
+ lambda do
120
120
  block_calls << Time.now
121
121
  end
122
122
  end
@@ -158,14 +158,14 @@ describe Ably::Modules::StateEmitter do
158
158
  context 'with :else option block', :api_private do
159
159
  let(:success_calls) { [] }
160
160
  let(:success_block) do
161
- proc do
161
+ lambda do
162
162
  success_calls << Time.now
163
163
  end
164
164
  end
165
165
 
166
166
  let(:failure_calls) { [] }
167
167
  let(:failure_block) do
168
- proc do |*args|
168
+ lambda do |*args|
169
169
  failure_calls << args
170
170
  end
171
171
  end
@@ -244,7 +244,7 @@ describe Ably::Modules::StateEmitter do
244
244
  end
245
245
 
246
246
  specify 'are passed to else blocks' do
247
- else_block = proc { |arguments| expect(arguments).to eql(arguments) }
247
+ else_block = lambda { |arguments| expect(arguments).to eql(arguments) }
248
248
  subject.once_or_if(:connected, else: else_block) do
249
249
  raise 'Success should not be called'
250
250
  end
@@ -254,11 +254,11 @@ describe Ably::Modules::StateEmitter do
254
254
 
255
255
  context 'with blocks that raise exceptions' do
256
256
  let(:success_block) do
257
- proc { raise 'Success exception' }
257
+ lambda { raise 'Success exception' }
258
258
  end
259
259
 
260
260
  let(:failure_block) do
261
- proc { raise 'Failure exception' }
261
+ lambda { raise 'Failure exception' }
262
262
  end
263
263
 
264
264
  let(:target_state) { :connected }
@@ -291,11 +291,11 @@ describe Ably::Modules::StateEmitter do
291
291
  let(:target_state) { :connected }
292
292
 
293
293
  let(:success_block) do
294
- proc { raise 'Success exception' }
294
+ lambda { raise 'Success exception' }
295
295
  end
296
296
 
297
297
  let(:failure_block) do
298
- proc { raise 'Failure exception' }
298
+ lambda { raise 'Failure exception' }
299
299
  end
300
300
 
301
301
  before do
@@ -318,7 +318,7 @@ describe Ably::Modules::StateEmitter do
318
318
  context '#once_state_changed', :api_private do
319
319
  let(:block_calls) { [] }
320
320
  let(:block) do
321
- proc do |*args|
321
+ lambda do |*args|
322
322
  block_calls << args
323
323
  end
324
324
  end
@@ -203,7 +203,7 @@ describe Ably::Realtime::Channel do
203
203
 
204
204
  context '#unsubscribe' do
205
205
  let(:callback) do
206
- Proc.new { |message| message_history[:received] += 1 }
206
+ lambda { |message| message_history[:received] += 1 }
207
207
  end
208
208
 
209
209
  before do
@@ -13,7 +13,7 @@ describe Ably::Realtime::Client do
13
13
  let(:client_options) { { key: 'appid.keyuid:keysecret', auto_connect: false } }
14
14
 
15
15
  it 'passes on the options to the initializer' do
16
- rest_client = instance_double('Ably::Rest::Client', auth: instance_double('Ably::Auth'), options: client_options)
16
+ rest_client = instance_double('Ably::Rest::Client', auth: instance_double('Ably::Auth'), options: client_options, environment: 'production', use_tls?: true, custom_tls_port: nil)
17
17
  expect(Ably::Rest::Client).to receive(:new).with(hash_including(client_options)).and_return(rest_client)
18
18
  subject
19
19
  end
@@ -28,6 +28,18 @@ describe Ably::Realtime::Client do
28
28
  end
29
29
  end
30
30
 
31
+ context 'push' do
32
+ let(:client_options) { { key: 'appid.keyuid:keysecret' } }
33
+
34
+ specify '#device is not supported and raises an exception' do
35
+ expect { subject.device }.to raise_error Ably::Exceptions::PushNotificationsNotSupported
36
+ end
37
+
38
+ specify '#push returns a Push object' do
39
+ expect(subject.push).to be_a(Ably::Realtime::Push)
40
+ end
41
+ end
42
+
31
43
  after(:all) do
32
44
  sleep 1 # let realtime library shut down any open clients
33
45
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
  require 'shared/protocol_msgbus_behaviour'
3
3
 
4
4
  describe Ably::Realtime::Connection do
5
- let(:client) { instance_double('Ably::Realtime::Client', logger: double('logger').as_null_object) }
5
+ let(:client) { instance_double('Ably::Realtime::Client', logger: double('logger').as_null_object, recover: nil, endpoint: double('endpoint', host: 'realtime.ably.io')) }
6
6
 
7
7
  subject do
8
8
  Ably::Realtime::Connection.new(client, {}).tap do |connection|
@@ -56,7 +56,7 @@ describe Ably::Realtime::Connection do
56
56
  describe '#off_resume' do
57
57
  it 'registers a callback' do
58
58
  subject.on_resume { callbacks << true }
59
- additional_proc = proc { raise 'This should not be called' }
59
+ additional_proc = lambda { raise 'This should not be called' }
60
60
  subject.off_resume(&additional_proc)
61
61
  subject.trigger_resumed
62
62
  expect(callbacks.count).to eql(1)
@@ -98,7 +98,7 @@ describe Ably::Realtime::Presence do
98
98
 
99
99
  context '#unsubscribe' do
100
100
  let(:callback) do
101
- Proc.new { |message| message_history[:received] += 1 }
101
+ lambda { |message| message_history[:received] += 1 }
102
102
  end
103
103
  before do
104
104
  subject.subscribe(enter_action, &callback)
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ably::Realtime::Channel::PushChannel do
4
+ subject { Ably::Realtime::Channel::PushChannel }
5
+
6
+ let(:channel_name) { 'unique' }
7
+ let(:client) { double('client').as_null_object }
8
+ let(:channel) { Ably::Realtime::Channel.new(client, channel_name) }
9
+
10
+ it 'is constructed with a channel' do
11
+ expect(subject.new(channel)).to be_a(Ably::Realtime::Channel::PushChannel)
12
+ end
13
+
14
+ it 'raises an exception if constructed with an invalid type' do
15
+ expect { subject.new(Hash.new) }.to raise_error(ArgumentError)
16
+ end
17
+
18
+ it 'exposes the channel as attribute #channel' do
19
+ expect(subject.new(channel).channel).to eql(channel)
20
+ end
21
+
22
+ it 'is available in the #push attribute of the channel' do
23
+ expect(channel.push).to be_a(Ably::Realtime::Channel::PushChannel)
24
+ expect(channel.push.channel).to eql(channel)
25
+ end
26
+
27
+ context 'methods not implemented as push notifications' do
28
+ subject { Ably::Realtime::Channel::PushChannel.new(channel) }
29
+
30
+ %w(subscribe_device subscribe_client_id unsubscribe_device unsubscribe_client_id get_subscriptions).each do |method_name|
31
+ specify "##{method_name} raises an unsupported exception" do
32
+ expect { subject.public_send(method_name, 'foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -2,7 +2,14 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Ably::Rest::Channel do
5
- let(:client) { instance_double('Ably::Rest::Client', encoders: [], post: instance_double('Faraday::Response', status: 201)) }
5
+ let(:client) do
6
+ instance_double(
7
+ 'Ably::Rest::Client',
8
+ encoders: [],
9
+ post: instance_double('Faraday::Response', status: 201),
10
+ idempotent_rest_publishing: false,
11
+ )
12
+ end
6
13
  let(:channel_name) { 'unique' }
7
14
 
8
15
  subject { Ably::Rest::Channel.new(client, channel_name) }
@@ -22,6 +29,19 @@ describe Ably::Rest::Channel do
22
29
  end
23
30
  end
24
31
 
32
+ context 'as frozen UTF_8 string' do
33
+ let(:channel_name) { 'unique'.freeze }
34
+ let(:encoding) { Encoding::UTF_8 }
35
+
36
+ it 'is permitted' do
37
+ expect(subject.name).to eql(channel_name)
38
+ end
39
+
40
+ it 'remains as UTF-8' do
41
+ expect(subject.name.encoding).to eql(encoding)
42
+ end
43
+ end
44
+
25
45
  context 'as SHIFT_JIS string' do
26
46
  let(:encoding) { Encoding::SHIFT_JIS }
27
47
 
@@ -74,6 +94,15 @@ describe Ably::Rest::Channel do
74
94
  end
75
95
  end
76
96
 
97
+ context 'as frozen UTF_8 string' do
98
+ let(:encoded_value) { 'unique'.freeze }
99
+ let(:encoding) { Encoding::UTF_8 }
100
+
101
+ it 'is permitted' do
102
+ expect(subject.publish(encoded_value, 'data')).to eql(true)
103
+ end
104
+ end
105
+
77
106
  context 'as SHIFT_JIS string' do
78
107
  let(:encoding) { Encoding::SHIFT_JIS }
79
108