ably 0.1.6 → 0.2.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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +8 -1
  6. data/Rakefile +10 -0
  7. data/ably.gemspec +18 -18
  8. data/lib/ably.rb +6 -5
  9. data/lib/ably/auth.rb +11 -14
  10. data/lib/ably/exceptions.rb +18 -15
  11. data/lib/ably/logger.rb +102 -0
  12. data/lib/ably/models/error_info.rb +1 -1
  13. data/lib/ably/models/message.rb +19 -5
  14. data/lib/ably/models/message_encoders/base.rb +107 -0
  15. data/lib/ably/models/message_encoders/base64.rb +39 -0
  16. data/lib/ably/models/message_encoders/cipher.rb +80 -0
  17. data/lib/ably/models/message_encoders/json.rb +33 -0
  18. data/lib/ably/models/message_encoders/utf8.rb +33 -0
  19. data/lib/ably/models/paginated_resource.rb +23 -6
  20. data/lib/ably/models/presence_message.rb +19 -7
  21. data/lib/ably/models/protocol_message.rb +5 -4
  22. data/lib/ably/models/token.rb +2 -2
  23. data/lib/ably/modules/channels_collection.rb +0 -3
  24. data/lib/ably/modules/conversions.rb +3 -3
  25. data/lib/ably/modules/encodeable.rb +68 -0
  26. data/lib/ably/modules/event_emitter.rb +10 -4
  27. data/lib/ably/modules/event_machine_helpers.rb +6 -4
  28. data/lib/ably/modules/http_helpers.rb +7 -2
  29. data/lib/ably/modules/model_common.rb +2 -0
  30. data/lib/ably/modules/state_emitter.rb +10 -1
  31. data/lib/ably/realtime.rb +19 -12
  32. data/lib/ably/realtime/channel.rb +26 -13
  33. data/lib/ably/realtime/client.rb +31 -7
  34. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -3
  35. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +13 -4
  36. data/lib/ably/realtime/connection.rb +152 -46
  37. data/lib/ably/realtime/connection/connection_manager.rb +168 -0
  38. data/lib/ably/realtime/connection/connection_state_machine.rb +56 -33
  39. data/lib/ably/realtime/connection/websocket_transport.rb +56 -29
  40. data/lib/ably/{models → realtime/models}/nil_channel.rb +1 -1
  41. data/lib/ably/realtime/presence.rb +38 -13
  42. data/lib/ably/rest.rb +7 -5
  43. data/lib/ably/rest/channel.rb +24 -3
  44. data/lib/ably/rest/client.rb +56 -17
  45. data/lib/ably/rest/middleware/encoder.rb +49 -0
  46. data/lib/ably/rest/middleware/exceptions.rb +3 -2
  47. data/lib/ably/rest/middleware/logger.rb +37 -0
  48. data/lib/ably/rest/presence.rb +10 -2
  49. data/lib/ably/util/crypto.rb +57 -29
  50. data/lib/ably/util/pub_sub.rb +11 -0
  51. data/lib/ably/version.rb +1 -1
  52. data/spec/acceptance/realtime/channel_spec.rb +65 -7
  53. data/spec/acceptance/realtime/connection_spec.rb +123 -27
  54. data/spec/acceptance/realtime/message_spec.rb +319 -34
  55. data/spec/acceptance/realtime/presence_history_spec.rb +58 -0
  56. data/spec/acceptance/realtime/presence_spec.rb +160 -18
  57. data/spec/acceptance/rest/auth_spec.rb +93 -49
  58. data/spec/acceptance/rest/base_spec.rb +10 -10
  59. data/spec/acceptance/rest/channel_spec.rb +35 -19
  60. data/spec/acceptance/rest/channels_spec.rb +8 -8
  61. data/spec/acceptance/rest/message_spec.rb +224 -0
  62. data/spec/acceptance/rest/presence_spec.rb +159 -23
  63. data/spec/acceptance/rest/stats_spec.rb +5 -5
  64. data/spec/acceptance/rest/time_spec.rb +4 -4
  65. data/spec/integration/rest/auth.rb +1 -1
  66. data/spec/resources/crypto-data-128.json +56 -0
  67. data/spec/resources/crypto-data-256.json +56 -0
  68. data/spec/rspec_config.rb +39 -0
  69. data/spec/spec_helper.rb +4 -42
  70. data/spec/support/api_helper.rb +1 -1
  71. data/spec/support/event_machine_helper.rb +0 -5
  72. data/spec/support/protocol_msgbus_helper.rb +3 -3
  73. data/spec/support/test_app.rb +3 -3
  74. data/spec/unit/logger_spec.rb +135 -0
  75. data/spec/unit/models/message_encoders/base64_spec.rb +181 -0
  76. data/spec/unit/models/message_encoders/cipher_spec.rb +260 -0
  77. data/spec/unit/models/message_encoders/json_spec.rb +135 -0
  78. data/spec/unit/models/message_encoders/utf8_spec.rb +100 -0
  79. data/spec/unit/models/message_spec.rb +16 -1
  80. data/spec/unit/models/paginated_resource_spec.rb +46 -0
  81. data/spec/unit/models/presence_message_spec.rb +18 -5
  82. data/spec/unit/models/token_spec.rb +1 -1
  83. data/spec/unit/modules/event_emitter_spec.rb +24 -10
  84. data/spec/unit/realtime/channel_spec.rb +3 -3
  85. data/spec/unit/realtime/channels_spec.rb +1 -1
  86. data/spec/unit/realtime/client_spec.rb +44 -2
  87. data/spec/unit/realtime/connection_spec.rb +2 -2
  88. data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +4 -4
  89. data/spec/unit/realtime/presence_spec.rb +1 -1
  90. data/spec/unit/realtime/realtime_spec.rb +3 -3
  91. data/spec/unit/realtime/websocket_transport_spec.rb +24 -0
  92. data/spec/unit/rest/channels_spec.rb +1 -1
  93. data/spec/unit/rest/client_spec.rb +45 -10
  94. data/spec/unit/util/crypto_spec.rb +82 -0
  95. data/spec/unit/{modules → util}/pub_sub_spec.rb +13 -1
  96. metadata +43 -12
  97. data/spec/acceptance/crypto.rb +0 -63
