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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.ruby-version.old +1 -0
  4. data/.travis.yml +0 -2
  5. data/Rakefile +22 -4
  6. data/SPEC.md +1676 -0
  7. data/ably.gemspec +1 -1
  8. data/lib/ably.rb +0 -8
  9. data/lib/ably/auth.rb +54 -46
  10. data/lib/ably/exceptions.rb +19 -5
  11. data/lib/ably/logger.rb +1 -1
  12. data/lib/ably/models/error_info.rb +1 -1
  13. data/lib/ably/models/idiomatic_ruby_wrapper.rb +11 -9
  14. data/lib/ably/models/message.rb +15 -12
  15. data/lib/ably/models/message_encoders/base.rb +6 -5
  16. data/lib/ably/models/message_encoders/base64.rb +1 -0
  17. data/lib/ably/models/message_encoders/cipher.rb +6 -3
  18. data/lib/ably/models/message_encoders/json.rb +1 -0
  19. data/lib/ably/models/message_encoders/utf8.rb +2 -9
  20. data/lib/ably/models/nil_logger.rb +20 -0
  21. data/lib/ably/models/paginated_resource.rb +5 -2
  22. data/lib/ably/models/presence_message.rb +21 -12
  23. data/lib/ably/models/protocol_message.rb +22 -6
  24. data/lib/ably/modules/ably.rb +11 -0
  25. data/lib/ably/modules/async_wrapper.rb +2 -0
  26. data/lib/ably/modules/conversions.rb +23 -3
  27. data/lib/ably/modules/encodeable.rb +2 -1
  28. data/lib/ably/modules/enum.rb +2 -0
  29. data/lib/ably/modules/event_emitter.rb +7 -1
  30. data/lib/ably/modules/event_machine_helpers.rb +2 -0
  31. data/lib/ably/modules/http_helpers.rb +2 -0
  32. data/lib/ably/modules/model_common.rb +12 -2
  33. data/lib/ably/modules/state_emitter.rb +76 -0
  34. data/lib/ably/modules/state_machine.rb +53 -0
  35. data/lib/ably/modules/statesman_monkey_patch.rb +33 -0
  36. data/lib/ably/modules/uses_state_machine.rb +74 -0
  37. data/lib/ably/realtime.rb +4 -2
  38. data/lib/ably/realtime/channel.rb +51 -58
  39. data/lib/ably/realtime/channel/channel_manager.rb +91 -0
  40. data/lib/ably/realtime/channel/channel_state_machine.rb +68 -0
  41. data/lib/ably/realtime/client.rb +70 -26
  42. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +31 -13
  43. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  44. data/lib/ably/realtime/connection.rb +135 -92
  45. data/lib/ably/realtime/connection/connection_manager.rb +216 -33
  46. data/lib/ably/realtime/connection/connection_state_machine.rb +30 -73
  47. data/lib/ably/realtime/models/nil_channel.rb +10 -1
  48. data/lib/ably/realtime/presence.rb +336 -92
  49. data/lib/ably/rest.rb +2 -2
  50. data/lib/ably/rest/channel.rb +13 -4
  51. data/lib/ably/rest/client.rb +138 -38
  52. data/lib/ably/rest/middleware/logger.rb +24 -3
  53. data/lib/ably/rest/presence.rb +12 -7
  54. data/lib/ably/version.rb +1 -1
  55. data/spec/acceptance/realtime/channel_history_spec.rb +101 -85
  56. data/spec/acceptance/realtime/channel_spec.rb +461 -120
  57. data/spec/acceptance/realtime/client_spec.rb +119 -0
  58. data/spec/acceptance/realtime/connection_failures_spec.rb +499 -0
  59. data/spec/acceptance/realtime/connection_spec.rb +571 -97
  60. data/spec/acceptance/realtime/message_spec.rb +347 -333
  61. data/spec/acceptance/realtime/presence_history_spec.rb +35 -40
  62. data/spec/acceptance/realtime/presence_spec.rb +769 -239
  63. data/spec/acceptance/realtime/stats_spec.rb +14 -22
  64. data/spec/acceptance/realtime/time_spec.rb +16 -20
  65. data/spec/acceptance/rest/auth_spec.rb +425 -364
  66. data/spec/acceptance/rest/base_spec.rb +108 -176
  67. data/spec/acceptance/rest/channel_spec.rb +89 -89
  68. data/spec/acceptance/rest/channels_spec.rb +30 -32
  69. data/spec/acceptance/rest/client_spec.rb +273 -0
  70. data/spec/acceptance/rest/encoders_spec.rb +185 -0
  71. data/spec/acceptance/rest/message_spec.rb +186 -163
  72. data/spec/acceptance/rest/presence_spec.rb +150 -111
  73. data/spec/acceptance/rest/stats_spec.rb +45 -40
  74. data/spec/acceptance/rest/time_spec.rb +8 -10
  75. data/spec/rspec_config.rb +10 -1
  76. data/spec/shared/client_initializer_behaviour.rb +212 -0
  77. data/spec/{support/model_helper.rb → shared/model_behaviour.rb} +6 -6
  78. data/spec/{support/protocol_msgbus_helper.rb → shared/protocol_msgbus_behaviour.rb} +1 -1
  79. data/spec/spec_helper.rb +9 -0
  80. data/spec/support/api_helper.rb +11 -0
  81. data/spec/support/event_machine_helper.rb +101 -3
  82. data/spec/support/markdown_spec_formatter.rb +90 -0
  83. data/spec/support/private_api_formatter.rb +36 -0
  84. data/spec/support/protocol_helper.rb +32 -0
  85. data/spec/support/random_helper.rb +15 -0
  86. data/spec/support/test_app.rb +4 -0
  87. data/spec/unit/auth_spec.rb +68 -0
  88. data/spec/unit/logger_spec.rb +77 -66
  89. data/spec/unit/models/error_info_spec.rb +1 -1
  90. data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +2 -3
  91. data/spec/unit/models/message_encoders/base64_spec.rb +2 -2
  92. data/spec/unit/models/message_encoders/cipher_spec.rb +2 -2
  93. data/spec/unit/models/message_encoders/utf8_spec.rb +2 -46
  94. data/spec/unit/models/message_spec.rb +160 -15
  95. data/spec/unit/models/paginated_resource_spec.rb +29 -27
  96. data/spec/unit/models/presence_message_spec.rb +163 -20
  97. data/spec/unit/models/protocol_message_spec.rb +43 -8
  98. data/spec/unit/modules/async_wrapper_spec.rb +2 -3
  99. data/spec/unit/modules/conversions_spec.rb +1 -1
  100. data/spec/unit/modules/enum_spec.rb +2 -3
  101. data/spec/unit/modules/event_emitter_spec.rb +62 -5
  102. data/spec/unit/modules/state_emitter_spec.rb +283 -0
  103. data/spec/unit/realtime/channel_spec.rb +107 -2
  104. data/spec/unit/realtime/channels_spec.rb +1 -0
  105. data/spec/unit/realtime/client_spec.rb +8 -48
  106. data/spec/unit/realtime/connection_spec.rb +3 -3
  107. data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +2 -2
  108. data/spec/unit/realtime/presence_spec.rb +13 -4
  109. data/spec/unit/realtime/realtime_spec.rb +0 -11
  110. data/spec/unit/realtime/websocket_transport_spec.rb +2 -2
  111. data/spec/unit/rest/channel_spec.rb +109 -0
  112. data/spec/unit/rest/channels_spec.rb +4 -3
  113. data/spec/unit/rest/client_spec.rb +30 -125
  114. data/spec/unit/rest/rest_spec.rb +10 -0
  115. data/spec/unit/util/crypto_spec.rb +10 -5
  116. data/spec/unit/util/pub_sub_spec.rb +5 -5
  117. metadata +44 -12
  118. data/spec/integration/modules/state_emitter_spec.rb +0 -80
  119. data/spec/integration/rest/auth.rb +0 -9
