ably 1.1.0 → 1.1.4
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.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +27 -0
- data/CHANGELOG.md +68 -2
- data/COPYRIGHT +1 -0
- data/LICENSE +172 -11
- data/MAINTAINERS.md +1 -0
- data/README.md +3 -7
- data/SPEC.md +944 -914
- data/ably.gemspec +7 -7
- data/lib/ably/auth.rb +12 -2
- data/lib/ably/exceptions.rb +2 -2
- data/lib/ably/logger.rb +7 -1
- data/lib/ably/modules/state_machine.rb +1 -1
- data/lib/ably/realtime/channel.rb +7 -11
- data/lib/ably/realtime/channel/channel_manager.rb +2 -2
- data/lib/ably/realtime/channel/channel_properties.rb +24 -0
- data/lib/ably/realtime/client.rb +12 -3
- data/lib/ably/realtime/connection.rb +31 -19
- data/lib/ably/realtime/connection/connection_manager.rb +19 -3
- data/lib/ably/realtime/connection/websocket_transport.rb +67 -1
- data/lib/ably/realtime/presence.rb +0 -14
- data/lib/ably/rest/channel.rb +25 -17
- data/lib/ably/rest/client.rb +22 -11
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/auth_spec.rb +16 -13
- data/spec/acceptance/realtime/channel_history_spec.rb +26 -20
- data/spec/acceptance/realtime/channel_spec.rb +21 -8
- data/spec/acceptance/realtime/client_spec.rb +80 -20
- data/spec/acceptance/realtime/connection_failures_spec.rb +71 -5
- data/spec/acceptance/realtime/connection_spec.rb +153 -26
- data/spec/acceptance/realtime/message_spec.rb +17 -17
- data/spec/acceptance/realtime/presence_history_spec.rb +0 -58
- data/spec/acceptance/realtime/presence_spec.rb +250 -162
- data/spec/acceptance/realtime/push_admin_spec.rb +49 -25
- data/spec/acceptance/rest/auth_spec.rb +6 -75
- data/spec/acceptance/rest/channel_spec.rb +79 -4
- data/spec/acceptance/rest/channels_spec.rb +6 -0
- data/spec/acceptance/rest/client_spec.rb +72 -12
- data/spec/acceptance/rest/message_spec.rb +8 -27
- data/spec/acceptance/rest/push_admin_spec.rb +67 -27
- data/spec/shared/client_initializer_behaviour.rb +0 -8
- data/spec/spec_helper.rb +2 -1
- data/spec/support/debug_failure_helper.rb +9 -5
- data/spec/support/serialization_helper.rb +21 -0
- data/spec/support/test_app.rb +2 -2
- data/spec/unit/modules/enum_spec.rb +1 -1
- data/spec/unit/realtime/client_spec.rb +20 -7
- data/spec/unit/realtime/connection_spec.rb +1 -1
- metadata +40 -29
- data/.travis.yml +0 -16
@@ -63,20 +63,22 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
context 'invalid recipient' do
|
66
|
+
let(:default_options) { { key: api_key, environment: environment, protocol: protocol, log_level: :fatal } }
|
67
|
+
|
66
68
|
it 'raises an error after receiving a 40x realtime response' do
|
67
|
-
skip 'validation on raw push is not enabled in realtime'
|
68
69
|
subject.publish({ invalid_recipient_details: 'foo.bar' }, basic_notification_payload).errback do |error|
|
69
|
-
expect(error.message).to match(/
|
70
|
+
expect(error.message).to match(/recipient must contain/)
|
70
71
|
stop_reactor
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
75
76
|
context 'invalid push data' do
|
77
|
+
let(:default_options) { { key: api_key, environment: environment, protocol: protocol, log_level: :fatal } }
|
78
|
+
|
76
79
|
it 'raises an error after receiving a 40x realtime response' do
|
77
|
-
skip 'validation on raw push is not enabled in realtime'
|
78
80
|
subject.publish(basic_recipient, { invalid_property_only: true }).errback do |error|
|
79
|
-
expect(error.message).to match(/
|
81
|
+
expect(error.message).to match(/Unexpected field/)
|
80
82
|
stop_reactor
|
81
83
|
end
|
82
84
|
end
|
@@ -99,31 +101,15 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
def request_body(request, protocol)
|
103
|
-
if protocol == :msgpack
|
104
|
-
MessagePack.unpack(request.body)
|
105
|
-
else
|
106
|
-
JSON.parse(request.body)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def serialize(object, protocol)
|
111
|
-
if protocol == :msgpack
|
112
|
-
MessagePack.pack(object)
|
113
|
-
else
|
114
|
-
JSON.dump(object)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
104
|
let!(:publish_stub) do
|
119
105
|
stub_request(:post, "#{client.rest_client.endpoint}/push/publish").
|
120
106
|
with do |request|
|
121
|
-
expect(
|
122
|
-
expect(
|
107
|
+
expect(deserialize_body(request.body, protocol)['recipient']['camelCase']['secondLevelCamelCase']).to eql('val')
|
108
|
+
expect(deserialize_body(request.body, protocol)['recipient']).to_not have_key('camel_case')
|
123
109
|
true
|
124
110
|
end.to_return(
|
125
111
|
:status => 201,
|
126
|
-
:body =>
|
112
|
+
:body => serialize_body({}, protocol),
|
127
113
|
:headers => { 'Content-Type' => content_type }
|
128
114
|
)
|
129
115
|
end
|
@@ -215,6 +201,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
215
201
|
let(:client_id) { random_str }
|
216
202
|
let(:fixture_count) { 6 }
|
217
203
|
|
204
|
+
before(:all) do
|
205
|
+
# As push tests often use the global scope (devices),
|
206
|
+
# we need to ensure tests cannot conflict
|
207
|
+
reload_test_app
|
208
|
+
end
|
209
|
+
|
218
210
|
before do
|
219
211
|
fixture_count.times.map do |index|
|
220
212
|
Thread.new do # Parallelise the setup
|
@@ -272,6 +264,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
272
264
|
let(:fixture_count) { 2 }
|
273
265
|
let(:client_id) { random_str }
|
274
266
|
|
267
|
+
before(:all) do
|
268
|
+
# As push tests often use the global scope (devices),
|
269
|
+
# we need to ensure tests cannot conflict
|
270
|
+
reload_test_app
|
271
|
+
end
|
272
|
+
|
275
273
|
before do
|
276
274
|
fixture_count.times.map do |index|
|
277
275
|
Thread.new do # Parallelise the setup
|
@@ -351,6 +349,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
351
349
|
}
|
352
350
|
end
|
353
351
|
|
352
|
+
before(:all) do
|
353
|
+
# As push tests often use the global scope (devices),
|
354
|
+
# we need to ensure tests cannot conflict
|
355
|
+
reload_test_app
|
356
|
+
end
|
357
|
+
|
354
358
|
after do
|
355
359
|
rest_device_registrations.remove_where client_id: client_id
|
356
360
|
end
|
@@ -386,6 +390,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
386
390
|
let(:device_id) { random_str }
|
387
391
|
let(:client_id) { random_str }
|
388
392
|
|
393
|
+
before(:all) do
|
394
|
+
# As push tests often use the global scope (devices),
|
395
|
+
# we need to ensure tests cannot conflict
|
396
|
+
reload_test_app
|
397
|
+
end
|
398
|
+
|
389
399
|
before do
|
390
400
|
rest_device_registrations.save({
|
391
401
|
id: "device-#{client_id}-0",
|
@@ -419,6 +429,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
419
429
|
let(:device_id) { random_str }
|
420
430
|
let(:client_id) { random_str }
|
421
431
|
|
432
|
+
before(:all) do
|
433
|
+
# As push tests often use the global scope (devices),
|
434
|
+
# we need to ensure tests cannot conflict
|
435
|
+
reload_test_app
|
436
|
+
end
|
437
|
+
|
422
438
|
before do
|
423
439
|
rest_device_registrations.save({
|
424
440
|
id: "device-#{client_id}-0",
|
@@ -479,6 +495,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
479
495
|
client.push.admin.channel_subscriptions
|
480
496
|
}
|
481
497
|
|
498
|
+
before(:all) do
|
499
|
+
# As push tests often use the global scope (devices),
|
500
|
+
# we need to ensure tests cannot conflict
|
501
|
+
reload_test_app
|
502
|
+
end
|
503
|
+
|
482
504
|
# Set up 2 devices with the same client_id
|
483
505
|
# and two device with the unique device_id and no client_id
|
484
506
|
before do
|
@@ -541,8 +563,10 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
541
563
|
describe '#list_channels' do
|
542
564
|
let(:fixture_count) { 6 }
|
543
565
|
|
544
|
-
before(:
|
545
|
-
|
566
|
+
before(:all) do
|
567
|
+
# As push tests often use the global scope (devices),
|
568
|
+
# we need to ensure tests cannot conflict
|
569
|
+
reload_test_app
|
546
570
|
end
|
547
571
|
|
548
572
|
before do
|
@@ -41,22 +41,10 @@ describe Ably::Auth do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def request_body_includes(request, protocol, key, val)
|
44
|
-
body =
|
45
|
-
MessagePack.unpack(request.body)
|
46
|
-
else
|
47
|
-
JSON.parse(request.body)
|
48
|
-
end
|
44
|
+
body = deserialize_body(request.body, protocol)
|
49
45
|
body[convert_to_mixed_case(key)].to_s == val.to_s
|
50
46
|
end
|
51
47
|
|
52
|
-
def serialize(object, protocol)
|
53
|
-
if protocol == :msgpack
|
54
|
-
MessagePack.pack(object)
|
55
|
-
else
|
56
|
-
JSON.dump(object)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
48
|
it 'has immutable options' do
|
61
49
|
expect { auth.options['key_name'] = 'new_name' }.to raise_error RuntimeError, /can't modify frozen.*Hash/
|
62
50
|
end
|
@@ -74,7 +62,7 @@ describe Ably::Auth do
|
|
74
62
|
|
75
63
|
it 'creates a TokenRequest automatically and sends it to Ably to obtain a token', webmock: true do
|
76
64
|
token_request_stub = stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken").
|
77
|
-
to_return(status: 201, body:
|
65
|
+
to_return(status: 201, body: serialize_body({}, protocol), headers: { 'Content-Type' => content_type })
|
78
66
|
expect(auth).to receive(:create_token_request).and_call_original
|
79
67
|
auth.request_token
|
80
68
|
|
@@ -107,7 +95,7 @@ describe Ably::Auth do
|
|
107
95
|
request_body_includes(request, protocol, token_param, coerce_if_time_value(token_param, random, multiply: 1000))
|
108
96
|
end.to_return(
|
109
97
|
:status => 201,
|
110
|
-
:body =>
|
98
|
+
:body => serialize_body(token_response, protocol),
|
111
99
|
:headers => { 'Content-Type' => content_type }
|
112
100
|
)
|
113
101
|
end
|
@@ -138,7 +126,7 @@ describe Ably::Auth do
|
|
138
126
|
request_body_includes(request, protocol, 'mac', mac)
|
139
127
|
end.to_return(
|
140
128
|
:status => 201,
|
141
|
-
:body =>
|
129
|
+
:body => serialize_body(token_response, protocol),
|
142
130
|
:headers => { 'Content-Type' => content_type })
|
143
131
|
end
|
144
132
|
|
@@ -168,7 +156,7 @@ describe Ably::Auth do
|
|
168
156
|
request_body_includes(request, protocol, 'mac', mac)
|
169
157
|
end.to_return(
|
170
158
|
:status => 201,
|
171
|
-
:body =>
|
159
|
+
:body => serialize_body(token_response, protocol),
|
172
160
|
:headers => { 'Content-Type' => content_type })
|
173
161
|
end
|
174
162
|
|
@@ -310,7 +298,7 @@ describe Ably::Auth do
|
|
310
298
|
request_body_includes(request, protocol, 'key_name', key_name)
|
311
299
|
end.to_return(
|
312
300
|
:status => 201,
|
313
|
-
:body =>
|
301
|
+
:body => serialize_body(token_response, protocol),
|
314
302
|
:headers => { 'Content-Type' => content_type }
|
315
303
|
)
|
316
304
|
end
|
@@ -1129,63 +1117,6 @@ describe Ably::Auth do
|
|
1129
1117
|
end
|
1130
1118
|
end
|
1131
1119
|
|
1132
|
-
context 'when implicit as a result of using :client_id' do
|
1133
|
-
let(:client_id) { '999' }
|
1134
|
-
let(:client) do
|
1135
|
-
Ably::Rest::Client.new(key: api_key, client_id: client_id, environment: environment, protocol: protocol)
|
1136
|
-
end
|
1137
|
-
let(:token) { 'unique-token' }
|
1138
|
-
let(:token_response) do
|
1139
|
-
{
|
1140
|
-
token: token
|
1141
|
-
}.to_json
|
1142
|
-
end
|
1143
|
-
|
1144
|
-
context 'and requests to the Ably server are mocked', :webmock do
|
1145
|
-
let!(:request_token_stub) do
|
1146
|
-
stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken").
|
1147
|
-
to_return(:status => 201, :body => token_response, :headers => { 'Content-Type' => 'application/json' })
|
1148
|
-
end
|
1149
|
-
let!(:publish_message_stub) do
|
1150
|
-
stub_request(:post, "#{client.endpoint}/channels/foo/publish").
|
1151
|
-
with(headers: { 'Authorization' => "Bearer #{encode64(token)}" }).
|
1152
|
-
to_return(status: 201, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
1153
|
-
end
|
1154
|
-
|
1155
|
-
it 'will send a token request to the server' do
|
1156
|
-
client.channel('foo').publish('event', 'data')
|
1157
|
-
expect(request_token_stub).to have_been_requested
|
1158
|
-
end
|
1159
|
-
end
|
1160
|
-
|
1161
|
-
describe 'a token is created' do
|
1162
|
-
let(:token) { client.auth.current_token_details }
|
1163
|
-
|
1164
|
-
it 'before a request is made' do
|
1165
|
-
expect(token).to be_nil
|
1166
|
-
end
|
1167
|
-
|
1168
|
-
it 'when a message is published' do
|
1169
|
-
expect(client.channel('foo').publish('event', 'data')).to be_truthy
|
1170
|
-
end
|
1171
|
-
|
1172
|
-
it 'with capability and TTL defaults (#TK2a, #TK2b)' do
|
1173
|
-
client.channel('foo').publish('event', 'data')
|
1174
|
-
|
1175
|
-
expect(token).to be_a(Ably::Models::TokenDetails)
|
1176
|
-
capability_with_str_key = { "*" => ["*"] } # Ably default is all capabilities
|
1177
|
-
capability = Hash[capability_with_str_key.keys.map(&:to_s).zip(capability_with_str_key.values)]
|
1178
|
-
expect(token.capability).to eq(capability)
|
1179
|
-
expect(token.expires.to_i).to be_within(2).of(Time.now.to_i + 60 * 60) # Ably default is 1hr
|
1180
|
-
expect(token.client_id).to eq(client_id)
|
1181
|
-
end
|
1182
|
-
|
1183
|
-
specify '#client_id contains the client_id' do
|
1184
|
-
expect(client.auth.client_id).to eql(client_id)
|
1185
|
-
end
|
1186
|
-
end
|
1187
|
-
end
|
1188
|
-
|
1189
1120
|
context 'when token expires' do
|
1190
1121
|
before do
|
1191
1122
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', 0 # allow token to be used even if about to expire
|
@@ -40,7 +40,7 @@ describe Ably::Rest::Channel do
|
|
40
40
|
|
41
41
|
it 'publishes the message without a client_id' do
|
42
42
|
expect(client).to receive(:post).
|
43
|
-
with("/channels/#{channel_name}/publish", hash_excluding(client_id: client_id)).
|
43
|
+
with("/channels/#{channel_name}/publish", hash_excluding(client_id: client_id), {}).
|
44
44
|
and_return(double('response', status: 201))
|
45
45
|
|
46
46
|
expect(channel.publish(name, data)).to eql(true)
|
@@ -82,6 +82,44 @@ describe Ably::Rest::Channel do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
context 'with a Message object' do
|
86
|
+
let(:name) { random_str }
|
87
|
+
|
88
|
+
let(:message) do
|
89
|
+
Ably::Models::Message(name: name, data: data)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'publishes the message' do
|
93
|
+
expect(client).to receive(:post).once.and_call_original
|
94
|
+
expect(channel.publish(message)).to eql(true)
|
95
|
+
expect(channel.history.items.first.name).to eql(name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with a Message object and query params' do
|
100
|
+
let(:message) do
|
101
|
+
Ably::Models::Message(name: name, data: data)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should fail to publish the message (RSL1l1)' do
|
105
|
+
expect(client).to receive(:post).once.and_call_original
|
106
|
+
expect { channel.publish(message, { _forceNack: 'true' }) }.to raise_error(Ably::Exceptions::InvalidRequest, /40099/)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with Messages and query params' do
|
111
|
+
let(:messages) do
|
112
|
+
10.times.map do |index|
|
113
|
+
{ name: index.to_s, data: { "index" => index + 10 } }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should fail to publish the message (RSL1l1)' do
|
118
|
+
expect(client).to receive(:post).once.and_call_original
|
119
|
+
expect { channel.publish(messages, { _forceNack: 'true' }) }.to raise_error(Ably::Exceptions::InvalidRequest, /40099/)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
85
123
|
context 'without adequate permissions on the channel' do
|
86
124
|
let(:capability) { { onlyChannel: ['subscribe'] } }
|
87
125
|
let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { capability: capability }) }
|
@@ -96,7 +134,7 @@ describe Ably::Rest::Channel do
|
|
96
134
|
let(:data) { random_str }
|
97
135
|
|
98
136
|
it 'publishes the message without a name attribute in the payload' do
|
99
|
-
expect(client).to receive(:post).with(anything, { "data" => data }).once.and_call_original
|
137
|
+
expect(client).to receive(:post).with(anything, { "data" => data }, {}).once.and_call_original
|
100
138
|
expect(channel.publish(nil, data)).to eql(true)
|
101
139
|
expect(channel.history.items.first.name).to be_nil
|
102
140
|
expect(channel.history.items.first.data).to eql(data)
|
@@ -107,7 +145,7 @@ describe Ably::Rest::Channel do
|
|
107
145
|
let(:name) { random_str }
|
108
146
|
|
109
147
|
it 'publishes the message without a data attribute in the payload' do
|
110
|
-
expect(client).to receive(:post).with(anything, { "name" => name }).once.and_call_original
|
148
|
+
expect(client).to receive(:post).with(anything, { "name" => name }, {}).once.and_call_original
|
111
149
|
expect(channel.publish(name)).to eql(true)
|
112
150
|
expect(channel.history.items.first.name).to eql(name)
|
113
151
|
expect(channel.history.items.first.data).to be_nil
|
@@ -118,7 +156,7 @@ describe Ably::Rest::Channel do
|
|
118
156
|
let(:name) { random_str }
|
119
157
|
|
120
158
|
it 'publishes the message without any attributes in the payload' do
|
121
|
-
expect(client).to receive(:post).with(anything, {}).once.and_call_original
|
159
|
+
expect(client).to receive(:post).with(anything, {}, {}).once.and_call_original
|
122
160
|
expect(channel.publish(nil)).to eql(true)
|
123
161
|
expect(channel.history.items.first.name).to be_nil
|
124
162
|
expect(channel.history.items.first.data).to be_nil
|
@@ -275,6 +313,43 @@ describe Ably::Rest::Channel do
|
|
275
313
|
end
|
276
314
|
end
|
277
315
|
end
|
316
|
+
|
317
|
+
context 'with a frozen message event name' do
|
318
|
+
let(:event_name) { random_str.freeze }
|
319
|
+
|
320
|
+
it 'succeeds and publishes with an implicit client_id' do
|
321
|
+
channel.publish([name: event_name])
|
322
|
+
channel.publish(event_name)
|
323
|
+
|
324
|
+
if !(RUBY_VERSION.match(/^1\./) || RUBY_VERSION.match(/^2\.[012]/))
|
325
|
+
channel.publish(+'foo-bar') # new style freeze, see https://github.com/ably/ably-ruby/issues/132
|
326
|
+
else
|
327
|
+
channel.publish('foo-bar'.freeze) # new + style not supported until Ruby 2.3
|
328
|
+
end
|
329
|
+
|
330
|
+
channel.history do |messages|
|
331
|
+
expect(messages.length).to eql(3)
|
332
|
+
expect(messages.first.name).to eql(event_name)
|
333
|
+
expect(messages[1].name).to eql(event_name)
|
334
|
+
expect(messages.last.name).to eql('foo-bar')
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
context 'with a frozen payload' do
|
340
|
+
let(:payload) { { foo: random_str.freeze }.freeze }
|
341
|
+
|
342
|
+
it 'succeeds and publishes with an implicit client_id' do
|
343
|
+
channel.publish([data: payload])
|
344
|
+
channel.publish(nil, payload)
|
345
|
+
|
346
|
+
channel.history do |messages|
|
347
|
+
expect(messages.length).to eql(2)
|
348
|
+
expect(messages.first.data).to eql(payload)
|
349
|
+
expect(messages.last.data).to eql(payload)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
278
353
|
end
|
279
354
|
|
280
355
|
describe '#history' do
|
@@ -60,5 +60,11 @@ describe Ably::Rest::Channels do
|
|
60
60
|
let(:channel_with_options) { client.channels[channel_name, options] }
|
61
61
|
it_behaves_like 'a channel'
|
62
62
|
end
|
63
|
+
|
64
|
+
describe 'using a frozen channel name' do
|
65
|
+
let(:channel) { client.channels[channel_name.freeze] }
|
66
|
+
let(:channel_with_options) { client.channels[channel_name.freeze, options] }
|
67
|
+
it_behaves_like 'a channel'
|
68
|
+
end
|
63
69
|
end
|
64
70
|
end
|
@@ -12,7 +12,7 @@ describe Ably::Rest::Client do
|
|
12
12
|
http_defaults = Ably::Rest::Client::HTTP_DEFAULTS
|
13
13
|
|
14
14
|
def encode64(text)
|
15
|
-
Base64.
|
15
|
+
Base64.urlsafe_encode64(text)
|
16
16
|
end
|
17
17
|
|
18
18
|
context '#initialize' do
|
@@ -56,14 +56,6 @@ describe Ably::Rest::Client do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
context 'with a :client_id configured' do
|
60
|
-
let(:client) { Ably::Rest::Client.new(client_options.merge(key: api_key, client_id: random_str)) }
|
61
|
-
|
62
|
-
it 'uses token authentication' do
|
63
|
-
expect(client.auth).to be_using_token_auth
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
59
|
context 'with a non string :client_id' do
|
68
60
|
let(:client) { Ably::Rest::Client.new(client_options.merge(key: api_key, client_id: 1)) }
|
69
61
|
|
@@ -144,11 +136,12 @@ describe Ably::Rest::Client do
|
|
144
136
|
let(:history_querystring) { history_params.map { |k, v| "#{k}=#{v}" }.join("&") }
|
145
137
|
|
146
138
|
context 'with basic auth', webmock: true do
|
147
|
-
let(:client_options) { default_options.merge(key: api_key) }
|
139
|
+
let(:client_options) { default_options.merge(key: api_key, client_id: client_id) }
|
148
140
|
|
149
141
|
let!(:get_message_history_stub) do
|
150
|
-
stub_request(:get, "https://#{environment}-#{Ably::Rest::Client::DOMAIN}/channels/#{channel_name}/messages?#{history_querystring}")
|
151
|
-
|
142
|
+
stub_request(:get, "https://#{environment}-#{Ably::Rest::Client::DOMAIN}/channels/#{channel_name}/messages?#{history_querystring}")
|
143
|
+
.with(headers: { 'X-Ably-ClientId' => encode64(client_id) })
|
144
|
+
.to_return(body: [], headers: { 'Content-Type' => 'application/json' })
|
152
145
|
end
|
153
146
|
|
154
147
|
it 'sends the API key in authentication part of the secure URL (the Authorization: Basic header is not used with the Faraday HTTP library by default)' do
|
@@ -1091,6 +1084,8 @@ describe Ably::Rest::Client do
|
|
1091
1084
|
|
1092
1085
|
context '#request (#RSC19*)' do
|
1093
1086
|
let(:client_options) { default_options.merge(key: api_key) }
|
1087
|
+
let(:device_id) { random_str }
|
1088
|
+
let(:endpoint) { client.endpoint }
|
1094
1089
|
|
1095
1090
|
context 'get' do
|
1096
1091
|
it 'returns an HttpPaginatedResponse object' do
|
@@ -1130,6 +1125,71 @@ describe Ably::Rest::Client do
|
|
1130
1125
|
end
|
1131
1126
|
end
|
1132
1127
|
end
|
1128
|
+
|
1129
|
+
context 'post', :webmock do
|
1130
|
+
before do
|
1131
|
+
stub_request(:delete, "#{endpoint}/push/deviceRegistrations/#{device_id}/resetUpdateToken").
|
1132
|
+
to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
it 'supports post' do
|
1136
|
+
response = client.request(:delete, "push/deviceRegistrations/#{device_id}/resetUpdateToken")
|
1137
|
+
|
1138
|
+
expect(response).to be_success
|
1139
|
+
end
|
1140
|
+
end
|
1141
|
+
|
1142
|
+
context 'delete', :webmock do
|
1143
|
+
before do
|
1144
|
+
stub_request(:delete, "#{endpoint}/push/channelSubscriptions?deviceId=#{device_id}").
|
1145
|
+
to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
it 'supports delete' do
|
1149
|
+
response = client.request(:delete, "/push/channelSubscriptions", { deviceId: device_id})
|
1150
|
+
|
1151
|
+
expect(response).to be_success
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
context 'patch', :webmock do
|
1156
|
+
let(:body_params) { { 'metadata' => { 'key' => 'value' } } }
|
1157
|
+
|
1158
|
+
before do
|
1159
|
+
stub_request(:patch, "#{endpoint}/push/deviceRegistrations/#{device_id}")
|
1160
|
+
.with(body: serialize_body(body_params, protocol))
|
1161
|
+
.to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
it 'supports patch' do
|
1165
|
+
response = client.request(:patch, "/push/deviceRegistrations/#{device_id}", {}, body_params)
|
1166
|
+
|
1167
|
+
expect(response).to be_success
|
1168
|
+
end
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
context 'put', :webmock do
|
1172
|
+
let(:body_params) do
|
1173
|
+
{
|
1174
|
+
'id' => random_str,
|
1175
|
+
'platform' => 'ios',
|
1176
|
+
'formFactor' => 'phone',
|
1177
|
+
'metadata' => { 'key' => 'value' }
|
1178
|
+
}
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
before do
|
1182
|
+
stub_request(:put, "#{endpoint}/push/deviceRegistrations/#{device_id}")
|
1183
|
+
.with(body: serialize_body(body_params, protocol))
|
1184
|
+
.to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
it 'supports put' do
|
1188
|
+
response = client.request(:put, "/push/deviceRegistrations/#{device_id}", {}, body_params)
|
1189
|
+
|
1190
|
+
expect(response).to be_success
|
1191
|
+
end
|
1192
|
+
end
|
1133
1193
|
end
|
1134
1194
|
|
1135
1195
|
context 'request_id generation' do
|