ably 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,59 +2,168 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Ably::Rest::Client, '#stats' do
5
+ include Ably::Modules::Conversions
6
+
7
+ LAST_YEAR = Time.now.year - 1
8
+ LAST_INTERVAL = Time.new(LAST_YEAR, 2, 3, 15, 5, 0) # 3rd Feb 20(x) 16:05:00
9
+
10
+ STATS_FIXTURES = [
11
+ {
12
+ intervalId: Ably::Models::Stat.to_interval_id(LAST_INTERVAL - 120, :minute),
13
+ inbound: { realtime: { messages: { count: 50, data: 5000 } } },
14
+ outbound: { realtime: { messages: { count: 20, data: 2000 } } }
15
+ },
16
+ {
17
+ intervalId: Ably::Models::Stat.to_interval_id(LAST_INTERVAL - 60, :minute),
18
+ inbound: { realtime: { messages: { count: 60, data: 6000 } } },
19
+ outbound: { realtime: { messages: { count: 10, data: 1000 } } }
20
+ },
21
+ {
22
+ intervalId: Ably::Models::Stat.to_interval_id(LAST_INTERVAL, :minute),
23
+ inbound: { realtime: { messages: { count: 70, data: 7000 } } },
24
+ outbound: { realtime: { messages: { count: 40, data: 4000 } } },
25
+ persisted: { presence: { count: 20, data: 2000 } },
26
+ connections: { tls: { peak: 20, opened: 10 } },
27
+ channels: { peak: 50, opened: 30 },
28
+ apiRequests: { succeeded: 50, failed: 10 },
29
+ tokenRequests: { succeeded: 60, failed: 20 },
30
+ }
31
+ ]
32
+
5
33
  before(:context) do
6
- WebMock.disable! # ensure previous test's WebMock does not have side effects
7
- reload_test_app
34
+ reload_test_app # ensure no previous stats interfere
35
+ TestApp.instance.create_test_stats(STATS_FIXTURES)
8
36
  end
9
37
 
10
- before(:context) do
11
- client = Ably::Rest::Client.new(api_key: api_key, environment: environment)
38
+ vary_by_protocol do
39
+ let(:client) { Ably::Rest::Client.new(api_key: api_key, environment: environment, protocol: protocol) }
12
40
 
13
- number_of_channels = 3
14
- number_of_messages_per_channel = 5
41
+ describe 'fetching application stats' do
42
+ context 'by minute' do
43
+ let(:first_inbound_realtime_count) { STATS_FIXTURES.first[:inbound][:realtime][:messages][:count] }
44
+ let(:last_inbound_realtime_count) { STATS_FIXTURES.last[:inbound][:realtime][:messages][:count] }
15
45
 
16
- # Wait until the start of the next minute according to the service
17
- # time because stats are created in 1 minute intervals
18
- service_time = client.time
19
- stats_setup_at = (service_time.to_i / 60 + 1) * 60
20
- sleep_time = stats_setup_at - Time.now.to_i
46
+ context 'with :from set to last interval and :limit set to 1' do
47
+ let(:subject) { client.stats(start: as_since_epoch(LAST_INTERVAL), by: :minute, limit: 1) }
48
+ let(:stat) { subject.first}
21
49
 
22
- if sleep_time > 30
23
- stats_setup_at -= 60 # there is enough time to generate the stats in this minute interval
24
- elsif sleep_time > 0
25
- sleep sleep_time
26
- end
50
+ it 'retrieves only one stat' do
51
+ expect(subject.count).to eql(1)
52
+ end
27
53
 
28
- number_of_channels.times do |i|
29
- channel = client.channel("stats-#{i}")
54
+ it 'returns all aggregated message data' do
55
+ expect(stat.all[:messages][:count]).to eql(70 + 40) # inbound + outbound
56
+ expect(stat.all[:messages][:data]).to eql(7000 + 4000) # inbound + outbound
57
+ end
30
58
 
31
- number_of_messages_per_channel.times do |j|
32
- channel.publish("event-#{j}", "data-#{j}") || raise("Unable to publish message")
33
- end
34
- end
59
+ it 'returns inbound realtime all data' do
60
+ expect(stat.inbound[:realtime][:all][:count]).to eql(70)
61
+ expect(stat.inbound[:realtime][:all][:data]).to eql(7000)
62
+ end
35
63
 