@@ -1,10 +1,10 @@
1
- require "spec_helper"
2
- require "securerandom"
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
3
 
4
- describe "REST" do
4
+ describe 'Ably::Rest Stats' do
5
5
  [:json, :msgpack].each do |protocol|
6
6
  context "over #{protocol}" do
7
- describe "fetching application stats" do
7
+ describe 'fetching application stats' do
8
8
  before(:context) do
9
9
  reload_test_app
10
10
  end
@@ -40,7 +40,7 @@ describe "REST" do
40
40
 
41
41
  [:minute, :hour, :day, :month].each do |interval|
42
42
  context "by #{interval}" do
43
- it "should return all the stats for the application" do
43
+ it 'should return all the stats for the application' do
44
44
  stats = @context_client.stats(start: @interval_start * 1000, by: interval.to_s, direction: 'forwards')
45
45
 
46
46
  expect(stats.size).to eql(1)
@@ -1,14 +1,14 @@
1
- require "spec_helper"
2
- require "securerandom"
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
3
 
4
- describe "REST" do
4
+ describe 'Ably::REST time' do
5
5
  [:msgpack, :json].each do |protocol|
6
6
  context "over #{protocol}" do
7
7
  let(:client) do
8
8
  Ably::Rest::Client.new(api_key: api_key, environment: environment, protocol: protocol)
9
9
  end
10
10
 
11
- describe "fetching the service time" do
11
+ describe 'fetching the service time' do
12
12
  it "should return the service time as a Time object" do
13
13
  expect(client.time).to be_within(2).of(Time.now)
14
14
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Ably::Auth do
4
4
  let(:client) { Ably::Rest::Client.new(key_id: 'id', key_secret: 'secret') }
5
5
 
6
- it "has immutable options" do
6
+ it 'has immutable options' do
7
7
  expect { client.auth.options['key_id'] = 'new_id' }.to raise_error RuntimeError, /can't modify frozen Hash/
8
8
  end
9
9
  end
