honeybadger 1.10.3 → 1.11.0.beta1

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +10 -0
  3. data/CHANGELOG.md +17 -10
  4. data/Gemfile.lock +1 -1
  5. data/features/rails.feature +6 -4
  6. data/features/step_definitions/rails_steps.rb +8 -0
  7. data/features/support/rails.rb +5 -0
  8. data/gemfiles/rack.gemfile.lock +1 -1
  9. data/gemfiles/rails2.3.gemfile.lock +1 -1
  10. data/gemfiles/rails3.0.gemfile.lock +1 -1
  11. data/gemfiles/rails3.1.gemfile.lock +1 -1
  12. data/gemfiles/rails3.2.gemfile.lock +1 -1
  13. data/gemfiles/rails4.gemfile.lock +1 -1
  14. data/gemfiles/rails4_cap3.gemfile +13 -0
  15. data/gemfiles/rails4_cap3.gemfile.lock +204 -0
  16. data/gemfiles/rake.gemfile.lock +1 -1
  17. data/gemfiles/sinatra.gemfile.lock +1 -1
  18. data/honeybadger.gemspec +7 -4
  19. data/lib/honeybadger.rb +14 -1
  20. data/lib/honeybadger/capistrano.rb +4 -45
  21. data/lib/honeybadger/capistrano/legacy.rb +45 -0
  22. data/lib/honeybadger/capistrano/tasks.rake +67 -0
  23. data/lib/honeybadger/configuration.rb +2 -2
  24. data/lib/honeybadger/monitor/worker.rb +1 -1
  25. data/lib/honeybadger/notice.rb +10 -1
  26. data/lib/honeybadger/rack.rb +1 -0
  27. data/lib/honeybadger/rails.rb +8 -0
  28. data/lib/honeybadger/railtie.rb +1 -7
  29. data/lib/honeybadger/stats.rb +1 -1
  30. data/lib/honeybadger/templates/{feedback_form.html.erb → feedback_form.erb} +12 -9
  31. data/lib/honeybadger/user_feedback.rb +47 -17
  32. data/lib/honeybadger_tasks.rb +3 -3
  33. data/lib/rails/generators/honeybadger/honeybadger_generator.rb +1 -2
  34. data/spec/honeybadger/capistrano_spec.rb +26 -23
  35. data/spec/honeybadger/configuration_spec.rb +25 -21
  36. data/spec/honeybadger/notice_spec.rb +30 -37
  37. data/spec/honeybadger/notifier_spec.rb +60 -4
  38. data/spec/honeybadger/rack_spec.rb +1 -0
  39. data/spec/honeybadger/user_feedback_spec.rb +29 -4
  40. data/spec/honeybadger_tasks_spec.rb +13 -4
  41. metadata +9 -6
  42. data/spec/honeybadger/stats_spec.rb +0 -57
@@ -17,12 +17,12 @@ module HoneybadgerTasks
17
17
  def self.deploy(opts = {})
18
18
  api_key = opts.delete(:api_key) || Honeybadger.configuration.api_key
19
19
  unless api_key =~ /\S/
20
- puts "I don't seem to be configured with an API key. Please check your configuration."
20
+ $stderr.puts "I don't seem to be configured with an API key. Please check your configuration."
21
21
  return false
22
22
  end
23
23
 
24
24
  unless opts[:environment] =~ /\S/
25
- puts "I don't know to which environment you are deploying (use the TO=production option)."
25
+ $stderr.puts "I don't know to which environment you are deploying (use the TO=production option)."
26
26
  return false
27
27
  end
28
28
 
@@ -60,7 +60,7 @@ module HoneybadgerTasks
60
60
  puts "Succesfully recorded deployment"
61
61
  return true
62
62
  else
63
- puts response.body
63
+ $stderr.puts "Error recording deployment: #{response.class} -- #{response.body || 'no response'}"
64
64
  return false
65
65
  end
66
66
  end
@@ -36,9 +36,8 @@ class HoneybadgerGenerator < Rails::Generators::Base
36
36
 
37
37
  def append_capistrano_hook
38
38
  if File.exists?('config/deploy.rb') && File.exists?('Capfile')
39
- append_file('config/deploy.rb', <<-HOOK)
39
+ append_file('Capfile', <<-HOOK)
40
40
 
41
- require './config/boot'
42
41
  require 'honeybadger/capistrano'
43
42
  HOOK
44
43
  end
@@ -1,33 +1,36 @@
1
1
  require 'spec_helper'