36
- # wait for stats to be persisted
37
- sleep 10
64
+ it 'returns inbound realtime message data' do
65
+ expect(stat.inbound[:realtime][:messages][:count]).to eql(70)
66
+ expect(stat.inbound[:realtime][:messages][:data]).to eql(7000)
67
+ end
38
68
 
39
- @stats_setup_at = stats_setup_at
40
- @messages_published_count = number_of_channels * number_of_messages_per_channel
41
- end
69
+ it 'returns outbound realtime all data' do
70
+ expect(stat.outbound[:realtime][:all][:count]).to eql(40)
71
+ expect(stat.outbound[:realtime][:all][:data]).to eql(4000)
72
+ end
42
73
 
43
- vary_by_protocol do
44
- describe 'fetching application stats' do
45
- [:minute, :hour, :day, :month].each do |interval|
46
- context "by #{interval}" do
47
- let(:client) { Ably::Rest::Client.new(api_key: api_key, environment: environment, protocol: protocol) }
74
+ it 'returns persisted presence all data' do
75
+ expect(stat.persisted[:all][:count]).to eql(20)
76
+ expect(stat.persisted[:all][:data]).to eql(2000)
77
+ end
78
+
79
+ it 'returns connections all data' do
80
+ expect(stat.connections[:tls][:peak]).to eql(20)
81
+ expect(stat.connections[:tls][:opened]).to eql(10)
82
+ end
83
+
84
+ it 'returns channels all data' do
85
+ expect(stat.channels[:peak]).to eql(50)
86
+ expect(stat.channels[:opened]).to eql(30)
87
+ end
88
+
89
+ it 'returns api_requests data' do
90
+ expect(stat.api_requests[:succeeded]).to eql(50)
91
+ expect(stat.api_requests[:failed]).to eql(10)
92
+ end
48
93
 
49
- it 'should return all the stats for the application' do
50
- stats = client.stats(start: @stats_setup_at * 1000, by: interval.to_s, direction: 'forwards')
94
+ it 'returns token_requests data' do
95
+ expect(stat.token_requests[:succeeded]).to eql(60)
96
+ expect(stat.token_requests[:failed]).to eql(20)
97
+ end
98
+
99
+ it 'returns stat objects with #interval_granularity equal to :minute' do
100
+ expect(stat.interval_granularity).to eq(:minute)
101
+ end
102
+
103
+ it 'returns stat objects with #interval_id matching :start' do
104
+ expect(stat.interval_id).to eql(LAST_INTERVAL.strftime('%Y-%m-%d:%H:%M'))
105
+ end
106
+
107
+ it 'returns stat objects with #interval_time matching :start Time' do
108
+ expect(stat.interval_time.to_i).to eql(LAST_INTERVAL.to_i)
109
+ end
110
+ end
111
+
112
+ context 'with :start set to first interval, :limit set to 1 and direction :forwards' do
113
+ let(:first_interval) { LAST_INTERVAL - 120 }
114
+ let(:subject) { client.stats(start: as_since_epoch(first_interval), by: :minute, direction: :forwards, limit: 1) }
115
+ let(:stat) { subject.first}
116
+
117
+ it 'returns the first interval stats as stats are provided forwards from :start' do
118
+ expect(stat.inbound[:realtime][:all][:count]).to eql(first_inbound_realtime_count)
119
+ end
120
+
121
+ it 'returns 3 pages of stats' do
122
+ expect(subject).to be_first_page
123
+ expect(subject).to_not be_last_page
124
+ page3 = subject.next_page.next_page
125
+ expect(page3).to be_last_page
126
+ expect(page3.first.inbound[:realtime][:all][:count]).to eql(last_inbound_realtime_count)
127
+ end
128
+ end
129
+
130
+ context 'with :end set to last interval, :limit set to 1 and direction :backwards' do
131
+ let(:subject) { client.stats(:end => as_since_epoch(LAST_INTERVAL), by: :minute, direction: :backwards, limit: 1) }
132
+ let(:stat) { subject.first}
133
+
134
+ it 'returns the 3rd interval stats first as stats are provided backwards from :end' do
135
+ expect(stat.inbound[:realtime][:all][:count]).to eql(last_inbound_realtime_count)
136
+ end
137
+
138
+ it 'returns 3 pages of stats' do
139
+ expect(subject).to be_first_page
140
+ expect(subject).to_not be_last_page
141
+ page3 = subject.next_page.next_page
142
+ expect(page3.first.inbound[:realtime][:all][:count]).to eql(first_inbound_realtime_count)
143
+ end
144
+ end
145
+ end
146
+
147
+ [:hour, :day, :month].each do |interval|
148
+ context "by #{interval}" do
149
+ let(:subject) { client.stats(start: as_since_epoch(LAST_INTERVAL), by: interval, direction: 'forwards', limit: 1) }
150
+ let(:stat) { subject.first }
151
+ let(:aggregate_messages_count) do
152
+ STATS_FIXTURES.inject(0) do |sum, fixture|
153
+ sum + fixture[:inbound][:realtime][:messages][:count] + fixture[:outbound][:realtime][:messages][:count]
154
+ end
155
+ end
156
+ let(:aggregate_messages_data) do
157
+ STATS_FIXTURES.inject(0) do |sum, fixture|
158
+ sum + fixture[:inbound][:realtime][:messages][:data] + fixture[:outbound][:realtime][:messages][:data]
159
+ end
160
+ end
51
161
 