@@ -0,0 +1,56 @@
1
+ {
2
+ "algorithm": "aes",
3
+ "mode": "cbc",
4
+ "keylength": 128,
5
+ "key": "WUP6u0K7MXI5Zeo0VppPwg==",
6
+ "iv": "HO4cYSP8LybPYBPZPHQOtg==",
7
+ "items": [
8
+ {
9
+ "encoded": {
10
+ "name": "example",
11
+ "data": "The quick brown fox jumped over the lazy dog"
12
+ },
13
+ "encrypted": {
14
+ "name": "example",
15
+ "data": "HO4cYSP8LybPYBPZPHQOtmHItcxYdSvcNUC6kXVpMn0VFL+9z2/5tJ6WFbR0SBT1xhFRuJ+MeBGTU3yOY9P5ow==",
16
+ "encoding": "utf-8/cipher+aes-128-cbc/base64"
17
+ }
18
+ },
19
+ {
20
+ "encoded": {
21
+ "name": "example",
22
+ "data": "AAECAwQFBgcICQoLDA0ODw==",
23
+ "encoding": "base64"
24
+ },
25
+ "encrypted": {
26
+ "name": "example",
27
+ "data": "HO4cYSP8LybPYBPZPHQOtuB3dfKG08yw7J4qx3kkjxdW0eoZv+nGAp76OKqYQ327",
28
+ "encoding": "cipher+aes-128-cbc/base64"
29
+ }
30
+ },
31
+ {
32
+ "encoded": {
33
+ "name": "example",
34
+ "data": "{\"example\":{\"json\":\"Object\"}}",
35
+ "encoding": "json"
36
+ },
37
+ "encrypted": {
38
+ "name": "example",
39
+ "data": "HO4cYSP8LybPYBPZPHQOtuD53yrD3YV3NBoTEYBh4U0N1QXHbtkfsDfTspKeLQFt",
40
+ "encoding": "json/utf-8/cipher+aes-128-cbc/base64"
41
+ }
42
+ },
43
+ {
44
+ "encoded": {
45
+ "name": "example",
46
+ "data": "[\"example\",\"json\",\"array\"]",
47
+ "encoding": "json"
48
+ },
49
+ "encrypted": {
50
+ "name": "example",
51
+ "data": "HO4cYSP8LybPYBPZPHQOtvmStzmExkdjvrn51J6cmaTZrGl+EsJ61sgxmZ6j6jcA",
52
+ "encoding": "json/utf-8/cipher+aes-128-cbc/base64"
53
+ }
54
+ }
55
+ ]
56
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "algorithm": "aes",
3
+ "mode": "cbc",
4
+ "keylength": 256,
5
+ "key": "o9qXZoPGDNla50VnRwH7cGqIrpyagTxGsRgimKJbY40=",
6
+ "iv": "NMDl1Acnel8HVdu1cEWdrw==",
7
+ "items": [
8
+ {
9
+ "encoded": {
10
+ "name": "example",
11
+ "data": "The quick brown fox jumped over the lazy dog"
12
+ },
13
+ "encrypted": {
14
+ "name": "example",
15
+ "data": "NMDl1Acnel8HVdu1cEWdr9CGPYFoBoLgJCzoybbQbnyfwx3UQ8CGuKyP/g56Za/JB3xW6XGkNzrHYvZwad4fvA==",
16
+ "encoding": "utf-8/cipher+aes-256-cbc/base64"
17
+ }
18
+ },
19
+ {
20
+ "encoded": {
21
+ "name": "example",
22
+ "data": "AAECAwQFBgcICQoLDA0ODw==",
23
+ "encoding": "base64"
24
+ },
25
+ "encrypted": {
26
+ "name": "example",
27
+ "data": "NMDl1Acnel8HVdu1cEWdr8UFEi56Ms0zPHszbppM61BC8Yf6ndq+kiCj9xXW97/O",
28
+ "encoding": "cipher+aes-256-cbc/base64"
29
+ }
30
+ },
31
+ {
32
+ "encoded": {
33
+ "name": "example",
34
+ "data": "{\"example\":{\"json\":\"Object\"}}",
35
+ "encoding": "json"
36
+ },
37
+ "encrypted": {
38
+ "name": "example",
39
+ "data": "NMDl1Acnel8HVdu1cEWdr21pS5//hdtQf3QqQzZM/jWAtn09Vh52E6jMdC3mWS98",
40
+ "encoding": "json/utf-8/cipher+aes-256-cbc/base64"
41
+ }
42
+ },
43
+ {
44
+ "encoded": {
45
+ "name": "example",
46
+ "data": "[\"example\",\"json\",\"array\"]",
47
+ "encoding": "json"
48
+ },
49
+ "encrypted": {
50
+ "name": "example",
51
+ "data": "NMDl1Acnel8HVdu1cEWdr4J5sVAFpnXsz0fTtsuwOaTRU+6P5GaWlNjePWwiOZCQ",
52
+ "encoding": "json/utf-8/cipher+aes-256-cbc/base64"
53
+ }
54
+ }
55
+ ]
56
+ }
@@ -0,0 +1,39 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ RSpec.configure do |config|
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ config.mock_with :rspec do |mocks|
13
+ # This option should be set when all dependencies are being loaded
14
+ # before a spec run, as is the case in a typical spec helper. It will
15
+ # cause any verifying double instantiation for a class that does not
16
+ # exist to raise, protecting against incorrectly spelt names.
17
+ mocks.verify_doubled_constant_names = true
18
+ end
19
+
20
+ # Run specs in random order to surface order dependencies. If you find an
21
+ # order dependency and want to debug it, you can fix the order by providing
22
+ # the seed, which is printed after each run.
23
+ # --seed 1234
24
+ config.order = 'random'
25
+
26
+ config.before(:example) do
27
+ WebMock.disable!
28
+ end
29
+
30
+ config.before(:example, :webmock => true) do
31
+ allow(TestApp).to receive(:instance).and_return(instance_double('TestApp',
32
+ app_id: 'app_id',
33
+ key_id: 'app_id.key_id',
34
+ api_key: 'app_id.key_id:secret',
35
+ environment: 'sandbox'
36
+ ))
37
+ WebMock.enable!
38
+ end
39
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,46 +1,8 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper"` to ensure that it is only
4
- # loaded once.
5
- #
6
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
-
8
1
  require 'webmock/rspec'
