bugsnag 5.5.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +33 -11
  3. data/CHANGELOG.md +23 -0
  4. data/Gemfile +20 -0
  5. data/Rakefile +19 -12
  6. data/UPGRADING.md +58 -0
  7. data/VERSION +1 -1
  8. data/bugsnag.gemspec +0 -9
  9. data/lib/bugsnag.rb +64 -86
  10. data/lib/bugsnag/configuration.rb +42 -26
  11. data/lib/bugsnag/delivery.rb +9 -0
  12. data/lib/bugsnag/delivery/synchronous.rb +3 -5
  13. data/lib/bugsnag/delivery/thread_queue.rb +4 -2
  14. data/lib/bugsnag/helpers.rb +5 -16
  15. data/lib/bugsnag/{delayed_job.rb → integrations/delayed_job.rb} +15 -7
  16. data/lib/bugsnag/{mailman.rb → integrations/mailman.rb} +13 -11
  17. data/lib/bugsnag/{que.rb → integrations/que.rb} +11 -11
  18. data/lib/bugsnag/{rack.rb → integrations/rack.rb} +22 -23
  19. data/lib/bugsnag/{rails → integrations/rails}/active_record_rescue.rb +9 -7
  20. data/lib/bugsnag/{rails → integrations/rails}/controller_methods.rb +0 -9
  21. data/lib/bugsnag/{railtie.rb → integrations/railtie.rb} +24 -21
  22. data/lib/bugsnag/{rake.rb → integrations/rake.rb} +12 -9
  23. data/lib/bugsnag/{resque.rb → integrations/resque.rb} +12 -9
  24. data/lib/bugsnag/integrations/shoryuken.rb +49 -0
  25. data/lib/bugsnag/{sidekiq.rb → integrations/sidekiq.rb} +13 -9
  26. data/lib/bugsnag/middleware/callbacks.rb +4 -8
  27. data/lib/bugsnag/middleware/classify_error.rb +7 -13
  28. data/lib/bugsnag/middleware/clearance_user.rb +8 -8
  29. data/lib/bugsnag/middleware/exception_meta_data.rb +34 -0
  30. data/lib/bugsnag/middleware/ignore_error_class.rb +21 -0
  31. data/lib/bugsnag/middleware/mailman.rb +4 -4
  32. data/lib/bugsnag/middleware/rack_request.rb +13 -13
  33. data/lib/bugsnag/middleware/rails3_request.rb +10 -10
  34. data/lib/bugsnag/middleware/rake.rb +5 -5
  35. data/lib/bugsnag/middleware/sidekiq.rb +5 -5
  36. data/lib/bugsnag/middleware/suggestion_data.rb +30 -0
  37. data/lib/bugsnag/middleware/warden_user.rb +6 -6
  38. data/lib/bugsnag/middleware_stack.rb +5 -5
  39. data/lib/bugsnag/report.rb +187 -0
  40. data/lib/bugsnag/stacktrace.rb +113 -0
  41. data/lib/bugsnag/tasks/bugsnag.rake +2 -70
  42. data/spec/cleaner_spec.rb +6 -0
  43. data/spec/configuration_spec.rb +1 -1
  44. data/spec/fixtures/middleware/internal_info_setter.rb +3 -3
  45. data/spec/fixtures/middleware/public_info_setter.rb +3 -3
  46. data/spec/fixtures/tasks/Rakefile +2 -3
  47. data/spec/integration_spec.rb +5 -20
  48. data/spec/{delayed_job_spec.rb → integrations/delayed_job_spec.rb} +0 -0
  49. data/spec/integrations/sidekiq_spec.rb +34 -0
  50. data/spec/middleware_spec.rb +108 -35
  51. data/spec/rack_spec.rb +1 -1
  52. data/spec/{notification_spec.rb → report_spec.rb} +226 -209
  53. data/spec/spec_helper.rb +18 -0
  54. data/spec/{code_spec.rb → stacktrace_spec.rb} +1 -1
  55. metadata +23 -139
  56. data/.document +0 -5
  57. data/lib/bugsnag/capistrano.rb +0 -7
  58. data/lib/bugsnag/capistrano2.rb +0 -32
  59. data/lib/bugsnag/delay/resque.rb +0 -21
  60. data/lib/bugsnag/deploy.rb +0 -35
  61. data/lib/bugsnag/middleware/rails2_request.rb +0 -52
  62. data/lib/bugsnag/notification.rb +0 -506
  63. data/lib/bugsnag/rails.rb +0 -70
  64. data/lib/bugsnag/rails/action_controller_rescue.rb +0 -74
  65. data/lib/bugsnag/shoryuken.rb +0 -41
  66. data/lib/bugsnag/tasks/bugsnag.cap +0 -48
  67. data/rails/init.rb +0 -7
@@ -42,6 +42,12 @@ describe Bugsnag::Cleaner do
42
42
  expect(subject.clean_object(obj)).to eq("André")
43
43
  end
44
44
 
45
+ it "cleans custom objects" do
46
+ class Macaron; end
47
+ a = Macaron.new
48
+ expect(subject.clean_object(a)).to eq('[OBJECT]')
49
+ end
50
+
45
51
  it "cleans up binary strings properly" do
46
52
  if RUBY_VERSION > "1.9"
47
53
  obj = "Andr\xc7\xff"
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  describe Bugsnag::Configuration do
5
5
  describe "delivery_method" do
6
6
  it "should have the default delivery method" do
7
- expect(subject.delivery_method).to eq(Bugsnag::Configuration::DEFAULT_DELIVERY_METHOD)
7
+ expect(subject.delivery_method).to eq(:thread_queue)
8
8
  end
9
9
 
10
10
  it "should have the defined delivery_method" do
@@ -4,8 +4,8 @@ class InternalInfoSetter
4
4
  @bugsnag = bugsnag
5
5
  end
6
6
 
7
- def call(notification)
8
- notification.meta_data[:custom][:info] = MESSAGE
9
- @bugsnag.call(notification)
7
+ def call(report)
8
+ report.meta_data.merge!({custom: {info: MESSAGE}})
9
+ @bugsnag.call(report)
10
10
  end
11
11
  end
@@ -4,8 +4,8 @@ class PublicInfoSetter
4
4
  @bugsnag = bugsnag