@@ -1,17 +1,115 @@
1
+ require 'eventmachine'
2
+ require 'rspec'
1
3
  require 'timeout'
2
4
 
3
5
  module RSpec
4
6
  module EventMachine
5
- def run_reactor(timeout = 3)
7
+ extend self
8
+
9
+ DEFAULT_TIMEOUT = 5
10
+
11
+ def run_reactor(timeout = DEFAULT_TIMEOUT)
6
12
  Timeout::timeout(timeout + 0.5) do
7
- EM.run do
13
+ ::EventMachine.run do
8
14
  yield
9
15
  end
10
16
  end
11
17
  end
12
18
 
13
19
  def stop_reactor
14
- EM.stop
20
+ ::EventMachine.next_tick do
21
+ ::EventMachine.stop
22
+ end
23
+ end
24
+
25
+ # Allows multiple Deferrables to be passed in and calls the provided block when
26
+ # all success callbacks have completed
27
+ def when_all(*deferrables, &block)
28
+ raise "Block expected" unless block_given?
29
+
30
+ options = if deferrables.last.kind_of?(Hash)
31
+ deferrables.pop
32
+ else
33
+ {}
34
+ end
35
+
36
+ successful_deferrables = {}
37
+
38
+ deferrables.each do |deferrable|
39
+ deferrable.callback do
40
+ successful_deferrables[deferrable.object_id] = true
41
+ if successful_deferrables.keys.sort == deferrables.map(&:object_id).sort
42
+ if options[:and_wait]
43
+ ::EventMachine.add_timer(options[:and_wait]) { block.call }
44
+ else
45
+ block.call
46
+ end
47
+ end
48
+ end
49
+
50
+ deferrable.errback do |error|
51
+ raise RuntimeError, "Deferrable failed: #{error.message}"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ RSpec.configure do |config|
59
+ config.before(:context, :event_machine) do |context|
60
+ context.class.class_eval do
61
+ include RSpec::EventMachine
15
62
  end