2
+ require 'capistrano'
2
3
 
3
- require 'capistrano/configuration'
4
- require 'honeybadger/capistrano'
4
+ if defined?(Capistrano::Configuration.instance)
5
+ describe 'Honeybadger::Capistrano' do
6
+ require 'capistrano/configuration'
7
+ require 'honeybadger/capistrano'
5
8
 
6
- describe Honeybadger::Capistrano do
7
- before(:each) do
8
- reset_config
9
+ before { reset_config }
9
10
 
10
- @configuration = Capistrano::Configuration.new
11
- Honeybadger::Capistrano.load_into(@configuration)
12
- @configuration.dry_run = true
13
- end
11
+ before(:each) do
12
+ @configuration = Capistrano::Configuration.new
13
+ Honeybadger::Capistrano.load_into(@configuration)
14
+ @configuration.dry_run = true
15
+ end
14
16
 
15
- it "defines honeybadger:deploy task" do
16
- expect(@configuration.find_task('honeybadger:deploy')).not_to be_nil
17
- end
17
+ it "defines honeybadger:deploy task" do
18
+ expect(@configuration.find_task('honeybadger:deploy')).not_to be_nil
19
+ end
18
20
 
19
- it "logs when calling honeybadger:deploy task" do
20
- @configuration.set(:current_revision, '084505b1c0e0bcf1526e673bb6ac99fbcb18aecc')
21
- @configuration.set(:repository, 'repository')
22
- @configuration.set(:current_release, '/home/deploy/rails_app/honeybadger')
23
- io = StringIO.new
24
- logger = Capistrano::Logger.new(:output => io)
25
- logger.level = Capistrano::Logger::MAX_LEVEL
21
+ it "logs when calling honeybadger:deploy task" do
22
+ @configuration.set(:current_revision, '084505b1c0e0bcf1526e673bb6ac99fbcb18aecc')
23
+ @configuration.set(:repository, 'repository')
24
+ @configuration.set(:current_release, '/home/deploy/rails_app/honeybadger')
25
+ io = StringIO.new
26
+ logger = Capistrano::Logger.new(:output => io)
27
+ logger.level = Capistrano::Logger::MAX_LEVEL
26
28
 
27
- @configuration.logger = logger
28
- @configuration.find_and_execute_task('honeybadger:deploy')
29
+ @configuration.logger = logger
30
+ @configuration.find_and_execute_task('honeybadger:deploy')
29
31
 
30
- expect(io.string).to include '** Notifying Honeybadger of Deploy'
31
- expect(io.string).to include '** Honeybadger Notification Complete'
32
+ expect(io.string).to include '** Notifying Honeybadger of Deploy'
33
+ expect(io.string).to include '** Honeybadger Notification Complete'
34
+ end
32
35
  end
33
36
  end
@@ -3,6 +3,7 @@ require 'socket'
3
3
 
4
4
  describe Honeybadger::Configuration do
5
5
  it "provides default values" do
6
+ assert_config_default :api_key, nil
6
7
  assert_config_default :proxy_host, nil
7
8
  assert_config_default :proxy_port, nil
8
9
  assert_config_default :proxy_user, nil
@@ -206,29 +207,32 @@ describe Honeybadger::Configuration do
206
207
  expect(config.public?).to be_true
207
208
  end
208
209
 
209
- it "is not be public if the notices feature is missing" do
210
- config = Honeybadger::Configuration.new
211
- config.features = {}
212
- expect(config.public?).to be_false
213
- end
210
+ describe "#metrics?" do
211
+ let(:config) { Honeybadger::Configuration.new }
214
212
 
215
- it "sends metrics by default in a public environment" do
216
- config = Honeybadger::Configuration.new
217
- config.environment_name = 'production'
218
- expect(config.metrics?).to be_true
219
- end
213
+ context "when public" do
214
+ before { config.stub(:public?).and_return(true) }
220
215
 
221
- it "sends not send metrics when disabled" do
222
- config = Honeybadger::Configuration.new
223
- config.environment_name = 'production'
224
- config.metrics = false
225
- expect(config.metrics?).to be_false
226
- end
216
+ it "sends metrics by default" do
217
+ expect(config.metrics?).to be_true
218
+ end
227
219
 
