ably 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +185 -0
  4. data/LICENSE +15 -0
  5. data/README.md +8 -4
  6. data/SPEC.md +999 -531
  7. data/ably.gemspec +1 -1
  8. data/lib/ably.rb +1 -1
  9. data/lib/ably/auth.rb +114 -87
  10. data/lib/ably/exceptions.rb +40 -14
  11. data/lib/ably/models/message.rb +3 -5
  12. data/lib/ably/models/paginated_result.rb +3 -12
  13. data/lib/ably/models/presence_message.rb +8 -2
  14. data/lib/ably/models/protocol_message.rb +15 -3
  15. data/lib/ably/models/stat.rb +1 -1
  16. data/lib/ably/models/token_details.rb +1 -1
  17. data/lib/ably/modules/channels_collection.rb +7 -1
  18. data/lib/ably/modules/conversions.rb +1 -1
  19. data/lib/ably/modules/encodeable.rb +6 -3
  20. data/lib/ably/modules/message_pack.rb +2 -2
  21. data/lib/ably/modules/model_common.rb +1 -1
  22. data/lib/ably/modules/state_machine.rb +2 -2
  23. data/lib/ably/realtime.rb +1 -0
  24. data/lib/ably/realtime/auth.rb +191 -0
  25. data/lib/ably/realtime/channel.rb +97 -25
  26. data/lib/ably/realtime/channel/channel_manager.rb +11 -3
  27. data/lib/ably/realtime/client.rb +22 -6
  28. data/lib/ably/realtime/connection.rb +74 -41
  29. data/lib/ably/realtime/connection/connection_manager.rb +48 -33
  30. data/lib/ably/realtime/presence.rb +17 -3
  31. data/lib/ably/rest/channel.rb +43 -16
  32. data/lib/ably/rest/client.rb +57 -26
  33. data/lib/ably/rest/middleware/exceptions.rb +3 -1
  34. data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -2
  35. data/lib/ably/rest/presence.rb +1 -0
  36. data/lib/ably/version.rb +1 -1
  37. data/spec/acceptance/realtime/auth_spec.rb +242 -0
  38. data/spec/acceptance/realtime/channel_spec.rb +277 -5
  39. data/spec/acceptance/realtime/channels_spec.rb +64 -0
  40. data/spec/acceptance/realtime/client_spec.rb +26 -5
  41. data/spec/acceptance/realtime/connection_failures_spec.rb +23 -6
  42. data/spec/acceptance/realtime/connection_spec.rb +167 -16
  43. data/spec/acceptance/realtime/message_spec.rb +9 -8
  44. data/spec/acceptance/realtime/presence_history_spec.rb +1 -0
  45. data/spec/acceptance/realtime/presence_spec.rb +121 -10
  46. data/spec/acceptance/realtime/stats_spec.rb +13 -1
  47. data/spec/acceptance/rest/auth_spec.rb +161 -79
  48. data/spec/acceptance/rest/base_spec.rb +3 -3
  49. data/spec/acceptance/rest/channel_spec.rb +142 -15
  50. data/spec/acceptance/rest/channels_spec.rb +23 -0
  51. data/spec/acceptance/rest/client_spec.rb +180 -18
  52. data/spec/acceptance/rest/message_spec.rb +8 -8
  53. data/spec/acceptance/rest/presence_spec.rb +136 -25
  54. data/spec/acceptance/rest/stats_spec.rb +60 -4
  55. data/spec/shared/client_initializer_behaviour.rb +54 -3
  56. data/spec/unit/auth_spec.rb +7 -6
  57. data/spec/unit/models/message_spec.rb +1 -9
  58. data/spec/unit/models/paginated_result_spec.rb +1 -18
  59. data/spec/unit/models/presence_message_spec.rb +1 -1
  60. data/spec/unit/models/protocol_message_spec.rb +21 -1
  61. data/spec/unit/realtime/channel_spec.rb +10 -3
  62. data/spec/unit/realtime/channels_spec.rb +27 -8
  63. data/spec/unit/rest/channel_spec.rb +0 -8
  64. data/spec/unit/rest/client_spec.rb +7 -7
  65. metadata +13 -7
  66. data/LICENSE.txt +0 -22
