ably-rest 0.8.3 → 0.8.5

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/lib/submodules/ably-ruby/CHANGELOG.md +10 -0
  4. data/lib/submodules/ably-ruby/README.md +1 -1
  5. data/lib/submodules/ably-ruby/Rakefile +1 -1
  6. data/lib/submodules/ably-ruby/lib/ably/auth.rb +24 -20
  7. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +3 -0
  8. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +41 -0
  9. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +43 -0
  10. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +1 -1
  11. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +1 -1
  12. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +2 -1
  13. data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +8 -6
  14. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +4 -0
  15. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +4 -1
  16. data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +35 -4
  17. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +13 -13
  18. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +13 -5
  19. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +27 -7
  20. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +22 -12
  21. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +16 -10
  22. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +6 -0
  23. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +5 -4
  24. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +42 -24
  25. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +25 -17
  26. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +4 -4
  27. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +3 -2
  28. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +2 -2
  29. data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +15 -0
  30. data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
  31. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +9 -9
  32. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +2 -2
  33. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +168 -21
  34. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channels_spec.rb +6 -2
  35. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +6 -5
  36. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +29 -19
  37. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +150 -35
  38. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +146 -23
  39. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +2 -2
  40. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +44 -24
  41. data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +1 -1
  42. data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +1 -1
  43. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +77 -46
  44. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +31 -3
  45. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +15 -5
  46. data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +9 -7
  47. data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +30 -4
  48. data/lib/submodules/ably-ruby/spec/support/protocol_helper.rb +9 -6
  49. data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +1 -1
  50. data/lib/submodules/ably-ruby/spec/unit/models/channel_state_change_spec.rb +44 -0
  51. data/lib/submodules/ably-ruby/spec/unit/models/connection_state_change_spec.rb +54 -0
  52. data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +8 -0
  53. data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +1 -1
  54. data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +18 -0
  55. metadata +6 -2
@@ -12,9 +12,10 @@ describe Ably::Rest::Channel do
12
12
  end
13
13
 
14
14
  describe '#publish' do
15
- let(:channel) { client.channel(random_str) }
16
- let(:name) { 'foo' }
17
- let(:data) { 'woop!' }
15
+ let(:channel_name) { random_str }
16
+ let(:channel) { client.channel(channel_name) }
17
+ let(:name) { 'foo' }
18
+ let(:data) { 'woop!' }
18
19
 
19
20
  context 'with name and data arguments' do
20
21
  it 'publishes the message and return true indicating success' do
@@ -22,6 +23,33 @@ describe Ably::Rest::Channel do
22
23
  expect(channel.history.items.first.name).to eql(name)
23
24
  expect(channel.history.items.first.data).to eql(data)
24
25
  end
26
+
27
+ context 'and additional attributes' do
28
+ let(:client_id) { random_str }
29
+
30
+ it 'publishes the message with the attributes and return true indicating success' do
31
+ expect(channel.publish(name, data, client_id: client_id)).to eql(true)
32
+ expect(channel.history.items.first.client_id).to eql(client_id)
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'with a client_id configured in the ClientOptions' do
38
+ let(:client_id) { random_str }
39
+ let(:client_options) { default_options.merge(client_id: client_id) }
40
+
41
+ it 'publishes the message without a client_id' do
42
+ expect(client).to receive(:post).
43
+ with("/channels/#{channel_name}/publish", hash_excluding(client_id: client_id)).
44
+ and_return(double('response', status: 201))
45
+
46
+ expect(channel.publish(name, data)).to eql(true)
47
+ end
48
+
49
+ it 'expects a client_id to be added by the realtime service' do
50
+ channel.publish name, data
51
+ expect(channel.history.items.first.client_id).to eql(client_id)
52
+ end
25
53
  end
26
54
 
27
55
  context 'with an array of Hash objects with :name and :data attributes' do
@@ -16,7 +16,7 @@ describe Ably::Rest::Client do
16
16
 
17
17
  context '#initialize' do
18
18
  let(:client_id) { random_str }
19
- let(:token_request) { client.auth.create_token_request(key_name: key_name, key_secret: key_secret, client_id: client_id) }
19
+ let(:token_request) { client.auth.create_token_request({}, key_name: key_name, key_secret: key_secret, client_id: client_id) }
20
20
 
21
21
  context 'with only an API key' do
22
22
  let(:client) { Ably::Rest::Client.new(client_options.merge(key: api_key)) }
@@ -63,6 +63,16 @@ describe Ably::Rest::Client do
63
63
  end
64
64
  end
65
65
 