228
- it "sends not send metrics in a development environment" do
229
- config = Honeybadger::Configuration.new
230
- config.environment_name = 'development'
231
- expect(config.metrics?).to be_false
220
+ context "when disabled" do
221
+ before { config.metrics = false }
222
+
223
+ it "does not send metrics" do
224
+ expect(config.metrics?).to be_false
225
+ end
226
+ end
227
+ end
228
+
229
+ context "when not public" do
230
+ before { config.stub(:public?).and_return(false) }
231
+
232
+ it "does not send metrics" do
233
+ expect(config.metrics?).to be_false
234
+ end
235
+ end
232
236
  end
233
237
 
234
238
  it "uses the assigned logger if set" do
@@ -237,7 +241,7 @@ describe Honeybadger::Configuration do
237
241
  expect(config.logger).to eq "CUSTOM LOGGER"
238
242
  end
239
243
 
240
- it 'gives a new instance if non defined' do
244
+ it "gives a new instance if non defined" do
241
245
  Honeybadger.configuration = nil
242
246
  expect(Honeybadger.configuration).to be_a Honeybadger::Configuration
243
247
  end
@@ -14,15 +14,6 @@ describe Honeybadger::Notice do
14
14
  Honeybadger::Notice.new(configuration.merge(args))
15
15
  end
16
16
 
17
- def stub_request(attrs = {})
18
- double('request', { :parameters => { 'one' => 'two' },
19
- :protocol => 'http',
20
- :host => 'some.host',
21
- :request_uri => '/some/uri',
22
- :session => { :to_hash => { 'a' => 'b' } },
23
- :env => { 'three' => 'four' } }.update(attrs))
24
- end
25
-
26
17
  context '#deliver' do
27
18
  context 'sender is configured' do
28
19
  it "delivers to sender" do
@@ -313,53 +304,55 @@ describe Honeybadger::Notice do
313
304
  assert_filters_hash(:session_data)
314
305
  end
315
306
 
316
- describe 'url' do
317
- let(:params_filters) { [] }
318
- let(:notice) { build_notice(:params_filters => params_filters, :url => url) }
319
-
320
- context 'filtered params in query' do
321
- let(:params_filters) { [:bar] }
322
- let(:url) { 'https://www.honeybadger.io/?foo=1&bar=2&baz=3' }
307
+ context 'filtered parameters in query string' do
308
+ let(:params_filters) { [:foo, :bar] }
323
309
 
310
+ describe '#url' do
311
+ let(:notice) { build_notice(:params_filters => params_filters, :url => 'https://www.honeybadger.io/?foo=1&bar=2&baz=3') }
324
312
  it 'filters query' do
325
- expect(notice.url).to eq 'https://www.honeybadger.io/?foo=1&bar=[FILTERED]&baz=3'
313
+ expect(notice.url).to eq 'https://www.honeybadger.io/?foo=[FILTERED]&bar=[FILTERED]&baz=3'
326
314
  end
327
315
  end
328
316
 
329
- context 'malformed query' do
330
- let(:url) { 'https://www.honeybadger.io/?foobar12' }
317
+ describe '#cgi_data' do
318
+ let(:cgi_data) { { 'QUERY_STRING' => 'foo=1&bar=2&baz=3', 'ORIGINAL_FULLPATH' => '/?foo=1&bar=2&baz=3' } }
319
+ let(:notice) { build_notice(:params_filters => params_filters, :cgi_data => cgi_data) }
320
+
321
+ subject { notice.cgi_data }
331
322
 
332
- it 'maintains query' do
333
- expect(notice.url).to eq url
323
+ it 'filters QUERY_STRING key' do
324
+ expect(subject['QUERY_STRING']).to eq 'foo=[FILTERED]&bar=[FILTERED]&baz=3'
334
325
  end
326
+
327
+ it 'filters ORIGINAL_FULLPATH key' do
328
+ expect(subject['ORIGINAL_FULLPATH']).to eq '/?foo=[FILTERED]&bar=[FILTERED]&baz=3'
329
+ end
330
+ end
331
+ end
332
+
333
+ describe '#filter_url' do
334
+ let(:notice) { build_notice(:params_filters => [], :url => url) }
335
+ subject { notice.send(:filter_url, url) }
336
+
337
+ context 'malformed query' do
338
+ let(:url) { 'https://www.honeybadger.io/?foobar12' }
339
+ it { should eq url }
335
340
  end
336
341
 
337
342
  context 'no query' do
338
343
  let(:url) { 'https://www.honeybadger.io' }
339
-
340
- it 'keeps original URL' do
341
- expect(notice.url).to eq url
342
- end
344
+ it { should eq url }
343
345
  end
