ably 0.6.2 → 0.7.0
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 +4 -4
- data/.rspec +1 -0
- data/.ruby-version.old +1 -0
- data/.travis.yml +0 -2
- data/Rakefile +22 -4
- data/SPEC.md +1676 -0
- data/ably.gemspec +1 -1
- data/lib/ably.rb +0 -8
- data/lib/ably/auth.rb +54 -46
- data/lib/ably/exceptions.rb +19 -5
- data/lib/ably/logger.rb +1 -1
- data/lib/ably/models/error_info.rb +1 -1
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +11 -9
- data/lib/ably/models/message.rb +15 -12
- data/lib/ably/models/message_encoders/base.rb +6 -5
- data/lib/ably/models/message_encoders/base64.rb +1 -0
- data/lib/ably/models/message_encoders/cipher.rb +6 -3
- data/lib/ably/models/message_encoders/json.rb +1 -0
- data/lib/ably/models/message_encoders/utf8.rb +2 -9
- data/lib/ably/models/nil_logger.rb +20 -0
- data/lib/ably/models/paginated_resource.rb +5 -2
- data/lib/ably/models/presence_message.rb +21 -12
- data/lib/ably/models/protocol_message.rb +22 -6
- data/lib/ably/modules/ably.rb +11 -0
- data/lib/ably/modules/async_wrapper.rb +2 -0
- data/lib/ably/modules/conversions.rb +23 -3
- data/lib/ably/modules/encodeable.rb +2 -1
- data/lib/ably/modules/enum.rb +2 -0
- data/lib/ably/modules/event_emitter.rb +7 -1
- data/lib/ably/modules/event_machine_helpers.rb +2 -0
- data/lib/ably/modules/http_helpers.rb +2 -0
- data/lib/ably/modules/model_common.rb +12 -2
- data/lib/ably/modules/state_emitter.rb +76 -0
- data/lib/ably/modules/state_machine.rb +53 -0
- data/lib/ably/modules/statesman_monkey_patch.rb +33 -0
- data/lib/ably/modules/uses_state_machine.rb +74 -0
- data/lib/ably/realtime.rb +4 -2
- data/lib/ably/realtime/channel.rb +51 -58
- data/lib/ably/realtime/channel/channel_manager.rb +91 -0
- data/lib/ably/realtime/channel/channel_state_machine.rb +68 -0
- data/lib/ably/realtime/client.rb +70 -26
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +31 -13
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
- data/lib/ably/realtime/connection.rb +135 -92
- data/lib/ably/realtime/connection/connection_manager.rb +216 -33
- data/lib/ably/realtime/connection/connection_state_machine.rb +30 -73
- data/lib/ably/realtime/models/nil_channel.rb +10 -1
- data/lib/ably/realtime/presence.rb +336 -92
- data/lib/ably/rest.rb +2 -2
- data/lib/ably/rest/channel.rb +13 -4
- data/lib/ably/rest/client.rb +138 -38
- data/lib/ably/rest/middleware/logger.rb +24 -3
- data/lib/ably/rest/presence.rb +12 -7
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +101 -85
- data/spec/acceptance/realtime/channel_spec.rb +461 -120
- data/spec/acceptance/realtime/client_spec.rb +119 -0
- data/spec/acceptance/realtime/connection_failures_spec.rb +499 -0
- data/spec/acceptance/realtime/connection_spec.rb +571 -97
- data/spec/acceptance/realtime/message_spec.rb +347 -333
- data/spec/acceptance/realtime/presence_history_spec.rb +35 -40
- data/spec/acceptance/realtime/presence_spec.rb +769 -239
- data/spec/acceptance/realtime/stats_spec.rb +14 -22
- data/spec/acceptance/realtime/time_spec.rb +16 -20
- data/spec/acceptance/rest/auth_spec.rb +425 -364
- data/spec/acceptance/rest/base_spec.rb +108 -176
- data/spec/acceptance/rest/channel_spec.rb +89 -89
- data/spec/acceptance/rest/channels_spec.rb +30 -32
- data/spec/acceptance/rest/client_spec.rb +273 -0
- data/spec/acceptance/rest/encoders_spec.rb +185 -0
- data/spec/acceptance/rest/message_spec.rb +186 -163
- data/spec/acceptance/rest/presence_spec.rb +150 -111
- data/spec/acceptance/rest/stats_spec.rb +45 -40
- data/spec/acceptance/rest/time_spec.rb +8 -10
- data/spec/rspec_config.rb +10 -1
- data/spec/shared/client_initializer_behaviour.rb +212 -0
- data/spec/{support/model_helper.rb → shared/model_behaviour.rb} +6 -6
- data/spec/{support/protocol_msgbus_helper.rb → shared/protocol_msgbus_behaviour.rb} +1 -1
- data/spec/spec_helper.rb +9 -0
- data/spec/support/api_helper.rb +11 -0
- data/spec/support/event_machine_helper.rb +101 -3
- data/spec/support/markdown_spec_formatter.rb +90 -0
- data/spec/support/private_api_formatter.rb +36 -0
- data/spec/support/protocol_helper.rb +32 -0
- data/spec/support/random_helper.rb +15 -0
- data/spec/support/test_app.rb +4 -0
- data/spec/unit/auth_spec.rb +68 -0
- data/spec/unit/logger_spec.rb +77 -66
- data/spec/unit/models/error_info_spec.rb +1 -1
- data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +2 -3
- data/spec/unit/models/message_encoders/base64_spec.rb +2 -2
- data/spec/unit/models/message_encoders/cipher_spec.rb +2 -2
- data/spec/unit/models/message_encoders/utf8_spec.rb +2 -46
- data/spec/unit/models/message_spec.rb +160 -15
- data/spec/unit/models/paginated_resource_spec.rb +29 -27
- data/spec/unit/models/presence_message_spec.rb +163 -20
- data/spec/unit/models/protocol_message_spec.rb +43 -8
- data/spec/unit/modules/async_wrapper_spec.rb +2 -3
- data/spec/unit/modules/conversions_spec.rb +1 -1
- data/spec/unit/modules/enum_spec.rb +2 -3
- data/spec/unit/modules/event_emitter_spec.rb +62 -5
- data/spec/unit/modules/state_emitter_spec.rb +283 -0
- data/spec/unit/realtime/channel_spec.rb +107 -2
- data/spec/unit/realtime/channels_spec.rb +1 -0
- data/spec/unit/realtime/client_spec.rb +8 -48
- data/spec/unit/realtime/connection_spec.rb +3 -3
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +2 -2
- data/spec/unit/realtime/presence_spec.rb +13 -4
- data/spec/unit/realtime/realtime_spec.rb +0 -11
- data/spec/unit/realtime/websocket_transport_spec.rb +2 -2
- data/spec/unit/rest/channel_spec.rb +109 -0
- data/spec/unit/rest/channels_spec.rb +4 -3
- data/spec/unit/rest/client_spec.rb +30 -125
- data/spec/unit/rest/rest_spec.rb +10 -0
- data/spec/unit/util/crypto_spec.rb +10 -5
- data/spec/unit/util/pub_sub_spec.rb +5 -5
- metadata +44 -12
- data/spec/integration/modules/state_emitter_spec.rb +0 -80
- data/spec/integration/rest/auth.rb +0 -9
@@ -1,5 +1,6 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'spec_helper'
|
2
|
-
require '
|
3
|
+
require 'shared/protocol_msgbus_behaviour'
|
3
4
|
|
4
5
|
describe Ably::Realtime::Channel do
|
5
6
|
let(:client) { double('client').as_null_object }
|
@@ -9,6 +10,110 @@ describe Ably::Realtime::Channel do
|
|
9
10
|
Ably::Realtime::Channel.new(client, channel_name)
|
10
11
|
end
|
11
12
|
|
13
|
+
describe '#initializer' do
|
14
|
+
let(:channel_name) { random_str.encode(encoding) }
|
15
|
+
|
16
|
+
context 'as UTF_8 string' do
|
17
|
+
let(:encoding) { Encoding::UTF_8 }
|
18
|
+
|
19
|
+
it 'is permitted' do
|
20
|
+
expect(subject.name).to eql(channel_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'remains as UTF-8' do
|
24
|
+
expect(subject.name.encoding).to eql(encoding)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'as SHIFT_JIS string' do
|
29
|
+
let(:encoding) { Encoding::SHIFT_JIS }
|
30
|
+
|
31
|
+
it 'gets converted to UTF-8' do
|
32
|
+
expect(subject.name.encoding).to eql(Encoding::UTF_8)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'is compatible with original encoding' do
|
36
|
+
expect(subject.name.encode(encoding)).to eql(channel_name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'as ASCII_8BIT string' do
|
41
|
+
let(:encoding) { Encoding::ASCII_8BIT }
|
42
|
+
|
43
|
+
it 'gets converted to UTF-8' do
|
44
|
+
expect(subject.name.encoding).to eql(Encoding::UTF_8)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'is compatible with original encoding' do
|
48
|
+
expect(subject.name.encode(encoding)).to eql(channel_name)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'as Integer' do
|
53
|
+
let(:channel_name) { 1 }
|
54
|
+
|
55
|
+
it 'raises an argument error' do
|
56
|
+
expect { subject }.to raise_error ArgumentError, /must be a String/
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'as Nil' do
|
61
|
+
let(:channel_name) { nil }
|
62
|
+
|
63
|
+
it 'raises an argument error' do
|
64
|
+
expect { subject }.to raise_error ArgumentError, /must be a String/
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#publish name argument' do
|
70
|
+
let(:encoded_value) { random_str.encode(encoding) }
|
71
|
+
|
72
|
+
before do
|
73
|
+
allow(subject).to receive(:create_message).and_return('message_stubbed')
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'as UTF_8 string' do
|
77
|
+
let(:encoding) { Encoding::UTF_8 }
|
78
|
+
|
79
|
+
it 'is permitted' do
|
80
|
+
expect(subject.publish(encoded_value, 'data')).to eql('message_stubbed')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'as SHIFT_JIS string' do
|
85
|
+
let(:encoding) { Encoding::SHIFT_JIS }
|
86
|
+
|
87
|
+
it 'is permitted' do
|
88
|
+
expect(subject.publish(encoded_value, 'data')).to eql('message_stubbed')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'as ASCII_8BIT string' do
|
93
|
+
let(:encoding) { Encoding::ASCII_8BIT }
|
94
|
+
|
95
|
+
it 'is permitted' do
|
96
|
+
expect(subject.publish(encoded_value, 'data')).to eql('message_stubbed')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'as Integer' do
|
101
|
+
let(:encoded_value) { 1 }
|
102
|
+
|
103
|
+
it 'raises an argument error' do
|
104
|
+
expect { subject.publish(encoded_value, 'data') }.to raise_error ArgumentError, /must be a String/
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'as Nil' do
|
109
|
+
let(:encoded_value) { nil }
|
110
|
+
|
111
|
+
it 'raises an argument error' do
|
112
|
+
expect { subject.publish(encoded_value, 'data') }.to raise_error ArgumentError, /must be a String/
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
12
117
|
describe 'callbacks' do
|
13
118
|
specify 'are supported for valid STATE events' do
|
14
119
|
state = nil
|
@@ -23,7 +128,7 @@ describe Ably::Realtime::Channel do
|
|
23
128
|
end
|
24
129
|
end
|
25
130
|
|
26
|
-
context 'msgbus' do
|
131
|
+
context 'msgbus', :api_private do
|
27
132
|
let(:message) do
|
28
133
|
Ably::Models::Message.new({
|
29
134
|
'name' => 'test',
|
@@ -1,70 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'spec_helper'
|
2
|
-
require '
|
3
|
+
require 'shared/client_initializer_behaviour'
|
3
4
|
|
4
5
|
describe Ably::Realtime::Client do
|
5
|
-
let(:client_options) { 'appid.keyuid:keysecret' }
|
6
6
|
subject do
|
7
7
|
Ably::Realtime::Client.new(client_options)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
it_behaves_like 'a client initializer'
|
11
|
+
|
12
|
+
context 'delegation to the REST Client' do
|
13
|
+
let(:client_options) { { api_key: 'appid.keyuid:keysecret' } }
|
12
14
|
|
13
15
|
it 'passes on the options to the initializer' do
|
14
|
-
rest_client = instance_double('Ably::Rest::Client', auth: instance_double('Ably::Auth'), options:
|
16
|
+
rest_client = instance_double('Ably::Rest::Client', auth: instance_double('Ably::Auth'), options: client_options)
|
15
17
|
expect(Ably::Rest::Client).to receive(:new).with(client_options).and_return(rest_client)
|
16
18
|
subject
|
17
19
|
end
|
18
20
|
|
19
21
|
context 'for attribute' do
|
20
|
-
[:environment, :use_tls?, :log_level].each do |attribute|
|
22
|
+
[:environment, :use_tls?, :log_level, :custom_host].each do |attribute|
|
21
23
|
specify "##{attribute}" do
|
22
24
|
expect(subject.rest_client).to receive(attribute)
|
23
25
|
subject.public_send attribute
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
27
|
-
|
28
|
-
context 'logger' do
|
29
|
-
context 'defaults' do
|
30
|
-
let(:logger) { subject.logger }
|
31
|
-
|
32
|
-
subject { Ably::Realtime::Client.new(client_options) }
|
33
|
-
|
34
|
-
it 'uses default Ruby Logger by default' do
|
35
|
-
expect(subject.logger.logger).to be_a(::Logger)
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'defaults to Logger::ERROR log level' do
|
39
|
-
expect(subject.logger.log_level).to eql(::Logger::ERROR)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'returns the connection ID' do
|
43
|
-
allow(subject).to receive_message_chain(:connection, :id).and_return('AAA')
|
44
|
-
expect(logger.logger.formatter.call(0, Time.now, '', 'unique_message')).to match(/AAA/)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'with custom logger and log_level' do
|
49
|
-
let(:custom_logger) do
|
50
|
-
Class.new do
|
51
|
-
extend Forwardable
|
52
|
-
def initialize
|
53
|
-
@logger = Logger.new(STDOUT)
|
54
|
-
end
|
55
|
-
def_delegators :@logger, :fatal, :error, :warn, :info, :debug, :level, :level=
|
56
|
-
end
|
57
|
-
end
|
58
|
-
subject { Ably::Realtime::Client.new(api_key: 'appid.keyuid:keysecret', logger: custom_logger.new, log_level: :debug) }
|
59
|
-
|
60
|
-
it 'uses the custom logger' do
|
61
|
-
expect(subject.logger.logger.class).to eql(custom_logger)
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'sets the custom log level' do
|
65
|
-
expect(subject.logger.log_level).to eql(Logger::DEBUG)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
29
|
end
|
70
30
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require '
|
3
|
-
require 'support/event_machine_helper'
|
2
|
+
require 'shared/protocol_msgbus_behaviour'
|
4
3
|
|
5
4
|
describe Ably::Realtime::Connection do
|
6
5
|
let(:client) { instance_double('Ably::Realtime::Client', logger: double('logger').as_null_object) }
|
@@ -10,8 +9,9 @@ describe Ably::Realtime::Connection do
|
|
10
9
|
end
|
11
10
|
|
12
11
|
before do
|
13
|
-
expect(EventMachine::Timer).to receive(:new) # Connection Manager #initializer
|
14
12
|
expect(EventMachine).to receive(:next_tick) # non_blocking_loop_while for delivery of messages async
|
13
|
+
subject.__incoming_protocol_msgbus__.off
|
14
|
+
subject.__outgoing_protocol_msgbus__.off
|
15
15
|
end
|
16
16
|
|
17
17
|
describe 'callbacks' do
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Ably::Realtime::Client::IncomingMessageDispatcher do
|
3
|
+
describe Ably::Realtime::Client::IncomingMessageDispatcher, :api_private do
|
4
4
|
let(:msgbus) do
|
5
5
|
Ably::Util::PubSub.new
|
6
6
|
end
|
7
7
|
let(:connection) do
|
8
|
-
instance_double('Ably::Realtime::Connection', __incoming_protocol_msgbus__: msgbus,
|
8
|
+
instance_double('Ably::Realtime::Connection', __incoming_protocol_msgbus__: msgbus, update_connection_id_and_key: true, id: nil)
|
9
9
|
end
|
10
10
|
let(:client) do
|
11
11
|
instance_double('Ably::Realtime::Client', channels: {})
|
@@ -1,5 +1,6 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'spec_helper'
|
2
|
-
require '
|
3
|
+
require 'shared/protocol_msgbus_behaviour'
|
3
4
|
|
4
5
|
describe Ably::Realtime::Presence do
|
5
6
|
let(:channel) { double('Ably::Realtime::Channel').as_null_object }
|
@@ -22,11 +23,11 @@ describe Ably::Realtime::Presence do
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
context 'msgbus' do
|
26
|
+
context 'msgbus', :api_private do
|
26
27
|
let(:message) do
|
27
28
|
Ably::Models::PresenceMessage.new({
|
28
29
|
'action' => 0,
|
29
|
-
'
|
30
|
+
'connection_id' => random_str,
|
30
31
|
}, instance_double('Ably::Models::ProtocolMessage'))
|
31
32
|
end
|
32
33
|
let(:msgbus) { subject.__incoming_msgbus__ }
|
@@ -48,10 +49,14 @@ describe Ably::Realtime::Presence do
|
|
48
49
|
let(:message_history) { Hash.new { |hash, key| hash[key] = 0 } }
|
49
50
|
let(:presence_action) { Ably::Models::PresenceMessage::ACTION.Enter }
|
50
51
|
let(:message) do
|
51
|
-
instance_double('Ably::Models::PresenceMessage', action: presence_action,
|
52
|
+
instance_double('Ably::Models::PresenceMessage', action: presence_action, connection_id: random_str, decode: true, member_key: random_str)
|
52
53
|
end
|
53
54
|
|
54
55
|
context '#subscribe' do
|
56
|
+
before do
|
57
|
+
subject.sync_completed
|
58
|
+
end
|
59
|
+
|
55
60
|
specify 'to all presence state actions' do
|
56
61
|
subject.subscribe { |message| message_history[:received] += 1}
|
57
62
|
subject.__incoming_msgbus__.publish(:presence, message)
|
@@ -67,6 +72,10 @@ describe Ably::Realtime::Presence do
|
|
67
72
|
end
|
68
73
|
|
69
74
|
context '#unsubscribe' do
|
75
|
+
before do
|
76
|
+
subject.sync_completed
|
77
|
+
end
|
78
|
+
|
70
79
|
let(:callback) do
|
71
80
|
Proc.new { |message| message_history[:received] += 1 }
|
72
81
|
end
|
@@ -6,15 +6,4 @@ describe Ably::Realtime do
|
|
6
6
|
specify 'constructor returns an Ably::Realtime::Client' do
|
7
7
|
expect(Ably::Realtime.new(options)).to be_instance_of(Ably::Realtime::Client)
|
8
8
|
end
|
9
|
-
|
10
|
-
describe Ably::Realtime::Client do
|
11
|
-
describe 'initializing the client' do
|
12
|
-
it 'should disallow an invalid key' do
|
13
|
-
expect { Ably::Realtime::Client.new({}) }.to raise_error(ArgumentError, /api_key is missing/)
|
14
|
-
expect { Ably::Realtime::Client.new(api_key: 'invalid') }.to raise_error(ArgumentError, /api_key is invalid/)
|
15
|
-
expect { Ably::Realtime::Client.new(api_key: 'invalid:asdad') }.to raise_error(ArgumentError, /api_key is invalid/)
|
16
|
-
expect { Ably::Realtime::Client.new(api_key: 'appid.keyuid:keysecret') }.to_not raise_error
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
9
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require '
|
2
|
+
require 'shared/protocol_msgbus_behaviour'
|
3
3
|
|
4
|
-
describe Ably::Realtime::Connection::WebsocketTransport do
|
4
|
+
describe Ably::Realtime::Connection::WebsocketTransport, :api_private do
|
5
5
|
let(:client_ignored) { double('Ably::Realtime::Client').as_null_object }
|
6
6
|
let(:connection) { instance_double('Ably::Realtime::Connection', client: client_ignored, id: nil) }
|
7
7
|
let(:url) { 'http://ably.io/' }
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Ably::Rest::Channels do
|
5
|
+
let(:client) { instance_double('Ably::Rest::Client', encoders: [], post: instance_double('Faraday::Response', status: 201)) }
|
6
|
+
let(:channel_name) { 'unique' }
|
7
|
+
|
8
|
+
subject { Ably::Rest::Channel.new(client, channel_name) }
|
9
|
+
|
10
|
+
describe '#initializer' do
|
11
|
+
let(:channel_name) { random_str.encode(encoding) }
|
12
|
+
|
13
|
+
context 'as UTF_8 string' do
|
14
|
+
let(:encoding) { Encoding::UTF_8 }
|
15
|
+
|
16
|
+
it 'is permitted' do
|
17
|
+
expect(subject.name).to eql(channel_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'remains as UTF-8' do
|
21
|
+
expect(subject.name.encoding).to eql(encoding)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'as SHIFT_JIS string' do
|
26
|
+
let(:encoding) { Encoding::SHIFT_JIS }
|
27
|
+
|
28
|
+
it 'gets converted to UTF-8' do
|
29
|
+
expect(subject.name.encoding).to eql(Encoding::UTF_8)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'is compatible with original encoding' do
|
33
|
+
expect(subject.name.encode(encoding)).to eql(channel_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'as ASCII_8BIT string' do
|
38
|
+
let(:encoding) { Encoding::ASCII_8BIT }
|
39
|
+
|
40
|
+
it 'gets converted to UTF-8' do
|
41
|
+
expect(subject.name.encoding).to eql(Encoding::UTF_8)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'is compatible with original encoding' do
|
45
|
+
expect(subject.name.encode(encoding)).to eql(channel_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'as Integer' do
|
50
|
+
let(:channel_name) { 1 }
|
51
|
+
|
52
|
+
it 'raises an argument error' do
|
53
|
+
expect { subject }.to raise_error ArgumentError, /must be a String/
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'as Nil' do
|
58
|
+
let(:channel_name) { nil }
|
59
|
+
|
60
|
+
it 'raises an argument error' do
|
61
|
+
expect { subject }.to raise_error ArgumentError, /must be a String/
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#publish name argument' do
|
67
|
+
let(:encoded_value) { random_str.encode(encoding) }
|
68
|
+
|
69
|
+
context 'as UTF_8 string' do
|
70
|
+
let(:encoding) { Encoding::UTF_8 }
|
71
|
+
|
72
|
+
it 'is permitted' do
|
73
|
+
expect(subject.publish(encoded_value, 'data')).to eql(true)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'as SHIFT_JIS string' do
|
78
|
+
let(:encoding) { Encoding::SHIFT_JIS }
|
79
|
+
|
80
|
+
it 'is permitted' do
|
81
|
+
expect(subject.publish(encoded_value, 'data')).to eql(true)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'as ASCII_8BIT string' do
|
86
|
+
let(:encoding) { Encoding::ASCII_8BIT }
|
87
|
+
|
88
|
+
it 'is permitted' do
|
89
|
+
expect(subject.publish(encoded_value, 'data')).to eql(true)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'as Integer' do
|
94
|
+
let(:encoded_value) { 1 }
|
95
|
+
|
96
|
+
it 'raises an argument error' do
|
97
|
+
expect { subject.publish(encoded_value, 'data') }.to raise_error ArgumentError, /must be a String/
|
98
|
+
end
|
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
|
+
end
|
109
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'spec_helper'
|
2
3
|
|
3
4
|
describe Ably::Rest::Channels do
|
4
|
-
let(:client)
|
5
|
-
let(:channel_name) { 'unique' }
|
6
|
-
let(:options)
|
5
|
+
let(:client) { instance_double('Ably::Rest::Client') }
|
6
|
+
let(:channel_name) { 'unique'.encode(Encoding::UTF_8) }
|
7
|
+
let(:options) { { 'bizarre' => 'value' } }
|
7
8
|
|
8
9
|
subject { Ably::Rest::Channels.new(client) }
|
9
10
|
|
@@ -1,145 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'spec_helper'
|
3
|
+
require 'shared/client_initializer_behaviour'
|
2
4
|
|
3
|
-
describe Ably::Rest do
|
4
|
-
|
5
|
-
|
6
|
-
specify 'constructor returns an Ably::Rest::Client' do
|
7
|
-
expect(Ably::Rest.new(options)).to be_instance_of(Ably::Rest::Client)
|
5
|
+
describe Ably::Rest::Client do
|
6
|
+
subject do
|
7
|
+
Ably::Rest::Client.new(client_options)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
describe 'initializing the client' do
|
12
|
-
it 'should disallow an invalid key' do
|
13
|
-
expect { Ably::Rest::Client.new({}) }.to raise_error(ArgumentError, /api_key is missing/)
|
14
|
-
expect { Ably::Rest::Client.new(api_key: 'invalid') }.to raise_error(ArgumentError, /api_key is invalid/)
|
15
|
-
expect { Ably::Rest::Client.new(api_key: 'invalid:asdad') }.to raise_error(ArgumentError, /api_key is invalid/)
|
16
|
-
expect { Ably::Rest::Client.new(api_key: 'appid.keyuid:keysecret') }.to_not raise_error
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should disallow api_key and key_id' do
|
20
|
-
expect { Ably::Rest::Client.new(api_key: 'valid', key_id: 'invalid') }.to raise_error(ArgumentError, /api_key and key_id or key_secret are mutually exclusive/)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should disallow api_key and key_secret' do
|
24
|
-
expect { Ably::Rest::Client.new(api_key: 'valid', key_secret: 'invalid') }.to raise_error(ArgumentError, /api_key and key_id or key_secret are mutually exclusive/)
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'using key_id and key_secret' do
|
28
|
-
let(:client) { Ably::Rest::Client.new(key_id: 'id', key_secret: 'secret') }
|
29
|
-
|
30
|
-
it 'should allow key_id and key_secret in place of api_key' do
|
31
|
-
expect(client.auth.api_key).to eql('id:secret')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'with a string key instead of options' do
|
36
|
-
let(:options) { 'app.key:secret' }
|
37
|
-
subject { Ably::Rest::Client.new(options) }
|
38
|
-
|
39
|
-
it 'should set the api_key' do
|
40
|
-
expect(subject.auth.api_key).to eql(options)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should set the key_id' do
|
44
|
-
expect(subject.auth.key_id).to eql('app.key')
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should set the key_secret' do
|
48
|
-
expect(subject.auth.key_secret).to eql('secret')
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'with a client_id' do
|
53
|
-
it "should require a valid key" do
|
54
|
-
expect { Ably::Rest::Client.new(client_id: 'valid') }.to raise_error(ArgumentError, /client_id cannot be provided without a complete API key/)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should default to the production REST end point' do
|
59
|
-
expect(Ably::Rest::Client.new(api_key: 'appid.keyuid:keysecret').endpoint.to_s).to eql('https://rest.ably.io')
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'should allow an environment to be set' do
|
63
|
-
expect(Ably::Rest::Client.new(api_key: 'appid.keyuid:keysecret', environment: 'sandbox').endpoint.to_s).to eql('https://sandbox-rest.ably.io')
|
64
|
-
end
|
65
|
-
|
66
|
-
context 'with TLS disabled' do
|
67
|
-
let(:client) { Ably::Rest::Client.new(api_key: 'appid.keyid:secret', tls: false) }
|
68
|
-
|
69
|
-
it 'uses plain text' do
|
70
|
-
expect(client.use_tls?).to eql(false)
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'uses HTTP' do
|
74
|
-
expect(client.endpoint.to_s).to eql('http://rest.ably.io')
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'fails when authenticating with basic auth' do
|
78
|
-
expect { client.channel('a').publish('event', 'message') }.to raise_error(Ably::Exceptions::InsecureRequestError)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'with no TLS option provided' do
|
83
|
-
let(:client) { Ably::Rest::Client.new(api_key: 'appid.keyid:secret') }
|
84
|
-
|
85
|
-
it 'defaults to TLS' do
|
86
|
-
expect(client.use_tls?).to eql(true)
|
87
|
-
end
|
88
|
-
end
|
10
|
+
it_behaves_like 'a client initializer'
|
89
11
|
|
90
|
-
|
91
|
-
|
12
|
+
context 'initializer options' do
|
13
|
+
context 'TLS' do
|
14
|
+
context 'disabled' do
|
15
|
+
let(:client_options) { { api_key: 'appid.keyuid:keysecret', tls: false } }
|
92
16
|
|
93
|
-
it '
|
94
|
-
expect(
|
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)
|
95
19
|
end
|
96
20
|
end
|
21
|
+
end
|
97
22
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
expect(subject.auth).to receive(:client_id).and_return('john')
|
103
|
-
expect(subject.client_id).to eql('john')
|
104
|
-
end
|
23
|
+
context ':use_token_auth' do
|
24
|
+
context 'set to false' do
|
25
|
+
context 'with an api_key with :tls => false' do
|
26
|
+
let(:client_options) { { use_token_auth: false, api_key: 'appid.keyuid:keysecret', tls: false } }
|
105
27
|
|
106
|
-
|
107
|
-
|
108
|
-
|
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)
|
30
|
+
end
|
109
31
|
end
|
110
|
-
end
|
111
32
|
|
112
|
-
|
113
|
-
|
114
|
-
subject { Ably::Rest::Client.new(options) }
|
33
|
+
context 'without an api_key' do
|
34
|
+
let(:client_options) { { use_token_auth: false } }
|
115
35
|
|
116
|
-
it '
|
117
|
-
expect
|
118
|
-
end
|
119
|
-
|
120
|
-
it 'defaults to Logger::ERROR log level' do
|
121
|
-
expect(subject.logger.log_level).to eql(::Logger::ERROR)
|
36
|
+
it 'fails as an api_key is required if not using token auth' do
|
37
|
+
expect { subject.channel('a').publish('event', 'message') }.to raise_error(ArgumentError)
|
122
38
|
end
|
123
39
|
end
|
40
|
+
end
|
124
41
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
extend Forwardable
|
129
|
-
def initialize
|
130
|
-
@logger = Logger.new(STDOUT)
|
131
|
-
end
|
132
|
-
def_delegators :@logger, :fatal, :error, :warn, :info, :debug, :level, :level=
|
133
|
-
end
|
134
|
-
end
|
135
|
-
subject { Ably::Rest::Client.new(options.merge(logger: custom_logger.new, log_level: :debug)) }
|
136
|
-
|
137
|
-
it 'uses the custom logger' do
|
138
|
-
expect(subject.logger.logger.class).to eql(custom_logger)
|
139
|
-
end
|
42
|
+
context 'set to true' do
|
43
|
+
context 'without an api_key or token_id' do
|
44
|
+
let(:client_options) { { use_token_auth: true, api_key: true } }
|
140
45
|
|
141
|
-
it '
|
142
|
-
expect
|
46
|
+
it 'fails as an api_key is required to issue tokens' do
|
47
|
+
expect { subject.channel('a').publish('event', 'message') }.to raise_error(ArgumentError)
|
143
48
|
end
|
144
49
|
end
|
145
50
|
end
|