ably 1.1.7 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +1 -1
- data/CHANGELOG.md +99 -0
- data/COPYRIGHT +1 -1
- data/README.md +2 -2
- data/SPEC.md +0 -7
- data/UPDATING.md +30 -0
- data/ably.gemspec +11 -24
- data/lib/ably/auth.rb +8 -8
- data/lib/ably/logger.rb +4 -4
- data/lib/ably/models/channel_options.rb +97 -0
- data/lib/ably/models/connection_details.rb +8 -2
- data/lib/ably/models/delta_extras.rb +29 -0
- data/lib/ably/models/device_details.rb +1 -1
- data/lib/ably/models/error_info.rb +6 -2
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
- data/lib/ably/models/message.rb +14 -3
- data/lib/ably/models/protocol_message.rb +23 -14
- data/lib/ably/models/token_details.rb +7 -2
- data/lib/ably/models/token_request.rb +1 -1
- data/lib/ably/modules/ably.rb +1 -1
- data/lib/ably/modules/channels_collection.rb +22 -2
- data/lib/ably/modules/conversions.rb +34 -0
- data/lib/ably/realtime/auth.rb +2 -2
- data/lib/ably/realtime/channel/channel_manager.rb +16 -4
- data/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
- data/lib/ably/realtime/channel/publisher.rb +3 -2
- data/lib/ably/realtime/channel.rb +54 -22
- data/lib/ably/realtime/channels.rb +1 -1
- data/lib/ably/realtime/connection/connection_manager.rb +13 -4
- data/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
- data/lib/ably/realtime/connection.rb +0 -3
- data/lib/ably/rest/channel.rb +28 -35
- data/lib/ably/rest/client.rb +23 -8
- data/lib/ably/rest/middleware/encoder.rb +1 -1
- data/lib/ably/rest/middleware/exceptions.rb +1 -1
- data/lib/ably/rest/middleware/external_exceptions.rb +1 -1
- data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +1 -1
- data/lib/ably/rest/middleware/logger.rb +1 -1
- data/lib/ably/rest/middleware/parse_json.rb +1 -1
- data/lib/ably/rest/middleware/parse_message_pack.rb +1 -1
- data/lib/ably/util/crypto.rb +1 -1
- data/lib/ably/version.rb +2 -2
- data/spec/acceptance/realtime/channel_spec.rb +458 -27
- data/spec/acceptance/realtime/channels_spec.rb +59 -7
- data/spec/acceptance/realtime/connection_failures_spec.rb +56 -1
- data/spec/acceptance/realtime/connection_spec.rb +270 -1
- data/spec/acceptance/realtime/message_spec.rb +77 -0
- data/spec/acceptance/realtime/presence_spec.rb +18 -1
- data/spec/acceptance/rest/auth_spec.rb +18 -0
- data/spec/acceptance/rest/channel_spec.rb +73 -11
- data/spec/acceptance/rest/channels_spec.rb +23 -6
- data/spec/acceptance/rest/client_spec.rb +3 -3
- data/spec/acceptance/rest/message_spec.rb +61 -3
- data/spec/lib/unit/models/channel_options_spec.rb +52 -0
- data/spec/run_parallel_tests +2 -7
- data/spec/support/test_app.rb +1 -1
- data/spec/unit/logger_spec.rb +6 -14
- data/spec/unit/models/delta_extras_spec.rb +14 -0
- data/spec/unit/models/error_info_spec.rb +17 -1
- data/spec/unit/models/message_spec.rb +38 -0
- data/spec/unit/models/protocol_message_spec.rb +77 -27
- data/spec/unit/models/token_details_spec.rb +14 -0
- data/spec/unit/realtime/channel_spec.rb +2 -1
- data/spec/unit/realtime/channels_spec.rb +53 -15
- data/spec/unit/rest/channel_spec.rb +40 -7
- data/spec/unit/rest/channels_spec.rb +81 -14
- data/spec/unit/rest/client_spec.rb +27 -0
- metadata +46 -11
@@ -1081,7 +1081,7 @@ describe Ably::Rest::Client do
|
|
1081
1081
|
end
|
1082
1082
|
|
1083
1083
|
context 'version headers', :webmock do
|
1084
|
-
[nil, 'ably-ruby/1.1.1 ruby/1.
|
1084
|
+
[nil, 'ably-ruby/1.1.1 ruby/3.1.1'].each do |agent|
|
1085
1085
|
context "with #{agent ? "custom #{agent}" : 'default'} agent" do
|
1086
1086
|
let(:client_options) { default_options.merge(key: api_key, agent: agent) }
|
1087
1087
|
|
@@ -1097,7 +1097,7 @@ describe Ably::Rest::Client do
|
|
1097
1097
|
it 'sends a protocol version and lib version header (#G4, #RSC7a, #RSC7b)' do
|
1098
1098
|
client.channels.get('foo').publish("event")
|
1099
1099
|
expect(publish_message_stub).to have_been_requested
|
1100
|
-
expect(Ably::PROTOCOL_VERSION).to eql('1.
|
1100
|
+
expect(Ably::PROTOCOL_VERSION).to eql('1.2')
|
1101
1101
|
end
|
1102
1102
|
end
|
1103
1103
|
end
|
@@ -1231,7 +1231,7 @@ describe Ably::Rest::Client do
|
|
1231
1231
|
end
|
1232
1232
|
end
|
1233
1233
|
|
1234
|
-
context 'request_id generation' do
|
1234
|
+
context 'request_id generation (#RSC7c)' do
|
1235
1235
|
context 'Timeout error' do
|
1236
1236
|
context 'with option add_request_ids: true and no fallback hosts', :webmock, :prevent_log_stubbing do
|
1237
1237
|
let(:custom_logger_object) { TestLogger.new }
|
@@ -24,6 +24,57 @@ describe Ably::Rest::Channel, 'messages' do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
context 'a single Message object (#RSL1a)' do
|
28
|
+
let(:name) { random_str }
|
29
|
+
let(:data) { random_str }
|
30
|
+
let(:message) { Ably::Models::Message.new(name: name, data: data) }
|
31
|
+
|
32
|
+
it 'publishes the message' do
|
33
|
+
channel.publish(message)
|
34
|
+
expect(channel.history.items.length).to eql(1)
|
35
|
+
message = channel.history.items.first
|
36
|
+
expect(message.name).to eq(name)
|
37
|
+
expect(message.data).to eq(data)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'an array of Message objects (#RSL1a)' do
|
42
|
+
let(:data) { random_str }
|
43
|
+
let(:message1) { Ably::Models::Message.new(name: random_str, data: data) }
|
44
|
+
let(:message2) { Ably::Models::Message.new(name: random_str, data: data) }
|
45
|
+
let(:message3) { Ably::Models::Message.new(name: random_str, data: data) }
|
46
|
+
|
47
|
+
it 'publishes three messages' do
|
48
|
+
channel.publish([message1, message2, message3])
|
49
|
+
expect(channel.history.items.length).to eql(3)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'an array of hashes (#RSL1a)' do
|
54
|
+
let(:data) { random_str }
|
55
|
+
let(:message1) { { name: random_str, data: data } }
|
56
|
+
let(:message2) { { name: random_str, data: data } }
|
57
|
+
let(:message3) { { name: random_str, data: data } }
|
58
|
+
|
59
|
+
it 'publishes three messages' do
|
60
|
+
channel.publish([message1, message2, message3])
|
61
|
+
expect(channel.history.items.length).to eql(3)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'a name with data payload (#RSL1a, #RSL1b)' do
|
66
|
+
let(:name) { random_str }
|
67
|
+
let(:data) { random_str }
|
68
|
+
|
69
|
+
it 'publishes the message' do
|
70
|
+
channel.publish(name, data)
|
71
|
+
expect(channel.history.items.length).to eql(1)
|
72
|
+
message = channel.history.items.first
|
73
|
+
expect(message.name).to eq(name)
|
74
|
+
expect(message.data).to eq(data)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
27
78
|
context 'with supported data payload content type' do
|
28
79
|
context 'JSON Object (Hash)' do
|
29
80
|
let(:data) { { 'Hash' => 'true' } }
|
@@ -153,13 +204,20 @@ describe Ably::Rest::Channel, 'messages' do
|
|
153
204
|
end
|
154
205
|
end
|
155
206
|
|
156
|
-
specify 'idempotent publishing is disabled by default with 1.1 (#TO3n)' do
|
207
|
+
specify 'idempotent publishing is disabled by default with <= 1.1 (#TO3n)' do
|
208
|
+
stub_const 'Ably::PROTOCOL_VERSION', '1.0'
|
209
|
+
client = Ably::Rest::Client.new(key: api_key, protocol: protocol)
|
210
|
+
expect(client.idempotent_rest_publishing).to be_falsey
|
211
|
+
stub_const 'Ably::PROTOCOL_VERSION', '1.1'
|
157
212
|
client = Ably::Rest::Client.new(key: api_key, protocol: protocol)
|
158
213
|
expect(client.idempotent_rest_publishing).to be_falsey
|
159
214
|
end
|
160
215
|
|
161
|
-
specify 'idempotent publishing is enabled by default with 1.2 (#TO3n)' do
|
162
|
-
stub_const 'Ably::
|
216
|
+
specify 'idempotent publishing is enabled by default with >= 1.2 (#TO3n)' do
|
217
|
+
stub_const 'Ably::PROTOCOL_VERSION', '1.2'
|
218
|
+
client = Ably::Rest::Client.new(key: api_key, protocol: protocol)
|
219
|
+
expect(client.idempotent_rest_publishing).to be_truthy
|
220
|
+
stub_const 'Ably::PROTOCOL_VERSION', '1.3'
|
163
221
|
client = Ably::Rest::Client.new(key: api_key, protocol: protocol)
|
164
222
|
expect(client.idempotent_rest_publishing).to be_truthy
|
165
223
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Ably::Models::ChannelOptions do
|
6
|
+
let(:modes) { nil }
|
7
|
+
let(:params) { {} }
|
8
|
+
let(:options) { described_class.new(modes: modes, params: params) }
|
9
|
+
|
10
|
+
describe '#modes_to_flags' do
|
11
|
+
let(:modes) { %w[publish subscribe presence_subscribe] }
|
12
|
+
|
13
|
+
subject(:protocol_message) do
|
14
|
+
Ably::Models::ProtocolMessage.new(action: Ably::Models::ProtocolMessage::ACTION.Attach, flags: options.modes_to_flags)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'converts modes to ProtocolMessage#flags correctly' do
|
18
|
+
expect(protocol_message.has_attach_publish_flag?).to eq(true)
|
19
|
+
expect(protocol_message.has_attach_subscribe_flag?).to eq(true)
|
20
|
+
expect(protocol_message.has_attach_presence_subscribe_flag?).to eq(true)
|
21
|
+
|
22
|
+
expect(protocol_message.has_attach_resume_flag?).to eq(false)
|
23
|
+
expect(protocol_message.has_attach_presence_flag?).to eq(false)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#set_modes_from_flags' do
|
28
|
+
let(:subscribe_flag) { 262144 }
|
29
|
+
|
30
|
+
it 'converts flags to ChannelOptions#modes correctly' do
|
31
|
+
result = options.set_modes_from_flags(subscribe_flag)
|
32
|
+
|
33
|
+
expect(result).to eq(options.modes)
|
34
|
+
expect(options.modes.map(&:to_sym)).to eq(%i[subscribe])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#set_params' do
|
39
|
+
let(:previous_params) { { example_attribute: 1 } }
|
40
|
+
let(:new_params) { { new_attribute: 1 } }
|
41
|
+
let(:params) { previous_params }
|
42
|
+
|
43
|
+
it 'should be able to overwrite attributes' do
|
44
|
+
expect { options.set_params(new_params) }.to \
|
45
|
+
change { options.params }.from(previous_params).to(new_params)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should be able to make params empty' do # (1)
|
49
|
+
expect { options.set_params({}) }.to change { options.params }.from(previous_params).to({})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/run_parallel_tests
CHANGED
@@ -11,13 +11,8 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
|
11
11
|
bundle exec rspec "${DIR}/unit"
|
12
12
|
unit_status=$?
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
# So it will be jumbled sadly for 1.9.*
|
17
|
-
bundle exec parallel_rspec "${DIR}/acceptance"
|
18
|
-
else
|
19
|
-
bundle exec parallel_rspec "${DIR}/acceptance" --prefix-output-with-test-env-number
|
20
|
-
fi
|
14
|
+
bundle exec parallel_rspec "${DIR}/acceptance" --prefix-output-with-test-env-number
|
15
|
+
|
21
16
|
acceptance_status=$?
|
22
17
|
|
23
18
|
if [ $unit_status -ne 0 ]; then
|
data/spec/support/test_app.rb
CHANGED
@@ -59,7 +59,7 @@ class TestApp
|
|
59
59
|
|
60
60
|
url = "#{sandbox_client.endpoint}/apps/#{app_id}"
|
61
61
|
|
62
|
-
basic_auth = Base64.
|
62
|
+
basic_auth = Base64.urlsafe_encode64(api_key).chomp
|
63
63
|
headers = { "Authorization" => "Basic #{basic_auth}" }
|
64
64
|
|
65
65
|
Faraday.delete(url, nil, headers)
|
data/spec/unit/logger_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Ably::Logger do
|
3
|
+
describe Ably::Logger, :prevent_log_stubbing do
|
4
4
|
let(:rest_client) do
|
5
5
|
instance_double('Ably::Rest::Client')
|
6
6
|
end
|
@@ -18,14 +18,10 @@ describe Ably::Logger do
|
|
18
18
|
|
19
19
|
context 'internals', :api_private do
|
20
20
|
it 'delegates to the default Logger object' do
|
21
|
-
received = false
|
22
21
|
expect(subject.logger).to be_a(::Logger)
|
23
|
-
|
24
|
-
|
25
|
-
received = true
|
26
|
-
end
|
22
|
+
expect(subject.logger).to receive(:warn).with('message')
|
23
|
+
|
27
24
|
subject.warn 'message'
|
28
|
-
expect(received).to be_truthy
|
29
25
|
end
|
30
26
|
|
31
27
|
context 'formatter' do
|
@@ -136,18 +132,14 @@ describe Ably::Logger do
|
|
136
132
|
end
|
137
133
|
|
138
134
|
it 'delegates log messages to logger', :api_private do
|
139
|
-
|
140
|
-
|
141
|
-
expect(args.concat([block ? block.call : nil]).join(',')).to match(/message/)
|
142
|
-
received = true
|
143
|
-
end
|
135
|
+
expect(custom_logger_object).to receive(:fatal).with('message')
|
136
|
+
|
144
137
|
subject.fatal 'message'
|
145
|
-
expect(received).to be_truthy
|
146
138
|
end
|
147
139
|
end
|
148
140
|
end
|
149
141
|
|
150
|
-
context 'with blocks'
|
142
|
+
context 'with blocks' do
|
151
143
|
it 'does not call the block unless the log level is met' do
|
152
144
|
log_level_blocks = []
|
153
145
|
subject.warn { log_level_blocks << :warn }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Ably::Models::DeltaExtras do
|
5
|
+
subject { described_class.new({ format: 'vcdiff', from: '1234-4567-8910-1001-1111'}) }
|
6
|
+
|
7
|
+
it 'should have `from` attribute' do
|
8
|
+
expect(subject.from).to eq('1234-4567-8910-1001-1111')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should have `format` attribute' do
|
12
|
+
expect(subject.format).to eq('vcdiff')
|
13
|
+
end
|
14
|
+
end
|
@@ -5,7 +5,7 @@ describe Ably::Models::ErrorInfo do
|
|
5
5
|
subject { Ably::Models::ErrorInfo }
|
6
6
|
|
7
7
|
context '#TI1, #TI4' do
|
8
|
-
it_behaves_like 'a model', with_simple_attributes: %w(code status_code href message) do
|
8
|
+
it_behaves_like 'a model', with_simple_attributes: %w(code status_code href message request_id cause) do
|
9
9
|
let(:model_args) { [] }
|
10
10
|
end
|
11
11
|
end
|
@@ -18,6 +18,22 @@ describe Ably::Models::ErrorInfo do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
context '#request_id #RSC7c' do
|
22
|
+
subject { Ably::Models::ErrorInfo.new('request_id' => '123-456-789-001') }
|
23
|
+
|
24
|
+
it 'should return request ID' do
|
25
|
+
expect(subject.request_id).to eql('123-456-789-001')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#cause #TI1' do
|
30
|
+
subject { Ably::Models::ErrorInfo.new('cause' => Ably::Models::ErrorInfo.new({})) }
|
31
|
+
|
32
|
+
it 'should return cause attribute' do
|
33
|
+
expect(subject.cause).to be_kind_of(Ably::Models::ErrorInfo)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
21
37
|
context 'log entries container help link #TI5' do
|
22
38
|
context 'without an error code' do
|
23
39
|
subject { Ably::Models::ErrorInfo.new('statusCode' => 401) }
|
@@ -270,6 +270,20 @@ describe Ably::Models::Message do
|
|
270
270
|
end
|
271
271
|
end
|
272
272
|
|
273
|
+
describe '#protocol_message_index (#RTL21)' do
|
274
|
+
let(:messages) { [{ name: 'test1' }, { name: 'test2' }, { name: 'test3' }] }
|
275
|
+
|
276
|
+
let(:protocol_message) do
|
277
|
+
Ably::Models::ProtocolMessage.new({ action: 1 }.merge(messages: messages))
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'should return correct protocol_message_index' do
|
281
|
+
expect(protocol_message.messages[0].protocol_message_index).to eq(0)
|
282
|
+
expect(protocol_message.messages[1].protocol_message_index).to eq(1)
|
283
|
+
expect(protocol_message.messages[2].protocol_message_index).to eq(2)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
273
287
|
context 'from REST request with embedded fields', :api_private do
|
274
288
|
let(:id) { random_str }
|
275
289
|
let(:protocol_message_id) { random_str }
|
@@ -606,4 +620,28 @@ describe Ably::Models::Message do
|
|
606
620
|
end
|
607
621
|
end
|
608
622
|
end
|
623
|
+
|
624
|
+
context '#delta_extras (TM2i)' do
|
625
|
+
let(:delta_extras) { message.delta_extras }
|
626
|
+
|
627
|
+
context 'when delta' do
|
628
|
+
let(:message) { subject.new({ extras: { delta: { from: '1234-1234-5678-9009', format: 'vcdiff' } } }) }
|
629
|
+
|
630
|
+
it 'should return vcdiff format' do
|
631
|
+
expect(delta_extras.format).to eq('vcdiff')
|
632
|
+
end
|
633
|
+
|
634
|
+
it 'should return 1234-1234-5678-9009 message id' do
|
635
|
+
expect(delta_extras.from).to eq('1234-1234-5678-9009')
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
context 'when no delta' do
|
640
|
+
let(:message) { subject.new({ extras: {} }) }
|
641
|
+
|
642
|
+
it 'should return nil' do
|
643
|
+
expect(delta_extras).to eq(nil)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
609
647
|
end
|
@@ -10,9 +10,9 @@ describe Ably::Models::ProtocolMessage do
|
|
10
10
|
subject.new({ action: 1 }.merge(options))
|
11
11
|
end
|
12
12
|
|
13
|
-
# TR4n, TR4b, TR4c, TR4d
|
13
|
+
# TR4n, TR4b, TR4c, TR4d
|
14
14
|
it_behaves_like 'a model',
|
15
|
-
with_simple_attributes: %w(id channel channel_serial connection_id
|
15
|
+
with_simple_attributes: %w(id channel channel_serial connection_id),
|
16
16
|
base_model_options: { action: 1 } do
|
17
17
|
|
18
18
|
let(:model_args) { [] }
|
@@ -176,6 +176,28 @@ describe Ably::Models::ProtocolMessage do
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
context 'when attach resumed flag' do
|
180
|
+
context 'flags is 34' do
|
181
|
+
let(:protocol_message) { new_protocol_message(flags: 34) }
|
182
|
+
|
183
|
+
it '#has_attach_resume_flag? is true' do
|
184
|
+
expect(protocol_message.has_attach_resume_flag?).to be_truthy
|
185
|
+
end
|
186
|
+
|
187
|
+
it '#has_attach_presence_flag? is false' do
|
188
|
+
expect(protocol_message.has_attach_presence_flag?).to be_falsey
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'flags is 0' do
|
193
|
+
let(:protocol_message) { new_protocol_message(flags: 0) }
|
194
|
+
|
195
|
+
it 'should raise an exception if flags is a float number' do
|
196
|
+
expect(protocol_message.has_attach_resume_flag?).to be_falsy
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
179
201
|
context 'when channel resumed and presence flags present' do
|
180
202
|
let(:protocol_message) { new_protocol_message(flags: 5) }
|
181
203
|
|
@@ -201,6 +223,24 @@ describe Ably::Models::ProtocolMessage do
|
|
201
223
|
end
|
202
224
|
end
|
203
225
|
|
226
|
+
context '#params (#RTL4k1)' do
|
227
|
+
let(:params) do
|
228
|
+
{ foo: :bar }
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'when present' do
|
232
|
+
specify do
|
233
|
+
expect(new_protocol_message({ params: params }).params).to eq(params)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context 'when empty' do
|
238
|
+
specify do
|
239
|
+
expect(new_protocol_message({}).params).to eq({})
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
204
244
|
context '#has_connection_serial?' do
|
205
245
|
context 'without connection_serial' do
|
206
246
|
let(:protocol_message) { new_protocol_message({}) }
|
@@ -308,6 +348,26 @@ describe Ably::Models::ProtocolMessage do
|
|
308
348
|
end
|
309
349
|
end
|
310
350
|
|
351
|
+
context '#messages (#RTL21)' do
|
352
|
+
let(:protocol_message) do
|
353
|
+
new_protocol_message(messages: [{ name: 'test1' }, { name: 'test2' }, { name: 'test3' }])
|
354
|
+
end
|
355
|
+
|
356
|
+
before do
|
357
|
+
message = Ably::Models::Message(name: 'test4')
|
358
|
+
message.assign_to_protocol_message(protocol_message)
|
359
|
+
protocol_message.add_message(message)
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'contains Message objects in ascending order' do
|
363
|
+
expect(protocol_message.messages.count).to eql(4)
|
364
|
+
protocol_message.messages.each_with_index do |message, index|
|
365
|
+
expect(message.protocol_message_index).to eql(index)
|
366
|
+
expect(message.name).to include('test')
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
311
371
|
context '#presence (#TR4l)' do
|
312
372
|
let(:protocol_message) { new_protocol_message(presence: [{ action: 1, data: 'test' }]) }
|
313
373
|
|
@@ -417,41 +477,27 @@ describe Ably::Models::ProtocolMessage do
|
|
417
477
|
end
|
418
478
|
end
|
419
479
|
end
|
420
|
-
|
421
|
-
context '#connection_key (#TR4e)' do
|
422
|
-
context 'existing only in #connection_details.connection_key' do
|
423
|
-
let(:protocol_message) { new_protocol_message(connectionDetails: { connectionKey: 'key' }) }
|
424
|
-
|
425
|
-
it 'is returned' do
|
426
|
-
expect(protocol_message.connection_key).to eql('key')
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
context 'existing in both #connection_key and #connection_details.connection_key' do
|
431
|
-
let(:protocol_message) { new_protocol_message(connectionKey: 'deprecated', connectionDetails: { connectionKey: 'key' }) }
|
432
|
-
|
433
|
-
it 'returns #connection_details.connection_key as #connection_key will be deprecated > 0.8' do
|
434
|
-
expect(protocol_message.connection_key).to eql('key')
|
435
|
-
end
|
436
|
-
end
|
437
|
-
end
|
438
480
|
end
|
439
481
|
|
440
482
|
context '#to_json', :api_private do
|
441
483
|
let(:json_object) { JSON.parse(model.to_json) }
|
442
|
-
let(:
|
484
|
+
let(:message1) { { 'name' => 'event1', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
485
|
+
let(:message2) { { 'name' => 'event2', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
486
|
+
let(:message3) { { 'name' => 'event3', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
443
487
|
let(:attached_action) { Ably::Models::ProtocolMessage::ACTION.Attached }
|
444
488
|
let(:message_action) { Ably::Models::ProtocolMessage::ACTION.Message }
|
445
489
|
|
446
490
|
context 'with valid data' do
|
447
|
-
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [
|
491
|
+
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [message1, message2, message3] }) }
|
448
492
|
|
449
493
|
it 'converts the attribute back to Java mixedCase notation using string keys' do
|
450
494
|
expect(json_object["channelSerial"]).to eql('unique')
|
451
495
|
end
|
452
496
|
|
453
497
|
it 'populates the messages' do
|
454
|
-
expect(json_object["messages"]
|
498
|
+
expect(json_object["messages"][0]).to include(message1)
|
499
|
+
expect(json_object["messages"][1]).to include(message2)
|
500
|
+
expect(json_object["messages"][2]).to include(message3)
|
455
501
|
end
|
456
502
|
end
|
457
503
|
|
@@ -464,7 +510,7 @@ describe Ably::Models::ProtocolMessage do
|
|
464
510
|
end
|
465
511
|
|
466
512
|
context 'is aliased by #to_s' do
|
467
|
-
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [
|
513
|
+
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [message1, message2, message3], :timestamp => as_since_epoch(Time.now) }) }
|
468
514
|
|
469
515
|
specify do
|
470
516
|
expect(json_object).to eql(JSON.parse("#{model}"))
|
@@ -473,14 +519,18 @@ describe Ably::Models::ProtocolMessage do
|
|
473
519
|
end
|
474
520
|
|
475
521
|
context '#to_msgpack', :api_private do
|
476
|
-
let(:model) { new_protocol_message({ :connectionSerial => 'unique', messages: [
|
477
|
-
let(:
|
522
|
+
let(:model) { new_protocol_message({ :connectionSerial => 'unique', messages: [message1, message2, message3] }) }
|
523
|
+
let(:message1) { { 'name' => 'event1', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
524
|
+
let(:message2) { { 'name' => 'event2', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
525
|
+
let(:message3) { { 'name' => 'event3', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
478
526
|
let(:packed) { model.to_msgpack }
|
479
527
|
let(:unpacked) { MessagePack.unpack(packed) }
|
480
528
|
|
481
529
|
it 'returns a unpackable msgpack object' do
|
482
530
|
expect(unpacked['connectionSerial']).to eq('unique')
|
483
|
-
expect(unpacked['messages'][0]['name']).to eq('
|
531
|
+
expect(unpacked['messages'][0]['name']).to eq('event1')
|
532
|
+
expect(unpacked['messages'][1]['name']).to eq('event2')
|
533
|
+
expect(unpacked['messages'][2]['name']).to eq('event3')
|
484
534
|
end
|
485
535
|
end
|
486
536
|
end
|
@@ -80,6 +80,20 @@ describe Ably::Models::TokenDetails do
|
|
80
80
|
expect(subject.expired?).to eql(false)
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
context 'with :from attribute' do
|
85
|
+
subject { Ably::Models::TokenDetails.new(expires: expire_time) }
|
86
|
+
|
87
|
+
let(:server_offset_time) { 2 * 60 * 60 } # 2 hours
|
88
|
+
|
89
|
+
it 'is false' do
|
90
|
+
expect(subject.expired?(from: (Time.now - server_offset_time))).to eql(false)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'is true' do
|
94
|
+
expect(subject.expired?(from: Time.now)).to eql(true)
|
95
|
+
end
|
96
|
+
end
|
83
97
|
end
|
84
98
|
end
|
85
99
|
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
require 'shared/protocol_msgbus_behaviour'
|
4
4
|
|
5
5
|
describe Ably::Realtime::Channel do
|
6
|
-
let(:client) {
|
6
|
+
let(:client) { Ably::Realtime::Client.new(token: 'valid') }
|
7
7
|
let(:channel_name) { 'test' }
|
8
8
|
|
9
9
|
subject do
|
@@ -71,6 +71,7 @@ describe Ably::Realtime::Channel do
|
|
71
71
|
let(:message) { instance_double('Ably::Models::Message', client_id: nil, size: 0) }
|
72
72
|
|
73
73
|
before do
|
74
|
+
allow(subject).to receive(:enqueue_messages_on_connection).and_return(message)
|
74
75
|
allow(subject).to receive(:create_message).and_return(message)
|
75
76
|
allow(subject).to receive(:attach).and_return(:true)
|
76
77
|
end
|
@@ -3,39 +3,77 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe Ably::Realtime::Channels do
|
5
5
|
let(:connection) { instance_double('Ably::Realtime::Connection', unsafe_on: true, on_resume: true) }
|
6
|
-
let(:client)
|
6
|
+
let(:client) do
|
7
|
+
instance_double('Ably::Realtime::Client', connection: connection, client_id: 'clientId', logger: double('logger').as_null_object)
|
8
|
+
end
|
7
9
|
let(:channel_name) { 'unique' }
|
8
|
-
let(:options)
|
10
|
+
let(:options) do
|
11
|
+
{ params: { bizarre: 'value' } }
|
12
|
+
end
|
9
13
|
|
10
14
|
subject { Ably::Realtime::Channels.new(client) }
|
11
15
|
|
12
16
|
context 'creating channels' do
|
13
17
|
context '#get' do
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
context "when channel doesn't exist" do
|
19
|
+
shared_examples 'creates a channel' do
|
20
|
+
it 'creates a channel (RTS3a)' do
|
21
|
+
expect(Ably::Realtime::Channel).to receive(:new).with(client, channel_name, channel_options)
|
22
|
+
subject.get(channel_name, channel_options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'hash' do
|
27
|
+
let(:channel_options) { options }
|
28
|
+
it { expect(channel_options).to be_a(Hash) }
|
29
|
+
|
30
|
+
include_examples 'creates a channel'
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'ChannelOptions object' do
|
34
|
+
let(:channel_options) { Ably::Models::ChannelOptions.new(options) }
|
35
|
+
it { expect(channel_options).to be_a(Ably::Models::ChannelOptions) }
|
36
|
+
|
37
|
+
include_examples 'creates a channel'
|
38
|
+
end
|
17
39
|
end
|
18
40
|
|
19
41
|
context 'when an existing channel exists' do
|
20
|
-
|
21
|
-
channel
|
22
|
-
|
23
|
-
|
42
|
+
shared_examples 'reuse a channel object if it exists' do
|
43
|
+
it 'will reuse a channel object if it exists (RTS3a)' do
|
44
|
+
channel = subject.get(channel_name, channel_options)
|
45
|
+
expect(channel).to be_a(Ably::Realtime::Channel)
|
46
|
+
expect(subject.get(channel_name, channel_options).object_id).to eql(channel.object_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'hash' do
|
51
|
+
let(:channel_options) { options }
|
52
|
+
it { expect(channel_options).to be_a(Hash) }
|
53
|
+
|
54
|
+
include_examples 'reuse a channel object if it exists'
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'ChannelOptions object' do
|
58
|
+
let(:channel_options) { Ably::Models::ChannelOptions.new(options) }
|
59
|
+
it { expect(channel_options).to be_a(Ably::Models::ChannelOptions) }
|
60
|
+
|
61
|
+
include_examples 'reuse a channel object if it exists'
|
24
62
|
end
|
25
63
|
|
26
|
-
it 'will update the options on the channel if provided' do
|
64
|
+
it 'will update the options on the channel if provided (RSN3c)' do
|
27
65
|
channel = subject.get(channel_name, options)
|
28
|
-
expect(channel.options).to
|
29
|
-
expect(channel.options).to_not include(:encrypted)
|
66
|
+
expect(channel.options.to_h).to eq(options)
|
67
|
+
expect(channel.options.to_h).to_not include(:encrypted)
|
30
68
|
subject.get(channel_name, encrypted: true)
|
31
|
-
expect(channel.options[:encrypted]).to
|
69
|
+
expect(channel.options[:encrypted]).to eq(true)
|
32
70
|
end
|
33
71
|
|
34
72
|
it 'will leave the options intact on the channel if not provided' do
|
35
73
|
channel = subject.get(channel_name, options)
|
36
|
-
expect(channel.options).to
|
74
|
+
expect(channel.options.to_h).to eq(options)
|
37
75
|
subject.get(channel_name)
|
38
|
-
expect(channel.options).to
|
76
|
+
expect(channel.options.to_h).to eq(options)
|
39
77
|
end
|
40
78
|
end
|
41
79
|
end
|