344
346
 
345
347
  context 'malformed url' do
346
348
  let(:url) { 'http s ! honeybadger' }
347
-
348
- before do
349
- expect { URI.parse(url) }.to raise_error
350
- end
351
-
352
- it 'keeps original URL' do
353
- expect(notice.url).to eq url
354
- end
349
+ before { expect { URI.parse(url) }.to raise_error }
350
+ it { should eq url }
355
351
  end
356
352
 
357
353
  context 'complex url' do
358
354
  let(:url) { 'https://foo:bar@www.honeybadger.io:123/asdf/?foo=1&bar=2&baz=3' }
359
-
360
- it 'keeps original URL' do
361
- expect(notice.url).to eq url
362
- end
355
+ it { should eq url }
363
356
  end
364
357
  end
365
358
 
@@ -7,10 +7,6 @@ describe 'Honeybadger' do
7
7
  class ContinuedException < Exception
8
8
  end
9
9
 
10
- before(:each) do
11
- reset_config
12
- end
13
-
14
10
  def assert_sends(notice, notice_args)
15
11
  Honeybadger::Notice.should_receive(:new).with(hash_including(notice_args))
16
12
  Honeybadger.sender.should_receive(:send_to_honeybadger).with(notice)
@@ -24,6 +20,66 @@ describe 'Honeybadger' do
24
20
  Honeybadger.configure { |config| config.environment_name = 'development' }
25
21
  end
26
22
 
23
+ before(:each) { reset_config }
24
+
25
+ describe "#ping" do
26
+ let(:config) { Honeybadger::Configuration.new }
27
+ let(:sender) { double() }
28
+
29
+ let(:invoke_subject) { Honeybadger.ping(config) }
30
+ subject { invoke_subject }
31
+
32
+ before do
33
+ config.framework = 'Rails 4.1.0'
34
+ config.environment_name = 'production'
35
+ config.hostname = 'twix'
36
+ stub_const('Honeybadger::VERSION', '1.11.0')
37
+
38
+ Honeybadger.stub(:sender).and_return(sender)
39
+ end
40
+
41
+ context "configuration is public" do
42
+ before { config.stub(:public?).and_return(true) }
43
+
44
+ it "pings the sender" do
45
+ sender.should_receive(:ping).with(hash_including(:version => '1.11.0', :framework => 'Rails 4.1.0', :environment => 'production', :hostname => 'twix'))
46
+ invoke_subject
47
+ end
48
+
49
+ context "result is truthy" do
50
+ before { sender.should_receive(:ping).and_return(result) }
51
+
52
+ context "result does not contain features" do
53
+ let(:result) { {} }
54
+ it { should be_nil }
55
+ specify { expect { subject }.not_to change(config, :features) }
56
+ end
57
+
58
+ context "result contains features" do
59
+ let(:result) { {'features' => {'notices' => true, 'metrics' => true}} }
60
+ it { should eq result['features'] }
61
+ specify { expect { subject }.to change(config, :features).to(result['features']) }
62
+ end
63
+ end
64
+
65
+ context "result is falsey" do
66
+ before { sender.should_receive(:ping) }
67
+ it { should be_nil }
68
+ specify { expect { invoke_subject }.not_to change(config, :features) }
69
+ end
70
+ end
71
+
72
+ context "configuration is not public" do
73
+ before { config.stub(:public?).and_return(false) }
74
+ it { should be_nil }
75
+
76
+ it "doesn't attempt to ping sender" do
77
+ sender.should_not_receive(:ping)
78
+ invoke_subject
79
+ end
80
+ end
81
+ end
82
+
27
83
  it "yields and save a configuration when configuring" do
28
84
  yielded_configuration = nil
29
85
  Honeybadger.configure do |config|
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'rack'
2
3
 
3
4
  describe Honeybadger::Rack do
4
5
  it "calls the upstream app with the environment" do
@@ -12,11 +12,12 @@ describe Honeybadger::UserFeedback do
12
12
  let(:response) { Net::HTTP.get_response(URI.parse("http://example.com/")) }
13
13
 
14
14
  before do
15
+ reset_config
15
16
  ShamRack.mount(informer_app, "example.com")
16
17
  end
17
18
 
18
19
  context "feedback feature is disabled by ping" do
19
- it 'does not modify the output' do
20
+ it "does not modify the output" do
20
21
  expect(response.body).to eq '<!-- HONEYBADGER FEEDBACK -->'