16
63
  end
64
+
65
+ # Running a reactor block and then calling the example block with #call
66
+ # does not work as expected as the example completes immediately and the block
67
+ # calls after hooks before it returns the EventMachine loop.
68
+ #
69
+ # As there is no public API to inject around blocks correctly without calling the after blocks,
70
+ # we have to monkey patch the run_after_example method at https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/example.rb#L376
71
+ # so that it does not run until we explicitly call it once the EventMachine reactor loop is finished.
72
+ #
73
+ def patch_example_block_with_surrounding_eventmachine_reactor(example)
74
+ example.example.class.class_eval do
75
+ alias_method :run_after_example_original, :run_after_example
76
+ public :run_after_example_original
77
+
78
+ # prevent after hooks being run for example until EventMachine reactor has finished
79
+ def run_after_example; end
80
+ end
81
+ end
82
+
83
+ def remove_patch_example_block(example)
84
+ example.example.class.class_eval do
85
+ remove_method :run_after_example
86
+ alias_method :run_after_example, :run_after_example_original
87
+ remove_method :run_after_example_original
88
+ end
89
+ end
90
+
91
+ config.around(:example, :event_machine) do |example|
92
+ timeout = if example.metadata[:em_timeout].is_a?(Numeric)
93
+ example.metadata[:em_timeout]
94
+ else
95
+ RSpec::EventMachine::DEFAULT_TIMEOUT
96
+ end
97
+
98
+ patch_example_block_with_surrounding_eventmachine_reactor example
99
+
100
+ begin
101
+ RSpec::EventMachine.run_reactor(timeout) do
102
+ example.call
103
+ raise example.exception if example.exception
104
+ end
105
+ ensure
106
+ example.example.run_after_example_original
107
+ remove_patch_example_block example
108
+ end
109
+ end
110
+
111
+ config.before(:example) do
112
+ # Ensure EventMachine shutdown hooks are deregistered for every test
113
+ EventMachine.instance_variable_set '@tails', []
114
+ end
17
115
  end
