honeybadger 1.8.1 → 1.9.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 (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