52
- expect(stats.size).to eql(1)
53
- stat = stats.first
162
+ it 'should aggregate the stats for that period' do
163
+ expect(subject.count).to eql(1)
54
164
 
55
- expect(@messages_published_count).to be_a(Numeric)
56
- expect(stat[:inbound][:all][:messages][:count]).to eql(@messages_published_count)
57
- expect(stat[:inbound][:rest][:messages][:count]).to eql(@messages_published_count)
165
+ expect(stat.all[:messages][:count]).to eql(aggregate_messages_count)
166
+ expect(stat.all[:messages][:data]).to eql(aggregate_messages_data)
58
167
  end
59
168
  end
60
169
  end
@@ -26,6 +26,7 @@ module ApiHelper
26
26
  end
27
27
 
28
28
  def reload_test_app
29
+ WebMock.disable!
29
30
  TestApp.reload
30
31
  end
31
32
 
@@ -43,7 +44,7 @@ RSpec.configure do |config|
43
44
 
44
45
  config.after(:suite) do
45
46
  WebMock.disable!
46
- TestApp.instance.delete if TestApp.instance_variable_get('@singleton__instance__')
47
+ TestApp.instance.delete
47
48
  end
48
49
  end
49
50
 
@@ -8,7 +8,7 @@ RSpec.configure do |config|
8
8
  next if example.metadata[:webmock] # new app is not needed for a mocked test
9
9
 
10
10
  if example.exception && ENV['RSPEC_RETRY']
11
- TestApp.reload
11
+ reload_test_app
12
12
  puts "** Test app reloaded before next retry **"
13
13
  end
14
14
  end
@@ -27,7 +27,10 @@ class TestApp
27
27
  # If an app has already been created and we need a new app, create a new test app
28
28
  # This is sometimes needed when a test needs to be isolated from any other tests
29
29
  def self.reload
30
- instance.create_test_app if instance_variable_get('@singleton__instance__')
30
+ if instance_variable_get('@singleton__instance__')
31
+ instance.delete
32
+ instance.create_test_app
33
+ end
31
34
  end
32
35
 
33
36
  include Singleton
@@ -37,7 +40,7 @@ class TestApp
37
40
  end
38
41
 
39
42
  def app_id
40
- @attributes["id"]
43
+ @attributes["appId"]
41
44
  end
42
45
 
43
46
  def key
@@ -65,6 +68,8 @@ class TestApp
65
68
  end
66
69
 
67
70
  def delete
71
+ return unless TestApp.instance_variable_get('@singleton__instance__')
72
+
68
73
  url = "#{sandbox_client.endpoint}/apps/#{app_id}"
69
74
 
70
75
  basic_auth = Base64.encode64(api_key).chomp
@@ -85,9 +90,7 @@ class TestApp
85
90
  'Content-Type' => 'application/json'
86
91
  }
87
92
 
88
- response = Faraday.post(url, APP_SPEC.to_json, headers)
89
-
90
- @attributes = JSON.parse(response.body)
93
+ @attributes = JSON.parse(Faraday.post(url, APP_SPEC.to_json, headers).body)
91
94
  end
92
95
 
93
96
  def host
@@ -98,6 +101,11 @@ class TestApp
98
101
  host.gsub(/rest/, 'realtime')
99
102
  end
100
103
 