@@ -0,0 +1,90 @@
1
+ module Ably::RSpec
2
+ # Generate Markdown Specification from the RSpec public API tests
3
+ #
4
+ class MarkdownSpecFormatter
5
+ ::RSpec::Core::Formatters.register self, :start, :close,
6
+ :example_group_started, :example_group_finished,
7
+ :example_passed, :example_failed, :example_pending,
8
+ :dump_summary
9
+
10
+ def initialize(output)
11
+ @output = File.open(File.expand_path('../../../SPEC.md', __FILE__), 'w')
12
+ @indent = 0
13
+ @passed = 0
14
+ @pending = 0
15
+ @failed = 0
16
+ end
17
+
18
+ def start(notification)
19
+ puts "\n\e[33m --> Creating SPEC.md <--\e[0m\n"
20
+ output.write "# Ably Client Library #{Ably::VERSION} Specification\n"
21
+ end
22
+
23
+ def close(notification)
24
+ output.close
25
+ end
26
+
27
+ def example_group_started(notification)
28
+ output.write "#{indent_prefix}#{notification.group.description}\n"
29
+ output.write "_(see #{heading_location_path(notification)})_\n" if indent == 0
30
+ @indent += 1
31
+ end
32
+
33
+ def example_group_finished(notification)
34
+ @indent -= 1
35
+ end
36
+
37
+ def example_passed(notification)
38
+ unless notification.example.metadata[:api_private]
39
+ output.write "#{indent_prefix}#{example_name_and_link(notification)}\n"
40
+ @passed += 1
41
+ end
42
+ end
43
+
44
+ def example_failed(notification)
45
+ unless notification.example.metadata[:api_private]
46
+ output.write "#{indent_prefix}FAILED: ~~#{example_name_and_link(notification)}~~\n"
47
+ @failed += 1
48
+ end
49
+ end
50
+
51
+ def example_pending(notification)
52
+ unless notification.example.metadata[:api_private]
53
+ output.write "#{indent_prefix}PENDING: *#{example_name_and_link(notification)}*\n"
54
+ @pending += 1
55
+ end
56
+ end
57
+
58
+ def dump_summary(notification)
59
+ output.write <<-EOF.gsub(' ', '')
60
+
61
+ -------
62
+
63
+ ## Test summary
64
+
65
+ * Passing tests: #{@passed}
66
+ * Pending tests: #{@pending}
67
+ * Failing tests: #{@failed}
68
+ EOF
69
+ end
70
+
71
+ private
72
+ attr_reader :output, :indent
73
+
74
+ def example_name_and_link(notification)
75
+ "[#{notification.example.metadata[:description]}](#{notification.example.location.gsub(/\:(\d+)/, '#L\1')})"
76
+ end
77
+
78
+ def heading_location_path(notification)
79
+ "[#{notification.group.location.gsub(/\:(\d+)/, '').gsub(%r{^.\/}, '')}](#{notification.group.location.gsub(/\:(\d+)/, '')})"
80
+ end
81
+
82
+ def indent_prefix
83
+ if indent > 0
84
+ "#{' ' * indent}* "
85
+ else
86
+ "\n### "
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,36 @@
1
+ module Ably::RSpec
2
+ # PrivateApiFormatter is an RSpec Formatter that prefixes all tests that are part of a Private API with '(private)'
3
+ #
4
+ # Private API methods are tested for this library, but every implementation of the Ably client library
5
+ # will likely be different and thus the private API method tests are not shared.
6
+ #
7
+ # Filter private API tests with `rspec --tag ~api_private`
8
+ #
9
+ class PrivateApiFormatter
10
+ ::RSpec::Core::Formatters.register self, :example_started
11
+
12
+ def initialize(output)
13
+ @output = output
14
+ end
15
+
16
+ def example_started(notification)
17
+ if notification.example.metadata[:api_private]
18
+ notification.example.metadata[:description] = "#{yellow('(private)')} #{green(notification.example.metadata[:description])}"
19
+ end
20
+ end
21
+
22
+ private
23
+ def colorize(color_code, string)
24
+ "\e[#{color_code}m#{string}\e[0m"
25
+ end
26
+
27
+ def yellow(string)
28
+ colorize(33, string)
29
+ end
30
+
31
+
32
+ def green(string)
33
+ colorize(32, string)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ module RSpec
2
+ module ProtocolHelper
3
+ PROTOCOLS = if ENV['TEST_LIMIT_PROTOCOLS']
4
+ JSON.parse(ENV['TEST_LIMIT_PROTOCOLS'])
5
+ else
6
+ {
7
+ json: 'JSON',
8
+ msgpack: 'MsgPack'
9
+ }
10
+ end
11
+
12
+ def vary_by_protocol(&block)
13
+ RSpec::ProtocolHelper::PROTOCOLS.each do |protocol, description|
14
+ context("using #{description} protocol", protocol: protocol, &block)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ RSpec.configure do |config|
21
+ config.extend RSpec::ProtocolHelper
22
+
23
+ config.before(:context, protocol: :json) do |context|
24
+ context.class.let(:protocol) { :json }
25
+ end
26
+
27
+ config.before(:context, protocol: :msgpack) do |context|
28
+ context.class.let(:protocol) { :msgpack }
29
+ end
30
+ end
31
+
32
+
@@ -0,0 +1,15 @@
1
+ require 'securerandom'
2
+
3
+ module RandomHelper
4
+ def random_str(length = 16)
5
+ SecureRandom.hex(length).encode(Encoding::UTF_8)
6
+ end
7
+
8
+ def random_int_str(size = 1_000_000_000)
9
+ SecureRandom.random_number(size).to_s.encode(Encoding::UTF_8)
10
+ end
11
+
12
+ RSpec.configure do |config|
13
+ config.include self
14
+ end
15
+ end
@@ -90,6 +90,10 @@ class TestApp
90
90
  @attributes = JSON.parse(response.body)