9
2
 
10
- require "ably"
11
-
12
- require "support/api_helper"
13
- require "support/event_machine_helper"
14
-
15
- RSpec.configure do |config|
16
- config.run_all_when_everything_filtered = true
17
- config.filter_run :focus
18
-
19
- config.mock_with :rspec do |mocks|
20
- # This option should be set when all dependencies are being loaded
21
- # before a spec run, as is the case in a typical spec helper. It will
22
- # cause any verifying double instantiation for a class that does not
23
- # exist to raise, protecting against incorrectly spelt names.
24
- mocks.verify_doubled_constant_names = true
25
- end
26
-
27
- # Run specs in random order to surface order dependencies. If you find an
28
- # order dependency and want to debug it, you can fix the order by providing
29
- # the seed, which is printed after each run.
30
- # --seed 1234
31
- config.order = 'random'
3
+ require 'ably'
32
4
 
33
- config.before(:example) do
34
- WebMock.disable!
35
- end
5
+ require 'support/api_helper'
6
+ require 'support/event_machine_helper'
36
7
 
37
- config.before(:example, :webmock => true) do
38
- allow(TestApp).to receive(:instance).and_return(instance_double('TestApp',
39
- app_id: 'app_id',
40
- key_id: 'app_id.key_id',
41
- api_key: 'app_id.key_id:secret',
42
- environment: 'sandbox'
43
- ))
44
- WebMock.enable!
45
- end
46
- end
8
+ require 'rspec_config'
@@ -1,4 +1,4 @@
1
- require "support/test_app"
1
+ require 'support/test_app'
2
2
 
3
3
  module ApiHelper
4
4
  def app_id
@@ -6,11 +6,6 @@ module RSpec
6
6
  Timeout::timeout(timeout + 0.5) do
7
7
  EM.run do
8
8
  yield
9
-
10
- EM.add_timer(timeout) do
11
- EM.stop
12
- raise RuntimeError, "EventMachine test did not complete in #{timeout} seconds"
13
- end
14
9
  end
15
10
  end
16
11
  end
@@ -1,6 +1,6 @@
1
1
  shared_examples 'a protocol message bus' do
2
2
  describe '__protocol_msgbus__ PubSub' do