5
5
  end
6
6
 
7
- def call(notification)
8
- notification.meta_data[:custom][:info] = MESSAGE
9
- @bugsnag.call(notification)
7
+ def call(report)
8
+ report.meta_data.merge!({custom: {info: MESSAGE}})
9
+ @bugsnag.call(report)
10
10
  end
11
11
  end
@@ -1,13 +1,12 @@
1
- require "bugsnag/rake"
1
+ require "bugsnag/integrations/rake"
2
2
 
3
3
  namespace :test do
4
4
  desc "used by integration_spec to test that Bugsnag::Middleware::Rake runs properly"
5
5
  task :crash do
6
6
  port = ENV['BUGSNAG_TEST_SERVER_PORT']
7
7
  Bugsnag.configure do |config|
8
- config.endpoint = "localhost:#{port}"
8
+ config.endpoint = "http://localhost:#{port}"
9
9
  config.api_key = "0" * 32
10
- config.use_ssl = false
11
10
  end
12
11
 
13
12
  raise
@@ -15,6 +15,7 @@ describe 'Bugsnag' do
15
15
  end
16
16
  Thread.new{ server.start }
17
17
  end
18
+
18
19
  after do
19
20
  server.stop
20
21
  queue.clear
@@ -39,8 +40,7 @@ describe 'Bugsnag' do
39
40
 
40
41
  it 'should send notifications over the wire' do
41
42
  Bugsnag.configure do |config|
42
- config.endpoint = "localhost:#{server.config[:Port]}"
43
- config.use_ssl = false
43
+ config.endpoint = "http://localhost:#{server.config[:Port]}"
44
44
  end
45
45
  WebMock.allow_net_connect!
46
46
 
@@ -49,22 +49,9 @@ describe 'Bugsnag' do
49
49
  expect(request['events'][0]['exceptions'][0]['message']).to eq('yo')
50
50
  end
51
51
 
52
- it 'should send deploys over the wire' do
53
- Bugsnag.configure do |config|
54
- config.endpoint = "localhost:#{server.config[:Port]}"
55
- config.use_ssl = false
56
- end
57
- WebMock.allow_net_connect!
58
-
59
- Bugsnag::Deploy.notify :app_version => '1.1.1'
60
-
61
- expect(request['appVersion']).to eq('1.1.1')
62
- end
63
-
64
52
  it 'should work with threadpool delivery' do
65
53
  Bugsnag.configure do |config|
66
- config.endpoint = "localhost:#{server.config[:Port]}"
67
- config.use_ssl = false
54
+ config.endpoint = "http://localhost:#{server.config[:Port]}"
68
55
  config.delivery_method = :thread_queue
69
56
  end
70
57
  WebMock.allow_net_connect!
@@ -78,8 +65,7 @@ describe 'Bugsnag' do
78
65
  is_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
79
66
  unless is_jruby #jruby doesn't support fork, so this test doesn't apply
80
67
  Bugsnag.configure do |config|
81
- config.endpoint = "localhost:#{server.config[:Port]}"
82
- config.use_ssl = false
68
+ config.endpoint = "http://localhost:#{server.config[:Port]}"
83
69
  config.delivery_method = :thread_queue
84
70
  end
85
71
  WebMock.allow_net_connect!
@@ -117,8 +103,7 @@ describe 'Bugsnag' do
117
103
  it 'should use a proxy when configured' do
118
104
  Bugsnag.configure do |config|
119
105
 
120
- config.endpoint = "localhost:#{server.config[:Port]}"
121
- config.use_ssl = false
106
+ config.endpoint = "http://localhost:#{server.config[:Port]}"
122
107
 
123
108
  config.proxy_host = 'localhost'
124
109
  config.proxy_port = proxy.config[:Port]
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'sidekiq/testing'
3
+
4
+ class FailingWorker
5
+ include Sidekiq::Worker
6
+ def perform(value)
7
+ puts "Work: #{100/value}"
8
+ end
9
+ end
10
+
11
+ describe Bugsnag::Sidekiq do
12
+ before do
13
+ Sidekiq::Testing.inline!
14
+ Sidekiq::Testing.server_middleware do |chain|
15
+ chain.add Bugsnag::Sidekiq
16
+ end
17
+ end
18
+
19
+ it "works" do
20
+ begin
21
+ FailingWorker.perform_async(-0)
22
+ fail("shouldn't be here")
23
+ rescue
24
+ end
25
+
26
+ expect(Bugsnag).to have_sent_notification {|payload|
27
+ event = get_event_from_payload(payload)
28
+ expect(event["metaData"]["sidekiq"]["msg"]["class"]).to eq("FailingWorker")
29
+ expect(event["metaData"]["sidekiq"]["msg"]["args"]).to eq([-0])
30
+ expect(event["metaData"]["sidekiq"]["msg"]["queue"]).to eq("default")
31
+ expect(event["severity"]).to eq("error")
32
+ }
33
+ end
34
+ end
@@ -28,8 +28,8 @@ describe Bugsnag::MiddlewareStack do
28
28
  it "runs before_bugsnag_notify callbacks, adding custom data" do
29
29
  callback_run_count = 0
30
30
  Bugsnag.before_notify_callbacks << lambda {|notif|
31
- notif.add_custom_data(:info, "here")
32
- notif.add_custom_data(:data, "also here")
31
+ notif.add_tab(:custom, {info: "here"})
32
+ notif.add_tab(:custom, {data: "also here"})
33
33
 
34
34
  callback_run_count += 1
35
35
  }
@@ -67,34 +67,35 @@ describe Bugsnag::MiddlewareStack do
67
67
 
68
68
  end
69
69
 
70
- it "allows overrides to override values set by internal middleware" do
70
+ it "allows block to override values set by internal middleware" do
71
71
  Bugsnag.configuration.internal_middleware.use(InternalInfoSetter)
72
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:info => "overridden"})
72
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
73
+ report.meta_data.merge!({custom: {info: 'overridden'}})
74
+ end
73
75
 