@@ -2,12 +2,13 @@ require 'spec_helper'
2
2
  require 'shared/protocol_msgbus_behaviour'
3
3
 
4
4
  describe Ably::Auth do
5
- let(:client) { double('client').as_null_object }
6
- let(:client_id) { nil }
7
- let(:options) { { key: 'appid.keyuid:keysecret', client_id: client_id } }
5
+ let(:client) { double('client').as_null_object }
6
+ let(:client_id) { nil }
7
+ let(:auth_options) { { key: 'appid.keyuid:keysecret', client_id: client_id } }
8
+ let(:token_params) { { } }
8
9
 
9
10
  subject do
10
- Ably::Auth.new(client, options)
11
+ Ably::Auth.new(client, auth_options, token_params)
11
12
  end
12
13
 
13
14
  describe 'client_id option' do
@@ -78,8 +79,8 @@ describe Ably::Auth do
78
79
  expect(Ably::Auth::TOKEN_DEFAULTS.fetch(:capability)).to eql(all_capabilities)
79
80
  end
80
81
 
81
- it 'should only have defaults for :ttl and :capability' do
82
- expect(Ably::Auth::TOKEN_DEFAULTS.keys).to contain_exactly(:ttl, :capability)
82
+ it 'should have defaults for :ttl and :capability' do
83
+ expect(Ably::Auth::TOKEN_DEFAULTS.keys).to include(:ttl, :capability)
83
84
  end
84
85
  end
85
86
  end
@@ -12,7 +12,7 @@ describe Ably::Models::Message do
12
12
  let(:protocol_message_timestamp) { as_since_epoch(Time.now) }
13
13
  let(:protocol_message) { Ably::Models::ProtocolMessage.new(action: 1, timestamp: protocol_message_timestamp) }
14
14
 
15
- it_behaves_like 'a model', with_simple_attributes: %w(name client_id data encoding) do
15
+ it_behaves_like 'a model', with_simple_attributes: %w(id name client_id data encoding) do
16
16
  let(:model_args) { [protocol_message: protocol_message] }
17
17
  end
18
18
 
@@ -150,14 +150,6 @@ describe Ably::Models::Message do
150
150
  end
151
151
  end
152
152
 
153
- context 'with invalid data' do
154
- let(:model) { subject.new({ clientId: 'joe' }, protocol_message: protocol_message) }
155
-
156
- it 'raises an exception' do
157
- expect { model.to_json }.to raise_error RuntimeError, /cannot generate a valid Hash/
158
- end
159
- end
160
-
161
153
  context 'with binary data' do
162
154
  let(:data) { MessagePack.pack(random_str(32)) }
163
155
  let(:model) { subject.new({ name: 'test', data: data }, protocol_message: protocol_message) }
@@ -157,7 +157,7 @@ describe Ably::Models::PaginatedResult do
157
157
  subject.next do |paginated_result|
158
158
  deferrable = subject.first
159
159
  deferrable.errback do |error|
160
- expect(error).to be_a(Ably::Exceptions::InvalidPageError)
160
+ expect(error).to be_a(Ably::Exceptions::PageMissing)
161
161
  stop_reactor
162
162
  end
163
163
  end
@@ -169,10 +169,6 @@ describe Ably::Models::PaginatedResult do
169
169
  end
170
170
 
171
171
  context 'with non paged http response' do
172
- it 'is the first page' do
173
- expect(subject).to be_first
174
- end
175
-
176
172
  it 'is the last page' do
177
173
  expect(subject).to be_last
178
174
  end
@@ -207,10 +203,6 @@ describe Ably::Models::PaginatedResult do
207
203
  }
208
204
  end
209
205
 
210
- it 'is the first page' do
211
- expect(subject).to be_first
212
- end
213
-
214
206
  it 'has next page' do
215
207
  expect(subject).to have_next
216
208
  end