91
91
  end
92
92
 
93
+ def host
94
+ sandbox_client.endpoint.host
95
+ end
96
+
93
97
  private
94
98
  def sandbox_client
95
99
  @sandbox_client ||= Ably::Rest::Client.new(api_key: 'app.key:secret', tls: true, environment: environment)
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'shared/protocol_msgbus_behaviour'
3
+
4
+ describe Ably::Auth do
5
+ let(:client) { double('client').as_null_object }
6
+ let(:client_id) { nil }
7
+ let(:options) { { api_key: 'appid.keyuid:keysecret', client_id: client_id } }
8
+
9
+ subject do
10
+ Ably::Auth.new(client, options)
11
+ end
12
+
13
+ describe 'client_id option' do
14
+ let(:client_id) { random_str.encode(encoding) }
15
+
16
+ context 'with nil value' do
17
+ let(:client_id) { nil }
18
+
19
+ it 'is permitted' do
20
+ expect(subject.client_id).to be_nil
21
+ end
22
+ end
23
+
24
+ context 'as UTF_8 string' do
25
+ let(:encoding) { Encoding::UTF_8 }
26
+
27
+ it 'is permitted' do
28
+ expect(subject.client_id).to eql(client_id)
29
+ end
30
+
31
+ it 'remains as UTF-8' do
32
+ expect(subject.client_id.encoding).to eql(encoding)
33
+ end
34
+ end
35
+
36
+ context 'as SHIFT_JIS string' do
37
+ let(:encoding) { Encoding::SHIFT_JIS }
38
+
39
+ it 'gets converted to UTF-8' do
40
+ expect(subject.client_id.encoding).to eql(Encoding::UTF_8)
41
+ end
42
+
43
+ it 'is compatible with original encoding' do
44
+ expect(subject.client_id.encode(encoding)).to eql(client_id)
45
+ end
46
+ end
47
+
48
+ context 'as ASCII_8BIT string' do
49
+ let(:encoding) { Encoding::ASCII_8BIT }
50
+
51
+ it 'gets converted to UTF-8' do
52
+ expect(subject.client_id.encoding).to eql(Encoding::UTF_8)
53
+ end
54
+
55
+ it 'is compatible with original encoding' do
56
+ expect(subject.client_id.encode(encoding)).to eql(client_id)
57
+ end
58
+ end
59
+
60
+ context 'as Integer' do
61
+ let(:client_id) { 1 }
62
+
63
+ it 'raises an argument error' do
64
+ expect { subject.client_id }.to raise_error ArgumentError, /must be a String/
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,96 +1,107 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Ably::Logger do
4
- let(:new_client) do
5
- instance_double('Ably::Realtime::Client', connection: instance_double('Ably::Realtime::Connection', id: nil))
6
- end
7
- let(:connected_client) do
8
- instance_double('Ably::Realtime::Client', connection: instance_double('Ably::Realtime::Connection', id: '0000'))
9
- end
10
4
  let(:rest_client) do
11
5
  instance_double('Ably::Rest::Client')
12
6
  end
13
7
 
14
- subject { Ably::Logger.new(new_client, Logger::INFO) }
8
+ subject { Ably::Logger.new(rest_client, Logger::INFO) }
15
9
 
16
10
  def uncolorize(string)
