honeybadger 1.8.1 → 1.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/CHANGELOG.md +14 -0
  2. data/Gemfile.lock +61 -19
  3. data/Guardfile +4 -4
  4. data/MIT-LICENSE +1 -0
  5. data/README.md +2 -2
  6. data/Rakefile +4 -14
  7. data/features/rails.feature +1 -1
  8. data/gemfiles/rack.gemfile.lock +62 -27
  9. data/gemfiles/rails2.3.gemfile.lock +73 -36
  10. data/gemfiles/rails3.0.gemfile.lock +59 -26
  11. data/gemfiles/rails3.1.gemfile.lock +59 -26
  12. data/gemfiles/rails3.2.gemfile.lock +63 -30
  13. data/gemfiles/rails4.gemfile.lock +69 -36
  14. data/gemfiles/rake.gemfile.lock +62 -27
  15. data/gemfiles/sinatra.gemfile.lock +62 -27
  16. data/honeybadger.gemspec +31 -17
  17. data/lib/honeybadger.rb +2 -3
  18. data/lib/honeybadger/array.rb +53 -0
  19. data/lib/honeybadger/configuration.rb +19 -2
  20. data/lib/honeybadger/monitor.rb +16 -0
  21. data/lib/honeybadger/monitor/railtie.rb +52 -0
  22. data/lib/honeybadger/monitor/sender.rb +33 -0
  23. data/lib/honeybadger/monitor/worker.rb +71 -0
  24. data/lib/honeybadger/railtie.rb +10 -0
  25. data/lib/honeybadger/sender.rb +60 -41
  26. data/{test/unit/backtrace_test.rb → spec/honeybadger/backtrace_spec.rb} +69 -71
  27. data/{test/unit/capistrano_test.rb → spec/honeybadger/capistrano_spec.rb} +8 -9
  28. data/{test/unit/configuration_test.rb → spec/honeybadger/configuration_spec.rb} +85 -59
  29. data/spec/honeybadger/logger_spec.rb +65 -0
  30. data/spec/honeybadger/monitor/worker_spec.rb +189 -0
  31. data/{test/unit/notice_test.rb → spec/honeybadger/notice_spec.rb} +169 -185
  32. data/spec/honeybadger/notifier_spec.rb +252 -0
  33. data/spec/honeybadger/rack_spec.rb +84 -0
  34. data/{test/unit/rails/action_controller_catcher_test.rb → spec/honeybadger/rails/action_controller_spec.rb} +65 -57
  35. data/{test/unit/rails_test.rb → spec/honeybadger/rails_spec.rb} +8 -8
  36. data/spec/honeybadger/sender_spec.rb +249 -0
  37. data/spec/honeybadger_tasks_spec.rb +165 -0
  38. data/spec/spec_helper.rb +18 -0
  39. data/spec/support/array_including.rb +31 -0
  40. data/spec/support/backtraced_exception.rb +9 -0
  41. data/spec/support/collected_sender.rb +12 -0
  42. data/spec/support/defines_constants.rb +18 -0
  43. data/{test/test_helper.rb → spec/support/helpers.rb} +8 -61
  44. metadata +93 -45
  45. data/test/unit/honeybadger_tasks_test.rb +0 -167
  46. data/test/unit/logger_test.rb +0 -74
  47. data/test/unit/notifier_test.rb +0 -265
  48. data/test/unit/rack_test.rb +0 -88
  49. data/test/unit/sender_test.rb +0 -290
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Honeybadger do
4
+ def stub_http(options = {})
5
+ response = options[:response] || Faraday::Response.new(:status => 200)
6
+ response.stub(:body => options.include?(:body) ? options[:body] : '{"id":"1234"}')
7
+ http = double(:post => response,
8
+ :adapter => nil,
9
+ :url_prefix= => nil,
10
+ :headers => nil)
11
+ Faraday.stub(:new => http)
12
+ http
13
+ end
14
+
15
+ def send_notice
16
+ Honeybadger.sender.send_to_honeybadger('data')
17
+ end
18
+
19
+ def stub_verbose_log
20
+ Honeybadger.stub(:write_verbose_log)
21
+ end
22
+
23
+ def configure
24
+ Honeybadger.configure { |config| }
25
+ end
26
+
27
+ it "reports that notifier is ready when configured" do
28
+ stub_verbose_log
29
+ Honeybadger.should_receive(:write_verbose_log).with(/Notifier (.*) ready/, anything)
30
+ configure
31
+ end
32
+
33
+ it "does not report that notifier is ready when internally configured" do
34
+ stub_verbose_log
35
+ Honeybadger.should_not_receive(:write_verbose_log)
36
+ Honeybadger.configure(true) { |config| }
37
+ end
38
+
39
+ it "prints environment info on a failed notification without a body" do
40
+ reset_config
41
+ stub_verbose_log
42
+ stub_http(:response => Faraday::Response.new(:status => 500), :body => nil)
43
+ Honeybadger.should_receive(:write_verbose_log).with(/Environment Info:/)
44
+ Honeybadger.should_not_receive(:write_verbose_log).with(/Response from Honeybadger:/, anything)
45
+ send_notice
46
+ end
47
+
48
+ it "prints environment info and response on a success with a body" do
49
+ reset_config
50
+ stub_verbose_log
51
+ stub_http
52
+ Honeybadger.should_receive(:write_verbose_log).with(/Environment Info:/)
53
+ Honeybadger.should_receive(:write_verbose_log).with(/Response from Honeybadger:/)
54
+ send_notice
55
+ end
56
+
57
+ it "prints environment info and response on a failure with a body" do
58
+ reset_config
59
+ stub_verbose_log
60
+ stub_http(:response => Faraday::Response.new(:status => 500))
61
+ Honeybadger.should_receive(:write_verbose_log).with(/Environment Info:/)
62
+ Honeybadger.should_receive(:write_verbose_log).with(/Response from Honeybadger:/)
63
+ send_notice
64
+ end
65
+ end
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+ require 'honeybadger/monitor'
3
+
4
+ describe Honeybadger::Monitor::Worker do
5
+ let(:instance) { Honeybadger::Monitor::Worker.send(:new) }
6
+ subject { instance }
7
+
8
+ before(:each) do
9
+ Thread.stub(:new)
10
+ # Create an attr_reader for @metrics and @sender
11
+ instance.stub(:metrics) { instance.instance_variable_get(:@metrics) }
12
+ instance.stub(:sender) { instance.instance_variable_get(:@sender) }
13
+ end
14
+
15
+ context 'initializing' do
16
+ describe '@metrics' do
17
+ subject { instance.instance_variable_get(:@metrics) }
18
+
19
+ it { should have_key(:timing) }
20
+ it { should have_key(:counter) }
21
+
22
+ it 'is initialized timing with empty hash' do
23
+ expect(subject[:timing]).to eq({})
24
+ end
25
+
26
+ it 'is initialized counter with empty hash' do
27
+ expect(subject[:counter]).to eq({})
28
+ end
29
+ end
30
+
31
+ describe '@delay' do
32
+ subject { instance.instance_variable_get(:@delay) }
33
+ it { should eq 60 }
34
+ end
35
+
36
+ describe '@per_request' do
37
+ subject { instance.instance_variable_get(:@per_request) }
38
+ it { should eq 100 }
39
+ end
40
+
41
+ describe '@sender' do
42
+ subject { instance.instance_variable_get(:@sender) }
43
+
44
+ it { should be_a Honeybadger::Monitor::Sender }
45
+ it { should be_a Honeybadger::Sender }
46
+
47
+ it 'is initialized with Honeybadger configuration' do
48
+ Honeybadger::Monitor::Sender.should_receive(:new).with(Honeybadger.configuration)
49
+ Honeybadger::Monitor::Worker.send(:new)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#timing' do
55
+ before(:each) do
56
+ expect(instance.metrics[:timing]).to be_empty
57
+ instance.timing(:test, 50)
58
+ end
59
+
60
+ it 'adds value to metrics hash' do
61
+ expect(instance.metrics[:timing][:test]).to eq [50]
62
+ end
63
+
64
+ it 'appends to existing values' do
65
+ instance.timing(:test, 60)
66
+ expect(instance.metrics[:timing][:test]).to eq [50, 60]
67
+ end
68
+ end
69
+
70
+ describe '#increment' do
71
+ before(:each) do
72
+ expect(instance.metrics[:counter]).to be_empty
73
+ instance.increment(:test, 50)
74
+ end
75
+
76
+ it 'adds value to metrics hash' do
77
+ expect(instance.metrics[:counter][:test]).to eq [50]
78
+ end
79
+
80
+ it 'appends to existing values' do
81
+ instance.increment(:test, 60)
82
+ expect(instance.metrics[:counter][:test]).to eq [50, 60]
83
+ end
84
+ end
85
+
86
+ describe '#send_metrics' do
87
+ subject { instance.send(:send_metrics) }
88
+
89
+ it 're-inits metrics' do
90
+ instance.increment(:test, 60)
91
+ expect { subject }.to change(instance, :metrics).to({ :timing => {}, :counter => {} })
92
+ end
93
+
94
+ it 'returns nil when there are no metrics to send' do
95
+ expect(instance.metrics[:timing]).to be_empty
96
+ expect(instance.metrics[:counter]).to be_empty
97
+ instance.sender.should_not_receive(:send_metrics)
98
+ expect(subject).to be_nil
99
+ end
100
+
101
+ it 'returns nil after sending metrics' do
102
+ instance.increment(:test, 60)
103
+ instance.should_not_receive(:log)
104
+ instance.sender.should_receive(:send_metrics)
105
+ expect(subject).to be_nil
106
+ end
107
+
108
+ context 'when constructingtiming metrics' do
109
+ before(:each) { 10.times { |i| instance.timing(:test, i) } }
110
+ after(:each) { subject }
111
+
112
+ it 'includes the mean value' do
113
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(['test:mean 4.5'])))
114
+ end
115
+
116
+ it 'includes the median value' do
117
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(['test:median 5'])))
118
+ end
119
+
120
+ it 'includes the percentile_90 value' do
121
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(['test:percentile_90 9'])))
122
+ end
123
+
124
+ it 'includes the min value' do
125
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(['test:min 0'])))
126
+ end
127
+
128
+ it 'includes the max value' do
129
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(['test:max 9'])))
130
+ end
131
+
132
+ it 'includes the stddev value' do
133
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(/test:stddev 3.027/)))
134
+ end
135
+
136
+ it 'includes a count of total metrics' do
137
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including(['test 10'])))
138
+ end
139
+ end
140
+
141
+ context 'when constructing counter metrics' do
142
+ it 'sums the values of each metric' do
143
+ 10.times { instance.increment(:test, 1) }
144
+ instance.sender.should_receive(:send_metrics).with(hash_including(:metrics => array_including('test 10')))
145
+ subject
146
+ end
147
+ end
148
+
149
+ context 'when sending metrics' do
150
+ before(:each) { instance.increment(:test, 1) }
151
+ after(:each) { subject }
152
+
153
+ it 'executes batches of 100' do
154
+ 199.times { |i| instance.increment(:"test_#{i}", 1) }
155
+ instance.sender.should_receive(:send_metrics).exactly(2).times
156
+ end
157
+
158
+ it 'includes the configured environment' do
159
+ Honeybadger.configure do |c|
160
+ c.environment_name = 'asdf'
161
+ end
162
+ instance.sender.should_receive(:send_metrics).with(hash_including(:environment => 'asdf'))
163
+ end
164
+
165
+ it 'includes the configured hostname' do
166
+ Honeybadger.configure do |c|
167
+ c.hostname = 'zxcv'
168
+ end
169
+ instance.sender.should_receive(:send_metrics).with(hash_including(:hostname => 'zxcv'))
170
+ end
171
+ end
172
+
173
+ context 'when an exception occurrs' do
174
+ before(:each) do
175
+ instance.increment(:test, 1)
176
+ instance.sender.stub(:send_metrics).and_raise(RuntimeError.new('cobra attack!'))
177
+ end
178
+
179
+ it 'logs the exception' do
180
+ instance.should_receive(:log).with(:error, /cobra attack/)
181
+ expect { subject }.not_to raise_error
182
+ end
183
+
184
+ it 'returns nil' do
185
+ expect(subject).to be_nil
186
+ end
187
+ end
188
+ end
189
+ end
@@ -1,7 +1,8 @@
1
- require 'test_helper'
1
+ require 'spec_helper'
2
2
  require 'json'