74
76
  expect(Bugsnag).to have_sent_notification{ |payload|
75
77
  event = get_event_from_payload(payload)
76
78
  expect(event["metaData"]["custom"]).not_to be_nil
77
- expect(event["metaData"]["custom"]["info"]).not_to eq(InternalInfoSetter::MESSAGE)
78
79
  expect(event["metaData"]["custom"]["info"]).to eq("overridden")
79
80
  }
80
81
  end
81
82
 
82
- it "doesn't allow overrides to override public middleware" do
83
+ it "allows block to override public middleware" do
83
84
  Bugsnag.configuration.middleware.use(PublicInfoSetter)
84
85
 
85
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:info => "overridden"})
86
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
87
+ report.meta_data.merge!({custom: {info: 'overridden'}})
88
+ end
86
89
 
87
90
  expect(Bugsnag).to have_sent_notification{ |payload|
88
91
  event = get_event_from_payload(payload)
89
92
  expect(event["metaData"]["custom"]).not_to be_nil
90
- expect(event["metaData"]["custom"]["info"]).not_to eq("overridden")
91
- expect(event["metaData"]["custom"]["info"]).to eq(PublicInfoSetter::MESSAGE)
93
+ expect(event["metaData"]["custom"]["info"]).to eq("overridden")
92
94
  }
93
95
  end
94
96
 
95
- it "does not have have before or after callbacks by default" do
97
+ it "does not have have before callbacks by default" do
96
98
  expect(Bugsnag.before_notify_callbacks.size).to eq(0)
97
- expect(Bugsnag.after_notify_callbacks.size).to eq(0)
98
99
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
99
100
  expect(Bugsnag).to have_sent_notification{ |payload|
100
101
  event = get_event_from_payload(payload)
@@ -102,18 +103,6 @@ describe Bugsnag::MiddlewareStack do
102
103
  }
103
104
  end
104
105
 
105
- it "runs after_bugsnag_notify callbacks" do
106
- callback_run_count = 0
107
- Bugsnag.after_notify_callbacks << lambda {|notif|
108
- callback_run_count += 1
109
- }
110
-
111
- Bugsnag.notify(BugsnagTestException.new("It crashed"))
112
-
113
- expect(callback_run_count).to eq(1)
114
- expect(Bugsnag::Notification).to have_sent_notification { }
115
- end
116
-
117
106
  it "does not execute disabled bugsnag middleware" do
118
107
  callback_run_count = 0
119
108
  Bugsnag.configure do |config|
@@ -133,7 +122,7 @@ describe Bugsnag::MiddlewareStack do
133
122
  notif.ignore!
134
123
  end
135
124
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
136
- expect(Bugsnag::Notification).not_to have_sent_notification { }
125
+ expect(Bugsnag).not_to have_sent_notification
137
126
  end
138
127
 
139
128
  it "allows inspection of meta_data before ignoring exception" do
@@ -148,34 +137,118 @@ describe Bugsnag::MiddlewareStack do
148
137
  end
149
138
 
150
139
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
151
- expect(Bugsnag::Notification).not_to have_sent_notification
140
+ expect(Bugsnag).not_to have_sent_notification
152
141
 
153
142
  end
154
143
 
155
144
  it "allows meta_data to be modified in a middleware" do
145
+ MetaDataAdder = Class.new do
146
+ def initialize(bugsnag)
147
+ @bugsnag = bugsnag
148
+ end
149
+
150
+ def call(report)
151
+ report.meta_data = {test: {value: "abcdef123456abcdef123456abcdef123456"}}
152
+ @bugsnag.call(report)
153
+ end
154
+ end
155
+
156
156
  MetaDataMunger = Class.new do
157
157
  def initialize(bugsnag)
158
158
  @bugsnag = bugsnag
159
159
  end
160
160
 
161
- def call(notification)
162
- token = notification.meta_data[:sidekiq][:args].first
163
- notification.meta_data[:sidekiq][:args] = ["#{token[0...6]}*****#{token[-4..-1]}"]
164
- @bugsnag.call(notification)
161
+ def call(report)
162
+ token = report.meta_data[:test][:value]
163
+ report.meta_data[:test][:value] = "#{token[0...6]}*****#{token[-4..-1]}"
164
+ @bugsnag.call(report)
165
165
  end
166
166
  end
167
167
 
168
168
  Bugsnag.configure do |c|
169
+ c.middleware.use MetaDataAdder
169
170
  c.middleware.use MetaDataMunger
170
171
  end
171
172
 
172
- notification = Bugsnag.notify(BugsnagTestException.new("It crashed"), {
173
- :sidekiq => {
174
- :args => ["abcdef123456abcdef123456abcdef123456"]
175
- }
176
- })
173
+ Bugsnag.notify(BugsnagTestException.new("It crashed"))
174
+
175
+ expect(Bugsnag).to have_sent_notification{ |payload|
176
+ event = get_event_from_payload(payload)
177
+ expect(event["metaData"]['test']['value']).to eq("abcdef*****3456")
178
+ }
179
+ end
177
180
 
178
- expect(notification.meta_data[:sidekiq][:args]).to eq(["abcdef*****3456"])
181
+ if ruby_version_greater_equal?("2.3.0")
182
+ context "with a ruby version >= 2.3.0" do
183
+ it "attaches did you mean metadata when necessary" do
184
+ begin
185
+ "Test".prepnd "T"
186
+ rescue Exception => e
187
+ Bugsnag.notify(e)
188
+ end
189
+
190
+ expect(Bugsnag).to have_sent_notification{ |payload|
191
+ event = get_event_from_payload(payload)
192
+ expect(event["metaData"]["error"]).to_not be_nil
193
+ expect(event["metaData"]["error"]).to eq({"suggestion" => "prepend"})
194
+ }
195
+ end
196
+ end
197
+ end
198
+
199
+ context "with a ruby version < 2.3.0" do
200
+ if !ruby_version_greater_equal?("2.3.0")
201
+ it "doesn't attach did you mean metadata" do
202
+ begin
203
+ "Test".prepnd "T"
204
+ rescue Exception => e
205
+ Bugsnag.notify(e)
206
+ end
207
+
208
+ expect(Bugsnag).to have_sent_notification{ |payload|
209
+ event = get_event_from_payload(payload)
210
+ expect(event["metaData"]["error"]).to be_nil
211
+ }
212
+ end
213
+ end
179
214
  end
180
215
 