@@ -256,10 +248,6 @@ describe Ably::Models::PaginatedResult do
256
248
  expect(subject.items[0][:id]).to eql(next_body[0][:id])
257
249
  end
258
250
 
259
- it 'is not the first page' do
260
- expect(subject).to_not be_first
261
- end
262
-
263
251
  it 'does not have a next page' do
264
252
  expect(subject).to_not have_next
265
253
  end
@@ -286,12 +274,7 @@ describe Ably::Models::PaginatedResult do
286
274
  it 'retrieves the first page of results' do
287
275
  expect(subject.items.length).to eql(body.length)
288
276
  end
289
-
290
- it 'is the first page' do
291
- expect(subject).to be_first
292
- end
293
277
  end
294
278
  end
295
279
  end
296
280
  end
297
-
@@ -9,7 +9,7 @@ describe Ably::Models::PresenceMessage do
9
9
  let(:protocol_message_timestamp) { as_since_epoch(Time.now) }
10
10
  let(:protocol_message) { Ably::Models::ProtocolMessage.new(action: 1, timestamp: protocol_message_timestamp) }
11
11
 
12
- it_behaves_like 'a model', with_simple_attributes: %w(client_id data encoding) do
12
+ it_behaves_like 'a model', with_simple_attributes: %w(id client_id data encoding) do
13
13
  let(:model_args) { [protocol_message] }
14
14
  end
15
15
 
@@ -11,7 +11,7 @@ describe Ably::Models::ProtocolMessage do
11
11
  end
12
12
 
13
13
  it_behaves_like 'a model',
14
- with_simple_attributes: %w(id channel channel_serial connection_id),
14
+ with_simple_attributes: %w(id channel channel_serial connection_id connection_key),
15
15
  base_model_options: { action: 1 } do
16
16
 
17
17
  let(:model_args) { [] }
@@ -264,6 +264,26 @@ describe Ably::Models::ProtocolMessage do
264
264
  end
265
265
  end
266
266
  end
267
+
268
+ context '#messages' do
269
+ let(:protocol_message) { new_protocol_message(messages: [{ name: 'test' }]) }
270
+
271
+ it 'contains Message objects' do
272
+ expect(protocol_message.messages.count).to eql(1)
273
+ expect(protocol_message.messages.first).to be_a(Ably::Models::Message)
274
+ expect(protocol_message.messages.first.name).to eql('test')
275
+ end
276
+ end
277
+
278
+ context '#presence' do
279
+ let(:protocol_message) { new_protocol_message(presence: [{ action: 1, data: 'test' }]) }
280
+
281
+ it 'contains PresenceMessage objects' do
282
+ expect(protocol_message.presence.count).to eql(1)
283
+ expect(protocol_message.presence.first).to be_a(Ably::Models::PresenceMessage)
284
+ expect(protocol_message.presence.first.data).to eql('test')
285
+ end
286
+ end
267
287
  end
268
288
 
269
289
  context '#to_json', :api_private do
@@ -71,6 +71,7 @@ describe Ably::Realtime::Channel do
71
71
 
72
72
  before do
73
73
  allow(subject).to receive(:create_message).and_return('message_stubbed')
74
+ allow(subject).to receive(:attach).and_return(:true)
74
75
  end
75
76
 
76
77
  context 'as UTF_8 string' do
@@ -108,8 +109,8 @@ describe Ably::Realtime::Channel do
108
109
  context 'as Nil' do
109
110
  let(:encoded_value) { nil }
110
111
 
111
- it 'raises an argument error' do
112
- expect { subject.publish(encoded_value, 'data') }.to raise_error ArgumentError, /must be a String/
112
+ it 'is permitted' do
113
+ expect(subject.publish(encoded_value, 'data')).to eql('message_stubbed')
113
114
  end
114
115
  end
115
116
  end
@@ -159,6 +160,10 @@ describe Ably::Realtime::Channel do
159
160
  let(:blur_message) { instance_double('Ably::Models::Message', name: 'blur', encode: nil, decode: nil) }
160
161
 
161
162
  context '#subscribe' do
