honeybadger 1.11.2 → 1.12.0.beta2
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/Appraisals +56 -46
- data/CHANGELOG.md +33 -0
- data/Gemfile.lock +1 -1
- data/MIT-LICENSE +2 -1
- data/Rakefile +3 -1
- data/features/standalone.feature +73 -0
- data/features/step_definitions/rack_steps.rb +1 -2
- data/features/step_definitions/standalone_steps.rb +12 -0
- data/features/support/env.rb +2 -0
- data/gemfiles/binding_of_caller.gemfile +8 -0
- data/gemfiles/rails.gemfile +11 -0
- data/gemfiles/standalone.gemfile +7 -0
- data/honeybadger.gemspec +22 -11
- data/lib/honeybadger.rb +15 -9
- data/lib/honeybadger/configuration.rb +9 -4
- data/lib/honeybadger/dependency.rb +65 -0
- data/lib/honeybadger/exception_extensions.rb +35 -0
- data/lib/honeybadger/integrations.rb +4 -0
- data/lib/honeybadger/integrations/delayed_job.rb +20 -0
- data/lib/honeybadger/integrations/delayed_job/plugin.rb +31 -0
- data/lib/honeybadger/integrations/sidekiq.rb +34 -0
- data/lib/honeybadger/notice.rb +48 -11
- data/lib/honeybadger/payload.rb +29 -0
- data/lib/honeybadger/rack.rb +8 -54
- data/lib/honeybadger/rack/error_notifier.rb +60 -0
- data/lib/honeybadger/rack/user_feedback.rb +74 -0
- data/lib/honeybadger/rack/user_informer.rb +28 -0
- data/lib/honeybadger/rails.rb +5 -4
- data/lib/honeybadger/railtie.rb +4 -3
- data/lib/honeybadger/user_feedback.rb +3 -67
- data/lib/honeybadger/user_informer.rb +3 -21
- data/spec/honeybadger/configuration_spec.rb +5 -1
- data/spec/honeybadger/dependency_spec.rb +134 -0
- data/spec/honeybadger/exception_extensions_spec.rb +40 -0
- data/spec/honeybadger/integrations/delayed_job_spec.rb +48 -0
- data/spec/honeybadger/integrations/sidekiq_spec.rb +60 -0
- data/spec/honeybadger/notice_spec.rb +176 -35
- data/spec/honeybadger/payload_spec.rb +27 -0
- data/spec/honeybadger/rails_spec.rb +4 -2
- metadata +24 -13
- data/gemfiles/rack.gemfile.lock +0 -125
- data/gemfiles/rails2.3.gemfile.lock +0 -141
- data/gemfiles/rails3.0.gemfile.lock +0 -193
- data/gemfiles/rails3.1.gemfile.lock +0 -203
- data/gemfiles/rails3.2.gemfile.lock +0 -201
- data/gemfiles/rails4.0.gemfile.lock +0 -197
- data/gemfiles/rails4.1.gemfile.lock +0 -202
- data/gemfiles/rake.gemfile.lock +0 -124
- data/gemfiles/sinatra.gemfile.lock +0 -124
data/lib/honeybadger/rack.rb
CHANGED
@@ -1,58 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
# Synopsis:
|
6
|
-
#
|
7
|
-
# require 'rack'
|
8
|
-
# require 'honeybadger'
|
9
|
-
#
|
10
|
-
# Honeybadger.configure do |config|
|
11
|
-
# config.api_key = 'my_api_key'
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# app = Rack::Builder.app do
|
15
|
-
# run lambda { |env| raise "Rack down" }
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# use Honeybadger::Rack
|
19
|
-
# run app
|
20
|
-
#
|
21
|
-
# Use a standard Honeybadger.configure call to configure your api key.
|
22
|
-
class Rack
|
23
|
-
def initialize(app)
|
24
|
-
@app = app
|
25
|
-
Honeybadger.configuration.framework = "Rack: #{::Rack.release}"
|
26
|
-
end
|
1
|
+
require 'honeybadger/rack/error_notifier'
|
2
|
+
require 'honeybadger/rack/user_informer'
|
3
|
+
require 'honeybadger/rack/user_feedback'
|
27
4
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
any? { |ua| ua === env['HTTP_USER_AGENT'] }
|
34
|
-
end
|
35
|
-
|
36
|
-
def notify_honeybadger(exception,env)
|
37
|
-
Honeybadger.notify_or_ignore(exception, :rack_env => env) unless ignored_user_agent?(env)
|
38
|
-
end
|
39
|
-
|
40
|
-
def call(env)
|
41
|
-
begin
|
42
|
-
response = @app.call(env)
|
43
|
-
rescue Exception => raised
|
44
|
-
env['honeybadger.error_id'] = notify_honeybadger(raised, env)
|
45
|
-
raise
|
46
|
-
ensure
|
47
|
-
Honeybadger.context.clear!
|
48
|
-
end
|
49
|
-
|
50
|
-
framework_exception = env['rack.exception'] || env['sinatra.error']
|
51
|
-
if framework_exception
|
52
|
-
env['honeybadger.error_id'] = notify_honeybadger(framework_exception, env)
|
53
|
-
end
|
54
|
-
|
55
|
-
response
|
5
|
+
module Honeybadger
|
6
|
+
module Rack
|
7
|
+
def self.new(*args, &block)
|
8
|
+
warn '[DEPRECATION] Honeybadger::Rack is deprecated in 2.0. Use Honeybadger::Rack::ErrorNotifier.'
|
9
|
+
ErrorNotifier.new(*args, &block)
|
56
10
|
end
|
57
11
|
end
|
58
12
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
module Rack
|
3
|
+
# Middleware for Rack applications. Any errors raised by the upstream
|
4
|
+
# application will be delivered to Honeybadger and re-raised.
|
5
|
+
#
|
6
|
+
# Synopsis:
|
7
|
+
#
|
8
|
+
# require 'rack'
|
9
|
+
# require 'honeybadger'
|
10
|
+
#
|
11
|
+
# Honeybadger.configure do |config|
|
12
|
+
# config.api_key = 'my_api_key'
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# app = Rack::Builder.app do
|
16
|
+
# run lambda { |env| raise "Rack down" }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# use Honeybadger::Rack::ErrorNotifier
|
20
|
+
# run app
|
21
|
+
#
|
22
|
+
# Use a standard Honeybadger.configure call to configure your api key.
|
23
|
+
class ErrorNotifier
|
24
|
+
def initialize(app)
|
25
|
+
@app = app
|
26
|
+
Honeybadger.configuration.framework = "Rack: #{::Rack.release}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def ignored_user_agent?(env)
|
30
|
+
true if Honeybadger.
|
31
|
+
configuration.
|
32
|
+
ignore_user_agent.
|
33
|
+
flatten.
|
34
|
+
any? { |ua| ua === env['HTTP_USER_AGENT'] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def notify_honeybadger(exception,env)
|
38
|
+
Honeybadger.notify_or_ignore(exception, :rack_env => env) unless ignored_user_agent?(env)
|
39
|
+
end
|
40
|
+
|
41
|
+
def call(env)
|
42
|
+
begin
|
43
|
+
response = @app.call(env)
|
44
|
+
rescue Exception => raised
|
45
|
+
env['honeybadger.error_id'] = notify_honeybadger(raised, env)
|
46
|
+
raise
|
47
|
+
ensure
|
48
|
+
Honeybadger.context.clear!
|
49
|
+
end
|
50
|
+
|
51
|
+
framework_exception = env['rack.exception'] || env['sinatra.error']
|
52
|
+
if framework_exception
|
53
|
+
env['honeybadger.error_id'] = notify_honeybadger(framework_exception, env)
|
54
|
+
end
|
55
|
+
|
56
|
+
response
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'i18n'
|
6
|
+
rescue LoadError
|
7
|
+
module Honeybadger
|
8
|
+
module I18n
|
9
|
+
def self.t(key, options={})
|
10
|
+
options[:default]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Honeybadger
|
17
|
+
module Rack
|
18
|
+
class UserFeedback
|
19
|
+
def initialize(app)
|
20
|
+
@app = app
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
status, headers, body = @app.call(env)
|
25
|
+
if enabled? && env['honeybadger.error_id'] && form = render_form(env['honeybadger.error_id'])
|
26
|
+
new_body = []
|
27
|
+
body.each do |chunk|
|
28
|
+
new_body << chunk.gsub("<!-- HONEYBADGER FEEDBACK -->", form)
|
29
|
+
end
|
30
|
+
body.close if body.respond_to?(:close)
|
31
|
+
headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
|
32
|
+
body = new_body
|
33
|
+
end
|
34
|
+
[status, headers, body]
|
35
|
+
end
|
36
|
+
|
37
|
+
def config
|
38
|
+
Honeybadger.configuration
|
39
|
+
end
|
40
|
+
|
41
|
+
def enabled?
|
42
|
+
config.feedback && config.features['feedback']
|
43
|
+
end
|
44
|
+
|
45
|
+
def action
|
46
|
+
URI.parse("#{config.protocol}://#{config.host}:#{config.port}/v1/feedback/").to_s
|
47
|
+
rescue URI::InvalidURIError
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def render_form(error_id, action = action)
|
52
|
+
return unless action
|
53
|
+
ERB.new(@template ||= File.read(template_file)).result(binding)
|
54
|
+
end
|
55
|
+
|
56
|
+
def custom_template_file
|
57
|
+
@custom_template_file ||= config.project_root &&
|
58
|
+
File.join(config.project_root, 'lib', 'honeybadger', 'templates', 'feedback_form.erb')
|
59
|
+
end
|
60
|
+
|
61
|
+
def custom_template_file?
|
62
|
+
custom_template_file && File.exists?(custom_template_file)
|
63
|
+
end
|
64
|
+
|
65
|
+
def template_file
|
66
|
+
if custom_template_file?
|
67
|
+
custom_template_file
|
68
|
+
else
|
69
|
+
File.expand_path('../../templates/feedback_form.erb', __FILE__)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
module Rack
|
3
|
+
class UserInformer
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def replacement(with)
|
9
|
+
Honeybadger.configuration.user_information.gsub(/\{\{\s*error_id\s*\}\}/, with.to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
status, headers, body = @app.call(env)
|
14
|
+
if env['honeybadger.error_id'] && Honeybadger.configuration.user_information
|
15
|
+
new_body = []
|
16
|
+
replace = replacement(env['honeybadger.error_id'])
|
17
|
+
body.each do |chunk|
|
18
|
+
new_body << chunk.gsub("<!-- HONEYBADGER ERROR -->", replace)
|
19
|
+
end
|
20
|
+
body.close if body.respond_to?(:close)
|
21
|
+
headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
|
22
|
+
body = new_body
|
23
|
+
end
|
24
|
+
[status, headers, body]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/honeybadger/rails.rb
CHANGED
@@ -18,11 +18,11 @@ module Honeybadger
|
|
18
18
|
|
19
19
|
if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:middleware)
|
20
20
|
::Rails.configuration.middleware.insert_after 'ActionController::Failsafe',
|
21
|
-
Honeybadger::Rack
|
21
|
+
Honeybadger::Rack::ErrorNotifier
|
22
22
|
::Rails.configuration.middleware.insert_after 'Rack::Lock',
|
23
|
-
Honeybadger::UserInformer
|
24
|
-
::Rails.configuration.middleware.insert_after Honeybadger::UserInformer,
|
25
|
-
Honeybadger::UserFeedback
|
23
|
+
Honeybadger::Rack::UserInformer
|
24
|
+
::Rails.configuration.middleware.insert_after Honeybadger::Rack::UserInformer,
|
25
|
+
Honeybadger::Rack::UserFeedback
|
26
26
|
end
|
27
27
|
|
28
28
|
Honeybadger.configure(true) do |config|
|
@@ -34,6 +34,7 @@ module Honeybadger
|
|
34
34
|
|
35
35
|
if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:after_initialize)
|
36
36
|
::Rails.configuration.after_initialize do
|
37
|
+
Honeybadger::Dependency.inject!
|
37
38
|
Honeybadger.ping(Honeybadger.configuration)
|
38
39
|
end
|
39
40
|
end
|
data/lib/honeybadger/railtie.rb
CHANGED
@@ -10,9 +10,9 @@ module Honeybadger
|
|
10
10
|
end
|
11
11
|
|
12
12
|
initializer "honeybadger.use_rack_middleware" do |app|
|
13
|
-
app.config.middleware.insert 0, "Honeybadger::UserInformer"
|
14
|
-
app.config.middleware.insert_after "Honeybadger::UserInformer","Honeybadger::UserFeedback"
|
15
|
-
app.config.middleware.insert_after "Honeybadger::UserFeedback","Honeybadger::Rack"
|
13
|
+
app.config.middleware.insert 0, "Honeybadger::Rack::UserInformer"
|
14
|
+
app.config.middleware.insert_after "Honeybadger::Rack::UserInformer","Honeybadger::Rack::UserFeedback"
|
15
|
+
app.config.middleware.insert_after "Honeybadger::Rack::UserFeedback","Honeybadger::Rack::ErrorNotifier"
|
16
16
|
end
|
17
17
|
|
18
18
|
config.after_initialize do
|
@@ -44,6 +44,7 @@ module Honeybadger
|
|
44
44
|
::ActionDispatch::ShowExceptions.send(:include,Honeybadger::Rails::Middleware::ExceptionsCatcher)
|
45
45
|
end
|
46
46
|
|
47
|
+
Honeybadger::Dependency.inject!
|
47
48
|
Honeybadger.ping(Honeybadger.configuration)
|
48
49
|
end
|
49
50
|
end
|
@@ -1,72 +1,8 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'uri'
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'i18n'
|
6
|
-
rescue LoadError
|
7
|
-
module Honeybadger
|
8
|
-
module I18n
|
9
|
-
def self.t(key, options={})
|
10
|
-
options[:default]
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
1
|
module Honeybadger
|
17
|
-
class UserFeedback
|
2
|
+
class UserFeedback < Rack::UserFeedback
|
18
3
|
def initialize(app)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
def call(env)
|
23
|
-
status, headers, body = @app.call(env)
|
24
|
-
if enabled? && env['honeybadger.error_id'] && form = render_form(env['honeybadger.error_id'])
|
25
|
-
new_body = []
|
26
|
-
body.each do |chunk|
|
27
|
-
new_body << chunk.gsub("<!-- HONEYBADGER FEEDBACK -->", form)
|
28
|
-
end
|
29
|
-
body.close if body.respond_to?(:close)
|
30
|
-
headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
|
31
|
-
body = new_body
|
32
|
-
end
|
33
|
-
[status, headers, body]
|
34
|
-
end
|
35
|
-
|
36
|
-
def config
|
37
|
-
Honeybadger.configuration
|
38
|
-
end
|
39
|
-
|
40
|
-
def enabled?
|
41
|
-
config.feedback && config.features['feedback']
|
42
|
-
end
|
43
|
-
|
44
|
-
def action
|
45
|
-
URI.parse("#{config.protocol}://#{config.host}:#{config.port}/v1/feedback/").to_s
|
46
|
-
rescue URI::InvalidURIError
|
47
|
-
nil
|
48
|
-
end
|
49
|
-
|
50
|
-
def render_form(error_id, action = action)
|
51
|
-
return unless action
|
52
|
-
ERB.new(@template ||= File.read(template_file)).result(binding)
|
53
|
-
end
|
54
|
-
|
55
|
-
def custom_template_file
|
56
|
-
@custom_template_file ||= config.project_root &&
|
57
|
-
File.join(config.project_root, 'lib', 'honeybadger', 'templates', 'feedback_form.erb')
|
58
|
-
end
|
59
|
-
|
60
|
-
def custom_template_file?
|
61
|
-
custom_template_file && File.exists?(custom_template_file)
|
62
|
-
end
|
63
|
-
|
64
|
-
def template_file
|
65
|
-
if custom_template_file?
|
66
|
-
custom_template_file
|
67
|
-
else
|
68
|
-
File.expand_path('../templates/feedback_form.erb', __FILE__)
|
69
|
-
end
|
4
|
+
warn '[DEPRECATION] Honeybadger::UserFeedback is deprecated in 2.0. Use Honeybadger::Rack::UserFeedback.'
|
5
|
+
super
|
70
6
|
end
|
71
7
|
end
|
72
8
|
end
|
@@ -1,26 +1,8 @@
|
|
1
1
|
module Honeybadger
|
2
|
-
class UserInformer
|
2
|
+
class UserInformer < Rack::UserInformer
|
3
3
|
def initialize(app)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def replacement(with)
|
8
|
-
Honeybadger.configuration.user_information.gsub(/\{\{\s*error_id\s*\}\}/, with.to_s)
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
status, headers, body = @app.call(env)
|
13
|
-
if env['honeybadger.error_id'] && Honeybadger.configuration.user_information
|
14
|
-
new_body = []
|
15
|
-
replace = replacement(env['honeybadger.error_id'])
|
16
|
-
body.each do |chunk|
|
17
|
-
new_body << chunk.gsub("<!-- HONEYBADGER ERROR -->", replace)
|
18
|
-
end
|
19
|
-
body.close if body.respond_to?(:close)
|
20
|
-
headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
|
21
|
-
body = new_body
|
22
|
-
end
|
23
|
-
[status, headers, body]
|
4
|
+
warn '[DEPRECATION] Honeybadger::UserInformer is deprecated in 2.0. Use Honeybadger::Rack::UserInformer.'
|
5
|
+
super
|
24
6
|
end
|
25
7
|
end
|
26
8
|
end
|
@@ -30,11 +30,13 @@ describe Honeybadger::Configuration do
|
|
30
30
|
assert_config_default :source_extract_radius, 2
|
31
31
|
assert_config_default :async, nil
|
32
32
|
assert_config_default :send_request_session, true
|
33
|
+
assert_config_default :send_local_variables, false
|
33
34
|
assert_config_default :debug, false
|
34
35
|
assert_config_default :log_exception_on_send_failure, false
|
35
36
|
assert_config_default :fingerprint, nil
|
36
37
|
assert_config_default :hostname, Socket.gethostname
|
37
38
|
assert_config_default :feedback, true
|
39
|
+
assert_config_default :features, {'notices' => true, 'local_variables' => true}
|
38
40
|
end
|
39
41
|
|
40
42
|
it "configures async as Proc" do
|
@@ -116,6 +118,7 @@ describe Honeybadger::Configuration do
|
|
116
118
|
assert_config_overridable :send_request_session
|
117
119
|
assert_config_overridable :debug
|
118
120
|
assert_config_overridable :hostname
|
121
|
+
assert_config_overridable :features
|
119
122
|
assert_config_overridable :metrics
|
120
123
|
assert_config_overridable :feedback
|
121
124
|
assert_config_overridable :log_exception_on_send_failure
|
@@ -134,7 +137,8 @@ describe Honeybadger::Configuration do
|
|
134
137
|
:notifier_version, :params_filters, :project_root, :port, :protocol,
|
135
138
|
:proxy_host, :proxy_pass, :proxy_port, :proxy_user, :secure,
|
136
139
|
:source_extract_radius, :async, :send_request_session, :debug,
|
137
|
-
:fingerprint, :hostname, :metrics, :feedback,
|
140
|
+
:fingerprint, :hostname, :features, :metrics, :feedback,
|
141
|
+
:log_exception_on_send_failure].each do |option|
|
138
142
|
expect(hash[option]).to eq config[option]
|
139
143
|
end
|
140
144
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Honeybadger::Dependency do
|
4
|
+
let(:dependency) { Honeybadger::Dependency.new }
|
5
|
+
subject { dependency }
|
6
|
+
|
7
|
+
before { Honeybadger::Dependency.stub(:instances).and_return([]) }
|
8
|
+
|
9
|
+
describe ".register" do
|
10
|
+
it "returns a new dependency" do
|
11
|
+
instance = double()
|
12
|
+
Honeybadger::Dependency.stub(:new).and_return(instance)
|
13
|
+
expect(Honeybadger::Dependency.register {}).to eq [instance]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "registers a new dependency" do
|
17
|
+
expect { Honeybadger::Dependency.register {} }.to change(described_class, :instances).from([]).to([kind_of(Honeybadger::Dependency)])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".inject!" do
|
22
|
+
it "injects all satisfied instances" do
|
23
|
+
Honeybadger::Dependency.instances.replace([mock_dependency, mock_dependency])
|
24
|
+
Honeybadger::Dependency.inject!
|
25
|
+
end
|
26
|
+
|
27
|
+
it "skips all unsatisfied instances" do
|
28
|
+
Honeybadger::Dependency.instances.replace([mock_dependency(false), mock_dependency(false)])
|
29
|
+
Honeybadger::Dependency.inject!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#requirement" do
|
34
|
+
let(:block) { Proc.new {} }
|
35
|
+
|
36
|
+
it "returns and Array of requirements" do
|
37
|
+
expect(subject.requirement(&block)).to eq [block]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "registers a new requirement" do
|
41
|
+
expect { subject.requirement(&block) }.to change(subject, :requirements).from([]).to([block])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#injection" do
|
46
|
+
let(:block) { Proc.new {} }
|
47
|
+
|
48
|
+
it "returns an Array of injections" do
|
49
|
+
expect(subject.injection(&block)).to eq [block]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "registers a new injection" do
|
53
|
+
expect { subject.injection(&block) }.to change(subject, :injections).from([]).to([block])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#ok?" do
|
58
|
+
subject { dependency.ok? }
|
59
|
+
|
60
|
+
context "when not injected yet" do
|
61
|
+
it { should be_true }
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when already injected" do
|
65
|
+
before { dependency.inject! }
|
66
|
+
|
67
|
+
it { should be_false }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "all requirements are met" do
|
71
|
+
before do
|
72
|
+
3.times { dependency.requirement { true } }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "some requirements fail" do
|
77
|
+
before do
|
78
|
+
3.times { dependency.requirement { true } }
|
79
|
+
dependency.requirement { false }
|
80
|
+
end
|
81
|
+
|
82
|
+
it { should be_false }
|
83
|
+
end
|
84
|
+
|
85
|
+
context "some requirements error" do
|
86
|
+
before do
|
87
|
+
dependency.requirement { true }
|
88
|
+
dependency.requirement { fail 'oops!' }
|
89
|
+
end
|
90
|
+
|
91
|
+
it { should be_false }
|
92
|
+
|
93
|
+
it "logs the failure" do
|
94
|
+
Honeybadger.should_receive(:write_verbose_log).with(/oops!/, :error).once
|
95
|
+
dependency.ok?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#inject!" do
|
101
|
+
it "calls injections" do
|
102
|
+
dependency.injections.replace([mock_injection, mock_injection])
|
103
|
+
dependency.inject!
|
104
|
+
end
|
105
|
+
|
106
|
+
context "some injections fail" do
|
107
|
+
before do
|
108
|
+
failing_injection = Proc.new { fail 'oh noes!' }
|
109
|
+
dependency.injections.replace([mock_injection, failing_injection, mock_injection(false)])
|
110
|
+
end
|
111
|
+
|
112
|
+
it "halts injection silently" do
|
113
|
+
expect { dependency.inject! }.not_to raise_error
|
114
|
+
end
|
115
|
+
|
116
|
+
it "logs the failure" do
|
117
|
+
Honeybadger.should_receive(:write_verbose_log).with(/oh noes!/, :error).once
|
118
|
+
dependency.inject!
|
119
|
+
end
|
120
|
+
|
121
|
+
it "marks the dependency as injected" do
|
122
|
+
expect { dependency.inject!}.to change(dependency, :injected?).from(false).to(true)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def mock_dependency(ok = true)
|
128
|
+
double(:ok? => ok).tap { |d| d.send(ok ? :should_receive : :should_not_receive, :inject!) }
|
129
|
+
end
|
130
|
+
|
131
|
+
def mock_injection(positive = true)
|
132
|
+
double().tap { |d| d.send(positive ? :should_receive : :should_not_receive, :call) }
|
133
|
+
end
|
134
|
+
end
|