ably-rest 0.7.5 → 0.8.1
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 +8 -8
- data/.travis.yml +2 -0
- data/README.md +41 -15
- data/SPEC.md +654 -518
- data/lib/submodules/ably-ruby/.gitignore +1 -0
- data/lib/submodules/ably-ruby/.gitmodules +3 -0
- data/lib/submodules/ably-ruby/README.md +54 -26
- data/lib/submodules/ably-ruby/SPEC.md +468 -322
- data/lib/submodules/ably-ruby/ably.gemspec +4 -2
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +185 -131
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/paginated_resource.rb +31 -44
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +1 -2
- data/lib/submodules/ably-ruby/lib/ably/models/stat.rb +67 -24
- data/lib/submodules/ably-ruby/lib/ably/models/stats_types.rb +131 -0
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +101 -0
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +108 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +3 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/http_helpers.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +3 -7
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +32 -5
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +4 -8
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +5 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +12 -1
- data/lib/submodules/ably-ruby/lib/ably/rest.rb +3 -7
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +13 -10
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +19 -20
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +14 -12
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +74 -23
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +3 -3
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +18 -18
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +5 -5
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +12 -12
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +5 -5
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +56 -13
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +8 -8
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +262 -158
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +11 -9
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +28 -21
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +30 -27
- data/lib/submodules/ably-ruby/spec/acceptance/rest/encoders_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +10 -10
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +93 -56
- data/lib/submodules/ably-ruby/spec/acceptance/rest/stats_spec.rb +50 -45
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/rspec_config.rb +3 -2
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +36 -28
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +3 -0
- data/lib/submodules/ably-ruby/spec/support/api_helper.rb +3 -3
- data/lib/submodules/ably-ruby/spec/support/markdown_spec_formatter.rb +1 -1
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +20 -33
- data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +18 -1
- data/lib/submodules/ably-ruby/spec/unit/models/paginated_resource_spec.rb +81 -72
- data/lib/submodules/ably-ruby/spec/unit/models/stats_spec.rb +289 -0
- data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +111 -0
- data/lib/submodules/ably-ruby/spec/unit/models/token_request_spec.rb +110 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +8 -8
- data/lib/submodules/ably-ruby/spec/unit/rest/rest_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +1 -1
- metadata +9 -7
- data/lib/submodules/ably-ruby/lib/ably/models/token.rb +0 -74
- data/lib/submodules/ably-ruby/spec/resources/crypto-data-128.json +0 -56
- data/lib/submodules/ably-ruby/spec/resources/crypto-data-256.json +0 -56
- data/lib/submodules/ably-ruby/spec/unit/models/stat_spec.rb +0 -113
- data/lib/submodules/ably-ruby/spec/unit/models/token_spec.rb +0 -86
|
@@ -4,7 +4,7 @@ require 'shared/protocol_msgbus_behaviour'
|
|
|
4
4
|
describe Ably::Auth do
|
|
5
5
|
let(:client) { double('client').as_null_object }
|
|
6
6
|
let(:client_id) { nil }
|
|
7
|
-
let(:options) { {
|
|
7
|
+
let(:options) { { key: 'appid.keyuid:keysecret', client_id: client_id } }
|
|
8
8
|
|
|
9
9
|
subject do
|
|
10
10
|
Ably::Auth.new(client, options)
|
|
@@ -65,4 +65,21 @@ describe Ably::Auth do
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
|
+
|
|
69
|
+
context 'defaults' do
|
|
70
|
+
let(:one_hour) { 60 * 60 }
|
|
71
|
+
let(:all_capabilities) { { "*" => ["*"] } }
|
|
72
|
+
|
|
73
|
+
it 'should default TTL to 1 hour' do
|
|
74
|
+
expect(Ably::Auth::TOKEN_DEFAULTS.fetch(:ttl)).to eql(one_hour)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should default capability to all' do
|
|
78
|
+
expect(Ably::Auth::TOKEN_DEFAULTS.fetch(:capability)).to eql(all_capabilities)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'should only have defaults for :ttl and :capability' do
|
|
82
|
+
expect(Ably::Auth::TOKEN_DEFAULTS.keys).to contain_exactly(:ttl, :capability)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
68
85
|
end
|
|
@@ -5,7 +5,7 @@ describe Ably::Models::PaginatedResource do
|
|
|
5
5
|
let(:paginated_resource_class) { Ably::Models::PaginatedResource }
|
|
6
6
|
let(:headers) { Hash.new }
|
|
7
7
|
let(:client) do
|
|
8
|
-
instance_double('Ably::Rest::Client', logger:
|
|
8
|
+
instance_double('Ably::Rest::Client', logger: Ably::Models::NilLogger.new).tap do |client|
|
|
9
9
|
allow(client).to receive(:get).and_return(http_response)
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -27,57 +27,54 @@ describe Ably::Models::PaginatedResource do
|
|
|
27
27
|
let(:first_paged_request) { paginated_resource_class.new(http_response, full_url, client, paginated_resource_options) }
|
|
28
28
|
subject { first_paged_request }
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
it 'supports alias methods for length' do
|
|
35
|
-
expect(subject.count).to eql(subject.length)
|
|
36
|
-
expect(subject.size).to eql(subject.length)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'is Enumerable' do
|
|
40
|
-
expect(subject).to be_kind_of(Enumerable)
|
|
41
|
-
end
|
|
30
|
+
context '#items' do
|
|
31
|
+
it 'returns correct length from body' do
|
|
32
|
+
expect(subject.items.length).to eql(body.length)
|
|
33
|
+
end
|
|
42
34
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
it 'is Enumerable' do
|
|
36
|
+
expect(subject.items).to be_kind_of(Enumerable)
|
|
37
|
+
end
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
expect(subject.each).to be_a(Enumerator)
|
|
39
|
+
it 'is iterable' do
|
|
40
|
+
expect(subject.items.map { |d| d }).to eql(body)
|
|
50
41
|
end
|
|
51
42
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
context '#each' do
|
|
44
|
+
it 'returns an enumerator' do
|
|
45
|
+
expect(subject.items.each).to be_a(Enumerator)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'yields each item' do
|
|
49
|
+
items = []
|
|
50
|
+
subject.items.each do |item|
|
|
51
|
+
items << item
|
|
52
|
+
end
|
|
53
|
+
expect(items).to eq(body)
|
|
56
54
|
end
|
|
57
|
-
expect(items).to eq(body)
|
|
58
55
|
end
|
|
59
|
-
end
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
it 'provides [] accessor method' do
|
|
58
|
+
expect(subject.items[0][:id]).to eql(body[0][:id])
|
|
59
|
+
expect(subject.items[1][:id]).to eql(body[1][:id])
|
|
60
|
+
expect(subject.items[2]).to be_nil
|
|
61
|
+
end
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
specify '#first gets the first item in page' do
|
|
64
|
+
expect(subject.items.first[:id]).to eql(body[0][:id])
|
|
65
|
+
end
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
specify '#last gets the last item in page' do
|
|
68
|
+
expect(subject.items.last[:id]).to eql(body[1][:id])
|
|
69
|
+
end
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
context 'with coercion', :api_private do
|
|
72
|
+
let(:paginated_resource_options) { { coerce_into: 'OpenStruct' } }
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
it 'returns coerced objects' do
|
|
75
|
+
expect(subject.items.first).to be_a(OpenStruct)
|
|
76
|
+
expect(subject.items.first.id).to eql(body.first[:id])
|
|
77
|
+
end
|
|
81
78
|
end
|
|
82
79
|
end
|
|
83
80
|
|
|
@@ -90,7 +87,7 @@ describe Ably::Models::PaginatedResource do
|
|
|
90
87
|
}
|
|
91
88
|
end
|
|
92
89
|
let(:paged_client) do
|
|
93
|
-
instance_double('Ably::Rest::Client', logger:
|
|
90
|
+
instance_double('Ably::Rest::Client', logger: Ably::Models::NilLogger.new).tap do |client|
|
|
94
91
|
allow(client).to receive(:get).and_return(http_response_page2)
|
|
95
92
|
end
|
|
96
93
|
end
|
|
@@ -116,15 +113,15 @@ describe Ably::Models::PaginatedResource do
|
|
|
116
113
|
end
|
|
117
114
|
|
|
118
115
|
it 'calls the block for each resource after retrieving the resources' do
|
|
119
|
-
expect(subject[0][:added_attribute_from_block]).to eql("id:#{body[0][:id]}")
|
|
116
|
+
expect(subject.items[0][:added_attribute_from_block]).to eql("id:#{body[0][:id]}")
|
|
120
117
|
end
|
|
121
118
|
|
|
122
119
|
it 'calls the block for each resource on second page after retrieving the resources' do
|
|
123
|
-
page_1_first_id = subject[0][:id]
|
|
124
|
-
next_page = subject.
|
|
120
|
+
page_1_first_id = subject.items[0][:id]
|
|
121
|
+
next_page = subject.next
|
|
125
122
|
|
|
126
|
-
expect(next_page[0][:added_attribute_from_block]).to eql("id:#{body_page2[0][:id]}")
|
|
127
|
-
expect(next_page[0][:id]).to_not eql(page_1_first_id)
|
|
123
|
+
expect(next_page.items[0][:added_attribute_from_block]).to eql("id:#{body_page2[0][:id]}")
|
|
124
|
+
expect(next_page.items[0][:id]).to_not eql(page_1_first_id)
|
|
128
125
|
end
|
|
129
126
|
end
|
|
130
127
|
|
|
@@ -136,17 +133,17 @@ describe Ably::Models::PaginatedResource do
|
|
|
136
133
|
paginated_resource_class.new(http_response, full_url, paged_client, async_blocking_operations: true)
|
|
137
134
|
end
|
|
138
135
|
|
|
139
|
-
context '#
|
|
136
|
+
context '#next' do
|
|
140
137
|
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
|
141
138
|
run_reactor do
|
|
142
|
-
expect(subject.
|
|
139
|
+
expect(subject.next).to be_a(Ably::Util::SafeDeferrable)
|
|
143
140
|
stop_reactor
|
|
144
141
|
end
|
|
145
142
|
end
|
|
146
143
|
|
|
147
144
|
it 'allows a success callback block to be added' do
|
|
148
145
|
run_reactor do
|
|
149
|
-
subject.
|
|
146
|
+
subject.next do |paginated_resource|
|
|
150
147
|
expect(paginated_resource).to be_a(Ably::Models::PaginatedResource)
|
|
151
148
|
stop_reactor
|
|
152
149
|
end
|
|
@@ -154,11 +151,11 @@ describe Ably::Models::PaginatedResource do
|
|
|
154
151
|
end
|
|
155
152
|
end
|
|
156
153
|
|
|
157
|
-
context '#
|
|
154
|
+
context '#first' do
|
|
158
155
|
it 'calls the errback callback when first page headers are missing' do
|
|
159
156
|
run_reactor do
|
|
160
|
-
subject.
|
|
161
|
-
deferrable = subject.
|
|
157
|
+
subject.next do |paginated_resource|
|
|
158
|
+
deferrable = subject.first
|
|
162
159
|
deferrable.errback do |error|
|
|
163
160
|
expect(error).to be_a(Ably::Exceptions::InvalidPageError)
|
|
164
161
|
stop_reactor
|
|
@@ -173,23 +170,27 @@ describe Ably::Models::PaginatedResource do
|
|
|
173
170
|
|
|
174
171
|
context 'with non paged http response' do
|
|
175
172
|
it 'is the first page' do
|
|
176
|
-
expect(subject).to
|
|
173
|
+
expect(subject).to be_first
|
|
177
174
|
end
|
|
178
175
|
|
|
179
176
|
it 'is the last page' do
|
|
180
|
-
expect(subject).to
|
|
177
|
+
expect(subject).to be_last
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'does not have next page' do
|
|
181
|
+
expect(subject).to_not have_next
|
|
181
182
|
end
|
|
182
183
|
|
|
183
184
|
it 'does not support pagination' do
|
|
184
185
|
expect(subject.supports_pagination?).to_not eql(true)
|
|
185
186
|
end
|
|
186
187
|
|
|
187
|
-
it '
|
|
188
|
-
expect
|
|
188
|
+
it 'returns nil when accessing next page' do
|
|
189
|
+
expect(subject.next).to be_nil
|
|
189
190
|
end
|
|
190
191
|
|
|
191
|
-
it '
|
|
192
|
-
expect
|
|
192
|
+
it 'returns nil when accessing first page' do
|
|
193
|
+
expect(subject.first).to be_nil
|
|
193
194
|
end
|
|
194
195
|
end
|
|
195
196
|
|
|
@@ -207,11 +208,15 @@ describe Ably::Models::PaginatedResource do
|
|
|
207
208
|
end
|
|
208
209
|
|
|
209
210
|
it 'is the first page' do
|
|
210
|
-
expect(subject).to
|
|
211
|
+
expect(subject).to be_first
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it 'has next page' do
|
|
215
|
+
expect(subject).to have_next
|
|
211
216
|
end
|
|
212
217
|
|
|
213
218
|
it 'is not the last page' do
|
|
214
|
-
expect(subject).to_not
|
|
219
|
+
expect(subject).to_not be_last
|
|
215
220
|
end
|
|
216
221
|
|
|
217
222
|
it 'supports pagination' do
|
|
@@ -236,7 +241,7 @@ describe Ably::Models::PaginatedResource do
|
|
|
236
241
|
headers: next_headers
|
|
237
242
|
})
|
|
238
243
|
end
|
|
239
|
-
let(:subject) { first_paged_request.
|
|
244
|
+
let(:subject) { first_paged_request.next }
|
|
240
245
|
|
|
241
246
|
before do
|
|
242
247
|
expect(client).to receive(:get).with("#{base_url}/history?index=1").and_return(next_http_response).once
|
|
@@ -247,39 +252,43 @@ describe Ably::Models::PaginatedResource do
|
|
|
247
252
|
end
|
|
248
253
|
|
|
249
254
|
it 'retrieves the next page of results' do
|
|
250
|
-
expect(subject.length).to eql(next_body.length)
|
|
251
|
-
expect(subject[0][:id]).to eql(next_body[0][:id])
|
|
255
|
+
expect(subject.items.length).to eql(next_body.length)
|
|
256
|
+
expect(subject.items[0][:id]).to eql(next_body[0][:id])
|
|
252
257
|
end
|
|
253
258
|
|
|
254
259
|
it 'is not the first page' do
|
|
255
|
-
expect(subject).to_not
|
|
260
|
+
expect(subject).to_not be_first
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it 'does not have a next page' do
|
|
264
|
+
expect(subject).to_not have_next
|
|
256
265
|
end
|
|
257
266
|
|
|
258
267
|
it 'is the last page' do
|
|
259
|
-
expect(subject).to
|
|
268
|
+
expect(subject).to be_last
|
|
260
269
|
end
|
|
261
270
|
|
|
262
|
-
it '
|
|
263
|
-
expect(subject).to
|
|
264
|
-
expect
|
|
271
|
+
it 'returns nil when trying to access the last page when it is the last page' do
|
|
272
|
+
expect(subject).to be_last
|
|
273
|
+
expect(subject.next).to be_nil
|
|
265
274
|
end
|
|
266
275
|
|
|
267
276
|
context 'and then first page' do
|
|
268
277
|
before do
|
|
269
278
|
expect(client).to receive(:get).with("#{base_url}/history?index=0").and_return(http_response).once
|
|
270
279
|
end
|
|
271
|
-
subject { first_paged_request.
|
|
280
|
+
subject { first_paged_request.next.first }
|
|
272
281
|
|
|
273
282
|
it 'returns a PaginatedResource' do
|
|
274
283
|
expect(subject).to be_a(paginated_resource_class)
|
|
275
284
|
end
|
|
276
285
|
|
|
277
286
|
it 'retrieves the first page of results' do
|
|
278
|
-
expect(subject.length).to eql(body.length)
|
|
287
|
+
expect(subject.items.length).to eql(body.length)
|
|
279
288
|
end
|
|
280
289
|
|
|
281
290
|
it 'is the first page' do
|
|
282
|
-
expect(subject).to
|
|
291
|
+
expect(subject).to be_first
|
|
283
292
|
end
|
|
284
293
|
end
|
|
285
294
|
end
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require 'shared/model_behaviour'
|
|
4
|
+
|
|
5
|
+
describe Ably::Models::Stats do
|
|
6
|
+
include Ably::Modules::Conversions
|
|
7
|
+
|
|
8
|
+
subject { Ably::Models::Stats }
|
|
9
|
+
|
|
10
|
+
%w(all persisted).each do |attribute|
|
|
11
|
+
context "##{attribute} stats" do
|
|
12
|
+
let(:data) do
|
|
13
|
+
{ attribute.to_sym => { messages: { count: 5 }, all: { data: 10 } } }
|
|
14
|
+
end
|
|
15
|
+
subject { Ably::Models::Stats.new(data.merge(interval_id: '2004-02')).public_send(attribute) }
|
|
16
|
+
|
|
17
|
+
it 'returns a MessageTypes object' do
|
|
18
|
+
expect(subject).to be_a(Ably::Models::Stats::MessageTypes)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns value for message counts' do
|
|
22
|
+
expect(subject.messages.count).to eql(5)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'returns value for all data transferred' do
|
|
26
|
+
expect(subject.all.data).to eql(10)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'returns zero for empty values' do
|
|
30
|
+
expect(subject.presence.count).to eql(0)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'raises an exception for unknown attributes' do
|
|
34
|
+
expect { subject.unknown }.to raise_error NoMethodError
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
%w(all presence messages).each do |type|
|
|
38
|
+
context "##{type}" do
|
|
39
|
+
it 'is a MessageCount object' do
|
|
40
|
+
expect(subject.public_send(type)).to be_a(Ably::Models::Stats::MessageCount)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
%w(inbound outbound).each do |direction|
|
|
48
|
+
context "##{direction} stats" do
|
|
49
|
+
let(:data) do
|
|
50
|
+
{
|
|
51
|
+
direction.to_sym => {
|
|
52
|
+
realtime: { messages: { count: 5 }, presence: { data: 10 } },
|
|
53
|
+
all: { messages: { count: 25 }, presence: { data: 210 } }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
subject { Ably::Models::Stats.new(data.merge(interval_id: '2004-02')).public_send(direction) }
|
|
58
|
+
|
|
59
|
+
it 'returns a MessageTraffic object' do
|
|
60
|
+
expect(subject).to be_a(Ably::Models::Stats::MessageTraffic)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'returns value for realtime message counts' do
|
|
64
|
+
expect(subject.realtime.messages.count).to eql(5)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'returns value for all presence data' do
|
|
68
|
+
expect(subject.all.presence.data).to eql(210)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'raises an exception for unknown attributes' do
|
|
72
|
+
expect { subject.unknown }.to raise_error NoMethodError
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
%w(realtime rest webhook all).each do |type|
|
|
76
|
+
context "##{type}" do
|
|
77
|
+
it 'is a MessageTypes object' do
|
|
78
|
+
expect(subject.public_send(type)).to be_a(Ably::Models::Stats::MessageTypes)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context '#connections stats' do
|
|
86
|
+
let(:data) do
|
|
87
|
+
{ connections: { tls: { opened: 5 }, all: { peak: 10 } } }
|
|
88
|
+
end
|
|
89
|
+
subject { Ably::Models::Stats.new(data.merge(interval_id: '2004-02')).connections }
|
|
90
|
+
|
|
91
|
+
it 'returns a ConnectionTypes object' do
|
|
92
|
+
expect(subject).to be_a(Ably::Models::Stats::ConnectionTypes)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'returns value for tls opened counts' do
|
|
96
|
+
expect(subject.tls.opened).to eql(5)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'returns value for all peak connections' do
|
|
100
|
+
expect(subject.all.peak).to eql(10)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'returns zero for empty values' do
|
|
104
|
+
expect(subject.all.refused).to eql(0)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'raises an exception for unknown attributes' do
|
|
108
|
+
expect { subject.unknown }.to raise_error NoMethodError
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
%w(tls plain all).each do |type|
|
|
112
|
+
context "##{type}" do
|
|
113
|
+
it 'is a ResourceCount object' do
|
|
114
|
+
expect(subject.public_send(type)).to be_a(Ably::Models::Stats::ResourceCount)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context '#channels stats' do
|
|
121
|
+
let(:data) do
|
|
122
|
+
{ channels: { opened: 5, peak: 10 } }
|
|
123
|
+
end
|
|
124
|
+
subject { Ably::Models::Stats.new(data.merge(interval_id: '2004-02')).channels }
|
|
125
|
+
|
|
126
|
+
it 'returns a ResourceCount object' do
|
|
127
|
+
expect(subject).to be_a(Ably::Models::Stats::ResourceCount)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'returns value for opened counts' do
|
|
131
|
+
expect(subject.opened).to eql(5)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'returns value for peak channels' do
|
|
135
|
+
expect(subject.peak).to eql(10)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'returns zero for empty values' do
|
|
139
|
+
expect(subject.refused).to eql(0)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'raises an exception for unknown attributes' do
|
|
143
|
+
expect { subject.unknown }.to raise_error NoMethodError
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
%w(opened peak mean min refused).each do |type|
|
|
147
|
+
context "##{type}" do
|
|
148
|
+
it 'is a Integer object' do
|
|
149
|
+
expect(subject.public_send(type)).to be_a(Integer)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
%w(api_requests token_requests).each do |request_type|
|
|
156
|
+
context "##{request_type} stats" do
|
|
157
|
+
let(:data) do
|
|
158
|
+
{
|
|
159
|
+
request_type.to_sym => { succeeded: 5, failed: 10 }
|
|
160
|
+
}
|
|
161
|
+
end
|
|
162
|
+
subject { Ably::Models::Stats.new(data.merge(interval_id: '2004-02')).public_send(request_type) }
|
|
163
|
+
|
|
164
|
+
it 'returns a RequestCount object' do
|
|
165
|
+
expect(subject).to be_a(Ably::Models::Stats::RequestCount)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'returns value for succeeded' do
|
|
169
|
+
expect(subject.succeeded).to eql(5)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it 'returns value for failed' do
|
|
173
|
+
expect(subject.failed).to eql(10)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'raises an exception for unknown attributes' do
|
|
177
|
+
expect { subject.unknown }.to raise_error NoMethodError
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
%w(succeeded failed refused).each do |type|
|
|
181
|
+
context "##{type}" do
|
|
182
|
+
it 'is a Integer object' do
|
|
183
|
+
expect(subject.public_send(type)).to be_a(Integer)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe '#interval_granularity' do
|
|
191
|
+
subject { Ably::Models::Stats.new(interval_id: '2004-02') }
|
|
192
|
+
|
|
193
|
+
it 'returns the granularity of the interval_id' do
|
|
194
|
+
expect(subject.interval_granularity).to eq(:month)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe '#interval_time' do
|
|
199
|
+
subject { Ably::Models::Stats.new(interval_id: '2004-02-01:05:06') }
|
|
200
|
+
|
|
201
|
+
it 'returns a Time object representing the start of the interval' do
|
|
202
|
+
expect(subject.interval_time.to_i).to eql(Time.new(2004, 02, 01, 05, 06, 00, '+00:00').to_i)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
context 'class methods' do
|
|
207
|
+
describe '#to_interval_id' do
|
|
208
|
+
context 'when time zone of time argument is UTC' do
|
|
209
|
+
it 'converts time 2014-02-03:05:06 with granularity :month into 2014-02' do
|
|
210
|
+
expect(subject.to_interval_id(Time.new(2014, 2, 1, 0, 0, 0, '+00:00'), :month)).to eql('2014-02')
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it 'converts time 2014-02-03:05:06 with granularity :day into 2014-02-03' do
|
|
214
|
+
expect(subject.to_interval_id(Time.new(2014, 2, 3, 0, 0, 0, '+00:00'), :day)).to eql('2014-02-03')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'converts time 2014-02-03:05:06 with granularity :hour into 2014-02-03:05' do
|
|
218
|
+
expect(subject.to_interval_id(Time.new(2014, 2, 3, 5, 0, 0, '+00:00'), :hour)).to eql('2014-02-03:05')
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it 'converts time 2014-02-03:05:06 with granularity :minute into 2014-02-03:05:06' do
|
|
222
|
+
expect(subject.to_interval_id(Time.new(2014, 2, 3, 5, 6, 0, '+00:00'), :minute)).to eql('2014-02-03:05:06')
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'fails with invalid granularity' do
|
|
226
|
+
expect { subject.to_interval_id(Time.now, :invalid) }.to raise_error KeyError
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it 'fails with invalid time' do
|
|
230
|
+
expect { subject.to_interval_id(nil, :month) }.to raise_error ArgumentError
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
context 'when time zone of time argument is +02:00' do
|
|
235
|
+
it 'converts time 2014-02-03:06 with granularity :hour into 2014-02-03:04 at UTC +00:00' do
|
|
236
|
+
expect(subject.to_interval_id(Time.new(2014, 2, 3, 6, 0, 0, '+02:00'), :hour)).to eql('2014-02-03:04')
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
describe '#from_interval_id' do
|
|
242
|
+
it 'converts a month interval_id 2014-02 into a Time object in UTC 0' do
|
|
243
|
+
expect(subject.from_interval_id('2014-02')).to eql(Time.gm(2014, 2))
|
|
244
|
+
expect(subject.from_interval_id('2014-02').utc_offset).to eql(0)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it 'converts a day interval_id 2014-02-03 into a Time object in UTC 0' do
|
|
248
|
+
expect(subject.from_interval_id('2014-02-03')).to eql(Time.gm(2014, 2, 3))
|
|
249
|
+
expect(subject.from_interval_id('2014-02-03').utc_offset).to eql(0)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it 'converts an hour interval_id 2014-02-03:05 into a Time object in UTC 0' do
|
|
253
|
+
expect(subject.from_interval_id('2014-02-03:05')).to eql(Time.gm(2014, 2, 3, 5))
|
|
254
|
+
expect(subject.from_interval_id('2014-02-03:05').utc_offset).to eql(0)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it 'converts a minute interval_id 2014-02-03:05:06 into a Time object in UTC 0' do
|
|
258
|
+
expect(subject.from_interval_id('2014-02-03:05:06')).to eql(Time.gm(2014, 2, 3, 5, 6))
|
|
259
|
+
expect(subject.from_interval_id('2014-02-03:05:06').utc_offset).to eql(0)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'fails with an invalid interval_id 14-20' do
|
|
263
|
+
expect { subject.from_interval_id('14-20') }.to raise_error ArgumentError
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
describe '#granularity_from_interval_id' do
|
|
268
|
+
it 'returns a :month interval_id for 2014-02' do
|
|
269
|
+
expect(subject.granularity_from_interval_id('2014-02')).to eq(:month)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
it 'returns a :day interval_id for 2014-02-03' do
|
|
273
|
+
expect(subject.granularity_from_interval_id('2014-02-03')).to eq(:day)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it 'returns a :hour interval_id for 2014-02-03:05' do
|
|
277
|
+
expect(subject.granularity_from_interval_id('2014-02-03:05')).to eq(:hour)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it 'returns a :minute interval_id for 2014-02-03:05:06' do
|
|
281
|
+
expect(subject.granularity_from_interval_id('2014-02-03:05:06')).to eq(:minute)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it 'fails with an invalid interval_id 14-20' do
|
|
285
|
+
expect { subject.granularity_from_interval_id('14-20') }.to raise_error ArgumentError
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|