104
+ def create_test_stats(stats)
105
+ client = Ably::Rest::Client.new(api_key: api_key, environment: environment)
106
+ client.post('/stats', stats)
107
+ end
108
+
101
109
  private
102
110
  def sandbox_client
103
111
  @sandbox_client ||= Ably::Rest::Client.new(api_key: 'app.key:secret', tls: true, environment: environment)
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'shared/model_behaviour'
4
+
5
+ describe Ably::Models::Stat do
6
+ include Ably::Modules::Conversions
7
+
8
+ subject { Ably::Models::Stat }
9
+
10
+ it_behaves_like 'a model', with_simple_attributes: %w(interval_id all inbound outbound persisted connections channels api_requests token_requests) do
11
+ let(:model_args) { [] }
12
+ end
13
+
14
+ describe '#interval_granularity' do
15
+ subject { Ably::Models::Stat.new(interval_id: '2004-02') }
16
+
17
+ it 'returns the granularity of the interval_id' do
18
+ expect(subject.interval_granularity).to eq(:month)
19
+ end
20
+ end
21
+
22
+ describe '#interval_time' do
23
+ subject { Ably::Models::Stat.new(interval_id: '2004-02-01:05:06') }
24
+
25
+ it 'returns a Time object representing the start of the interval' do
26
+ expect(subject.interval_time.to_i).to eql(Time.new(2004, 02, 01, 05, 06, 00, '+00:00').to_i)
27
+ end
28
+ end
29
+
30
+ context 'class methods' do
31
+ describe '#to_interval_id' do
32
+ context 'when time zone of time argument is UTC' do
33
+ it 'converts time 2014-02-03:05:06 with granularity :month into 2014-02' do
34
+ expect(subject.to_interval_id(Time.new(2014, 2, 1, 0, 0, 0, '+00:00'), :month)).to eql('2014-02')
35
+ end
36
+
37
+ it 'converts time 2014-02-03:05:06 with granularity :day into 2014-02-03' do
38
+ expect(subject.to_interval_id(Time.new(2014, 2, 3, 0, 0, 0, '+00:00'), :day)).to eql('2014-02-03')
39
+ end
40
+
41
+ it 'converts time 2014-02-03:05:06 with granularity :hour into 2014-02-03:05' do
42
+ expect(subject.to_interval_id(Time.new(2014, 2, 3, 5, 0, 0, '+00:00'), :hour)).to eql('2014-02-03:05')
43
+ end
44
+
45
+ it 'converts time 2014-02-03:05:06 with granularity :minute into 2014-02-03:05:06' do
46
+ expect(subject.to_interval_id(Time.new(2014, 2, 3, 5, 6, 0, '+00:00'), :minute)).to eql('2014-02-03:05:06')
47
+ end
48
+
49
+ it 'fails with invalid granularity' do
50
+ expect { subject.to_interval_id(Time.now, :invalid) }.to raise_error KeyError
51
+ end
52
+
53
+ it 'fails with invalid time' do
54
+ expect { subject.to_interval_id(nil, :month) }.to raise_error ArgumentError
55
+ end
56
+ end
57
+
58
+ context 'when time zone of time argument is +02:00' do
59
+ it 'converts time 2014-02-03:06 with granularity :hour into 2014-02-03:04 at UTC +00:00' do
60
+ expect(subject.to_interval_id(Time.new(2014, 2, 3, 6, 0, 0, '+02:00'), :hour)).to eql('2014-02-03:04')
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#from_interval_id' do
66
+ it 'converts a month interval_id 2014-02 into a Time object in UTC 0' do
67
+ expect(subject.from_interval_id('2014-02')).to eql(Time.new(2014, 2))
68
+ expect(subject.from_interval_id('2014-02').utc_offset).to eql(0)
69
+ end
70
+
71
+ it 'converts a day interval_id 2014-02-03 into a Time object in UTC 0' do
72
+ expect(subject.from_interval_id('2014-02-03')).to eql(Time.new(2014, 2, 3))
73
+ expect(subject.from_interval_id('2014-02-03').utc_offset).to eql(0)
74
+ end
75
+
76
+ it 'converts an hour interval_id 2014-02-03:05 into a Time object in UTC 0' do
77
+ expect(subject.from_interval_id('2014-02-03:05')).to eql(Time.new(2014, 2, 3, 5))
78
+ expect(subject.from_interval_id('2014-02-03:05').utc_offset).to eql(0)
79
+ end
80
+
81
+ it 'converts a minute interval_id 2014-02-03:05:06 into a Time object in UTC 0' do
82
+ expect(subject.from_interval_id('2014-02-03:05:06')).to eql(Time.new(2014, 2, 3, 5, 6))
83
+ expect(subject.from_interval_id('2014-02-03:05:06').utc_offset).to eql(0)
84
+ end
85
+
86
+ it 'fails with an invalid interval_id 14-20' do
87
+ expect { subject.from_interval_id('14-20') }.to raise_error ArgumentError
88
+ end
89
+ end
90
+
91
+ describe '#granularity_from_interval_id' do
92
+ it 'returns a :month interval_id for 2014-02' do
93
+ expect(subject.granularity_from_interval_id('2014-02')).to eq(:month)
94
+ end
95
+
96
+ it 'returns a :day interval_id for 2014-02-03' do
97
+ expect(subject.granularity_from_interval_id('2014-02-03')).to eq(:day)
98
+ end
99
+
100
+ it 'returns a :hour interval_id for 2014-02-03:05' do
101
+ expect(subject.granularity_from_interval_id('2014-02-03:05')).to eq(:hour)
102
+ end
103
+
104
+ it 'returns a :minute interval_id for 2014-02-03:05:06' do
105
+ expect(subject.granularity_from_interval_id('2014-02-03:05:06')).to eq(:minute)
106
+ end
107
+
108
+ it 'fails with an invalid interval_id 14-20' do
109
+ expect { subject.granularity_from_interval_id('14-20') }.to raise_error ArgumentError
110
+ end
111
+ end
112
+ end
113
+ end
@@ -5,7 +5,7 @@ describe Ably::Realtime::Client::IncomingMessageDispatcher, :api_private do
5
5
  Ably::Util::PubSub.new