21
22
  end
22
23
  end
@@ -29,25 +30,49 @@ describe Honeybadger::UserFeedback do
29
30
  context "there is a honeybadger id" do
30
31
  let(:honeybadger_id) { 1 }
31
32
 
32
- it 'modifies output' do
33
+ it "modifies output" do
33
34
  rendered_length = informer_app.render_form(1).size
34
35
  expect(response.body).to match(/honeybadger_feedback_token/)
35
36
  expect(response["Content-Length"].to_i).to eq rendered_length
36
37
  end
37
38
 
39
+ context "a project root is configured" do
40
+ let(:tmp_dir) { File.expand_path('../../../tmp', __FILE__) }
41
+ let(:template_dir) { File.join(tmp_dir, 'lib', 'honeybadger', 'templates') }
42
+ let(:template_file) { File.join(template_dir, 'feedback_form.erb') }
43
+
44
+ before do
45
+ FileUtils.mkdir_p(template_dir)
46
+ FileUtils.rm_f(template_file)
47
+ Honeybadger.configure(true) do |config|
48
+ config.project_root = tmp_dir
49
+ end
50
+ end
51
+
52
+ context "custom template is implemented" do
53
+ before do
54
+ File.open(template_file, 'w') { |f| f.write 'custom feedback form' }
55
+ end
56
+
57
+ it "renders with custom template" do
58
+ expect(response.body).to match(/custom feedback form/)
59
+ end
60
+ end
61
+ end
62
+
38
63
  context "feedback feature is disabled by customer" do
39
64
  before do
40
65
  Honeybadger.configuration.feedback = false
41
66
  end
42
67
 
43
- it 'does not modify the output' do
68
+ it "does not modify the output" do
44
69
  expect(response.body).to eq '<!-- HONEYBADGER FEEDBACK -->'
45
70
  end
46
71
  end
47
72
  end
48
73
 
49
74
  context "there is no honeybadger id" do
50
- it 'does not modify the output' do
75
+ it "does not modify the output" do
51
76
  expect(response.body).to eq '<!-- HONEYBADGER FEEDBACK -->'
52
77
  end
53
78
  end
@@ -17,14 +17,17 @@ describe HoneybadgerTasks do
17
17
  end
18
18
 
19
19
  context "being quiet" do
20
- before(:each) { HoneybadgerTasks.stub(:puts) }
20
+ before do
21
+ HoneybadgerTasks.stub(:puts)
22
+ $stderr.stub(:puts)
23
+ end
21
24
 
22
25
  context "in a configured project" do
23
26
  before(:each) { Honeybadger.configure { |config| config.api_key = "1234123412341234" } }
24
27
 
25
28
  context "on deploy({})" do
26
29
  it "complains about missing rails env" do
27
- HoneybadgerTasks.should_receive(:puts).with(/which environment/i)
30
+ $stderr.should_receive(:puts).with(/which environment/i)
28
31
  HoneybadgerTasks.deploy({})
29
32
  end
30
33
 
@@ -95,11 +98,17 @@ describe HoneybadgerTasks do
95
98
  end
96
99
 
97
100
  it "puts the response body on failure" do
98
- HoneybadgerTasks.should_receive(:puts).with("body")
101
+ $stderr.should_receive(:puts).with(/body/)
99
102
  @http_proxy.should_receive(:request).with(anything).and_return(unsuccessful_response('body'))
100
103
  HoneybadgerTasks.deploy(@options)
101
104
  end
102
105
 
106
+ it "puts the response class on failure" do
107
+ $stderr.should_receive(:puts).with(/Net::HTTPClientError/)
108
+ @http_proxy.should_receive(:request).with(anything).and_return(unsuccessful_response)
109
+ HoneybadgerTasks.deploy(@options)
110
+ end
111
+
103
112
  it "returns false on failure" do
104
113
  @http_proxy.should_receive(:request).with(anything).and_return(unsuccessful_response('body'))
105
114
  output = HoneybadgerTasks.deploy(@options)
@@ -148,7 +157,7 @@ describe HoneybadgerTasks do
148
157
 
149
158
  context "on deploy(:environment => 'staging')" do
150
159
  it "complains about missing api key" do
151
- HoneybadgerTasks.should_receive(:puts).with(/api key/i)
160
+ $stderr.should_receive(:puts).with(/api key/i)
152
161
  HoneybadgerTasks.deploy(:environment => "staging")
153
162
  end
154
163