163
+ before do
164
+ allow(subject).to receive(:attach).and_return(:true)
165
+ end
166
+
162
167
  specify 'without a block raises an invalid ArgumentError' do
163
168
  expect { subject.subscribe }.to raise_error ArgumentError
164
169
  end
@@ -199,8 +204,10 @@ describe Ably::Realtime::Channel do
199
204
  let(:callback) do
200
205
  Proc.new { |message| message_history[:received] += 1 }
201
206
  end
207
+
202
208
  before do
203
- subject.subscribe(click_event, &callback)
209
+ allow(subject).to receive(:attach).and_return(:true)
210
+ subject.subscribe click_event, &callback
204
211
  end
205
212
 
206
213
  specify 'with no event name specified unsubscribes that block from all events' do
@@ -10,15 +10,34 @@ describe Ably::Realtime::Channels do
10
10
  subject { Ably::Realtime::Channels.new(client) }
11
11
 
12
12
  context 'creating channels' do
13
- it '#get creates a channel' do
14
- expect(Ably::Realtime::Channel).to receive(:new).with(client, channel_name, options)
15
- subject.get(channel_name, options)
16
- end
13
+ context '#get' do
14
+ it 'creates a channel if it does not exist' do
15
+ expect(Ably::Realtime::Channel).to receive(:new).with(client, channel_name, options)
16
+ subject.get(channel_name, options)
17
+ end
17
18
 
18
- it '#get will reuse the channel object' do
19
- channel = subject.get(channel_name, options)
20
- expect(channel).to be_a(Ably::Realtime::Channel)
21
- expect(subject.get(channel_name, options).object_id).to eql(channel.object_id)
19
+ context 'when an existing channel exists' do
20
+ it 'will reuse a channel object if it exists' do
21
+ channel = subject.get(channel_name, options)
22
+ expect(channel).to be_a(Ably::Realtime::Channel)
23
+ expect(subject.get(channel_name, options).object_id).to eql(channel.object_id)
24
+ end
25
+
26
+ it 'will update the options on the channel if provided' do
27
+ channel = subject.get(channel_name, options)
28
+ expect(channel.options).to eql(options)
29
+ expect(channel.options).to_not include(:encrypted)
30
+ subject.get(channel_name, encrypted: true)
31
+ expect(channel.options[:encrypted]).to eql(true)
32
+ end
33
+
34
+ it 'will leave the options intact on the channel if not provided' do
35
+ channel = subject.get(channel_name, options)
36
+ expect(channel.options).to eql(options)
37
+ subject.get(channel_name)
38
+ expect(channel.options).to eql(options)
39
+ end
40
+ end
22
41
  end
23
42
 
24
43
  it '[] creates a channel' do
@@ -97,13 +97,5 @@ describe Ably::Rest::Channel do
97
97
  expect { subject.publish(encoded_value, 'data') }.to raise_error ArgumentError, /must be a String/
98
98
  end
99
99
  end
100
-
101
- context 'as Nil' do
102
- let(:encoded_value) { nil }
103
-
104
- it 'raises an argument error' do
105
- expect { subject.publish(encoded_value, 'data') }.to raise_error ArgumentError, /must be a String/
106
- end
107
- end
108
100
  end
109
101
  end
@@ -15,35 +15,35 @@ describe Ably::Rest::Client do
15
15
  let(:client_options) { { key: 'appid.keyuid:keysecret', tls: false } }
16
16
 
17
17
  it 'fails for any operation with basic auth and attempting to send an API key over a non-secure connection' do
18
- expect { subject.channel('a').publish('event', 'message') }.to raise_error(Ably::Exceptions::InsecureRequestError)
18
+ expect { subject.channel('a').publish('event', 'message') }.to raise_error(Ably::Exceptions::InsecureRequest)
19
19
  end
20
20
  end
21
21
  end
22
22
 
23
23
  context ':use_token_auth' do
24
24
  context 'set to false' do
25
- context 'with an key with :tls => false' do
25
+ context 'with a key and :tls => false' do
26
26
  let(:client_options) { { use_token_auth: false, key: 'appid.keyuid:keysecret', tls: false } }
