bugsnag 4.2.1 → 6.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.yardopts +12 -0
- data/CHANGELOG.md +814 -0
- data/README.md +21 -25
- data/VERSION +1 -1
- data/bugsnag.gemspec +19 -8
- data/lib/bugsnag/breadcrumb_type.rb +14 -0
- data/lib/bugsnag/breadcrumbs/breadcrumb.rb +109 -0
- data/lib/bugsnag/breadcrumbs/breadcrumbs.rb +13 -0
- data/lib/bugsnag/breadcrumbs/on_breadcrumb_callback_list.rb +48 -0
- data/lib/bugsnag/breadcrumbs/validator.rb +29 -0
- data/lib/bugsnag/cleaner.rb +170 -59
- data/lib/bugsnag/code_extractor.rb +137 -0
- data/lib/bugsnag/configuration.rb +670 -45
- data/lib/bugsnag/delivery/synchronous.rb +31 -14
- data/lib/bugsnag/delivery/thread_queue.rb +23 -6
- data/lib/bugsnag/delivery.rb +13 -0
- data/lib/bugsnag/endpoint_configuration.rb +11 -0
- data/lib/bugsnag/endpoint_validator.rb +80 -0
- data/lib/bugsnag/error.rb +25 -0
- data/lib/bugsnag/event.rb +5 -0
- data/lib/bugsnag/feature_flag.rb +74 -0
- data/lib/bugsnag/helpers.rb +121 -25
- data/lib/bugsnag/integrations/delayed_job.rb +51 -0
- data/lib/bugsnag/integrations/mailman.rb +43 -0
- data/lib/bugsnag/integrations/mongo.rb +133 -0
- data/lib/bugsnag/integrations/que.rb +53 -0
- data/lib/bugsnag/integrations/rack.rb +83 -0
- data/lib/bugsnag/integrations/rails/active_job.rb +100 -0
- data/lib/bugsnag/{rails → integrations/rails}/active_record_rescue.rb +10 -1
- data/lib/bugsnag/{rails → integrations/rails}/controller_methods.rb +1 -9
- data/lib/bugsnag/integrations/rails/rails_breadcrumbs.rb +115 -0
- data/lib/bugsnag/integrations/railtie.rb +153 -0
- data/lib/bugsnag/integrations/rake.rb +74 -0
- data/lib/bugsnag/integrations/resque.rb +94 -0
- data/lib/bugsnag/integrations/shoryuken.rb +50 -0
- data/lib/bugsnag/integrations/sidekiq.rb +68 -0
- data/lib/bugsnag/meta_data.rb +1 -0
- data/lib/bugsnag/middleware/active_job.rb +18 -0
- data/lib/bugsnag/middleware/breadcrumbs.rb +21 -0
- data/lib/bugsnag/middleware/callbacks.rb +6 -8
- data/lib/bugsnag/middleware/classify_error.rb +50 -0
- data/lib/bugsnag/middleware/clearance_user.rb +33 -0
- data/lib/bugsnag/middleware/delayed_job.rb +93 -0
- data/lib/bugsnag/middleware/discard_error_class.rb +30 -0
- data/lib/bugsnag/middleware/exception_meta_data.rb +42 -0
- data/lib/bugsnag/middleware/ignore_error_class.rb +26 -0
- data/lib/bugsnag/middleware/mailman.rb +6 -4
- data/lib/bugsnag/middleware/rack_request.rb +126 -30
- data/lib/bugsnag/middleware/rails3_request.rb +15 -17
- data/lib/bugsnag/middleware/rake.rb +7 -5
- data/lib/bugsnag/middleware/session_data.rb +25 -0
- data/lib/bugsnag/middleware/sidekiq.rb +9 -4
- data/lib/bugsnag/middleware/suggestion_data.rb +34 -0
- data/lib/bugsnag/middleware/warden_user.rb +11 -6
- data/lib/bugsnag/middleware_stack.rb +62 -9
- data/lib/bugsnag/on_error_callbacks.rb +33 -0
- data/lib/bugsnag/report.rb +516 -0
- data/lib/bugsnag/session_tracker.rb +182 -0
- data/lib/bugsnag/stacktrace.rb +82 -0
- data/lib/bugsnag/tasks/bugsnag.rake +2 -70
- data/lib/bugsnag/utility/circular_buffer.rb +62 -0
- data/lib/bugsnag/utility/duplicator.rb +124 -0
- data/lib/bugsnag/utility/feature_data_store.rb +41 -0
- data/lib/bugsnag/utility/feature_flag_delegate.rb +89 -0
- data/lib/bugsnag/utility/metadata_delegate.rb +102 -0
- data/lib/bugsnag.rb +528 -80
- metadata +61 -123
- data/.document +0 -5
- data/.gitignore +0 -52
- data/.rspec +0 -3
- data/.travis.yml +0 -14
- data/CONTRIBUTING.md +0 -47
- data/Gemfile +0 -2
- data/Rakefile +0 -29
- data/lib/bugsnag/capistrano.rb +0 -7
- data/lib/bugsnag/capistrano2.rb +0 -32
- data/lib/bugsnag/delay/resque.rb +0 -21
- data/lib/bugsnag/delayed_job.rb +0 -57
- data/lib/bugsnag/deploy.rb +0 -34
- data/lib/bugsnag/mailman.rb +0 -28
- data/lib/bugsnag/middleware/rails2_request.rb +0 -52
- data/lib/bugsnag/notification.rb +0 -459
- data/lib/bugsnag/rack.rb +0 -53
- data/lib/bugsnag/rails/action_controller_rescue.rb +0 -62
- data/lib/bugsnag/rails.rb +0 -66
- data/lib/bugsnag/railtie.rb +0 -80
- data/lib/bugsnag/rake.rb +0 -25
- data/lib/bugsnag/resque.rb +0 -40
- data/lib/bugsnag/sidekiq.rb +0 -42
- data/lib/bugsnag/tasks/bugsnag.cap +0 -48
- data/rails/init.rb +0 -7
- data/spec/cleaner_spec.rb +0 -138
- data/spec/code_spec.rb +0 -86
- data/spec/fixtures/crashes/end_of_file.rb +0 -9
- data/spec/fixtures/crashes/short_file.rb +0 -1
- data/spec/fixtures/crashes/start_of_file.rb +0 -9
- data/spec/fixtures/middleware/internal_info_setter.rb +0 -11
- data/spec/fixtures/middleware/public_info_setter.rb +0 -11
- data/spec/fixtures/tasks/Rakefile +0 -15
- data/spec/helper_spec.rb +0 -163
- data/spec/integration_spec.rb +0 -132
- data/spec/middleware_spec.rb +0 -181
- data/spec/notification_spec.rb +0 -877
- data/spec/rack_spec.rb +0 -56
- data/spec/spec_helper.rb +0 -53
data/spec/notification_spec.rb
DELETED
@@ -1,877 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'securerandom'
|
4
|
-
require 'ostruct'
|
5
|
-
|
6
|
-
module ActiveRecord; class RecordNotFound < RuntimeError; end; end
|
7
|
-
class NestedException < StandardError; attr_accessor :original_exception; end
|
8
|
-
class BugsnagTestExceptionWithMetaData < Exception; include Bugsnag::MetaData; end
|
9
|
-
class BugsnagSubclassTestException < BugsnagTestException; end
|
10
|
-
|
11
|
-
class Ruby21Exception < RuntimeError
|
12
|
-
attr_accessor :cause
|
13
|
-
def self.raise!(msg)
|
14
|
-
e = new(msg)
|
15
|
-
e.cause = $!
|
16
|
-
raise e
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class JRubyException
|
21
|
-
def self.raise!
|
22
|
-
new.gloops
|
23
|
-
end
|
24
|
-
|
25
|
-
def gloops
|
26
|
-
java.lang.System.out.printf(nil)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe Bugsnag::Notification do
|
31
|
-
it "should contain an api_key if one is set" do
|
32
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
33
|
-
|
34
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
35
|
-
expect(payload["apiKey"]).to eq("c9d60ae4c7e70c4b6c4ebd3e8056d2b8")
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
it "does not notify if api_key is not set" do
|
40
|
-
Bugsnag.configuration.api_key = nil
|
41
|
-
|
42
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
43
|
-
|
44
|
-
expect(Bugsnag).not_to have_sent_notification
|
45
|
-
end
|
46
|
-
|
47
|
-
it "does not notify if api_key is empty" do
|
48
|
-
Bugsnag.configuration.api_key = ""
|
49
|
-
|
50
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
51
|
-
|
52
|
-
expect(Bugsnag).not_to have_sent_notification
|
53
|
-
end
|
54
|
-
|
55
|
-
it "lets you override the api_key" do
|
56
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), :api_key => "9d84383f9be2ca94902e45c756a9979d")
|
57
|
-
|
58
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
59
|
-
expect(payload["apiKey"]).to eq("9d84383f9be2ca94902e45c756a9979d")
|
60
|
-
}
|
61
|
-
end
|
62
|
-
|
63
|
-
it "lets you override the groupingHash" do
|
64
|
-
|
65
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:grouping_hash => "this is my grouping hash"})
|
66
|
-
|
67
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
68
|
-
event = get_event_from_payload(payload)
|
69
|
-
expect(event["groupingHash"]).to eq("this is my grouping hash")
|
70
|
-
}
|
71
|
-
end
|
72
|
-
|
73
|
-
it "uses the env variable apiKey" do
|
74
|
-
ENV["BUGSNAG_API_KEY"] = "c9d60ae4c7e70c4b6c4ebd3e8056d2b9"
|
75
|
-
|
76
|
-
Bugsnag.instance_variable_set(:@configuration, Bugsnag::Configuration.new)
|
77
|
-
Bugsnag.configure do |config|
|
78
|
-
config.release_stage = "production"
|
79
|
-
config.delivery_method = :synchronous
|
80
|
-
end
|
81
|
-
|
82
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
83
|
-
|
84
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
85
|
-
expect(payload["apiKey"]).to eq("c9d60ae4c7e70c4b6c4ebd3e8056d2b9")
|
86
|
-
}
|
87
|
-
end
|
88
|
-
|
89
|
-
it "has the right exception class" do
|
90
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
91
|
-
|
92
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
93
|
-
exception = get_exception_from_payload(payload)
|
94
|
-
expect(exception["errorClass"]).to eq("BugsnagTestException")
|
95
|
-
}
|
96
|
-
end
|
97
|
-
|
98
|
-
it "has the right exception message" do
|
99
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
100
|
-
|
101
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
102
|
-
exception = get_exception_from_payload(payload)
|
103
|
-
expect(exception["message"]).to eq("It crashed")
|
104
|
-
}
|
105
|
-
end
|
106
|
-
|
107
|
-
it "has a valid stacktrace" do
|
108
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
109
|
-
|
110
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
111
|
-
exception = get_exception_from_payload(payload)
|
112
|
-
expect(exception["stacktrace"].length).to be > 0
|
113
|
-
}
|
114
|
-
end
|
115
|
-
|
116
|
-
# TODO: nested context
|
117
|
-
|
118
|
-
it "accepts tabs in overrides and adds them to metaData" do
|
119
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
120
|
-
:some_tab => {
|
121
|
-
:info => "here",
|
122
|
-
:data => "also here"
|
123
|
-
}
|
124
|
-
})
|
125
|
-
|
126
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
127
|
-
event = get_event_from_payload(payload)
|
128
|
-
expect(event["metaData"]["some_tab"]).to eq(
|
129
|
-
"info" => "here",
|
130
|
-
"data" => "also here"
|
131
|
-
)
|
132
|
-
}
|
133
|
-
end
|
134
|
-
|
135
|
-
it "accepts non-hash overrides and adds them to the custom tab in metaData" do
|
136
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
137
|
-
:info => "here",
|
138
|
-
:data => "also here"
|
139
|
-
})
|
140
|
-
|
141
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
142
|
-
event = get_event_from_payload(payload)
|
143
|
-
expect(event["metaData"]["custom"]).to eq(
|
144
|
-
"info" => "here",
|
145
|
-
"data" => "also here"
|
146
|
-
)
|
147
|
-
}
|
148
|
-
end
|
149
|
-
|
150
|
-
it "accepts meta data from an exception that mixes in Bugsnag::MetaData" do
|
151
|
-
exception = BugsnagTestExceptionWithMetaData.new("It crashed")
|
152
|
-
exception.bugsnag_meta_data = {
|
153
|
-
:some_tab => {
|
154
|
-
:info => "here",
|
155
|
-
:data => "also here"
|
156
|
-
}
|
157
|
-
}
|
158
|
-
|
159
|
-
Bugsnag.notify(exception)
|
160
|
-
|
161
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
162
|
-
event = get_event_from_payload(payload)
|
163
|
-
expect(event["metaData"]["some_tab"]).to eq(
|
164
|
-
"info" => "here",
|
165
|
-
"data" => "also here"
|
166
|
-
)
|
167
|
-
}
|
168
|
-
end
|
169
|
-
|
170
|
-
it "accepts meta data from an exception that mixes in Bugsnag::MetaData, but override using the overrides" do
|
171
|
-
exception = BugsnagTestExceptionWithMetaData.new("It crashed")
|
172
|
-
exception.bugsnag_meta_data = {
|
173
|
-
:some_tab => {
|
174
|
-
:info => "here",
|
175
|
-
:data => "also here"
|
176
|
-
}
|
177
|
-
}
|
178
|
-
|
179
|
-
Bugsnag.notify(exception, {:some_tab => {:info => "overridden"}})
|
180
|
-
|
181
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
182
|
-
event = get_event_from_payload(payload)
|
183
|
-
expect(event["metaData"]["some_tab"]).to eq(
|
184
|
-
"info" => "overridden",
|
185
|
-
"data" => "also here"
|
186
|
-
)
|
187
|
-
}
|
188
|
-
end
|
189
|
-
|
190
|
-
it "accepts user_id from an exception that mixes in Bugsnag::MetaData" do
|
191
|
-
exception = BugsnagTestExceptionWithMetaData.new("It crashed")
|
192
|
-
exception.bugsnag_user_id = "exception_user_id"
|
193
|
-
|
194
|
-
Bugsnag.notify(exception)
|
195
|
-
|
196
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
197
|
-
event = get_event_from_payload(payload)
|
198
|
-
expect(event["user"]["id"]).to eq("exception_user_id")
|
199
|
-
}
|
200
|
-
end
|
201
|
-
|
202
|
-
it "accepts user_id from an exception that mixes in Bugsnag::MetaData, but override using the overrides" do
|
203
|
-
exception = BugsnagTestExceptionWithMetaData.new("It crashed")
|
204
|
-
exception.bugsnag_user_id = "exception_user_id"
|
205
|
-
|
206
|
-
Bugsnag.notify(exception, {:user_id => "override_user_id"})
|
207
|
-
|
208
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
209
|
-
event = get_event_from_payload(payload)
|
210
|
-
expect(event["user"]["id"]).to eq("override_user_id")
|
211
|
-
}
|
212
|
-
end
|
213
|
-
|
214
|
-
it "accepts context from an exception that mixes in Bugsnag::MetaData" do
|
215
|
-
exception = BugsnagTestExceptionWithMetaData.new("It crashed")
|
216
|
-
exception.bugsnag_context = "exception_context"
|
217
|
-
|
218
|
-
Bugsnag.notify(exception)
|
219
|
-
|
220
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
221
|
-
event = get_event_from_payload(payload)
|
222
|
-
expect(event["context"]).to eq("exception_context")
|
223
|
-
}
|
224
|
-
end
|
225
|
-
|
226
|
-
it "accept contexts from an exception that mixes in Bugsnag::MetaData, but override using the overrides" do
|
227
|
-
|
228
|
-
exception = BugsnagTestExceptionWithMetaData.new("It crashed")
|
229
|
-
exception.bugsnag_context = "exception_context"
|
230
|
-
|
231
|
-
Bugsnag.notify(exception, {:context => "override_context"})
|
232
|
-
|
233
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
234
|
-
event = get_event_from_payload(payload)
|
235
|
-
expect(event["context"]).to eq("override_context")
|
236
|
-
}
|
237
|
-
end
|
238
|
-
|
239
|
-
it "accepts meta_data in overrides (for backwards compatibility) and merge it into metaData" do
|
240
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
241
|
-
:meta_data => {
|
242
|
-
:some_tab => {
|
243
|
-
:info => "here",
|
244
|
-
:data => "also here"
|
245
|
-
}
|
246
|
-
}
|
247
|
-
})
|
248
|
-
|
249
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
250
|
-
event = get_event_from_payload(payload)
|
251
|
-
expect(event["metaData"]["some_tab"]).to eq(
|
252
|
-
"info" => "here",
|
253
|
-
"data" => "also here"
|
254
|
-
)
|
255
|
-
}
|
256
|
-
end
|
257
|
-
|
258
|
-
it "truncates large meta_data before sending" do
|
259
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
260
|
-
:meta_data => {
|
261
|
-
:some_tab => {
|
262
|
-
:giant => SecureRandom.hex(500_000/2),
|
263
|
-
:mega => SecureRandom.hex(500_000/2)
|
264
|
-
}
|
265
|
-
}
|
266
|
-
})
|
267
|
-
|
268
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
269
|
-
# Truncated body should be no bigger than
|
270
|
-
# 2 truncated hashes (4096*2) + rest of payload (20000)
|
271
|
-
expect(::JSON.dump(payload).length).to be < 4096*2 + 20000
|
272
|
-
}
|
273
|
-
end
|
274
|
-
|
275
|
-
it "truncates large messages before sending" do
|
276
|
-
Bugsnag.notify(BugsnagTestException.new(SecureRandom.hex(500_000)), {
|
277
|
-
:meta_data => {
|
278
|
-
:some_tab => {
|
279
|
-
:giant => SecureRandom.hex(500_000/2),
|
280
|
-
:mega => SecureRandom.hex(500_000/2)
|
281
|
-
}
|
282
|
-
}
|
283
|
-
})
|
284
|
-
|
285
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
286
|
-
# Truncated body should be no bigger than
|
287
|
-
# 2 truncated hashes (4096*2) + rest of payload (20000)
|
288
|
-
expect(::JSON.dump(payload).length).to be < 4096*2 + 20000
|
289
|
-
}
|
290
|
-
end
|
291
|
-
|
292
|
-
it "truncate large stacktraces before sending" do
|
293
|
-
ex = BugsnagTestException.new("It crashed")
|
294
|
-
stacktrace = []
|
295
|
-
5000.times {|i| stacktrace.push("/Some/path/rspec/example.rb:113:in `instance_eval'")}
|
296
|
-
ex.set_backtrace(stacktrace)
|
297
|
-
Bugsnag.notify(ex)
|
298
|
-
|
299
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
300
|
-
# Truncated body should be no bigger than
|
301
|
-
# 400 stacktrace lines * approx 60 chars per line + rest of payload (20000)
|
302
|
-
expect(::JSON.dump(payload).length).to be < 400*60 + 20000
|
303
|
-
}
|
304
|
-
end
|
305
|
-
|
306
|
-
it "accepts a severity in overrides" do
|
307
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
308
|
-
:severity => "info"
|
309
|
-
})
|
310
|
-
|
311
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
312
|
-
event = get_event_from_payload(payload)
|
313
|
-
expect(event["severity"]).to eq("info")
|
314
|
-
}
|
315
|
-
|
316
|
-
end
|
317
|
-
|
318
|
-
it "defaults to warning severity" do
|
319
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
320
|
-
|
321
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
322
|
-
event = get_event_from_payload(payload)
|
323
|
-
expect(event["severity"]).to eq("warning")
|
324
|
-
}
|
325
|
-
end
|
326
|
-
|
327
|
-
it "does not accept a bad severity in overrides" do
|
328
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
329
|
-
:severity => "fatal"
|
330
|
-
})
|
331
|
-
|
332
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
333
|
-
event = get_event_from_payload(payload)
|
334
|
-
expect(event["severity"]).to eq("warning")
|
335
|
-
}
|
336
|
-
end
|
337
|
-
|
338
|
-
it "lets you override severity using block syntax" do
|
339
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed")) do |notification|
|
340
|
-
notification.severity = "info"
|
341
|
-
end
|
342
|
-
|
343
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
344
|
-
event = get_event_from_payload(payload)
|
345
|
-
expect(event["severity"]).to eq("info")
|
346
|
-
}
|
347
|
-
end
|
348
|
-
|
349
|
-
it "autonotifies errors" do
|
350
|
-
Bugsnag.auto_notify(BugsnagTestException.new("It crashed"))
|
351
|
-
|
352
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
353
|
-
event = get_event_from_payload(payload)
|
354
|
-
expect(event["severity"]).to eq("error")
|
355
|
-
}
|
356
|
-
end
|
357
|
-
|
358
|
-
|
359
|
-
it "accepts a context in overrides" do
|
360
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
361
|
-
:context => "test_context"
|
362
|
-
})
|
363
|
-
|
364
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
365
|
-
event = get_event_from_payload(payload)
|
366
|
-
expect(event["context"]).to eq("test_context")
|
367
|
-
}
|
368
|
-
end
|
369
|
-
|
370
|
-
it "accepts a user_id in overrides" do
|
371
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {
|
372
|
-
:user_id => "test_user"
|
373
|
-
})
|
374
|
-
|
375
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
376
|
-
event = get_event_from_payload(payload)
|
377
|
-
expect(event["user"]["id"]).to eq("test_user")
|
378
|
-
}
|
379
|
-
end
|
380
|
-
|
381
|
-
it "does not send a notification if auto_notify is false" do
|
382
|
-
Bugsnag.configure do |config|
|
383
|
-
config.auto_notify = false
|
384
|
-
end
|
385
|
-
|
386
|
-
Bugsnag.auto_notify(BugsnagTestException.new("It crashed"))
|
387
|
-
|
388
|
-
expect(Bugsnag).not_to have_sent_notification
|
389
|
-
end
|
390
|
-
|
391
|
-
it "contains a release_stage" do
|
392
|
-
Bugsnag.configure do |config|
|
393
|
-
config.release_stage = "production"
|
394
|
-
end
|
395
|
-
|
396
|
-
Bugsnag.auto_notify(BugsnagTestException.new("It crashed"))
|
397
|
-
|
398
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
399
|
-
event = get_event_from_payload(payload)
|
400
|
-
expect(event["app"]["releaseStage"]).to eq("production")
|
401
|
-
}
|
402
|
-
end
|
403
|
-
|
404
|
-
it "respects the notify_release_stages setting by not sending in development" do
|
405
|
-
Bugsnag.configuration.notify_release_stages = ["production"]
|
406
|
-
Bugsnag.configuration.release_stage = "development"
|
407
|
-
|
408
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
409
|
-
|
410
|
-
expect(Bugsnag).not_to have_sent_notification
|
411
|
-
end
|
412
|
-
|
413
|
-
it "respects the notify_release_stages setting when set" do
|
414
|
-
Bugsnag.configuration.release_stage = "development"
|
415
|
-
Bugsnag.configuration.notify_release_stages = ["development"]
|
416
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
417
|
-
|
418
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
419
|
-
event = get_event_from_payload(payload)
|
420
|
-
expect(event["exceptions"].length).to eq(1)
|
421
|
-
}
|
422
|
-
end
|
423
|
-
|
424
|
-
it "uses the https://notify.bugsnag.com endpoint by default" do
|
425
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
426
|
-
|
427
|
-
expect(WebMock).to have_requested(:post, "https://notify.bugsnag.com")
|
428
|
-
end
|
429
|
-
|
430
|
-
it "uses ssl when use_ssl is true" do
|
431
|
-
Bugsnag.configuration.use_ssl = true
|
432
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
433
|
-
|
434
|
-
expect(WebMock).to have_requested(:post, "https://notify.bugsnag.com")
|
435
|
-
end
|
436
|
-
|
437
|
-
it "does not use ssl when use_ssl is false" do
|
438
|
-
stub_request(:post, "http://notify.bugsnag.com/")
|
439
|
-
Bugsnag.configuration.use_ssl = false
|
440
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
441
|
-
|
442
|
-
expect(WebMock).to have_requested(:post, "http://notify.bugsnag.com")
|
443
|
-
end
|
444
|
-
|
445
|
-
it "uses ssl when use_ssl is unset" do
|
446
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
447
|
-
|
448
|
-
expect(WebMock).to have_requested(:post, "https://notify.bugsnag.com")
|
449
|
-
end
|
450
|
-
|
451
|
-
it "does not mark the top-most stacktrace line as inProject if out of project" do
|
452
|
-
Bugsnag.configuration.project_root = "/Random/location/here"
|
453
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
454
|
-
|
455
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
456
|
-
exception = get_exception_from_payload(payload)
|
457
|
-
expect(exception["stacktrace"].size).to be >= 1
|
458
|
-
expect(exception["stacktrace"].first["inProject"]).to be_nil
|
459
|
-
}
|
460
|
-
end
|
461
|
-
|
462
|
-
it "does not mark the top-most stacktrace line as inProject if it matches a vendor path" do
|
463
|
-
Bugsnag.configuration.project_root = File.expand_path('../../', __FILE__)
|
464
|
-
Bugsnag.configuration.vendor_paths = [File.expand_path('../', __FILE__)]
|
465
|
-
|
466
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
467
|
-
|
468
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
469
|
-
exception = get_exception_from_payload(payload)
|
470
|
-
expect(exception["stacktrace"].size).to be >= 1
|
471
|
-
expect(exception["stacktrace"].first["inProject"]).to be_nil
|
472
|
-
}
|
473
|
-
end
|
474
|
-
|
475
|
-
it "marks the top-most stacktrace line as inProject if necessary" do
|
476
|
-
Bugsnag.configuration.project_root = File.expand_path File.dirname(__FILE__)
|
477
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
478
|
-
|
479
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
480
|
-
exception = get_exception_from_payload(payload)
|
481
|
-
expect(exception["stacktrace"].size).to be >= 1
|
482
|
-
expect(exception["stacktrace"].first["inProject"]).to eq(true)
|
483
|
-
}
|
484
|
-
end
|
485
|
-
|
486
|
-
it "adds app_version to the payload if it is set" do
|
487
|
-
Bugsnag.configuration.app_version = "1.1.1"
|
488
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"))
|
489
|
-
|
490
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
491
|
-
event = get_event_from_payload(payload)
|
492
|
-
expect(event["app"]["version"]).to eq("1.1.1")
|
493
|
-
}
|
494
|
-
end
|
495
|
-
|
496
|
-
it "filters params from all payload hashes if they are set in default params_filters" do
|
497
|
-
|
498
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "12345", :other_data => "123456"}}})
|
499
|
-
|
500
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
501
|
-
event = get_event_from_payload(payload)
|
502
|
-
expect(event["metaData"]).not_to be_nil
|
503
|
-
expect(event["metaData"]["request"]).not_to be_nil
|
504
|
-
expect(event["metaData"]["request"]["params"]).not_to be_nil
|
505
|
-
expect(event["metaData"]["request"]["params"]["password"]).to eq("[FILTERED]")
|
506
|
-
expect(event["metaData"]["request"]["params"]["other_password"]).to eq("[FILTERED]")
|
507
|
-
expect(event["metaData"]["request"]["params"]["other_data"]).to eq("123456")
|
508
|
-
}
|
509
|
-
end
|
510
|
-
|
511
|
-
it "filters params from all payload hashes if they are added to params_filters" do
|
512
|
-
|
513
|
-
Bugsnag.configuration.params_filters << "other_data"
|
514
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
|
515
|
-
|
516
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
517
|
-
event = get_event_from_payload(payload)
|
518
|
-
expect(event["metaData"]).not_to be_nil
|
519
|
-
expect(event["metaData"]["request"]).not_to be_nil
|
520
|
-
expect(event["metaData"]["request"]["params"]).not_to be_nil
|
521
|
-
expect(event["metaData"]["request"]["params"]["password"]).to eq("[FILTERED]")
|
522
|
-
expect(event["metaData"]["request"]["params"]["other_password"]).to eq("[FILTERED]")
|
523
|
-
expect(event["metaData"]["request"]["params"]["other_data"]).to eq("[FILTERED]")
|
524
|
-
}
|
525
|
-
end
|
526
|
-
|
527
|
-
it "filters params from all payload hashes if they are added to params_filters as regex" do
|
528
|
-
|
529
|
-
Bugsnag.configuration.params_filters << /other_data/
|
530
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
|
531
|
-
|
532
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
533
|
-
event = get_event_from_payload(payload)
|
534
|
-
expect(event["metaData"]).not_to be_nil
|
535
|
-
expect(event["metaData"]["request"]).not_to be_nil
|
536
|
-
expect(event["metaData"]["request"]["params"]).not_to be_nil
|
537
|
-
expect(event["metaData"]["request"]["params"]["password"]).to eq("[FILTERED]")
|
538
|
-
expect(event["metaData"]["request"]["params"]["other_password"]).to eq("[FILTERED]")
|
539
|
-
expect(event["metaData"]["request"]["params"]["other_data"]).to eq("[FILTERED]")
|
540
|
-
}
|
541
|
-
end
|
542
|
-
|
543
|
-
it "filters params from all payload hashes if they are added to params_filters as partial regex" do
|
544
|
-
|
545
|
-
Bugsnag.configuration.params_filters << /r_data/
|
546
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:password => "1234", :other_password => "123456", :other_data => "123456"}}})
|
547
|
-
|
548
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
549
|
-
event = get_event_from_payload(payload)
|
550
|
-
expect(event["metaData"]).not_to be_nil
|
551
|
-
expect(event["metaData"]["request"]).not_to be_nil
|
552
|
-
expect(event["metaData"]["request"]["params"]).not_to be_nil
|
553
|
-
expect(event["metaData"]["request"]["params"]["password"]).to eq("[FILTERED]")
|
554
|
-
expect(event["metaData"]["request"]["params"]["other_password"]).to eq("[FILTERED]")
|
555
|
-
expect(event["metaData"]["request"]["params"]["other_data"]).to eq("[FILTERED]")
|
556
|
-
}
|
557
|
-
end
|
558
|
-
|
559
|
-
it "does not filter params from payload hashes if their values are nil" do
|
560
|
-
Bugsnag.notify(BugsnagTestException.new("It crashed"), {:request => {:params => {:nil_param => nil}}})
|
561
|
-
|
562
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
563
|
-
event = get_event_from_payload(payload)
|
564
|
-
expect(event["metaData"]).not_to be_nil
|
565
|
-
expect(event["metaData"]["request"]).not_to be_nil
|
566
|
-
expect(event["metaData"]["request"]["params"]).not_to be_nil
|
567
|
-
expect(event["metaData"]["request"]["params"]).to have_key("nil_param")
|
568
|
-
}
|
569
|
-
end
|
570
|
-
|
571
|
-
it "does not notify if the exception class is in the default ignore_classes list" do
|
572
|
-
Bugsnag.notify_or_ignore(ActiveRecord::RecordNotFound.new("It crashed"))
|
573
|
-
|
574
|
-
expect(Bugsnag).not_to have_sent_notification
|
575
|
-
end
|
576
|
-
|
577
|
-
it "does not notify if the non-default exception class is added to the ignore_classes" do
|
578
|
-
Bugsnag.configuration.ignore_classes << "BugsnagTestException"
|
579
|
-
|
580
|
-
Bugsnag.notify_or_ignore(BugsnagTestException.new("It crashed"))
|
581
|
-
|
582
|
-
expect(Bugsnag).not_to have_sent_notification
|
583
|
-
end
|
584
|
-
|
585
|
-
it "does not notify if exception's ancestor is an ignored class" do
|
586
|
-
Bugsnag.configuration.ignore_classes << "BugsnagTestException"
|
587
|
-
|
588
|
-
Bugsnag.notify_or_ignore(BugsnagSubclassTestException.new("It crashed"))
|
589
|
-
|
590
|
-
expect(Bugsnag).not_to have_sent_notification
|
591
|
-
end
|
592
|
-
|
593
|
-
it "does not notify if any caused exception is an ignored class" do
|
594
|
-
Bugsnag.configuration.ignore_classes << "NestedException"
|
595
|
-
|
596
|
-
ex = NestedException.new("Self-referential exception")
|
597
|
-
ex.original_exception = BugsnagTestException.new("It crashed")
|
598
|
-
|
599
|
-
Bugsnag.notify_or_ignore(ex)
|
600
|
-
|
601
|
-
expect(Bugsnag).not_to have_sent_notification
|
602
|
-
end
|
603
|
-
|
604
|
-
it "accepts both String and Class instances as an ignored class" do
|
605
|
-
Bugsnag.configuration.ignore_classes << BugsnagTestException
|
606
|
-
|
607
|
-
Bugsnag.notify_or_ignore(BugsnagTestException.new("It crashed"))
|
608
|
-
|
609
|
-
expect(Bugsnag).not_to have_sent_notification
|
610
|
-
end
|
611
|
-
|
612
|
-
it "does not notify if the user agent is present and matches a regex in ignore_user_agents" do
|
613
|
-
Bugsnag.configuration.ignore_user_agents << %r{BugsnagUserAgent}
|
614
|
-
|
615
|
-
((Thread.current["bugsnag_req_data"] ||= {})[:rack_env] ||= {})["HTTP_USER_AGENT"] = "BugsnagUserAgent"
|
616
|
-
|
617
|
-
Bugsnag.notify_or_ignore(BugsnagTestException.new("It crashed"))
|
618
|
-
|
619
|
-
expect(Bugsnag::Notification).not_to have_sent_notification
|
620
|
-
end
|
621
|
-
|
622
|
-
it "sends the cause of the exception" do
|
623
|
-
begin
|
624
|
-
begin
|
625
|
-
raise "jiminey"
|
626
|
-
rescue
|
627
|
-
Ruby21Exception.raise! "cricket"
|
628
|
-
end
|
629
|
-
rescue
|
630
|
-
Bugsnag.notify $!
|
631
|
-
end
|
632
|
-
|
633
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
634
|
-
event = get_event_from_payload(payload)
|
635
|
-
expect(event["exceptions"].size).to eq(2)
|
636
|
-
}
|
637
|
-
end
|
638
|
-
|
639
|
-
it "does not unwrap the same exception twice" do
|
640
|
-
ex = NestedException.new("Self-referential exception")
|
641
|
-
ex.original_exception = ex
|
642
|
-
|
643
|
-
Bugsnag.notify_or_ignore(ex)
|
644
|
-
|
645
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
646
|
-
event = get_event_from_payload(payload)
|
647
|
-
expect(event["exceptions"].size).to eq(1)
|
648
|
-
}
|
649
|
-
end
|
650
|
-
|
651
|
-
it "does not unwrap more than 5 exceptions" do
|
652
|
-
|
653
|
-
first_ex = ex = NestedException.new("Deep exception")
|
654
|
-
10.times do |idx|
|
655
|
-
ex = ex.original_exception = NestedException.new("Deep exception #{idx}")
|
656
|
-
end
|
657
|
-
|
658
|
-
Bugsnag.notify_or_ignore(first_ex)
|
659
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
660
|
-
event = get_event_from_payload(payload)
|
661
|
-
expect(event["exceptions"].size).to eq(5)
|
662
|
-
}
|
663
|
-
end
|
664
|
-
|
665
|
-
it "calls to_exception on i18n error objects" do
|
666
|
-
Bugsnag.notify(OpenStruct.new(:to_exception => BugsnagTestException.new("message")))
|
667
|
-
|
668
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
669
|
-
exception = get_exception_from_payload(payload)
|
670
|
-
expect(exception["errorClass"]).to eq("BugsnagTestException")
|
671
|
-
expect(exception["message"]).to eq("message")
|
672
|
-
}
|
673
|
-
end
|
674
|
-
|
675
|
-
it "generates runtimeerror for non exceptions" do
|
676
|
-
notify_test_exception
|
677
|
-
|
678
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
679
|
-
exception = get_exception_from_payload(payload)
|
680
|
-
expect(exception["errorClass"]).to eq("RuntimeError")
|
681
|
-
expect(exception["message"]).to eq("test message")
|
682
|
-
}
|
683
|
-
end
|
684
|
-
|
685
|
-
it "supports unix-style paths in backtraces" do
|
686
|
-
ex = BugsnagTestException.new("It crashed")
|
687
|
-
ex.set_backtrace([
|
688
|
-
"/Users/james/app/spec/notification_spec.rb:419",
|
689
|
-
"/Some/path/rspec/example.rb:113:in `instance_eval'"
|
690
|
-
])
|
691
|
-
|
692
|
-
Bugsnag.notify(ex)
|
693
|
-
|
694
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
695
|
-
exception = get_exception_from_payload(payload)
|
696
|
-
expect(exception["stacktrace"].length).to eq(2)
|
697
|
-
|
698
|
-
line = exception["stacktrace"][0]
|
699
|
-
expect(line["file"]).to eq("/Users/james/app/spec/notification_spec.rb")
|
700
|
-
expect(line["lineNumber"]).to eq(419)
|
701
|
-
expect(line["method"]).to be nil
|
702
|
-
|
703
|
-
line = exception["stacktrace"][1]
|
704
|
-
expect(line["file"]).to eq("/Some/path/rspec/example.rb")
|
705
|
-
expect(line["lineNumber"]).to eq(113)
|
706
|
-
expect(line["method"]).to eq("instance_eval")
|
707
|
-
}
|
708
|
-
end
|
709
|
-
|
710
|
-
it "supports windows-style paths in backtraces" do
|
711
|
-
ex = BugsnagTestException.new("It crashed")
|
712
|
-
ex.set_backtrace([
|
713
|
-
"C:/projects/test/app/controllers/users_controller.rb:13:in `index'",
|
714
|
-
"C:/ruby/1.9.1/gems/actionpack-2.3.10/filters.rb:638:in `block in run_before_filters'"
|
715
|
-
])
|
716
|
-
|
717
|
-
Bugsnag.notify(ex)
|
718
|
-
|
719
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
720
|
-
exception = get_exception_from_payload(payload)
|
721
|
-
expect(exception["stacktrace"].length).to eq(2)
|
722
|
-
|
723
|
-
line = exception["stacktrace"][0]
|
724
|
-
expect(line["file"]).to eq("C:/projects/test/app/controllers/users_controller.rb")
|
725
|
-
expect(line["lineNumber"]).to eq(13)
|
726
|
-
expect(line["method"]).to eq("index")
|
727
|
-
|
728
|
-
line = exception["stacktrace"][1]
|
729
|
-
expect(line["file"]).to eq("C:/ruby/1.9.1/gems/actionpack-2.3.10/filters.rb")
|
730
|
-
expect(line["lineNumber"]).to eq(638)
|
731
|
-
expect(line["method"]).to eq("block in run_before_filters")
|
732
|
-
}
|
733
|
-
end
|
734
|
-
|
735
|
-
it "should fix invalid utf8" do
|
736
|
-
invalid_data = "fl\xc3ff"
|
737
|
-
invalid_data.force_encoding('BINARY') if invalid_data.respond_to?(:force_encoding)
|
738
|
-
|
739
|
-
notify_test_exception(:fluff => {:fluff => invalid_data})
|
740
|
-
|
741
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
742
|
-
if defined?(Encoding::UTF_8)
|
743
|
-
expect(payload.to_json).to match(/fl�ff/)
|
744
|
-
else
|
745
|
-
expect(payload.to_json).to match(/flff/)
|
746
|
-
end
|
747
|
-
}
|
748
|
-
end
|
749
|
-
|
750
|
-
it "should handle utf8 encoding errors in exceptions_list" do
|
751
|
-
invalid_data = "\"foo\xEBbar\""
|
752
|
-
invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
|
753
|
-
|
754
|
-
begin
|
755
|
-
JSON.parse(invalid_data)
|
756
|
-
rescue
|
757
|
-
Bugsnag.notify $!
|
758
|
-
end
|
759
|
-
|
760
|
-
expect(Bugsnag).to have_sent_notification { |payload|
|
761
|
-
if defined?(Encoding::UTF_8)
|
762
|
-
expect(payload.to_json).to match(/foo�bar/)
|
763
|
-
else
|
764
|
-
expect(payload.to_json).to match(/foobar/)
|
765
|
-
end
|
766
|
-
}
|
767
|
-
end
|
768
|
-
|
769
|
-
it "should handle utf8 encoding errors in notification context" do
|
770
|
-
invalid_data = "\"foo\xEBbar\""
|
771
|
-
invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
|
772
|
-
|
773
|
-
begin
|
774
|
-
raise
|
775
|
-
rescue
|
776
|
-
Bugsnag.notify($!, { :context => invalid_data })
|
777
|
-
end
|
778
|
-
|
779
|
-
expect(Bugsnag).to have_sent_notification { |payload|
|
780
|
-
if defined?(Encoding::UTF_8)
|
781
|
-
expect(payload.to_json).to match(/foo�bar/)
|
782
|
-
else
|
783
|
-
expect(payload.to_json).to match(/foobar/)
|
784
|
-
end
|
785
|
-
}
|
786
|
-
end
|
787
|
-
|
788
|
-
it "should handle utf8 encoding errors in notification app fields" do
|
789
|
-
invalid_data = "\"foo\xEBbar\""
|
790
|
-
invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
|
791
|
-
|
792
|
-
Bugsnag.configuration.app_version = invalid_data
|
793
|
-
Bugsnag.configuration.release_stage = invalid_data
|
794
|
-
Bugsnag.configuration.app_type = invalid_data
|
795
|
-
|
796
|
-
begin
|
797
|
-
raise
|
798
|
-
rescue
|
799
|
-
Bugsnag.notify $!
|
800
|
-
end
|
801
|
-
|
802
|
-
expect(Bugsnag).to have_sent_notification { |payload|
|
803
|
-
if defined?(Encoding::UTF_8)
|
804
|
-
expect(payload.to_json).to match(/foo�bar/)
|
805
|
-
else
|
806
|
-
expect(payload.to_json).to match(/foobar/)
|
807
|
-
end
|
808
|
-
}
|
809
|
-
end
|
810
|
-
|
811
|
-
it "should handle utf8 encoding errors in grouping_hash" do
|
812
|
-
invalid_data = "\"foo\xEBbar\""
|
813
|
-
invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
|
814
|
-
|
815
|
-
Bugsnag.before_notify_callbacks << lambda do |notif|
|
816
|
-
notif.grouping_hash = invalid_data
|
817
|
-
end
|
818
|
-
|
819
|
-
begin
|
820
|
-
raise
|
821
|
-
rescue
|
822
|
-
Bugsnag.notify $!
|
823
|
-
end
|
824
|
-
|
825
|
-
expect(Bugsnag).to have_sent_notification { |payload|
|
826
|
-
if defined?(Encoding::UTF_8)
|
827
|
-
expect(payload.to_json).to match(/foo�bar/)
|
828
|
-
else
|
829
|
-
expect(payload.to_json).to match(/foobar/)
|
830
|
-
end
|
831
|
-
}
|
832
|
-
end
|
833
|
-
|
834
|
-
it "should handle utf8 encoding errors in notification user fields" do
|
835
|
-
invalid_data = "\"foo\xEBbar\""
|
836
|
-
invalid_data = invalid_data.force_encoding("utf-8") if invalid_data.respond_to?(:force_encoding)
|
837
|
-
|
838
|
-
Bugsnag.before_notify_callbacks << lambda do |notif|
|
839
|
-
notif.user = {
|
840
|
-
:email => "#{invalid_data}@foo.com",
|
841
|
-
:name => invalid_data
|
842
|
-
}
|
843
|
-
end
|
844
|
-
|
845
|
-
begin
|
846
|
-
raise
|
847
|
-
rescue
|
848
|
-
Bugsnag.notify $!
|
849
|
-
end
|
850
|
-
|
851
|
-
expect(Bugsnag).to have_sent_notification { |payload|
|
852
|
-
if defined?(Encoding::UTF_8)
|
853
|
-
expect(payload.to_json).to match(/foo�bar/)
|
854
|
-
else
|
855
|
-
expect(payload.to_json).to match(/foobar/)
|
856
|
-
end
|
857
|
-
}
|
858
|
-
end
|
859
|
-
|
860
|
-
if defined?(JRUBY_VERSION)
|
861
|
-
|
862
|
-
it "should work with java.lang.Throwables" do
|
863
|
-
begin
|
864
|
-
JRubyException.raise!
|
865
|
-
rescue
|
866
|
-
Bugsnag.notify $!
|
867
|
-
end
|
868
|
-
|
869
|
-
expect(Bugsnag).to have_sent_notification{ |payload|
|
870
|
-
exception = get_exception_from_payload(payload)
|
871
|
-
expect(exception["errorClass"]).to eq('Java::JavaLang::ArrayIndexOutOfBoundsException')
|
872
|
-
expect(exception["message"]).to eq("2")
|
873
|
-
expect(exception["stacktrace"].size).to be > 0
|
874
|
-
}
|
875
|
-
end
|
876
|
-
end
|
877
|
-
end
|