66
+ context 'with an :auth_callback Proc (clientId provided in library options instead of as a token_request param)' do
67
+ let(:client) { Ably::Rest::Client.new(client_options.merge(client_id: client_id, auth_callback: Proc.new { token_request })) }
68
+ let(:token_request) { client.auth.create_token_request({}, key_name: key_name, key_secret: key_secret) }
69
+
70
+ it 'correctly sets the clientId on the token' do
71
+ expect { client.channel('channel_name').publish('event', 'message') }.to change { client.auth.current_token_details }
72
+ expect(client.auth.current_token_details.client_id).to eql(client_id)
73
+ end
74
+ end
75
+
66
76
  context 'with an auth URL' do
67
77
  let(:client_options) { default_options.merge(key: api_key, auth_url: token_request_url, auth_method: :get) }
68
78
  let(:token_request_url) { 'http://get.token.request.com/' }
@@ -74,7 +84,7 @@ describe Ably::Rest::Client do
74
84
  context 'before any REST request' do
75
85
  before do
76
86
  expect(client.auth).to receive(:token_request_from_auth_url).with(token_request_url, hash_including(:auth_method => :get)).once do
77
- client.auth.create_token_request(token_params: { client_id: client_id })
87
+ client.auth.create_token_request(client_id: client_id)
78
88
  end
79
89
  end
80
90
 
@@ -144,11 +154,11 @@ describe Ably::Rest::Client do
144
154
  send("token_request_#{@request_index > 2 ? 'next' : @request_index}")
145
155
  end))
146
156
  end
147
- let(:token_request_1) { client.auth.create_token_request(token_request_options.merge(client_id: random_str)) }
148
- let(:token_request_2) { client.auth.create_token_request(token_request_options.merge(client_id: random_str)) }
157
+ let(:token_request_1) { client.auth.create_token_request({}, token_request_options.merge(client_id: random_str)) }
158
+ let(:token_request_2) { client.auth.create_token_request({}, token_request_options.merge(client_id: random_str)) }
149
159
 
150
160
  # If token expires against whilst runnig tests in a slower CI environment then use this token
151
- let(:token_request_next) { client.auth.create_token_request(token_request_options.merge(client_id: random_str)) }
161
+ let(:token_request_next) { client.auth.create_token_request({}, token_request_options.merge(client_id: random_str)) }
152
162
 
153
163
  context 'when expired' do
154
164
  before do
@@ -93,23 +93,25 @@ describe Ably::Rest::Presence do
93
93
 
94
94
  context 'with :client_id option' do
95
95
  let(:client_id) { non_encoded_fixtures.first[:client_id] }
96
- let(:presence_page) { fixtures_channel.presence.get(client_id: client_id) }
96
+ let(:presence_page) { fixtures_channel.presence.get(client_id: client_id) }
97
97
 
98
98
  it 'returns a list members filtered by the provided client ID' do
99
- pending 'not implemented in the REST API yet' # TODO realtime/issues/243
100
99
  expect(presence_page.items.count).to eql(1)
101
100
  expect(presence_page.items.first.client_id).to eql(client_id)
102
101
  end
103
102
  end
104
103
 
105
104
  context 'with :connection_id option' do
106
- let(:connection_id) { fixtures_channel.presence.get.first.connection_id }
107
- let(:presence_page) { fixtures_channel.presence.get(connection_id: connection_id) }
105
+ let(:all_members) { fixtures_channel.presence.get.items }
106
+ let(:connection_id) { all_members.first.connection_id }
107
+ let(:presence_page) { fixtures_channel.presence.get(connection_id: connection_id) }
108
108
 
109
109
  it 'returns a list members filtered by the provided connection ID' do
110
- pending 'not implemented in the REST API yet' # TODO realtime/issues/243
111
- expect(presence_page.items.count).to eql(1)
112
- expect(presence_page.items.first.connetion_id).to eql(connetion_id)
110
+ expect(presence_page.items.all? { |member| member.connection_id == connection_id }).to eql(true)
111
+ end
112
+
113
+ it 'returns a list members filtered by the provided connection ID' do
114
+ expect(fixtures_channel.presence.get(connection_id: 'does.not.exist').items).to be_empty
113
115
  end
114
116
  end
115
117
  end
@@ -17,11 +17,34 @@ module RSpec
17
17
  end
18
18
 
19
19
  def stop_reactor
20
+ unless realtime_clients.empty?
21
+ realtime_clients.shift.tap do |client|
22
+ # Ensure close appens outside of the caller as this can cause errbacks on Deferrables
23
+ # e.g. connection.connect { connection.close } => # Error as calling close within the connected callback
24
+ ::EventMachine.add_timer(0.05) do
25
+ client.close if client.connection.can_transition_to?(:closing)
26
+ ::EventMachine.add_timer(0.1) { stop_reactor }
27
+ end
28
+ end
29
+ return
30
+ end
31
+
20
32
  ::EventMachine.next_tick do