3
+ require 'rack'
3
4
 
4
- class NoticeTest < Test::Unit::TestCase
5
+ describe Honeybadger::Notice do
5
6
  def configure
6
7
  Honeybadger::Configuration.new.tap do |config|
7
8
  config.api_key = 'abc123def456'
@@ -14,7 +15,7 @@ class NoticeTest < Test::Unit::TestCase
14
15
  end
15
16
 
16
17
  def stub_request(attrs = {})
17
- stub('request', { :parameters => { 'one' => 'two' },
18
+ double('request', { :parameters => { 'one' => 'two' },
18
19
  :protocol => 'http',
19
20
  :host => 'some.host',
20
21
  :request_uri => '/some/uri',
@@ -24,103 +25,100 @@ class NoticeTest < Test::Unit::TestCase
24
25
 
25
26
  context '#deliver' do
26
27
  context 'sender is configured' do
27
- should "deliver to sender" do
28
+ it "delivers to sender" do
28
29
  sender = stub_sender!
29
30
  notice = build_notice
30
- notice.stubs(:to_json => { :foo => 'bar' })
31
+ notice.stub(:to_json => { :foo => 'bar' })
31
32
 
33
+ sender.should_receive(:send_to_honeybadger).with(notice)
32
34
  notice.deliver
33
-
34
- assert_received(sender, :send_to_honeybadger) { |expect| expect.with(notice) }
35
35
  end
36
36
  end
37
37
 
38
38
  context 'sender is not configured' do
39
- should "return false" do
39
+ it "returns false" do
40
40
  notice = build_notice
41
41
  Honeybadger.sender = nil
42
- assert_equal false, notice.deliver
42
+ expect(notice.deliver).to be_false
43
43
  end
44
44
  end
45
45
  end
46
46
 
47
- should "generate json from as_json template" do
47
+ it "generates json from as_json template" do
48
48
  notice = build_notice
49
49
  hash = {'foo' => 'bar'}
50
- notice.expects(:as_json).once.returns(hash)
50
+ notice.should_receive(:as_json).once.and_return(hash)
51
51
  json = notice.to_json
52
52
 
53
53
  payload = nil
54
- assert_nothing_raised do
55
- payload = JSON.parse(json)
56
- end
54
+ expect { payload = JSON.parse(json) }.not_to raise_error
57
55
 
58
- assert_equal payload, hash
56
+ expect(payload).to eq hash
59
57
  end
60
58
 
61
- should "accept a project root" do
59
+ it "accepts a project root" do
62
60
  project_root = '/path/to/project'
63
61
  notice = build_notice(:project_root => project_root)
64
- assert_equal project_root, notice.project_root
62
+ expect(notice.project_root).to eq project_root
65
63
  end
66
64
 
67
- should "accept a component" do
68
- assert_equal 'users_controller', build_notice(:component => 'users_controller').controller
65
+ it "accepts a component" do
66
+ expect(build_notice(:component => 'users_controller').controller).to eq 'users_controller'
69
67
  end
70
68
 
71
- should "alias the component as controller" do
72
- assert_equal 'users_controller', build_notice(:controller => 'users_controller').component
73
- assert_equal 'users_controller', build_notice(:component => 'users_controller').controller
69
+ it "aliases the component as controller" do
70
+ expect(build_notice(:controller => 'users_controller').component).to eq 'users_controller'
71
+ expect(build_notice(:controller => 'users_controller').controller).to eq 'users_controller'
74
72
  end
75
73
 
76
- should "accept a action" do
77
- assert_equal 'index', build_notice(:action => 'index').action
74
+ it "accepts a action" do
75
+ expect(build_notice(:action => 'index').action).to eq 'index'
78
76
  end
79
77
 
80
- should "accept source excerpt radius" do
81
- assert_equal 3, build_notice(:source_extract_radius => 3).source_extract_radius
78
+ it "accepts source excerpt radius" do
79
+ expect(build_notice(:source_extract_radius => 3).source_extract_radius).to eq 3
82
80
  end
83
81
 
84
- should "accept a url" do
82
+ it "accepts a url" do
85
83
  url = 'http://some.host/uri'
86
84
  notice = build_notice(:url => url)
87
- assert_equal url, notice.url
85
+ expect(notice.url).to eq url
88
86
  end
89
87
 
90
- should "set the host name" do
88
+ it "sets the host name" do
91
89
  notice = build_notice
92
- assert_equal hostname, notice.hostname
90
+ expect(notice.hostname).to eq hostname
93
91
  end
94
92
 
95
- should "override the host name" do
93
+ it "overrides the host name" do
96
94
  notice = build_notice({ :hostname => 'asdf' })
97
- assert_equal 'asdf', notice.hostname
95
+ expect(notice.hostname).to eq 'asdf'
98
96
  end
99
97
 
100
98
  context "custom fingerprint" do
101
- should "include nil fingerprint when no fingerprint is specified" do
99
+ it "includes nil fingerprint when no fingerprint is specified" do
102
100
  notice = build_notice
103
- assert_equal nil, notice.fingerprint
101
+ expect(notice.fingerprint).to be_nil
104
102
  end
105
103
 
106
- should "accept fingerprint as string" do
104
+ it "accepts fingerprint as string" do
107
105
  notice = build_notice({ :fingerprint => 'foo' })
108
- assert_equal '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', notice.fingerprint
106
+ expect(notice.fingerprint).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
109
107
  end
110
108
 
111
- should "accept fingerprint responding to #call" do
112
- notice = build_notice({ :fingerprint => mock(:call => 'foo') })
113
- assert_equal '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', notice.fingerprint
109
+ it "accepts fingerprint responding to #call" do
110
+ notice = build_notice({ :fingerprint => double(:call => 'foo') })
111
+ expect(notice.fingerprint).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
114
112
  end
115
113
 
116
- should "accept fingerprint using #to_s" do
117
- notice = build_notice({ :fingerprint => mock(:to_s => 'foo') })
118
- assert_equal '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', notice.fingerprint
114
+ it "accepts fingerprint using #to_s" do
115
+ notice = build_notice({ :fingerprint => double(:to_s => 'foo') })
116
+ expect(notice.fingerprint).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
119
117
  end
120
118
  end
121
119
 
122
120
  context "with a backtrace" do
123
- setup do
121
+ before(:each) do
124
122
  @source = <<-RUBY
125
123
  $:<<'lib'
126
124
  require 'honeybadger'
@@ -141,73 +139,69 @@ class NoticeTest < Test::Unit::TestCase
141
139
  @exception.set_backtrace(@backtrace_array)
142
140
  end
143
141
 
144
- should "pass its backtrace filters for parsing" do
145
- Honeybadger::Backtrace.expects(:parse).with(@backtrace_array, {:filters => 'foo'}).returns(mock(:lines => []))
142
+ it "passes its backtrace filters for parsing" do
143
+ Honeybadger::Backtrace.should_receive(:parse).with(@backtrace_array, {:filters => 'foo'}).and_return(double(:lines => []))
146
144
 
147
- notice = Honeybadger::Notice.new({:exception => @exception, :backtrace_filters => 'foo'})
145
+ Honeybadger::Notice.new({:exception => @exception, :backtrace_filters => 'foo'})
148
146
  end
149
147
 
150
- should "pass its backtrace line filters for parsing" do
148
+ it "passes its backtrace line filters for parsing" do
151
149
  @backtrace_array.each do |line|
152
- Honeybadger::Backtrace::Line.expects(:parse).with(line, {:filters => 'foo'})
150
+ Honeybadger::Backtrace::Line.should_receive(:parse).with(line, {:filters => 'foo'})
153
151
  end
154
152
 
155
- notice = Honeybadger::Notice.new({:exception => @exception, :backtrace_filters => 'foo'})
153
+ Honeybadger::Notice.new({:exception => @exception, :backtrace_filters => 'foo'})
156
154
  end
157
155
 
158
- should "accept a backtrace from an exception or hash" do
156
+ it "accepts a backtrace from an exception or hash" do
159
157
  backtrace = Honeybadger::Backtrace.parse(@backtrace_array)
160
158
  notice_from_exception = build_notice(:exception => @exception)
161
159
 
162
- assert_equal backtrace,
163
- notice_from_exception.backtrace,
164
- "backtrace was not correctly set from an exception"
160
+ expect(notice_from_exception.backtrace).to eq backtrace # backtrace was not correctly set from an exception
165
161
 
166
162
  notice_from_hash = build_notice(:backtrace => @backtrace_array)
167
- assert_equal backtrace,
168
- notice_from_hash.backtrace,
169
- "backtrace was not correctly set from a hash"
163
+ expect(notice_from_hash.backtrace).to eq backtrace # backtrace was not correctly set from a hash
170
164
  end
171
165
 
172
166
  context "without application trace" do
173
- setup do
167
+ before(:each) do
174
168
  Honeybadger.configuration.project_root = '/foo/bar'
175
169
  @string_io = StringIO.new(@source)
176
- File.stubs(:exists?).with('my/file/backtrace').returns true
177
- File.stubs(:open).with('my/file/backtrace').yields @string_io
170
+ File.stub(:exists?).with('my/file/backtrace').and_return true
171
+ File.stub(:open).with('my/file/backtrace').and_yield @string_io
178
172
  end
179
173
 
180
- should "include source extract from backtrace" do
174
+ it "includes source extract from backtrace" do
181
175
  backtrace = Honeybadger::Backtrace.parse(@backtrace_array)
182
176
  notice_from_exception = build_notice(:exception => @exception)
183
177
  @string_io.rewind
184
178
 
185
- assert_not_equal notice_from_exception.source_extract, {}, 'Expected backtrace source extract to be found'
186
- assert_equal backtrace.lines.first.source, notice_from_exception.source_extract
179
+ expect(notice_from_exception.source_extract).not_to be_empty # Expected backtrace source extract to be found
180
+ expect(notice_from_exception.source_extract).to eq backtrace.lines.first.source
187
181
  end
188
182
  end
189
183
 
190
184
  context 'with an application trace' do
191
- setup do
185
+ before(:each) do
192
186
  Honeybadger.configuration.project_root = 'test/honeybadger/'
193
187
 
194
188
  @string_io = StringIO.new(@source)
195
- File.stubs(:exists?).with('test/honeybadger/rack_test.rb').returns true
196
- File.stubs(:open).with('test/honeybadger/rack_test.rb').yields @string_io
189
+ File.stub(:exists?).with('test/honeybadger/rack_test.rb').and_return true
190
+ File.stub(:open).with('test/honeybadger/rack_test.rb').and_yield @string_io
197
191
  end
198
192
 
199
- should "include source extract from first line of application trace" do
193
+ it "includes source extract from first line of application trace" do
200
194
  backtrace = Honeybadger::Backtrace.parse(@backtrace_array)
201
195
  notice_from_exception = build_notice(:exception => @exception)
202
196
  @string_io.rewind
203
197
 
204
- assert_not_equal notice_from_exception.source_extract, {}, 'Expected backtrace source extract to be found'
205
- assert_equal backtrace.lines[1].source, notice_from_exception.source_extract
198
+ expect(notice_from_exception.source_extract).not_to be_empty # Expected backtrace source extract to be found
199
+ expect(notice_from_exception.source_extract).to eq backtrace.lines[1].source
206
200
  end
207
201
  end
208
202
  end
209
203
 
210
- should "Use source extract from view when reporting an ActionView::Template::Error" do
204
+ it "Uses source extract from view when reporting an ActionView::Template::Error" do
211
205
  # TODO: I would like to stub out a real ActionView::Template::Error, but we're
212
206
  # currently locked at actionpack 2.3.8. Perhaps if one day we upgrade...
213
207
  source = <<-ERB
@@ -217,73 +211,73 @@ class NoticeTest < Test::Unit::TestCase
217
211
  4: <div>
218
212
  ERB
219
213
  exception = build_exception
220
- exception.stubs(:source_extract).returns(source)
214
+ exception.stub(:source_extract).and_return(source)
221
215
  notice = Honeybadger::Notice.new({:exception => exception})
222
216
 
223
- assert_equal({ '1' => ' <%= current_user.name %>', '2' => '</div>', '3' => '', '4' => '<div>'}, notice.source_extract)
217
+ expect(notice.source_extract).to eq({ '1' => ' <%= current_user.name %>', '2' => '</div>', '3' => '', '4' => '<div>'})
224
218
  end
225
219
 
226
- should "set the error class from an exception or hash" do
220
+ it "sets the error class from an exception or hash" do
227
221
  assert_accepts_exception_attribute :error_class do |exception|
228
222
  exception.class.name
229
223
  end
230
224
  end
231
225
 
232
- should "set the error message from an exception or hash" do
226
+ it "sets the error message from an exception or hash" do
233
227
  assert_accepts_exception_attribute :error_message do |exception|
234
228
  "#{exception.class.name}: #{exception.message}"
235
229
  end
236
230
  end
237
231
 
238
- should "accept parameters from a request or hash" do
232
+ it "accepts parameters from a request or hash" do
239
233
  parameters = { 'one' => 'two' }
240
234
  notice_from_hash = build_notice(:parameters => parameters)
241
- assert_equal notice_from_hash.parameters, parameters
235
+ expect(notice_from_hash.parameters).to eq parameters
242
236
  end
243
237
 
244
- should "accept session data from a session[:data] hash" do
238
+ it "accepts session data from a session[:data] hash" do
245
239
  data = { 'one' => 'two' }
246
240
  notice = build_notice(:session => { :data => data })
247
- assert_equal data, notice.session_data
241
+ expect(notice.session_data).to eq data
248
242
  end
249
243
 
250
- should "accept session data from a session_data hash" do
244
+ it "accepts session data from a session_data hash" do
251
245
  data = { 'one' => 'two' }
252
246
  notice = build_notice(:session_data => data)
253
- assert_equal data, notice.session_data
247
+ expect(notice.session_data).to eq data
254
248
  end
255
249
 
256
- should "accept an environment name" do
257
- assert_equal 'development', build_notice(:environment_name => 'development').environment_name
250
+ it "accepts an environment name" do
251
+ expect(build_notice(:environment_name => 'development').environment_name).to eq 'development'
258
252
  end
259
253
 
260
- should "accept CGI data from a hash" do
254
+ it "accepts CGI data from a hash" do
261
255
  data = { 'string' => 'value' }
262
256
  notice = build_notice(:cgi_data => data)
263
- assert_equal data, notice.cgi_data, "should take CGI data from a hash"
257
+ expect(notice.cgi_data).to eq data
264
258
  end
265
259
 
266
- should "accept notifier information" do
260
+ it "accepts notifier information" do
267
261
  params = { :notifier_name => 'a name for a notifier',
268
262
  :notifier_version => '1.0.5',
269
263
  :notifier_url => 'http://notifiers.r.us/download' }
270
264
  notice = build_notice(params)
271
- assert_equal params[:notifier_name], notice.notifier_name
272
- assert_equal params[:notifier_version], notice.notifier_version
273
- assert_equal params[:notifier_url], notice.notifier_url
265
+ expect(notice.notifier_name).to eq params[:notifier_name]
266
+ expect(notice.notifier_version).to eq params[:notifier_version]
267
+ expect(notice.notifier_url).to eq params[:notifier_url]
274
268
  end
275
269
 
276
- should "set sensible defaults without an exception" do
270
+ it "sets sensible defaults without an exception" do
277
271
  backtrace = Honeybadger::Backtrace.parse(build_backtrace_array)
278
272
  notice = build_notice(:backtrace => build_backtrace_array)
279
273
 
280
- assert_equal 'Notification', notice.error_message
274
+ expect(notice.error_message).to eq 'Notification'
281
275
  assert_array_starts_with backtrace.lines, notice.backtrace.lines
282
- assert_equal({}, notice.parameters)
283
- assert_equal({}, notice.session_data)
276
+ expect(notice.parameters).to be_empty
277
+ expect(notice.session_data).to be_empty
284
278
  end
285
279
 
286
- should "use the caller as the backtrace for an exception without a backtrace" do
280
+ it "uses the caller as the backtrace for an exception without a backtrace" do
287
281
  filters = Honeybadger::Configuration.new.backtrace_filters
288
282
  backtrace = Honeybadger::Backtrace.parse(caller, :filters => filters)
289
283
  notice = build_notice(:exception => StandardError.new('error'), :backtrace => nil)
@@ -291,110 +285,108 @@ class NoticeTest < Test::Unit::TestCase
291
285
  assert_array_starts_with backtrace.lines, notice.backtrace.lines
292
286
  end
293
287
 
294
- should "convert unserializable objects to strings" do
288
+ it "converts unserializable objects to strings" do
295
289
  assert_serializes_hash(:parameters)
296
290
  assert_serializes_hash(:cgi_data)
297
291
  assert_serializes_hash(:session_data)
298
292
  end
299
293
 
300
- should "filter parameters" do
294
+ it "filters parameters" do
301
295
  assert_filters_hash(:parameters)
302
296
  end
303
297
 
304
- should "filter cgi data" do
298
+ it "filters cgi data" do
305
299
  assert_filters_hash(:cgi_data)
306
300
  end
307
301
 
308
- should "filter session" do
302
+ it "filters session" do
309
303
  assert_filters_hash(:session_data)
310
304
  end
311
305
 
312
- should "remove rack.request.form_vars" do
306
+ it "removes rack.request.form_vars" do
313
307
  original = {
314
308
  "rack.request.form_vars" => "story%5Btitle%5D=The+TODO+label",
315
309
  "abc" => "123"
316
310
  }
317
311
 
318
312
  notice = build_notice(:cgi_data => original)
319
- assert_equal({"abc" => "123"}, notice.cgi_data)
313
+ expect(notice.cgi_data).to eq({"abc" => "123"})
320
314
  end
321
315
 
322
- should "not send empty request data" do
316
+ it "does not send empty request data" do
323
317
  notice = build_notice
324
- assert_nil notice.url
325
- assert_nil notice.controller
326
- assert_nil notice.action
318
+ notice.url.should be_nil
319
+ notice.controller.should be_nil
320
+ notice.action.should be_nil
327
321
 
328
322
  json = notice.to_json
329
323
  payload = JSON.parse(json)
330
- assert_nil payload['request']['url']
331
- assert_nil payload['request']['component']
332
- assert_nil payload['request']['action']
333
- assert_nil payload['request']['user']
324
+ payload['request']['url'].should be_nil
325
+ payload['request']['component'].should be_nil
326
+ payload['request']['action'].should be_nil
327
+ payload['request']['user'].should be_nil
334
328
  end
335
329
 
336
330
  %w(url controller action).each do |var|
337
- should "send a request if #{var} is present" do
331
+ it "sends a request if #{var} is present" do
338
332
  notice = build_notice(var.to_sym => 'value')
339
333
  json = notice.to_json
340
334
  payload = JSON.parse(json)
341
- assert_not_nil payload['request']
335
+ payload['request'].should_not be_nil
342
336
  end
343
337
  end
344
338
 
345
339
  %w(parameters cgi_data session_data context).each do |var|
346
- should "send a request if #{var} is present" do
340
+ it "sends a request if #{var} is present" do
347
341
  notice = build_notice(var.to_sym => { 'key' => 'value' })
348
342
  json = notice.to_json
349
343
  payload = JSON.parse(json)
350
- assert_not_nil payload['request']
344
+ payload['request'].should_not be_nil
351
345
  end
352
346
  end
353
347
 
354
- should "not ignore an exception not matching ignore filters" do
348
+ it "does not ignore an exception not matching ignore filters" do
355
349
  notice = build_notice(:error_class => 'ArgumentError',
356
350
  :ignore => ['Argument'],
357
- :ignore_by_filters => [lambda { |notice| false }])
358
- assert !notice.ignore?
351
+ :ignore_by_filters => [lambda { |n| false }])
352
+ expect(notice.ignore?).to be_false
359
353
  end
360
354
 
361
- should "ignore an exception with a matching error class" do
355
+ it "ignores an exception with a matching error class" do
362
356
  notice = build_notice(:error_class => 'ArgumentError',
363
357
  :ignore => [ArgumentError])
364
- assert notice.ignore?
358
+ expect(notice.ignore?).to be_true
365
359
  end
366
360
 
367
- should "ignore an exception with an equal error class name" do
361
+ it "ignores an exception with an equal error class name" do
368
362
  notice = build_notice(:error_class => 'ArgumentError',
369
363
  :ignore => ['ArgumentError'])
370
- assert notice.ignore?, "Expected ArgumentError to ignore ArgumentError"
364
+ expect(notice.ignore?).to be_true # Expected ArgumentError to ignore ArgumentError
371
365
  end
372
366
 
373
- should "ignore an exception matching error class name" do
367
+ it "ignores an exception matching error class name" do
374
368
  notice = build_notice(:error_class => 'ArgumentError',
375
369
  :ignore => [/Error$/])
376
- assert notice.ignore?, "Expected /Error$/ to ignore ArgumentError"
370
+ expect(notice.ignore?).to be_true # Expected /Error$/ to ignore ArgumentError
377
371
  end
378
372
 
379
- should "ignore an exception that inherits from ignored error class" do
373
+ it "ignores an exception that inherits from ignored error class" do
380
374
  class ::FooError < ArgumentError ; end
381
375
  notice = build_notice(:exception => FooError.new('Oh noes!'),
382
376
  :ignore => [ArgumentError])
383
- assert notice.ignore?, "Expected ArgumentError to ignore FooError"
377
+ expect(notice.ignore?).to be_true # Expected ArgumentError to ignore FooError
384
378
  end
385
379
 
386
- should "ignore an exception with a matching filter" do
380
+ it "ignores an exception with a matching filter" do
387
381
  filter = lambda {|notice| notice.error_class == 'ArgumentError' }
388
382
  notice = build_notice(:error_class => 'ArgumentError',
389
383
  :ignore_by_filters => [filter])
390
- assert notice.ignore?
384
+ expect(notice.ignore?).to be_true
391
385
  end
392
386
 
393
- should "not raise without an ignore list" do
387
+ it "does not raise without an ignore list" do
394
388
  notice = build_notice(:ignore => nil, :ignore_by_filters => nil)
395
- assert_nothing_raised do
396
- notice.ignore?
397
- end
389
+ expect { notice.ignore? }.not_to raise_error
398
390
  end
399
391
 
400
392
  ignored_error_classes = %w(
@@ -407,127 +399,123 @@ class NoticeTest < Test::Unit::TestCase
407
399
  )
408
400
 
409
401
  ignored_error_classes.each do |ignored_error_class|
410
- should "ignore #{ignored_error_class} error by default" do
402
+ it "ignores #{ignored_error_class} error by default" do
411
403
  notice = build_notice(:error_class => ignored_error_class)
412
- assert notice.ignore?
404
+ expect(notice.ignore?).to be_true
413
405
  end
414
406
  end
415
407
 
416
- should "act like a hash" do
408
+ it "acts like a hash" do
417
409
  notice = build_notice(:error_message => 'some message')
418
- assert_equal notice.error_message, notice[:error_message]
410
+ expect(notice[:error_message]).to eq notice.error_message
419
411
  end
420
412
 
421
- should "return params on notice[:request][:params]" do
413
+ it "returns params on notice[:request][:params]" do
422
414
  params = { 'one' => 'two' }
423
415
  notice = build_notice(:parameters => params)
424
- assert_equal params, notice[:request][:params]
416
+ expect(notice[:request][:params]).to eq params
425
417
  end
426
418
 
427
- should "return context on notice[:request][:context]" do
419
+ it "returns context on notice[:request][:context]" do
428
420
  context = { 'one' => 'two' }
429
421
  notice = build_notice(:context => context)
430
- assert_equal context, notice[:request][:context]
422
+ expect(notice[:request][:context]).to eq context
431
423
  end
432
424
 
433
- should "merge context from args with context from Honeybadger#context" do
425
+ it "merges context from args with context from Honeybadger#context" do
434
426
  Honeybadger.context({ 'one' => 'two', 'foo' => 'bar' })
435
427
  notice = build_notice(:context => { 'three' => 'four', 'foo' => 'baz' })
436
- assert_equal({ 'one' => 'two', 'three' => 'four', 'foo' => 'baz' }, notice[:request][:context])
428
+ expect(notice[:request][:context]).to eq({ 'one' => 'two', 'three' => 'four', 'foo' => 'baz' })
437
429
  end
438
430
 
439
- should "return nil context when context is not set" do
431
+ it "returns nil context when context is not set" do
440
432
  notice = build_notice
441
- assert_equal nil, notice[:request][:context]
433
+ notice[:request][:context].should be_nil
442
434
  end
443
435
 
444
- should "ensure #to_hash is called on objects that support it" do
445
- assert_nothing_raised do
446
- build_notice(:session => { :object => stub(:to_hash => {}) })
447
- end
436
+ it "ensures #to_hash is called on objects that support it" do
437
+ expect { build_notice(:session => { :object => double(:to_hash => {}) }) }.not_to raise_error
448
438
  end
449
439
 
450
- should "ensure #to_ary is called on objects that support it" do
451
- assert_nothing_raised do
452
- build_notice(:session => { :object => stub(:to_ary => {}) })
453
- end
440
+ it "ensures #to_ary is called on objects that support it" do
441
+ expect { build_notice(:session => { :object => double(:to_ary => {}) }) }.not_to raise_error
454
442
  end
455
443
 
456
- should "extract data from a rack environment hash" do
444
+ it "extracts data from a rack environment hash" do
457
445
  url = "https://subdomain.happylane.com:100/test/file.rb?var=value&var2=value2"
458
446
  parameters = { 'var' => 'value', 'var2' => 'value2' }
459
447
  env = Rack::MockRequest.env_for(url)
460
448
 
461
449
  notice = build_notice(:rack_env => env)
462
450
 
463
- assert_equal url, notice.url
464
- assert_equal parameters, notice.parameters
465
- assert_equal 'GET', notice.cgi_data['REQUEST_METHOD']
451
+ expect(notice.url).to eq url
452
+ expect(notice.parameters).to eq parameters
453
+ expect(notice.cgi_data['REQUEST_METHOD']).to eq 'GET'
466
454
  end
467
455
 
468
- should "extract data from a rack environment hash with action_dispatch info" do
456
+ it "extracts data from a rack environment hash with action_dispatch info" do
469
457
  params = { 'controller' => 'users', 'action' => 'index', 'id' => '7' }
470
458
  env = Rack::MockRequest.env_for('/', { 'action_dispatch.request.parameters' => params })
471
459
 
472
460
  notice = build_notice(:rack_env => env)
473
461
 
474
- assert_equal params, notice.parameters
475
- assert_equal params['controller'], notice.component
476
- assert_equal params['action'], notice.action
462
+ expect(notice.parameters).to eq params
463
+ expect(notice.component).to eq params['controller']
464
+ expect(notice.action).to eq params['action']
477
465
  end
478
466
 
479
- should "extract session data from a rack environment" do
467
+ it "extracts session data from a rack environment" do
480
468
  session_data = { 'something' => 'some value' }
481
469
  env = Rack::MockRequest.env_for('/', 'rack.session' => session_data)
482
470
 
483
471
  notice = build_notice(:rack_env => env)
484
472
 
485
- assert_equal session_data, notice.session_data
473
+ expect(notice.session_data).to eq session_data
486
474
  end
487
475
 
488
- should "prefer passed session data to rack session data" do
476
+ it "prefers passed session data to rack session data" do
489
477
  session_data = { 'something' => 'some value' }
490
478
  env = Rack::MockRequest.env_for('/')
491
479
 
492
480
  notice = build_notice(:rack_env => env, :session_data => session_data)
493
481
 
494
- assert_equal session_data, notice.session_data
482
+ expect(notice.session_data).to eq session_data
495
483
  end
496
484
 
497
485
  unless Gem::Version.new(Rack.release) < Gem::Version.new('1.2')
498
- should "fail gracefully when Rack params cannot be parsed" do
486
+ it "fails gracefully when Rack params cannot be parsed" do
499
487
  rack_env = Rack::MockRequest.env_for('http://www.example.com/explode', :method => 'POST', :input => 'foo=bar&bar=baz%')
500
488
  notice = Honeybadger::Notice.new(:rack_env => rack_env)
501
- assert_equal 1, notice.params.size
502
- assert_match /Failed to call params on Rack::Request/, notice.params[:error]
489
+ expect(notice.params.size).to eq 1
490
+ expect(notice.params[:error]).to match(/Failed to call params on Rack::Request/)
503
491
  end
504
492
  end
505
493
 
506
- should "not send session data when send_request_session is false" do
494
+ it "does not send session data when send_request_session is false" do
507
495
  notice = build_notice(:send_request_session => false, :session_data => { :foo => :bar })
508
- assert_equal nil, notice.session_data
496
+ notice.session_data.should be_nil
509
497
  end
510
498
 
511
- should "not allow infinite recursion" do
499
+ it "does not allow infinite recursion" do
512
500
  hash = {:a => :a}
513
501
  hash[:hash] = hash
514
502
  notice = Honeybadger::Notice.new(:parameters => hash)
515
- assert_equal "[possible infinite recursion halted]", notice.parameters[:hash]
503
+ expect(notice.parameters[:hash]).to eq "[possible infinite recursion halted]"
516
504
  end
517
505
 
518
- should "trim error message to 1k" do
506
+ it "trims error message to 1k" do
519
507
  message = 'asdfghjkl'*200
520
508
  e = StandardError.new(message)
521
509
  notice = Honeybadger::Notice.new(:exception => e)
522
- assert_operator 1024, :<, message.bytesize
523
- assert_equal 1024, notice.error_message.bytesize
510
+ message.bytesize.should > 1024
511
+ expect(notice.error_message.bytesize).to eq 1024
524
512
  end
525
513
 
526
- should "prefer notice args to exception attributes" do
514
+ it "prefers notice args to exception attributes" do
527
515
  e = RuntimeError.new('Not very helpful')
528
516
  notice = Honeybadger::Notice.new(:exception => e, :error_class => 'MyClass', :error_message => 'Something very specific went wrong.')
529
- assert_equal 'MyClass', notice.error_class
530
- assert_equal 'Something very specific went wrong.', notice.error_message
517
+ expect(notice.error_class).to eq 'MyClass'
518
+ expect(notice.error_message).to eq 'Something very specific went wrong.'
531
519
  end
532
520
 
533
521
  def assert_accepts_exception_attribute(attribute, args = {}, &block)
@@ -537,14 +525,10 @@ class NoticeTest < Test::Unit::TestCase
537
525
 
538
526
  notice_from_exception = build_notice(args.merge(:exception => exception))
539
527
 
540
- assert_equal notice_from_exception.send(attribute),
541
- value,
542
- "#{attribute} was not correctly set from an exception"
528
+ expect(notice_from_exception.send(attribute)).to eq value
543
529
 
544
530
  notice_from_hash = build_notice(args.merge(attribute => value))
545
- assert_equal notice_from_hash.send(attribute),
546
- value,
547
- "#{attribute} was not correctly set from a hash"
531
+ expect(notice_from_hash.send(attribute)).to eq value
548
532
  end
549
533
 
550
534
  def assert_serializes_hash(attribute)
@@ -558,11 +542,12 @@ class NoticeTest < Test::Unit::TestCase
558
542
  }
559
543
  notice = build_notice(attribute => hash)
560
544
  hash = notice.send(attribute)
561
- assert_equal object.to_s, hash[:strange_object], "objects should be serialized"
562
- assert_kind_of Hash, hash[:sub_hash], "subhashes should be kept"
563
- assert_equal object.to_s, hash[:sub_hash][:sub_object], "subhash members should be serialized"
564
- assert_kind_of Array, hash[:array], "arrays should be kept"
565
- assert_equal object.to_s, hash[:array].first, "array members should be serialized"
545
+ expect(object.to_s).to eq hash[:strange_object] # objects should be serialized
546
+
547
+ expect(hash[:sub_hash]).to be_a Hash # subhashes should be kept
548
+ expect(object.to_s).to eq hash[:sub_hash][:sub_object] # subhash members should be serialized
549
+ expect(hash[:array]).to be_a Array # arrays should be kept
550
+ expect(object.to_s).to eq hash[:array].first # array members should be serialized
566
551
  end
567
552
  end
568
553
 
@@ -578,8 +563,7 @@ class NoticeTest < Test::Unit::TestCase
578
563
 
579
564
  notice = build_notice(:params_filters => filters, attribute => original)
580
565
 
581
- assert_equal(filtered,
582
- notice.send(attribute))
566
+ expect(notice.send(attribute)).to eq filtered
583
567
  end
584
568
 
585
569
  def build_backtrace_array