17
11
  regex_pattern = /\033\[[0-9]+m(.+?)\033\[0m/m
18
12
  string.gsub(regex_pattern, '\1')
19
13
  end
20
14
 
21
- it 'uses the Ruby Logger by default' do
15
+ it 'uses the language provided Logger by default' do
22
16
  expect(subject.logger).to be_a(Logger)
23
17
  end
24
18
 
25
- it 'delegates to the logger object' do
26
- expect(subject.logger).to receive(:warn).with('message')
27
- subject.warn 'message'
28
- end
19
+ context 'internals', :api_private do
20
+ it 'delegates to the logger object' do
21
+ expect(subject.logger).to receive(:warn).with('message')
22
+ subject.warn 'message'
23
+ end
29
24
 
30
- context 'formatter' do
31
- context 'when debugging' do
32
- it 'uses short time format' do
33
- formatted = subject.logger.formatter.call(Logger::DEBUG, Time.now, 'progid', 'unique_message')
34
- formatted = uncolorize(formatted)
35
- expect(formatted).to match(/^\d+:\d+:\d+.\d{3} DEBUG/)
25
+ context 'formatter' do
26
+ context 'when debugging' do
27
+ it 'uses short time format' do
28
+ formatted = subject.logger.formatter.call(Logger::DEBUG, Time.now, 'progid', 'unique_message')
29
+ formatted = uncolorize(formatted)
30
+ expect(formatted).to match(/^\d+:\d+:\d+.\d{3} DEBUG/)
31
+ end
36
32
  end
37
- end
38
33
 
39
- context 'when info -> fatal' do
40
- it 'uses long time format' do
41
- formatted = subject.logger.formatter.call(Logger::INFO, Time.now, 'progid', 'unique_message')
42
- formatted = uncolorize(formatted)
43
- expect(formatted).to match(/^\d+-\d+-\d+ \d+:\d+:\d+.\d{3} INFO/)
34
+ context 'when info -> fatal' do
35
+ it 'uses long time format' do
36
+ formatted = subject.logger.formatter.call(Logger::INFO, Time.now, 'progid', 'unique_message')
37
+ formatted = uncolorize(formatted)
38
+ expect(formatted).to match(/^\d+-\d+-\d+ \d+:\d+:\d+.\d{3} INFO/)
39
+ end
44
40
  end
45
- end
46
41
 
47
- context 'with Realtime disconnected client' do
48
- subject { Ably::Logger.new(new_client, Logger::INFO) }
42
+ if defined?(Ably::Realtime)
43
+ context 'with Realtime client' do
44
+ let(:new_realtime_client) do
45
+ instance_double('Ably::Realtime::Client', connection: instance_double('Ably::Realtime::Connection', id: nil))
46
+ end
47
+ let(:connected_realtime_client) do
48
+ instance_double('Ably::Realtime::Client', connection: instance_double('Ably::Realtime::Connection', id: '0000'))
49
+ end
50
+ before do
51
+ allow(new_realtime_client).to receive(:kind_of?).with(Ably::Realtime::Client).and_return(true)
52
+ allow(connected_realtime_client).to receive(:kind_of?).with(Ably::Realtime::Client).and_return(true)
53
+ end
49
54
 
50
- it 'formats logs with an empty client ID' do
51
- formatted = subject.logger.formatter.call(Logger::DEBUG, Time.now, 'progid', 'unique_message')
52
- formatted = uncolorize(formatted)
53
- expect(formatted).to match(/\[ \-\- \]/)
54
- expect(formatted).to match(%r{unique_message$})
55
- expect(formatted).to match(%r{DEBUG})
56
- end
57
- end
55
+ context 'with Realtime disconnected client' do
56
+ subject { Ably::Logger.new(new_realtime_client, Logger::INFO) }
57
+
58
+ it 'formats logs with an empty client ID' do
59
+ formatted = subject.logger.formatter.call(Logger::DEBUG, Time.now, 'progid', 'unique_message')
60
+ formatted = uncolorize(formatted)
61
+ expect(formatted).to match(/\[ \-\- \]/)
62
+ expect(formatted).to match(%r{unique_message$})
63
+ expect(formatted).to match(%r{DEBUG})
64
+ end
65
+ end
58
66
 
59
- context 'with Realtime connected client' do
60
- subject { Ably::Logger.new(connected_client, Logger::INFO) }
67
+ context 'with Realtime connected client' do
68
+ subject { Ably::Logger.new(connected_realtime_client, Logger::INFO) }
61
69
 
62
- it 'formats logs with a client ID' do
63
- formatted = subject.logger.formatter.call(Logger::DEBUG, Time.now, 'progid', 'unique_message')
64
- formatted = uncolorize(formatted)
65
- expect(formatted).to match(/\[0000]/)
66
- expect(formatted).to match(%r{unique_message$})
67
- expect(formatted).to match(%r{DEBUG})
70
+ it 'formats logs with a client ID' do
71
+ formatted = subject.logger.formatter.call(Logger::DEBUG, Time.now, 'progid', 'unique_message')
72
+ formatted = uncolorize(formatted)
73
+ expect(formatted).to match(/\[0000\]/)
74
+ expect(formatted).to match(%r{unique_message$})
75
+ expect(formatted).to match(%r{DEBUG})
76
+ end
77
+ end
78
+ end
68
79
  end
69
- end
70
80
 
71
- context 'with REST client' do
72
- subject { Ably::Logger.new(rest_client, Logger::INFO) }
81
+ context 'with REST client' do
82
+ subject { Ably::Logger.new(rest_client, Logger::INFO) }
73
83
 
74
- it 'formats logs without a client ID' do
75
- formatted = subject.logger.formatter.call(Logger::FATAL, Time.now, 'progid', 'unique_message')
76
- formatted = uncolorize(formatted)
77
- expect(formatted).to_not match(/\[.*\]/)
78
- expect(formatted).to match(%r{unique_message$})
79
- expect(formatted).to match(%r{FATAL})
84
+ it 'formats logs without a client ID' do
85
+ formatted = subject.logger.formatter.call(Logger::FATAL, Time.now, 'progid', 'unique_message')
86
+ formatted = uncolorize(formatted)
87
+ expect(formatted).to_not match(/\[.*\]/)
88
+ expect(formatted).to match(%r{unique_message$})
89
+ expect(formatted).to match(%r{FATAL})
90
+ end
80
91
  end
81
- end
82
92
 
83
- context 'severity argument' do
84
- it 'can be an Integer' do
85
- formatted = subject.logger.formatter.call(Logger::INFO, Time.now, 'progid', 'unique_message')
86
- formatted = uncolorize(formatted)
87
- expect(formatted).to match(/^\d+-\d+-\d+ \d+:\d+:\d+.\d{3} INFO/)
88
- end
93
+ context 'severity argument' do
94
+ it 'can be an Integer' do
95
+ formatted = subject.logger.formatter.call(Logger::INFO, Time.now, 'progid', 'unique_message')
96
+ formatted = uncolorize(formatted)
97
+ expect(formatted).to match(/^\d+-\d+-\d+ \d+:\d+:\d+.\d{3} INFO/)
98
+ end
89
99
 
90
- it 'can be a string' do
91
- formatted = subject.logger.formatter.call('INFO', Time.now, 'progid', 'unique_message')
92
- formatted = uncolorize(formatted)
93
- expect(formatted).to match(/^\d+-\d+-\d+ \d+:\d+:\d+.\d{3} INFO/)
100
+ it 'can be a string' do
101
+ formatted = subject.logger.formatter.call('INFO', Time.now, 'progid', 'unique_message')
102
+ formatted = uncolorize(formatted)
103
+ expect(formatted).to match(/^\d+-\d+-\d+ \d+:\d+:\d+.\d{3} INFO/)
104
+ end
94
105
  end
95
106
  end
96
107
  end
@@ -100,7 +111,7 @@ describe Ably::Logger do
100
111
  let(:custom_logger_with_bad_interface) do
101
112
  Class.new.new
102
113
  end
103
- subject { Ably::Logger.new(new_client, Logger::INFO, custom_logger_with_bad_interface) }
114
+ subject { Ably::Logger.new(rest_client, Logger::INFO, custom_logger_with_bad_interface) }
104
115
 
105
116
  it 'raises an exception' do
106
117
  expect { subject }.to raise_error ArgumentError, /The custom Logger's interface does not provide the method/
@@ -119,14 +130,14 @@ describe Ably::Logger do
119
130
  end
120
131
  let(:custom_logger_object) { custom_logger.new }
121
132
 
122
- subject { Ably::Logger.new(new_client, Logger::INFO, custom_logger_object) }
133
+ subject { Ably::Logger.new(rest_client, Logger::INFO, custom_logger_object) }
123
134
 
124
135
  it 'is used' do
125
136
  expect { subject }.to_not raise_error
126
137
  expect(subject.logger.class).to eql(custom_logger)
127
138
  end
128
139
 
129
- it 'delegates log messages to logger' do
140
+ it 'delegates log messages to logger', :api_private do
130
141
  expect(custom_logger_object).to receive(:fatal).with('message')
131
142
  subject.fatal 'message'
132
143
  end