ably-rest 0.7.1 → 0.7.3
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.
- checksums.yaml +13 -5
- data/.gitmodules +1 -1
- data/.rspec +1 -0
- data/.travis.yml +7 -3
- data/SPEC.md +495 -419
- data/ably-rest.gemspec +19 -5
- data/lib/ably-rest.rb +9 -1
- data/lib/submodules/ably-ruby/.gitignore +6 -0
- data/lib/submodules/ably-ruby/.rspec +1 -0
- data/lib/submodules/ably-ruby/.ruby-version.old +1 -0
- data/lib/submodules/ably-ruby/.travis.yml +10 -0
- data/lib/submodules/ably-ruby/Gemfile +4 -0
- data/lib/submodules/ably-ruby/LICENSE.txt +22 -0
- data/lib/submodules/ably-ruby/README.md +122 -0
- data/lib/submodules/ably-ruby/Rakefile +34 -0
- data/lib/submodules/ably-ruby/SPEC.md +1794 -0
- data/lib/submodules/ably-ruby/ably.gemspec +36 -0
- data/lib/submodules/ably-ruby/lib/ably.rb +12 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +438 -0
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +102 -0
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +37 -0
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +223 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +132 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/base.rb +108 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/base64.rb +40 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/cipher.rb +83 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/json.rb +34 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/utf8.rb +26 -0
- data/lib/submodules/ably-ruby/lib/ably/models/nil_logger.rb +20 -0
- data/lib/submodules/ably-ruby/lib/ably/models/paginated_resource.rb +173 -0
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +147 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +210 -0
- data/lib/submodules/ably-ruby/lib/ably/models/stat.rb +161 -0
- data/lib/submodules/ably-ruby/lib/ably/models/token.rb +74 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +15 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +62 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +100 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/enum.rb +202 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +128 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/event_machine_helpers.rb +26 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/http_helpers.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/message_pack.rb +14 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +153 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +57 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/statesman_monkey_patch.rb +33 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +74 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +64 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +298 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +92 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channels.rb +50 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +184 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +184 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +70 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +445 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +368 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +91 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +188 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/models/nil_channel.rb +30 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +564 -0
- data/lib/submodules/ably-ruby/lib/ably/rest.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +104 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channels.rb +44 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +396 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/encoder.rb +49 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/external_exceptions.rb +24 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +17 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/logger.rb +58 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_json.rb +27 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +27 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +92 -0
- data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +105 -0
- data/lib/submodules/ably-ruby/lib/ably/util/pub_sub.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +3 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +154 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +558 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +119 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +575 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +785 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +457 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +55 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +1001 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +23 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +27 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +564 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +165 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +134 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +41 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +273 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/encoders_spec.rb +185 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +247 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +292 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/stats_spec.rb +172 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +15 -0
- data/lib/submodules/ably-ruby/spec/resources/crypto-data-128.json +56 -0
- data/lib/submodules/ably-ruby/spec/resources/crypto-data-256.json +56 -0
- data/lib/submodules/ably-ruby/spec/rspec_config.rb +57 -0
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +212 -0
- data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +86 -0
- data/lib/submodules/ably-ruby/spec/shared/protocol_msgbus_behaviour.rb +36 -0
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +20 -0
- data/lib/submodules/ably-ruby/spec/support/api_helper.rb +60 -0
- data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +104 -0
- data/lib/submodules/ably-ruby/spec/support/markdown_spec_formatter.rb +118 -0
- data/lib/submodules/ably-ruby/spec/support/private_api_formatter.rb +36 -0
- data/lib/submodules/ably-ruby/spec/support/protocol_helper.rb +32 -0
- data/lib/submodules/ably-ruby/spec/support/random_helper.rb +15 -0
- data/lib/submodules/ably-ruby/spec/support/rest_testapp_before_retry.rb +15 -0
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +113 -0
- data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +68 -0
- data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +146 -0
- data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +18 -0
- data/lib/submodules/ably-ruby/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +349 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/base64_spec.rb +181 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/cipher_spec.rb +260 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/json_spec.rb +135 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/utf8_spec.rb +56 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +389 -0
- data/lib/submodules/ably-ruby/spec/unit/models/paginated_resource_spec.rb +288 -0
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +386 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +315 -0
- data/lib/submodules/ably-ruby/spec/unit/models/stat_spec.rb +113 -0
- data/lib/submodules/ably-ruby/spec/unit/models/token_spec.rb +86 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +124 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/conversions_spec.rb +72 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +272 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +184 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +283 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +206 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +81 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +33 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/incoming_message_dispatcher_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +111 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +9 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/websocket_transport_spec.rb +25 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +109 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channels_spec.rb +79 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +53 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/rest_spec.rb +10 -0
- data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +87 -0
- data/lib/submodules/ably-ruby/spec/unit/util/pub_sub_spec.rb +86 -0
- metadata +182 -27
|
@@ -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
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ably::Models::Token do
|
|
4
|
+
subject { Ably::Models::Token }
|
|
5
|
+
|
|
6
|
+
it_behaves_like 'a model', with_simple_attributes: %w(id capability client_id nonce) do
|
|
7
|
+
let(:model_args) { [] }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context 'defaults' do
|
|
11
|
+
let(:one_hour) { 60 * 60 }
|
|
12
|
+
let(:all_capabilities) { { "*" => ["*"] } }
|
|
13
|
+
|
|
14
|
+
it 'should default TTL to 1 hour' do
|
|
15
|
+
expect(Ably::Models::Token::DEFAULTS[:ttl]).to eql(one_hour)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should default capability to all' do
|
|
19
|
+
expect(Ably::Models::Token::DEFAULTS[:capability]).to eql(all_capabilities)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should only have defaults for :ttl and :capability' do
|
|
23
|
+
expect(Ably::Models::Token::DEFAULTS.keys).to contain_exactly(:ttl, :capability)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'attributes' do
|
|
28
|
+
let(:unique_value) { 'unique_value' }
|
|
29
|
+
|
|
30
|
+
context '#key_id' do
|
|
31
|
+
subject { Ably::Models::Token.new({ key: unique_value }) }
|
|
32
|
+
it 'retrieves attribute :key' do
|
|
33
|
+
expect(subject.key_id).to eql(unique_value)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
{ :issued_at => :issued_at, :expires_at => :expires }.each do |method_name, attribute|
|
|
38
|
+
let(:time) { Time.now }
|
|
39
|
+
context "##{method_name}" do
|
|
40
|
+
subject { Ably::Models::Token.new({ attribute.to_sym => time.to_i }) }
|
|
41
|
+
|
|
42
|
+
it "retrieves attribute :#{attribute} as Time" do
|
|
43
|
+
expect(subject.public_send(method_name)).to be_a(Time)
|
|
44
|
+
expect(subject.public_send(method_name).to_i).to eql(time.to_i)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context '#expired?' do
|
|
50
|
+
let(:expire_time) { Time.now + Ably::Models::Token::TOKEN_EXPIRY_BUFFER }
|
|
51
|
+
|
|
52
|
+
context 'once grace period buffer has passed' do
|
|
53
|
+
subject { Ably::Models::Token.new(expires: expire_time - 1) }
|
|
54
|
+
|
|
55
|
+
it 'is true' do
|
|
56
|
+
expect(subject.expired?).to eql(true)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'within grace period buffer' do
|
|
61
|
+
subject { Ably::Models::Token.new(expires: expire_time + 1) }
|
|
62
|
+
|
|
63
|
+
it 'is false' do
|
|
64
|
+
expect(subject.expired?).to eql(false)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context '==' do
|
|
71
|
+
let(:token_attributes) { { id: 'unique' } }
|
|
72
|
+
|
|
73
|
+
it 'is true when attributes are the same' do
|
|
74
|
+
new_token = -> { Ably::Models::Token.new(token_attributes) }
|
|
75
|
+
expect(new_token[]).to eq(new_token[])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'is false when attributes are not the same' do
|
|
79
|
+
expect(Ably::Models::Token.new(id: 1)).to_not eq(Ably::Models::Token.new(id: 2))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'is false when class type differs' do
|
|
83
|
+
expect(Ably::Models::Token.new(id: 1)).to_not eq(nil)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ably::Modules::AsyncWrapper, :api_private do
|
|
4
|
+
include RSpec::EventMachine
|
|
5
|
+
|
|
6
|
+
let(:class_with_module) do
|
|
7
|
+
Class.new do
|
|
8
|
+
include Ably::Modules::AsyncWrapper
|
|
9
|
+
|
|
10
|
+
def operation(&success_callback)
|
|
11
|
+
async_wrap success_callback, &@block
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def block=(block)
|
|
15
|
+
@block = block
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
let(:subject) { class_with_module.new }
|
|
20
|
+
let(:result) { random_str }
|
|
21
|
+
let(:sleep_time) { 0.1 }
|
|
22
|
+
|
|
23
|
+
before do
|
|
24
|
+
subject.block = block
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context '#async_wrap blocking block' do
|
|
28
|
+
context 'returns result' do
|
|
29
|
+
let(:block) do
|
|
30
|
+
proc do
|
|
31
|
+
sleep sleep_time
|
|
32
|
+
result
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'calls the success_callback block with result when provided' do
|
|
37
|
+
run_reactor do
|
|
38
|
+
subject.operation do |result|
|
|
39
|
+
expect(result).to eql(result)
|
|
40
|
+
stop_reactor
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns a deferrable that succeeds with result' do
|
|
46
|
+
run_reactor do
|
|
47
|
+
deferrable = subject.operation
|
|
48
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
|
49
|
+
deferrable.callback do |result|
|
|
50
|
+
expect(result).to eql(result)
|
|
51
|
+
stop_reactor
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'does not call the errback' do
|
|
57
|
+
run_reactor do
|
|
58
|
+
deferrable = subject.operation
|
|
59
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
|
60
|
+
deferrable.callback do |result|
|
|
61
|
+
expect(result).to eql(result)
|
|
62
|
+
EventMachine.add_timer(sleep_time * 2) { stop_reactor }
|
|
63
|
+
end
|
|
64
|
+
deferrable.errback do |result|
|
|
65
|
+
raise 'Errback should not have been called'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'does not block EventMachine' do
|
|
71
|
+
run_reactor do
|
|
72
|
+
timers_called = 0
|
|
73
|
+
EventMachine.add_periodic_timer(sleep_time / 5) { timers_called += 1 }
|
|
74
|
+
|
|
75
|
+
subject.operation do |result|
|
|
76
|
+
expect(timers_called).to be >= 4
|
|
77
|
+
stop_reactor
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'raises an Exception' do
|
|
84
|
+
let(:block) do
|
|
85
|
+
proc do
|
|
86
|
+
sleep sleep_time
|
|
87
|
+
raise RuntimeError, 'Intentional'
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'calls the errback block of the deferrable' do
|
|
92
|
+
run_reactor do
|
|
93
|
+
deferrable = subject.operation
|
|
94
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
|
95
|
+
deferrable.errback do |error|
|
|
96
|
+
expect(error).to be_a(RuntimeError)
|
|
97
|
+
expect(error.message).to match(/Intentional/)
|
|
98
|
+
stop_reactor
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'does not call the success_callback block' do
|
|
104
|
+
run_reactor do
|
|
105
|
+
subject.operation do |result|
|
|
106
|
+
raise 'Callback should not have been called'
|
|
107
|
+
end
|
|
108
|
+
EventMachine.add_timer(sleep_time * 2) { stop_reactor }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'does not call the callback block of the deferrable' do
|
|
113
|
+
run_reactor do
|
|
114
|
+
deferrable = subject.operation
|
|
115
|
+
expect(deferrable).to be_a(EventMachine::Deferrable)
|
|
116
|
+
deferrable.callback do |result|
|
|
117
|
+
raise 'Callback should not have been called'
|
|
118
|
+
end
|
|
119
|
+
EventMachine.add_timer(sleep_time * 2) { stop_reactor }
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ably::Modules::Conversions, :api_private do
|
|
4
|
+
let(:class_with_module) { Class.new do; include Ably::Modules::Conversions; end }
|
|
5
|
+
let(:subject) { class_with_module.new }
|
|
6
|
+
before do
|
|
7
|
+
# make method being tested public
|
|
8
|
+
class_with_module.class_eval %{ public :#{method} }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context '#as_since_epoch' do
|
|
12
|
+
let(:method) { :as_since_epoch }
|
|
13
|
+
|
|
14
|
+
context 'with time' do
|
|
15
|
+
let(:time) { Time.new }
|
|
16
|
+
|
|
17
|
+
it 'converts to milliseconds by default' do
|
|
18
|
+
expect(subject.as_since_epoch(time)).to be_within(1).of(time.to_f * 1_000)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'converted to seconds' do
|
|
22
|
+
expect(subject.as_since_epoch(time, granularity: :s)).to eql(time.to_i)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with numeric' do
|
|
27
|
+
it 'converts to integer' do
|
|
28
|
+
expect(subject.as_since_epoch(1.01)).to eql(1)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'accepts integers' do
|
|
32
|
+
expect(subject.as_since_epoch(1)).to eql(1)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'with any other object' do
|
|
37
|
+
it 'raises an exception' do
|
|
38
|
+
expect { subject.as_since_epoch(Object.new) }.to raise_error ArgumentError
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context '#as_time_from_epoch' do
|
|
44
|
+
let(:method) { :as_time_from_epoch }
|
|
45
|
+
let(:time) { Time.new }
|
|
46
|
+
|
|
47
|
+
context 'with numeric' do
|
|
48
|
+
let(:millisecond) { Time.new.to_f * 1_000 }
|
|
49
|
+
let(:seconds) { Time.new.to_f }
|
|
50
|
+
|
|
51
|
+
it 'converts to Time from milliseconds by default' do
|
|
52
|
+
expect(subject.as_time_from_epoch(millisecond).to_f).to be_within(0.01).of(time.to_f)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'converts to Time from seconds' do
|
|
56
|
+
expect(subject.as_time_from_epoch(seconds, granularity: :s).to_i).to eql(time.to_i)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'with Time' do
|
|
61
|
+
it 'leaves intact' do
|
|
62
|
+
expect(subject.as_time_from_epoch(time)).to eql(time)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'with any other object' do
|
|
67
|
+
it 'raises an exception' do
|
|
68
|
+
expect { subject.as_time_from_epoch(Object.new) }.to raise_error ArgumentError
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ably::Modules::Enum, :api_private do
|
|
4
|
+
class ExampleClassWithEnum
|
|
5
|
+
extend Ably::Modules::Enum
|
|
6
|
+
ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', :value_zero, 'value_1', :value_snake_case_2, :SentenceCase)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
let(:enum) { ExampleClassWithEnum::ENUMEXAMPLE }
|
|
10
|
+
let(:enum_name) { 'ENUMEXAMPLE' }
|
|
11
|
+
|
|
12
|
+
context 'convertor method added to class' do
|
|
13
|
+
subject { ExampleClassWithEnum }
|
|
14
|
+
|
|
15
|
+
it 'converts symbols' do
|
|
16
|
+
expect(subject.ENUMEXAMPLE(:value_zero)).to eql(enum.get(:value_zero))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'converts strings' do
|
|
20
|
+
expect(subject.ENUMEXAMPLE('ValueZero')).to eql(enum.get(:value_zero))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'converts integer index' do
|
|
24
|
+
expect(subject.ENUMEXAMPLE(0)).to eql(enum.get(:value_zero))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'convertor method added to instance' do
|
|
29
|
+
subject { ExampleClassWithEnum.new }
|
|
30
|
+
|
|
31
|
+
it 'converts symbols' do
|
|
32
|
+
expect(subject.ENUMEXAMPLE(:value_zero)).to eql(enum.get(:value_zero))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'converts strings' do
|
|
36
|
+
expect(subject.ENUMEXAMPLE('ValueZero')).to eql(enum.get(:value_zero))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'converts integer index' do
|
|
40
|
+
expect(subject.ENUMEXAMPLE(0)).to eql(enum.get(:value_zero))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'defined Enum from Array class' do
|
|
45
|
+
subject { enum }
|
|
46
|
+
|
|
47
|
+
it 'provides a MixedCase const for each provided value' do
|
|
48
|
+
expect(subject.ValueZero).to be_a(subject)
|
|
49
|
+
expect(subject.ValueSnakeCase2).to be_a(subject)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context '#get' do
|
|
53
|
+
context 'by integer index' do
|
|
54
|
+
let(:return_val) { subject.get(0) }
|
|
55
|
+
it 'returns an enum' do
|
|
56
|
+
expect(return_val).to be_a(subject)
|
|
57
|
+
expect(return_val.to_sym).to eql(:value_zero)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context 'by string value' do
|
|
62
|
+
let(:return_val) { subject.get('value_zero') }
|
|
63
|
+
it 'returns an enum' do
|
|
64
|
+
expect(return_val).to be_a(subject)
|
|
65
|
+
expect(return_val.to_sym).to eql(:value_zero)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'by symbol' do
|
|
70
|
+
let(:return_val) { subject.get(:sentence_case) }
|
|
71
|
+
it 'returns an enum' do
|
|
72
|
+
expect(return_val).to be_a(subject)
|
|
73
|
+
expect(return_val.to_sym).to eql(:sentence_case)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context 'by enum' do
|
|
78
|
+
let(:return_val) { subject.get(subject.get(:sentence_case)) }
|
|
79
|
+
it 'returns an enum' do
|
|
80
|
+
expect(return_val).to be_a(subject)
|
|
81
|
+
expect(return_val.to_sym).to eql(:sentence_case)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context 'by invalid type' do
|
|
86
|
+
let(:return_val) { subject.get(Array.new) }
|
|
87
|
+
it 'raises an error' do
|
|
88
|
+
expect { return_val }.to raise_error KeyError
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context '#[]' do
|
|
94
|
+
let(:argument) { random_str }
|
|
95
|
+
before do
|
|
96
|
+
expect(subject).to receive(:get).with(argument).once.and_return(true)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'is an alias for get' do
|
|
100
|
+
subject[argument]
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'returns the provided Enum name' do
|
|
105
|
+
expect(subject.name).to eql(enum_name)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
specify '#to_s returns the Enum name' do
|
|
109
|
+
expect("#{subject}").to eql(enum_name)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context '#size' do
|
|
113
|
+
it 'returns the number of enum items' do
|
|
114
|
+
expect(subject.size).to eql(4)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'has alias #length' do
|
|
118
|
+
expect(subject.length).to eql(subject.size)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'freezes the Enum' do
|
|
123
|
+
expect(subject.send(:by_index)).to be_frozen
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'prevents modification' do
|
|
127
|
+
expect { subject.send(:define_values, :enum_id) }.to raise_error RuntimeError, /cannot be modified/
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'behaves like Enumerable' do
|
|
131
|
+
expect(subject.map(&:to_sym)).to eql([:value_zero, :value_1, :value_snake_case_2, :sentence_case])
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context '#each' do
|
|
135
|
+
it 'returns an enumerator' do
|
|
136
|
+
expect(subject.each).to be_a(Enumerator)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'yields each channel' do
|
|
140
|
+
expect(subject.each.map(&:to_sym)).to eql([:value_zero, :value_1, :value_snake_case_2, :sentence_case])
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context 'defined Enum from Hash class' do
|
|
146
|
+
class ExampleClassWithEnumFromHash
|
|
147
|
+
extend Ably::Modules::Enum
|
|
148
|
+
ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE',
|
|
149
|
+
value_one: 1,
|
|
150
|
+
value_five: 5
|
|
151
|
+
)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
subject { ExampleClassWithEnumFromHash::ENUMEXAMPLE }
|
|
155
|
+
|
|
156
|
+
it 'provides a MixedCase const for each provided value' do
|
|
157
|
+
expect(subject.ValueOne).to be_a(subject)
|
|
158
|
+
expect(subject.ValueFive).to be_a(subject)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
context '#get' do
|
|
162
|
+
context 'by integer index for 1' do
|
|
163
|
+
let(:return_val) { subject.get(1) }
|
|
164
|
+
it 'returns an enum' do
|
|
165
|
+
expect(return_val).to be_a(subject)
|
|
166
|
+
expect(return_val.to_sym).to eql(:value_one)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context 'by integer index for 5' do
|
|
171
|
+
let(:return_val) { subject.get(5) }
|
|
172
|
+
it 'returns an enum' do
|
|
173
|
+
expect(return_val).to be_a(subject)
|
|
174
|
+
expect(return_val.to_sym).to eql(:value_five)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
context 'by invalid integer index' do
|
|
179
|
+
let(:return_val) { subject.get(0) }
|
|
180
|
+
it 'raises an exception' do
|
|
181
|
+
expect { return_val }.to raise_error KeyError
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context 'by string value' do
|
|
186
|
+
let(:return_val) { subject.get('value_five') }
|
|
187
|
+
it 'returns an enum' do
|
|
188
|
+
expect(return_val).to be_a(subject)
|
|
189
|
+
expect(return_val.to_sym).to eql(:value_five)
|
|
190
|
+
expect(return_val.to_i).to eql(5)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
context 'defined Enum from another Enum' do
|
|
197
|
+
class ExampleBaseEnum
|
|
198
|
+
extend Ably::Modules::Enum
|
|
199
|
+
ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', :one, :second_enum)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
class ExampleOtherEnum
|
|
203
|
+
extend Ably::Modules::Enum
|
|
204
|
+
ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', ExampleBaseEnum::ENUMEXAMPLE)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
subject { ExampleOtherEnum::ENUMEXAMPLE }
|
|
208
|
+
|
|
209
|
+
it 'provides a MixedCase const for each provided value' do
|
|
210
|
+
expect(subject.One).to be_a(subject)
|
|
211
|
+
expect(subject.SecondEnum).to be_a(subject)
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context 'Enum instance' do
|
|
216
|
+
context '#==' do
|
|
217
|
+
subject { enum.get(:value_snake_case_2) }
|
|
218
|
+
|
|
219
|
+
it 'compares with a symbol' do
|
|
220
|
+
expect(subject).to eq(:value_Snake_Case_2)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it 'compares with a string' do
|
|
224
|
+
expect(subject).to eq('ValueSnakeCase2')
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'compares with a integer index' do
|
|
228
|
+
expect(subject).to eq(subject.to_i)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'compares with itself' do
|
|
232
|
+
expect(subject).to eq(subject)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it 'compares with other Objects' do
|
|
236
|
+
expect(subject).to_not eq(Object.new)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
context '#to_s' do
|
|
241
|
+
subject { enum.get(:value_zero) }
|
|
242
|
+
|
|
243
|
+
it 'returns ENUMNAME.CamelCase name' do
|
|
244
|
+
expect(subject.to_s).to eql("#{enum_name}.ValueZero")
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
context '#to_sym' do
|
|
249
|
+
subject { enum.get(:value_zero) }
|
|
250
|
+
|
|
251
|
+
it 'returns a snake_case symbol' do
|
|
252
|
+
expect(subject.to_sym).to eql(:value_zero)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
context '#to_i' do
|
|
257
|
+
subject { enum.get(:value_1) }
|
|
258
|
+
|
|
259
|
+
it 'returns the Enum index' do
|
|
260
|
+
expect(subject.to_i).to eql(1)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
context '#to_json' do
|
|
265
|
+
subject { enum.get(:value_1) }
|
|
266
|
+
|
|
267
|
+
it 'returns a symbol string key value' do
|
|
268
|
+
expect(subject.to_json).to eql('"value_1"')
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|