216
+ it "doesn't allow handledState properties to be changed in middleware" do
217
+ HandledStateChanger = Class.new do
218
+ def initialize(bugsnag)
219
+ @bugsnag = bugsnag
220
+ end
221
+
222
+ def call(report)
223
+ report.severity_reason = {
224
+ :test => "test"
225
+ }
226
+ @bugsnag.call(report)
227
+ end
228
+ end
229
+
230
+ Bugsnag.configure do |c|
231
+ c.middleware.use HandledStateChanger
232
+ end
233
+
234
+ Bugsnag.notify(BugsnagTestException.new("It crashed"), true) do |report|
235
+ report.severity_reason = {
236
+ :type => "middleware_handler",
237
+ :attributes => {
238
+ :name => "middleware_test"
239
+ }
240
+ }
241
+ end
242
+
243
+ expect(Bugsnag).to have_sent_notification{ |payload|
244
+ event = get_event_from_payload(payload)
245
+ expect(event["unhandled"]).to be true
246
+ expect(event["severityReason"]).to eq({
247
+ "type" => "middleware_handler",
248
+ "attributes" => {
249
+ "name" => "middleware_test"
250
+ }
251
+ })
252
+ }
253
+ end
181
254
  end
@@ -54,7 +54,7 @@ describe Bugsnag::Rack do
54
54
 
55
55
  rack_stack.call(rack_env) rescue nil
56
56
 
57
- expect(Bugsnag::Notification).not_to have_sent_notification
57
+ expect(Bugsnag).not_to have_sent_notification
58
58
  end
59
59
  end
60
60
 
@@ -27,7 +27,7 @@ class JRubyException
27
27
  end
28
28
  end
29
29
 
30
- describe Bugsnag::Notification do
30
+ describe Bugsnag::Report do
31
31
  it "should contain an api_key if one is set" do
32
32
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
33
33
 
@@ -53,7 +53,9 @@ describe Bugsnag::Notification do
53
53
  end
54
54
 
55
55
  it "lets you override the api_key" do
56
- Bugsnag.notify(BugsnagTestException.new("It crashed"), :api_key => "9d84383f9be2ca94902e45c756a9979d")
56
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
57
+ report.api_key = "9d84383f9be2ca94902e45c756a9979d"
58
+ end
57
59
 
58
60
  expect(Bugsnag).to have_sent_notification{ |payload|
59
61
  expect(payload["apiKey"]).to eq("9d84383f9be2ca94902e45c756a9979d")
@@ -62,7 +64,9 @@ describe Bugsnag::Notification do
62
64
 
63
65
  it "lets you override the groupingHash" do
64
66
 
65
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:grouping_hash => "this is my grouping hash"})
67
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
68
+ report.grouping_hash = "this is my grouping hash"
69
+ end
66
70
 
67
71
  expect(Bugsnag).to have_sent_notification{ |payload|
68
72
  event = get_event_from_payload(payload)
@@ -115,7 +119,7 @@ describe Bugsnag::Notification do
115
119
 
116
120
  it "uses correct unhandled defaults" do
117
121
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
118
-
122
+
119
123
  expect(Bugsnag).to have_sent_notification{ |payload|
120
124
  event = get_event_from_payload(payload)
121
125
  expect(event["unhandled"]).to be false
@@ -126,19 +130,6 @@ describe Bugsnag::Notification do
126
130
  }
127
131
  end
128
132
 
129
- it "sets correct severityReason if severity is modified" do
130
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:severity => "info"})
131
-
132
- expect(Bugsnag).to have_sent_notification{ |payload|
133
- event = get_event_from_payload(payload)
134
- expect(event["unhandled"]).to be false
135
- expect(event["severity"]).to eq("info")
136
- expect(event["severityReason"]).to eq({
137
- "type" => "userSpecifiedSeverity"
138
- })
139
- }
140
- end
141
-
142
133
  it "sets correct severityReason if severity is modified in a block" do
143
134
  Bugsnag.notify(BugsnagTestException.new("It crashed")) do |notification|
144
135
  notification.severity = "info"
@@ -153,28 +144,6 @@ describe Bugsnag::Notification do
153
144
  }
154
145
  end
155
146
 
156
- it "sets unhandled and severityReasons through auto_notify" do
157
- Bugsnag.auto_notify(BugsnagTestException.new("It crashed"), {
158
- :severity_reason => {
159
- :type => "unhandledExceptionMiddleware",
160
- :attributes => {
161
- :framework => "ruby test"
162
- }
163
- }
164
- })
165
- expect(Bugsnag).to have_sent_notification{ |payload|
166
- event = get_event_from_payload(payload)
167
- expect(event["unhandled"]).to be true
168
- expect(event["severity"]).to eq("error")
169
- expect(event["severityReason"]).to eq({
170
- "type" => "unhandledExceptionMiddleware",
171
- "attributes" => {
172
- "framework" => "ruby test"
173
- }
174
- })
175
- }
176
- end
177
-
178
147
  it "sets correct severity and reason for specific error classes" do
179
148
  Bugsnag.notify(SignalException.new("TERM"))
180
149
  expect(Bugsnag).to have_sent_notification{ |payload|
@@ -193,12 +162,14 @@ describe Bugsnag::Notification do
193
162
  # TODO: nested context
194
163
 
195
164
  it "accepts tabs in overrides and adds them to metaData" do
196
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
197
- :some_tab => {
198
- :info => "here",
199
- :data => "also here"
200
- }
201
- })
165
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
166
+ report.meta_data.merge!({
167
+ some_tab: {
168
+ info: "here",
169
+ data: "also here"
170
+ }
171
+ })
172
+ end
202
173
 
203
174
  expect(Bugsnag).to have_sent_notification{ |payload|
204
175
  event = get_event_from_payload(payload)
@@ -209,22 +180,27 @@ describe Bugsnag::Notification do
209
180
  }
210
181
  end
211
182
 
212
- it "accepts non-hash overrides and adds them to the custom tab in metaData" do
213
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
214
- :info => "here",
215
- :data => "also here"
216
- })
183
+ it "accepts meta data from an exception that mixes in Bugsnag::MetaData" do
184
+ exception = BugsnagTestExceptionWithMetaData.new("It crashed")
185
+ exception.bugsnag_meta_data = {
186
+ some_tab: {
187
+ info: "here",
188
+ data: "also here"
189
+ }
190
+ }
191
+
192
+ Bugsnag.notify(exception)
217
193
 
