ably 0.7.1 → 0.7.2

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.
@@ -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