27
27
 
28
28
  it 'fails for any operation with basic auth and attempting to send an API key over a non-secure connection' do
29
- expect { subject.channel('a').publish('event', 'message') }.to raise_error(Ably::Exceptions::InsecureRequestError)
29
+ expect { subject.channel('a').publish('event', 'message') }.to raise_error(Ably::Exceptions::InsecureRequest)
30
30
  end
31
31
  end
32
32
 
33
- context 'without an key' do
33
+ context 'without a key' do
34
34
  let(:client_options) { { use_token_auth: false } }
35
35
 
36
- it 'fails as an key is required if not using token auth' do
36
+ it 'fails as a key is required if not using token auth' do
37
37
  expect { subject.channel('a').publish('event', 'message') }.to raise_error(ArgumentError)
38
38
  end
39
39
  end
40
40
  end
41
41
 
42
42
  context 'set to true' do
43
- context 'without an key or token' do
43
+ context 'without a key or token' do
44
44
  let(:client_options) { { use_token_auth: true, key: true } }
45
45
 
46
- it 'fails as an key is required to issue tokens' do
46
+ it 'fails as a key is required to issue tokens' do
47
47
  expect { subject.channel('a').publish('event', 'message') }.to raise_error(ArgumentError)
48
48
  end
49
49
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ably
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lewis Marshall
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-05-20 00:00:00.000000000 Z
12
+ date: 2015-08-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -99,16 +99,16 @@ dependencies:
99
99
  name: msgpack
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - '='
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: 0.6.0pre1
104
+ version: 0.6.2
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - '='
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
- version: 0.6.0pre1
111
+ version: 0.6.2
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: bundler
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -233,8 +233,9 @@ files:
233
233
  - ".gitmodules"
234
234
  - ".rspec"
235
235
  - ".travis.yml"
236
+ - CHANGELOG.md
236
237
  - Gemfile
237
- - LICENSE.txt
238
+ - LICENSE
238
239
  - README.md
239
240
  - Rakefile
240
241
  - SPEC.md
@@ -278,6 +279,7 @@ files:
278
279
  - lib/ably/modules/statesman_monkey_patch.rb
279
280
  - lib/ably/modules/uses_state_machine.rb
280
281
  - lib/ably/realtime.rb
282
+ - lib/ably/realtime/auth.rb
281
283
  - lib/ably/realtime/channel.rb
282
284
  - lib/ably/realtime/channel/channel_manager.rb
283
285
  - lib/ably/realtime/channel/channel_state_machine.rb
@@ -310,8 +312,10 @@ files:
310
312
  - lib/ably/util/pub_sub.rb
311
313
  - lib/ably/util/safe_deferrable.rb
312
314
  - lib/ably/version.rb
315
+ - spec/acceptance/realtime/auth_spec.rb
313
316
  - spec/acceptance/realtime/channel_history_spec.rb
314
317
  - spec/acceptance/realtime/channel_spec.rb
318
+ - spec/acceptance/realtime/channels_spec.rb
315
319
  - spec/acceptance/realtime/client_spec.rb
316
320
  - spec/acceptance/realtime/connection_failures_spec.rb
317
321
  - spec/acceptance/realtime/connection_spec.rb
@@ -404,8 +408,10 @@ signing_key:
404
408
  specification_version: 4
405
409
  summary: A Ruby client library for ably.io, the realtime messaging service
406
410
  test_files:
411
+ - spec/acceptance/realtime/auth_spec.rb
407
412
  - spec/acceptance/realtime/channel_history_spec.rb
408
413
  - spec/acceptance/realtime/channel_spec.rb
414
+ - spec/acceptance/realtime/channels_spec.rb
409
415
  - spec/acceptance/realtime/client_spec.rb
410
416
  - spec/acceptance/realtime/connection_failures_spec.rb
411
417
  - spec/acceptance/realtime/connection_spec.rb
@@ -1,22 +0,0 @@
1
- Copyright (c) 2015 Ably
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.