218
194
  expect(Bugsnag).to have_sent_notification{ |payload|
219
195
  event = get_event_from_payload(payload)
220
- expect(event["metaData"]["custom"]).to eq(
196
+ expect(event["metaData"]["some_tab"]).to eq(
221
197
  "info" => "here",
222
198
  "data" => "also here"
223
199
  )
224
200
  }
225
201
  end
226
202
 
227
- it "accepts meta data from an exception that mixes in Bugsnag::MetaData" do
203
+ it "removes tabs" do
228
204
  exception = BugsnagTestExceptionWithMetaData.new("It crashed")
229
205
  exception.bugsnag_meta_data = {
230
206
  :some_tab => {
@@ -233,7 +209,28 @@ describe Bugsnag::Notification do
233
209
  }
234
210
  }
235
211
 
236
- Bugsnag.notify(exception)
212
+ Bugsnag.notify(exception) do |report|
213
+ report.remove_tab(:some_tab)
214
+ end
215
+
216
+ expect(Bugsnag).to have_sent_notification{ |payload|
217
+ event = get_event_from_payload(payload)
218
+ expect(event["metaData"]["some_tab"]).to be_nil
219
+ }
220
+ end
221
+
222
+ it "ignores removing nil tabs" do
223
+ exception = BugsnagTestExceptionWithMetaData.new("It crashed")
224
+ exception.bugsnag_meta_data = {
225
+ :some_tab => {
226
+ :info => "here",
227
+ :data => "also here"
228
+ }
229
+ }
230
+
231
+ Bugsnag.notify(exception) do |report|
232
+ report.remove_tab(nil)
233
+ end
237
234
 
238
235
  expect(Bugsnag).to have_sent_notification{ |payload|
239
236
  event = get_event_from_payload(payload)
@@ -244,6 +241,21 @@ describe Bugsnag::Notification do
244
241
  }
245
242
  end
246
243
 
244
+ it "Creates a custom tab for metadata which is not a Hash" do
245
+ exception = Exception.new("It crashed")
246
+
247
+ Bugsnag.notify(exception) do |report|
248
+ report.add_tab(:some_tab, "added")
249
+ end
250
+
251
+ expect(Bugsnag).to have_sent_notification{ |payload|
252
+ event = get_event_from_payload(payload)
253
+ expect(event["metaData"]["custom"]).to eq(
254
+ "some_tab" => "added",
255
+ )
256
+ }
257
+ end
258
+
247
259
  it "accepts meta data from an exception that mixes in Bugsnag::MetaData, but override using the overrides" do
248
260
  exception = BugsnagTestExceptionWithMetaData.new("It crashed")
249
261
  exception.bugsnag_meta_data = {
@@ -253,7 +265,9 @@ describe Bugsnag::Notification do
253
265
  }
254
266
  }
255
267
 
256
- Bugsnag.notify(exception, {:some_tab => {:info => "overridden"}})
268
+ Bugsnag.notify(exception) do |report|
269
+ report.add_tab(:some_tab, {:info => "overridden"})
270
+ end
257
271
 
258
272
  expect(Bugsnag).to have_sent_notification{ |payload|
259
273
  event = get_event_from_payload(payload)
@@ -280,7 +294,9 @@ describe Bugsnag::Notification do
280
294
  exception = BugsnagTestExceptionWithMetaData.new("It crashed")
281
295
  exception.bugsnag_user_id = "exception_user_id"
282
296
 
283
- Bugsnag.notify(exception, {:user_id => "override_user_id"})
297
+ Bugsnag.notify(exception) do |report|
298
+ report.user.merge!({:id => "override_user_id"})
299
+ end
284
300
 
285
301
  expect(Bugsnag).to have_sent_notification{ |payload|
286
302
  event = get_event_from_payload(payload)
@@ -317,7 +333,9 @@ describe Bugsnag::Notification do
317
333
  exception = BugsnagTestExceptionWithMetaData.new("It crashed")
318
334
  exception.bugsnag_context = "exception_context"
319
335
 
320
- Bugsnag.notify(exception, {:context => "override_context"})
336
+ Bugsnag.notify(exception) do |report|
337
+ report.context = "override_context"
338
+ end
321
339
 
322
340
  expect(Bugsnag).to have_sent_notification{ |payload|
323
341
  event = get_event_from_payload(payload)
@@ -326,14 +344,14 @@ describe Bugsnag::Notification do
326
344
  end
327
345
 
328
346
  it "accepts meta_data in overrides (for backwards compatibility) and merge it into metaData" do
329
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
330
- :meta_data => {
331
- :some_tab => {
332
- :info => "here",
333
- :data => "also here"
347
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
348
+ report.meta_data.merge!({
349
+ some_tab: {
350
+ info: "here",
351
+ data: "also here"
334
352
  }
335
- }
336
- })
353
+ })
354
+ end
337
355
 
338
356
  expect(Bugsnag).to have_sent_notification{ |payload|
339
357
  event = get_event_from_payload(payload)
@@ -345,14 +363,14 @@ describe Bugsnag::Notification do
345
363
  end
346
364
 
347
365
  it "truncates large meta_data before sending" do
348
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
349
- :meta_data => {
350
- :some_tab => {
351
- :giant => SecureRandom.hex(500_000/2),
352
- :mega => SecureRandom.hex(500_000/2)
366
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
367
+ report.meta_data.merge!({
368
+ some_tab: {
369
+ giant: SecureRandom.hex(500_000/2),
370
+ mega: SecureRandom.hex(500_000/2)
353
371
  }
354
- }
355
- })
372
+ })
373
+ end
356
374
 
357
375
  expect(Bugsnag).to have_sent_notification{ |payload|
358
376
  # Truncated body should be no bigger than
@@ -362,14 +380,14 @@ describe Bugsnag::Notification do
362
380
  end
363
381
 
364
382
  it "truncates large messages before sending" do
365
- Bugsnag.notify(BugsnagTestException.new(SecureRandom.hex(500_000)), {
366
- :meta_data => {
367
- :some_tab => {
368
- :giant => SecureRandom.hex(500_000/2),
369
- :mega => SecureRandom.hex(500_000/2)
383
+ Bugsnag.notify(BugsnagTestException.new(SecureRandom.hex(500_000))) do |report|
384
+ report.meta_data.merge!({
385
+ some_tab: {
386
+ giant: SecureRandom.hex(500_000/2),
387
+ mega: SecureRandom.hex(500_000/2)
370
388
  }
371
- }
372
- })
389
+ })
390
+ end
373
391
 
374
392
  expect(Bugsnag).to have_sent_notification{ |payload|
375
393
  # Truncated body should be no bigger than
@@ -393,9 +411,9 @@ describe Bugsnag::Notification do
393
411
  end
394
412
 
395
413
  it "accepts a severity in overrides" do
396
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
397
- :severity => "info"
398
- })
414
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
415
+ report.severity = "info"
416
+ end
399
417
 
400
418
  expect(Bugsnag).to have_sent_notification{ |payload|
401
419
  event = get_event_from_payload(payload)
@@ -413,42 +431,10 @@ describe Bugsnag::Notification do
413
431
  }
414
432
  end
415
433
 
416
- it "does not accept a bad severity in overrides" do
417
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
418
- :severity => "fatal"
419
- })
420
-
421
- expect(Bugsnag).to have_sent_notification{ |payload|
422
- event = get_event_from_payload(payload)
423
- expect(event["severity"]).to eq("warning")
424
- }
425
- end
426
-
427
- it "lets you override severity using block syntax" do
428
- Bugsnag.notify(BugsnagTestException.new("It crashed")) do |notification|
429
- notification.severity = "info"
430
- end
431
-
432
- expect(Bugsnag).to have_sent_notification{ |payload|
433
- event = get_event_from_payload(payload)
434
- expect(event["severity"]).to eq("info")
435
- }
436
- end
437
-
438
- it "autonotifies errors" do
439
- Bugsnag.auto_notify(BugsnagTestException.new("It crashed"))
440
-
441
- expect(Bugsnag).to have_sent_notification{ |payload|
442
- event = get_event_from_payload(payload)
443
- expect(event["severity"]).to eq("error")
444
- }
445
- end
446
-
447
-
448
434
  it "accepts a context in overrides" do
449
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
450
- :context => "test_context"
451
- })
435
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
436
+ report.context = 'test_context'
437
+ end
452
438
 