21
33
  ::EventMachine.stop
22
34
  end
23
35
  end
24
36
 
37
+ # Ensures that any clients used in tests will have their connections
38
+ # explicitly closed when stop_reactor is called
39
+ def auto_close(realtime_client)
40
+ realtime_clients << realtime_client
41
+ realtime_client
42
+ end
43
+
44
+ def realtime_clients
45
+ @realtime_clients ||= []
46
+ end
47
+
25
48
  # Allows multiple Deferrables to be passed in and calls the provided block when
26
49
  # all success callbacks have completed
27
50
  def when_all(*deferrables)
@@ -48,7 +71,7 @@ module RSpec
48
71
  end
49
72
 
50
73
  deferrable.errback do |error|
51
- raise RuntimeError, "Deferrable failed: #{error.message}"
74
+ raise RuntimeError, "Error: Deferrable failed: #{error}"
52
75
  end
53
76
  end
54
77
  end
@@ -56,9 +79,12 @@ module RSpec
56
79
  def wait_until(condition_block, &block)
57
80
  raise ArgumentError, 'Block required' unless block_given?
58
81
 
59
- yield if condition_block.call
60
- ::EventMachine.add_timer(0.1) do
61
- wait_until condition_block, &block
82
+ if condition_block.call
83
+ yield
84
+ else
85
+ ::EventMachine.add_timer(0.1) do
86
+ wait_until condition_block, &block
87
+ end
62
88
  end
63
89
  end
64
90
  end
@@ -1,12 +1,15 @@
1
1
  module RSpec
2
2
  module ProtocolHelper
3
- PROTOCOLS = if ENV['TEST_LIMIT_PROTOCOLS']
4
- JSON.parse(ENV['TEST_LIMIT_PROTOCOLS'])
3
+ SUPPORTED_PROTOCOLS = {
4
+ json: 'JSON',
5
+ msgpack: 'MsgPack'
6
+ }
7
+
8
+ PROTOCOLS = if ENV['PROTOCOL']
9
+ protocol = ENV['PROTOCOL'].downcase.to_sym
10
+ { protocol => SUPPORTED_PROTOCOLS[protocol] }
5
11
  else
6
- {
7
- json: 'JSON',
8
- msgpack: 'MsgPack'
9
- }
12
+ SUPPORTED_PROTOCOLS
10
13
  end
11
14
 
12
15
  def vary_by_protocol(&block)
@@ -8,7 +8,7 @@ describe Ably::Auth do
8
8
  let(:token_params) { { } }
9
9
 
10
10
  subject do
11
- Ably::Auth.new(client, auth_options, token_params)
11
+ Ably::Auth.new(client, token_params, auth_options)
12
12
  end
13
13
 
14
14
  describe 'client_id option' do
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'shared/model_behaviour'
3
+
4
+ describe Ably::Models::ChannelStateChange do
5
+ let(:unique) { random_str }
6
+
7
+ subject { Ably::Models::ChannelStateChange }
8
+
9
+ context '#current' do
10
+ it 'is required' do
11
+ expect { subject.new(previous: true) }.to raise_error ArgumentError
12
+ end
13
+
14
+ it 'is an attribute' do
15
+ expect(subject.new(current: unique, previous: true).current).to eql(unique)
16
+ end
17
+ end
18
+
19
+ context '#previous' do
20
+ it 'is required' do
21
+ expect { subject.new(current: true) }.to raise_error ArgumentError
22
+ end
23
+
24
+ it 'is an attribute' do
25
+ expect(subject.new(previous: unique, current: true).previous).to eql(unique)
26
+ end
27
+ end
28
+
29
+ context '#reason' do
30
+ it 'is not required' do
31
+ expect { subject.new(previous: true, current: true) }.to_not raise_error
32
+ end
33
+
34
+ it 'is an attribute' do
35
+ expect(subject.new(reason: unique, previous: unique, current: true).reason).to eql(unique)
36
+ end
37
+ end
38
+
39
+ context 'invalid attributes' do
40
+ it 'raises an argument error' do
41
+ expect { subject.new(invalid: true, current: true, previous: true) }.to raise_error ArgumentError
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'shared/model_behaviour'
3
+
4
+ describe Ably::Models::ConnectionStateChange do
5
+ let(:unique) { random_str }
6
+
7
+ subject { Ably::Models::ConnectionStateChange }
8
+
9
+ context '#current' do
10
+ it 'is required' do
11
+ expect { subject.new(previous: true) }.to raise_error ArgumentError
12
+ end
13
+
14
+ it 'is an attribute' do
15
+ expect(subject.new(current: unique, previous: true).current).to eql(unique)
16
+ end
17
+ end
18
+
19
+ context '#previous' do
20
+ it 'is required' do
21
+ expect { subject.new(current: true) }.to raise_error ArgumentError
22
+ end
23
+
24
+ it 'is an attribute' do
25
+ expect(subject.new(previous: unique, current: true).previous).to eql(unique)
26
+ end
27
+ end
28
+
29
+ context '#retry_in' do
30
+ it 'is not required' do
31
+ expect { subject.new(previous: true, current: true) }.to_not raise_error
32
+ end
33
+
34
+ it 'is an attribute' do
35
+ expect(subject.new(retry_in: unique, previous: unique, current: true).retry_in).to eql(unique)
36
+ end
37
+ end
38
+
39
+ context '#reason' do
40
+ it 'is not required' do
41
+ expect { subject.new(previous: true, current: true) }.to_not raise_error
42
+ end
43
+
44
+ it 'is an attribute' do
45
+ expect(subject.new(reason: unique, previous: unique, current: true).reason).to eql(unique)
46
+ end
47
+ end
48
+
49
+ context 'invalid attributes' do
50
+ it 'raises an argument error' do
51
+ expect { subject.new(invalid: true, current: true, previous: true) }.to raise_error ArgumentError
52
+ end
53
+ end
54
+ end
@@ -70,6 +70,14 @@ describe Ably::Models::TokenDetails do
70
70
  expect(subject.expired?).to eql(false)