6
6
  end
7
7
  let(:connection) do
8
- instance_double('Ably::Realtime::Connection', __incoming_protocol_msgbus__: msgbus, update_connection_id_and_key: true, id: nil)
8
+ instance_double('Ably::Realtime::Connection', __incoming_protocol_msgbus__: msgbus, configure_new: true, id: nil)
9
9
  end
10
10
  let(:client) do
11
11
  instance_double('Ably::Realtime::Client', channels: {})
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ably
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
5
- prerelease:
4
+ version: 0.7.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Lewis Marshall
@@ -10,230 +9,202 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2015-01-18 00:00:00.000000000 Z
12
+ date: 2015-02-10 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: eventmachine
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ~>
18
+ - - "~>"
21
19
  - !ruby/object:Gem::Version
22
20
  version: '1.0'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ~>
25
+ - - "~>"
29
26
  - !ruby/object:Gem::Version
30
27
  version: '1.0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: em-http-request
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ~>
32
+ - - "~>"
37
33
  - !ruby/object:Gem::Version
38
34
  version: '1.1'
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ~>
39
+ - - "~>"
45
40
  - !ruby/object:Gem::Version
46
41
  version: '1.1'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: statesman
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ~>
46
+ - - "~>"
53
47
  - !ruby/object:Gem::Version
54
48
  version: 1.0.0
55
49
  type: :runtime
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ~>
53
+ - - "~>"
61
54
  - !ruby/object:Gem::Version
62
55
  version: 1.0.0
63
56
  - !ruby/object:Gem::Dependency
64
57
  name: faraday
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ~>
60
+ - - "~>"
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0.9'
71
63
  type: :runtime
72
64
  prerelease: false
73
65
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
  requirements:
76
- - - ~>
67
+ - - "~>"
77
68
  - !ruby/object:Gem::Version
78
69
  version: '0.9'
79
70
  - !ruby/object:Gem::Dependency
80
71
  name: json
81
72
  requirement: !ruby/object:Gem::Requirement
82
- none: false
83
73
  requirements:
84
- - - ! '>='
74
+ - - ">="
85
75
  - !ruby/object:Gem::Version
86
76
  version: '0'
87
77
  type: :runtime
88
78
  prerelease: false
89
79
  version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
80
  requirements:
92
- - - ! '>='
81
+ - - ">="
93
82
  - !ruby/object:Gem::Version
94
83
  version: '0'
95
84
  - !ruby/object:Gem::Dependency
96
85
  name: websocket-driver
97
86
  requirement: !ruby/object:Gem::Requirement