453
439
  expect(Bugsnag).to have_sent_notification{ |payload|
454
440
  event = get_event_from_payload(payload)
@@ -457,9 +443,9 @@ describe Bugsnag::Notification do
457
443
  end
458
444
 
459
445
  it "accepts a user_id in overrides" do
460
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {
461
- :user_id => "test_user"
462
- })
446
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
447
+ report.user = {id: 'test_user'}
448
+ end
463
449
 
464
450
  expect(Bugsnag).to have_sent_notification{ |payload|
465
451
  event = get_event_from_payload(payload)
@@ -467,12 +453,12 @@ describe Bugsnag::Notification do
467
453
  }
468
454
  end
469
455
 
470
- it "does not send a notification if auto_notify is false" do
456
+ it "does not send an automatic notification if auto_notify is false" do
471
457
  Bugsnag.configure do |config|
472
458
  config.auto_notify = false
473
459
  end
474
460
 
475
- Bugsnag.auto_notify(BugsnagTestException.new("It crashed"))
461
+ Bugsnag.notify(BugsnagTestException.new("It crashed"), true)
476
462
 
477
463
  expect(Bugsnag).not_to have_sent_notification
478
464
  end
@@ -482,7 +468,7 @@ describe Bugsnag::Notification do
482
468
  config.release_stage = "production"
483
469
  end
484
470
 
485
- Bugsnag.auto_notify(BugsnagTestException.new("It crashed"))
471
+ Bugsnag.notify(BugsnagTestException.new("It crashed"))
486
472
 
487
473
  expect(Bugsnag).to have_sent_notification{ |payload|
488
474
  event = get_event_from_payload(payload)
@@ -516,27 +502,6 @@ describe Bugsnag::Notification do
516
502
  expect(WebMock).to have_requested(:post, "https://notify.bugsnag.com")
517
503
  end
518
504
 
519
- it "uses ssl when use_ssl is true" do
520
- Bugsnag.configuration.use_ssl = true
521
- Bugsnag.notify(BugsnagTestException.new("It crashed"))
522
-
523
- expect(WebMock).to have_requested(:post, "https://notify.bugsnag.com")
524
- end
525
-
526
- it "does not use ssl when use_ssl is false" do
527
- stub_request(:post, "http://notify.bugsnag.com/")
528
- Bugsnag.configuration.use_ssl = false
529
- Bugsnag.notify(BugsnagTestException.new("It crashed"))
530
-
531
- expect(WebMock).to have_requested(:post, "http://notify.bugsnag.com")
532
- end
533
-
534
- it "uses ssl when use_ssl is unset" do
535
- Bugsnag.notify(BugsnagTestException.new("It crashed"))
536
-
537
- expect(WebMock).to have_requested(:post, "https://notify.bugsnag.com")
538
- end
539
-
540
505
  it "does not mark the top-most stacktrace line as inProject if out of project" do
541
506
  Bugsnag.configuration.project_root = "/Random/location/here"
542
507
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
@@ -548,19 +513,6 @@ describe Bugsnag::Notification do
548
513
  }
549
514
  end
550
515
 
551
- it "does not mark the top-most stacktrace line as inProject if it matches a vendor path" do
552
- Bugsnag.configuration.project_root = File.expand_path('../../', __FILE__)
553
- Bugsnag.configuration.vendor_paths = [File.expand_path('../', __FILE__)]
554
-
555
- Bugsnag.notify(BugsnagTestException.new("It crashed"))
556
-
557
- expect(Bugsnag).to have_sent_notification{ |payload|
558
- exception = get_exception_from_payload(payload)
559
- expect(exception["stacktrace"].size).to be >= 1
560
- expect(exception["stacktrace"].first["inProject"]).to be_nil
561
- }
562
- end
563
-
564
516
  it "marks the top-most stacktrace line as inProject if necessary" do
