ably-rest 0.8.3 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
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