71
71
  end
72
72
  end
73
+
74
+ context 'when expires is not available (i.e. string tokens)' do
75
+ subject { Ably::Models::TokenDetails.new() }
76
+
77
+ it 'is always false' do
78
+ expect(subject.expired?).to eql(false)
79
+ end
80
+ end
73
81
  end
74
82
  end
75
83
 
@@ -82,7 +82,7 @@ describe Ably::Modules::AsyncWrapper, :api_private do
82
82
  expect(result).to eql(result)
83
83
  EventMachine.add_timer(sleep_time * 2) { stop_reactor }
84
84
  end
85
- deferrable.errback do |result|
85
+ deferrable.errback do |error|
86
86
  raise 'Errback should not have been called'
87
87
  end
88
88
  end
@@ -21,6 +21,24 @@ describe Ably::Util::Crypto do
21
21
  end
22
22
  end
23
23
 
24
+ context 'get_default_params' do
25
+ it 'uses the defaults and generates a key if not provided' do
26
+ expect(Ably::Util::Crypto.get_default_params[:algorithm]).to eql('AES')
27
+ expect(Ably::Util::Crypto.get_default_params[:mode]).to eql('CBC')
28
+ expect(Ably::Util::Crypto.get_default_params[:key_length]).to eql(128)
29
+ expect(Ably::Util::Crypto.get_default_params[:key].unpack('b*').first.length).to eql(128)
30
+ end
31
+
32
+ it 'uses the defaults and sets the key size when key is provided' do
33
+ key_192 = '123456781234567812345678'
34
+ params = Ably::Util::Crypto.get_default_params(key_192)
35
+ expect(params[:algorithm]).to eql('AES')
36
+ expect(params[:mode]).to eql('CBC')
37
+ expect(params[:key_length]).to eql(192)
38
+ expect(params[:key]).to eql(key_192)
39
+ end
40
+ end
41
+
24
42
  context 'encrypts & decrypt' do
25
43
  let(:string) { random_str }
26
44
  let(:byte_array) { random_str.to_msgpack.unpack('C*') }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ably-rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew O'Riordan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-19 00:00:00.000000000 Z
11
+ date: 2015-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -187,6 +187,8 @@ files:
187
187
  - lib/submodules/ably-ruby/lib/ably/auth.rb
188
188
  - lib/submodules/ably-ruby/lib/ably/exceptions.rb
189
189
  - lib/submodules/ably-ruby/lib/ably/logger.rb
190
+ - lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb
191
+ - lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb
190
192
  - lib/submodules/ably-ruby/lib/ably/models/error_info.rb
191
193
  - lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb
192
194
  - lib/submodules/ably-ruby/lib/ably/models/message.rb
@@ -293,6 +295,8 @@ files:
293
295
  - lib/submodules/ably-ruby/spec/support/test_app.rb
294
296
  - lib/submodules/ably-ruby/spec/unit/auth_spec.rb
295
297
  - lib/submodules/ably-ruby/spec/unit/logger_spec.rb
298
+ - lib/submodules/ably-ruby/spec/unit/models/channel_state_change_spec.rb
299
+ - lib/submodules/ably-ruby/spec/unit/models/connection_state_change_spec.rb
296
300
  - lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb
297
301
  - lib/submodules/ably-ruby/spec/unit/models/idiomatic_ruby_wrapper_spec.rb
298
302
  - lib/submodules/ably-ruby/spec/unit/models/message_encoders/base64_spec.rb