565
517
  Bugsnag.configuration.project_root = File.expand_path File.dirname(__FILE__)
566
518
  Bugsnag.notify(BugsnagTestException.new("It crashed"))
@@ -582,9 +534,11 @@ describe Bugsnag::Notification do
582
534
  }
583
535
  end
584
536
 
585
- it "filters params from all payload hashes if they are set in default params_filters" do
537
+ it "filters params from all payload hashes if they are set in default meta_data_filters" do
586
538
 
587
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "12345", :other_data => "123456"}}})
539
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
540
+ report.meta_data.merge!({:request => {:params => {:password => "1234", :other_password => "12345", :other_data => "123456"}}})
541
+ end
588
542
 
589
543
  expect(Bugsnag).to have_sent_notification{ |payload|
590
544
  event = get_event_from_payload(payload)
@@ -597,10 +551,12 @@ describe Bugsnag::Notification do
597
551
  }
598
552
  end
599
553
 
600
- it "filters params from all payload hashes if they are added to params_filters" do
554
+ it "filters params from all payload hashes if they are added to meta_data_filters" do
601
555
 
602
- Bugsnag.configuration.params_filters << "other_data"
603
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
556
+ Bugsnag.configuration.meta_data_filters << "other_data"
557
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
558
+ report.meta_data.merge!({:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
559
+ end
604
560
 
605
561
  expect(Bugsnag).to have_sent_notification{ |payload|
606
562
  event = get_event_from_payload(payload)
@@ -613,10 +569,12 @@ describe Bugsnag::Notification do
613
569
  }
614
570
  end
615
571
 
616
- it "filters params from all payload hashes if they are added to params_filters as regex" do
572
+ it "filters params from all payload hashes if they are added to meta_data_filters as regex" do
617
573
 
618
- Bugsnag.configuration.params_filters << /other_data/
619
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
574
+ Bugsnag.configuration.meta_data_filters << /other_data/
575
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
576
+ report.meta_data.merge!({:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
577
+ end
620
578
 
621
579
  expect(Bugsnag).to have_sent_notification{ |payload|
622
580
  event = get_event_from_payload(payload)
@@ -629,10 +587,12 @@ describe Bugsnag::Notification do
629
587
  }
630
588
  end
631
589
 
632
- it "filters params from all payload hashes if they are added to params_filters as partial regex" do
590
+ it "filters params from all payload hashes if they are added to meta_data_filters as partial regex" do
633
591
 
634
- Bugsnag.configuration.params_filters << /r_data/
635
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
592
+ Bugsnag.configuration.meta_data_filters << /r_data/
593
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
594
+ report.meta_data.merge!({:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
595
+ end
636
596
 
637
597
  expect(Bugsnag).to have_sent_notification{ |payload|
638
598
  event = get_event_from_payload(payload)
@@ -646,7 +606,9 @@ describe Bugsnag::Notification do
646
606
  end
647
607
 
648
608
  it "does not filter params from payload hashes if their values are nil" do
649
- Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:nil_param => nil}}})
609
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
610
+ report.meta_data.merge!({:request => {:params => {:nil_param => nil}}})
611
+ end
650
612
 
651
613
  expect(Bugsnag).to have_sent_notification{ |payload|
652
614
  event = get_event_from_payload(payload)
@@ -657,49 +619,46 @@ describe Bugsnag::Notification do
657
619
  }
658
620
  end
659
621
 
660
- it "does not notify if the non-default exception class is added to the ignore_classes" do
661
- Bugsnag.configuration.ignore_classes << "BugsnagTestException"
662
-
663
- Bugsnag.notify_or_ignore(BugsnagTestException.new("It crashed"))
622
+ it "does not notify if report ignored" do
623
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
624
+ report.ignore!
625
+ end
664
626
 
665
627
  expect(Bugsnag).not_to have_sent_notification
666
628
  end
667
629
 
668
- it "does not notify if exception's ancestor is an ignored class" do
669
- Bugsnag.configuration.ignore_classes << "BugsnagTestException"
670
-
671
- Bugsnag.notify_or_ignore(BugsnagSubclassTestException.new("It crashed"))
630
+ it "does not notify if the exception class is in the default ignore_classes list" do
631
+ Bugsnag.configuration.ignore_classes << ActiveRecord::RecordNotFound
632
+ Bugsnag.notify(ActiveRecord::RecordNotFound.new("It crashed"))
672
633
 
673
634
  expect(Bugsnag).not_to have_sent_notification
674
635
  end
675
636
 
676
- it "does not notify if any caused exception is an ignored class" do
677
- Bugsnag.configuration.ignore_classes << "NestedException"
678
-
679
- ex = NestedException.new("Self-referential exception")
680
- ex.original_exception = BugsnagTestException.new("It crashed")
637
+ it "does not notify if the non-default exception class is added to the ignore_classes" do
638
+ Bugsnag.configuration.ignore_classes << BugsnagTestException
681
639
 
682
- Bugsnag.notify_or_ignore(ex)
640
+ Bugsnag.notify(BugsnagTestException.new("It crashed"))
683
641
 
684
642
  expect(Bugsnag).not_to have_sent_notification
685
643
  end
686
644
 
687
- it "accepts both String and Class instances as an ignored class" do
645
+ it "does not notify if exception's ancestor is an ignored class" do
688
646
  Bugsnag.configuration.ignore_classes << BugsnagTestException
689
647
 
690
- Bugsnag.notify_or_ignore(BugsnagTestException.new("It crashed"))
648
+ Bugsnag.notify(BugsnagSubclassTestException.new("It crashed"))
691
649
 
692
650
  expect(Bugsnag).not_to have_sent_notification
693
651
  end
694
652
 
695
- it "does not notify if the user agent is present and matches a regex in ignore_user_agents" do
696
- Bugsnag.configuration.ignore_user_agents << %r{BugsnagUserAgent}
653
+ it "does not notify if any caused exception is an ignored class" do
654
+ Bugsnag.configuration.ignore_classes << NestedException
697
655
 
698
- ((Thread.current["bugsnag_req_data"] ||= {})[:rack_env] ||= {})["HTTP_USER_AGENT"] = "BugsnagUserAgent"
656
+ ex = NestedException.new("Self-referential exception")
657
+ ex.original_exception = BugsnagTestException.new("It crashed")
699
658
 
700
- Bugsnag.notify_or_ignore(BugsnagTestException.new("It crashed"))
659
+ Bugsnag.notify(ex)
701
660
 
702
- expect(Bugsnag::Notification).not_to have_sent_notification
661
+ expect(Bugsnag).not_to have_sent_notification
703
662
  end
704
663
 
705
664
  it "sends the cause of the exception" do
@@ -723,7 +682,7 @@ describe Bugsnag::Notification do
723
682
  ex = NestedException.new("Self-referential exception")
724
683
  ex.original_exception = ex
725
684
 
726
- Bugsnag.notify_or_ignore(ex)
685
+ Bugsnag.notify(ex)
727
686
 
728
687
  expect(Bugsnag).to have_sent_notification{ |payload|
729
688
  event = get_event_from_payload(payload)
@@ -738,7 +697,7 @@ describe Bugsnag::Notification do
738
697
  ex = ex.original_exception = NestedException.new("Deep exception #{idx}")
739
698
  end
740
699
 
741
- Bugsnag.notify_or_ignore(first_ex)
700
+ Bugsnag.notify(first_ex)
742
701
  expect(Bugsnag).to have_sent_notification{ |payload|
743
702
  event = get_event_from_payload(payload)
744
703
  expect(event["exceptions"].size).to eq(5)
@@ -819,34 +778,39 @@ describe Bugsnag::Notification do
819
778
  invalid_data = "fl\xc3ff"
820
779
  invalid_data.force_encoding('BINARY') if invalid_data.respond_to?(:force_encoding)
821
780
 
822
- notify_test_exception(:fluff => {:fluff => invalid_data})
781
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
782
+ report.meta_data.merge!({fluff: {fluff: invalid_data}})
783
+ end
823
784
 
824
785
  expect(Bugsnag).to have_sent_notification{ |payload|
786
+ event = get_event_from_payload(payload)
825
787
  if defined?(Encoding::UTF_8)
826
- expect(payload.to_json).to match(/fl�ff/)
788
+ expect(event['metaData']['fluff']['fluff']).to match(/fl�ff/)
827
789
  else
828
- expect(payload.to_json).to match(/flff/)
790
+ expect(event['metaData']['fluff']['fluff']).to match(/flff/)
829
791
  end
830
792
  }
831
793
  end
832
794
 
833
- it "should handle utf8 encoding errors in exceptions_list" do
834
- invalid_data = "\"foo\xEBbar\""
835
- invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
795
+ if RUBY_VERSION < '2.3.0'
796
+ it "should handle utf8 encoding errors in exceptions_list" do
797
+ invalid_data = "\"foo\xEBbar\""
798
+ invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
836
799
 
837
- begin
838
- JSON.parse(invalid_data)
839
- rescue
840
- Bugsnag.notify $!
841
- end
842
-
843
- expect(Bugsnag).to have_sent_notification { |payload|
844
- if defined?(Encoding::UTF_8)
845
- expect(payload.to_json).to match(/foo�bar/)
846
- else
847
- expect(payload.to_json).to match(/foobar/)
800
+ begin
801
+ JSON.parse(invalid_data)
802
+ rescue
803
+ Bugsnag.notify $!
848
804
  end
849
- }
805
+
806
+ expect(Bugsnag).to have_sent_notification { |payload|
807
+ if defined?(Encoding::UTF_8)
808
+ expect(payload.to_json).to match(/foo�bar/)
809
+ else
810
+ expect(payload.to_json).to match(/foobar/)
811
+ end
812
+ }
813
+ end
850
814
  end
851
815
 
852
816
  it "should handle utf8 encoding errors in notification context" do
@@ -856,7 +820,9 @@ describe Bugsnag::Notification do
856
820
  begin
857
821
  raise
858
822
  rescue
859
- Bugsnag.notify($!, { :context => invalid_data })
823
+ Bugsnag.notify($!) do |report|
824
+ report.context = invalid_data
825
+ end
860
826
  end
861
827
 
862
828
  expect(Bugsnag).to have_sent_notification { |payload|
@@ -955,6 +921,57 @@ describe Bugsnag::Notification do
955
921
  }
956
922
  end
957
923
 
924
+ it 'should use defaults when notify is called' do
925
+ Bugsnag.notify(BugsnagTestException.new("It crashed"))
926
+
927
+ expect(Bugsnag).to have_sent_notification{ |payload|
928
+ event = payload["events"][0]
929
+ expect(event["unhandled"]).to be false
930
+ expect(event["severityReason"]).to eq({"type" => "handledException"})
931
+ }
932
+ end
933
+
934
+ it 'should attach severity reason through a block when auto_notify is true' do
935
+ Bugsnag.notify(BugsnagTestException.new("It crashed"), true) do |report|
936
+ report.severity_reason = {
937
+ :type => "middleware_handler",
938
+ :attributes => {
939
+ :name => "middleware_test"
940
+ }
941
+ }
942
+ end
943
+
944
+ expect(Bugsnag).to have_sent_notification{ |payload|
945
+ event = payload["events"][0]
946
+ expect(event["severityReason"]).to eq(
947
+ {
948
+ "type" => "middleware_handler",
949
+ "attributes" => {
950
+ "name" => "middleware_test"
951
+ }
952
+ }
953
+ )
954
+ expect(event["unhandled"]).to be true
955
+ }
956
+ end
957
+
958
+ it 'should not attach severity reason from callback when auto_notify is false' do
959
+ Bugsnag.notify(BugsnagTestException.new("It crashed")) do |report|
960
+ report.severity_reason = {
961
+ :type => "middleware_handler",
962
+ :attributes => {
963
+ :name => "middleware_test"
964
+ }
965
+ }
966
+ end
967
+
968
+ expect(Bugsnag).to have_sent_notification{ |payload|
969
+ event = payload["events"][0]
970
+ expect(event["unhandled"]).to be false
971
+ expect(event["severityReason"]).to eq({"type" => "handledException"})
972
+ }
973
+ end
974
+
958
975
  if defined?(JRUBY_VERSION)
959
976
 
960
977
  it "should work with java.lang.Throwables" do