3
- let(:message) do
3
+ let(:protocol_message) do
4
4
  Ably::Models::ProtocolMessage.new(
5
5
  action: 15,
6
6
  channel: 'channel',
@@ -11,8 +11,8 @@ shared_examples 'a protocol message bus' do
11
11
 
12
12
  specify 'supports valid ProtocolMessage messages' do
13
13
  received = 0
14
- msgbus.subscribe(:message) { received += 1 }
15
- expect { msgbus.publish(:message, message) }.to change { received }.to(1)
14
+ msgbus.subscribe(:protocol_message) { received += 1 }
15
+ expect { msgbus.publish(:protocol_message, protocol_message) }.to change { received }.to(1)
16
16
  end
17
17
 
18
18
  specify 'fail with unacceptable STATE event names' do
@@ -1,4 +1,4 @@
1
- require "singleton"
1
+ require 'singleton'
2
2
 
3
3
  class TestApp
4
4
  APP_SPEC = {
@@ -81,8 +81,8 @@ class TestApp
81
81
  url = "#{sandbox_client.endpoint}/apps"
82
82
 
83
83
  headers = {
84
- "Accept" => "application/json",
85
- "Content-Type" => "application/json"
84
+ 'Accept' => 'application/json',
85
+ 'Content-Type' => 'application/json'
86
86
  }
87
87
 
88
88
  response = Faraday.post(url, APP_SPEC.to_json, headers)
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+
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
+ let(:rest_client) do
11
+ instance_double('Ably::Rest::Client')
12
+ end
13
+
14
+ subject { Ably::Logger.new(new_client, Logger::INFO) }
15
+
16
+ def uncolorize(string)
17
+ regex_pattern = /\033\[[0-9]+m(.+?)\033\[0m/m
18
+ string.gsub(regex_pattern, '\1')
19
+ end
20
+
21
+ it 'uses the Ruby Logger by default' do
22
+ expect(subject.logger).to be_a(Logger)
23
+ end
24
+
25
+ it 'delegates to the logger object' do
26
+ expect(subject.logger).to receive(:warn).with('message')
27
+ subject.warn 'message'
28
+ end
29
+
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/)
36
+ end
37
+ end
38
+
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/)
44
+ end
45
+ end
46
+
47
+ context 'with Realtime disconnected client' do
48
+ subject { Ably::Logger.new(new_client, Logger::INFO) }
49
+
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
58
+
59
+ context 'with Realtime connected client' do
60
+ subject { Ably::Logger.new(connected_client, Logger::INFO) }
61
+
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})
68
+ end
69
+ end
70
+
71
+ context 'with REST client' do
72
+ subject { Ably::Logger.new(rest_client, Logger::INFO) }
73
+
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})
80
+ end
81
+ end
82
+
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
89
+
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/)
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'with a custom Logger' do
99
+ context 'with an invalid interface' do
100
+ let(:custom_logger_with_bad_interface) do
101
+ Class.new.new
102
+ end
103
+ subject { Ably::Logger.new(new_client, Logger::INFO, custom_logger_with_bad_interface) }
104
+
105
+ it 'raises an exception' do
106
+ expect { subject }.to raise_error ArgumentError, /The custom Logger's interface does not provide the method/
107
+ end
108
+ end
109
+
110
+ context 'with a valid interface' do
111
+ let(:custom_logger) do
112
+ Class.new do
113
+ extend Forwardable
114
+ def initialize
115
+ @logger = Logger.new(STDOUT)
116
+ end
117
+ def_delegators :@logger, :fatal, :error, :warn, :info, :debug, :level, :level=
118
+ end
119
+ end
120
+ let(:custom_logger_object) { custom_logger.new }
121
+
122
+ subject { Ably::Logger.new(new_client, Logger::INFO, custom_logger_object) }
123
+
124
+ it 'is used' do
125
+ expect { subject }.to_not raise_error
126
+ expect(subject.logger.class).to eql(custom_logger)
127
+ end
128
+
129
+ it 'delegates log messages to logger' do
130
+ expect(custom_logger_object).to receive(:fatal).with('message')
131
+ subject.fatal 'message'
132
+ end
133
+ end
134
+ end
135
+ end