98
- none: false
99
87
  requirements:
100
- - - ~>
88
+ - - "~>"
101
89
  - !ruby/object:Gem::Version
102
90
  version: '0.3'
103
91
  type: :runtime
104
92
  prerelease: false
105
93
  version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
94
  requirements:
108
- - - ~>
95
+ - - "~>"
109
96
  - !ruby/object:Gem::Version
110
97
  version: '0.3'
111
98
  - !ruby/object:Gem::Dependency
112
99
  name: msgpack-ably
113
100
  requirement: !ruby/object:Gem::Requirement
114
- none: false
115
101
  requirements:
116
- - - ~>
102
+ - - "~>"
117
103
  - !ruby/object:Gem::Version
118
104
  version: 0.5.10
119
105
  type: :runtime
120
106
  prerelease: false
121
107
  version_requirements: !ruby/object:Gem::Requirement
122
- none: false
123
108
  requirements:
124
- - - ~>
109
+ - - "~>"
125
110
  - !ruby/object:Gem::Version
126
111
  version: 0.5.10
127
112
  - !ruby/object:Gem::Dependency
128
113
  name: bundler
129
114
  requirement: !ruby/object:Gem::Requirement
130
- none: false
131
115
  requirements:
132
- - - ~>
116
+ - - "~>"
133
117
  - !ruby/object:Gem::Version
134
118
  version: '1.3'
135
119
  type: :development
136
120
  prerelease: false
137
121
  version_requirements: !ruby/object:Gem::Requirement
138
- none: false
139
122
  requirements:
140
- - - ~>
123
+ - - "~>"
141
124
  - !ruby/object:Gem::Version
142
125
  version: '1.3'
143
126
  - !ruby/object:Gem::Dependency
144
127
  name: rake
145
128
  requirement: !ruby/object:Gem::Requirement
146
- none: false
147
129
  requirements:
148
- - - ! '>='
130
+ - - ">="
149
131
  - !ruby/object:Gem::Version
150
132
  version: '0'
151
133
  type: :development
152
134
  prerelease: false
153
135
  version_requirements: !ruby/object:Gem::Requirement
154
- none: false
155
136
  requirements:
156
- - - ! '>='
137
+ - - ">="
157
138
  - !ruby/object:Gem::Version
158
139
  version: '0'
159
140
  - !ruby/object:Gem::Dependency
160
141
  name: redcarpet
161
142
  requirement: !ruby/object:Gem::Requirement
162
- none: false
163
143
  requirements:
164
- - - ! '>='
144
+ - - ">="
165
145
  - !ruby/object:Gem::Version
166
146
  version: '0'
167
147
  type: :development
168
148
  prerelease: false
169
149
  version_requirements: !ruby/object:Gem::Requirement
170
- none: false
171
150
  requirements:
172
- - - ! '>='
151
+ - - ">="
173
152
  - !ruby/object:Gem::Version
174
153
  version: '0'
175
154
  - !ruby/object:Gem::Dependency
176
155
  name: rspec
177
156
  requirement: !ruby/object:Gem::Requirement
178
- none: false
179
157
  requirements:
180
- - - ~>
158
+ - - "~>"
181
159
  - !ruby/object:Gem::Version
182
160
  version: 3.1.0
183
161
  type: :development
184
162
  prerelease: false
185
163
  version_requirements: !ruby/object:Gem::Requirement
186
- none: false
187
164
  requirements:
188
- - - ~>
165
+ - - "~>"
189
166
  - !ruby/object:Gem::Version
190
167
  version: 3.1.0
191
168
  - !ruby/object:Gem::Dependency
192
169
  name: rspec-retry
193
170
  requirement: !ruby/object:Gem::Requirement
194
- none: false
195
171
  requirements:
196
- - - ! '>='
172
+ - - ">="
197
173
  - !ruby/object:Gem::Version
198
174
  version: '0'
199
175
  type: :development
200
176
  prerelease: false
201
177
  version_requirements: !ruby/object:Gem::Requirement
202
- none: false
203
178
  requirements:
204
- - - ! '>='
179
+ - - ">="
205
180
  - !ruby/object:Gem::Version
206
181
  version: '0'
207
182
  - !ruby/object:Gem::Dependency
208
183
  name: yard
209
184
  requirement: !ruby/object:Gem::Requirement
210
- none: false
211
185
  requirements:
212
- - - ! '>='
186
+ - - ">="
213
187
  - !ruby/object:Gem::Version
214
188
  version: '0'
215
189
  type: :development
216
190
  prerelease: false
217
191
  version_requirements: !ruby/object:Gem::Requirement
218
- none: false
219
192
  requirements:
220
- - - ! '>='
193
+ - - ">="
221
194
  - !ruby/object:Gem::Version
222
195
  version: '0'
223
196
  - !ruby/object:Gem::Dependency
224
197
  name: webmock
225
198
  requirement: !ruby/object:Gem::Requirement
226
- none: false
227
199
  requirements:
228
- - - ! '>='
200
+ - - ">="
229
201
  - !ruby/object:Gem::Version
230
202
  version: '0'
231
203
  type: :development
232
204
  prerelease: false
233
205
  version_requirements: !ruby/object:Gem::Requirement
234
- none: false
235
206
  requirements:
236
- - - ! '>='
207
+ - - ">="
237
208
  - !ruby/object:Gem::Version
238
209
  version: '0'
239
210
  description: A Ruby client library for ably.io, the real-time messaging service
@@ -244,10 +215,10 @@ executables: []
244
215
  extensions: []
245
216
  extra_rdoc_files: []
246
217
  files:
247
- - .gitignore
248
- - .rspec
249
- - .ruby-version.old
250
- - .travis.yml
218
+ - ".gitignore"
219
+ - ".rspec"
220
+ - ".ruby-version.old"
221
+ - ".travis.yml"
251
222
  - Gemfile
252
223
  - LICENSE.txt
253
224
  - README.md
@@ -270,6 +241,7 @@ files:
270
241
  - lib/ably/models/paginated_resource.rb
271
242
  - lib/ably/models/presence_message.rb
272
243
  - lib/ably/models/protocol_message.rb
244
+ - lib/ably/models/stat.rb
273
245
  - lib/ably/models/token.rb
274
246
  - lib/ably/modules/ably.rb
275
247
  - lib/ably/modules/async_wrapper.rb
@@ -362,6 +334,7 @@ files:
362
334
  - spec/unit/models/paginated_resource_spec.rb
363
335
  - spec/unit/models/presence_message_spec.rb
364
336
  - spec/unit/models/protocol_message_spec.rb
337
+ - spec/unit/models/stat_spec.rb
365
338
  - spec/unit/models/token_spec.rb
366
339
  - spec/unit/modules/async_wrapper_spec.rb
367
340
  - spec/unit/modules/conversions_spec.rb
@@ -385,33 +358,26 @@ files:
385
358
  homepage: http://github.com/ably/ably-ruby
386
359
  licenses:
387
360
  - MIT
361
+ metadata: {}
388
362
  post_install_message:
389
363
  rdoc_options: []
390
364
  require_paths:
391
365
  - lib
392
366
  required_ruby_version: !ruby/object:Gem::Requirement
393
- none: false
394
367
  requirements:
395
- - - ! '>='
368
+ - - ">="
396
369
  - !ruby/object:Gem::Version
397
370
  version: '0'
398
- segments:
399
- - 0
400
- hash: -4532338095489684894
401
371
  required_rubygems_version: !ruby/object:Gem::Requirement
402
- none: false
403
372
  requirements:
404
- - - ! '>='
373
+ - - ">="
405
374
  - !ruby/object:Gem::Version
406
375
  version: '0'
407
- segments:
408
- - 0
409
- hash: -4532338095489684894
410
376
  requirements: []
411
377
  rubyforge_project:
412
- rubygems_version: 1.8.23.2
378
+ rubygems_version: 2.2.2
413
379
  signing_key:
414
- specification_version: 3
380
+ specification_version: 4
415
381
  summary: A Ruby client library for ably.io, the real-time messaging service
416
382
  test_files:
417
383
  - spec/acceptance/realtime/channel_history_spec.rb
@@ -461,6 +427,7 @@ test_files:
461
427
  - spec/unit/models/paginated_resource_spec.rb
462
428
  - spec/unit/models/presence_message_spec.rb
463
429
  - spec/unit/models/protocol_message_spec.rb
430
+ - spec/unit/models/stat_spec.rb
464
431
  - spec/unit/models/token_spec.rb
465
432
  - spec/unit/modules/async_wrapper_spec.rb
466
433
  - spec/unit/modules/conversions_spec.rb