exception_handling 2.6.0 → 2.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.jenkins/Jenkinsfile +24 -8
  4. data/.rspec +3 -0
  5. data/CHANGELOG.md +6 -1
  6. data/Gemfile +4 -4
  7. data/Gemfile.lock +29 -19
  8. data/Rakefile +7 -6
  9. data/lib/exception_handling/exception_info.rb +3 -6
  10. data/lib/exception_handling/log_stub_error.rb +2 -1
  11. data/lib/exception_handling/version.rb +1 -1
  12. data/{test → spec}/helpers/controller_helpers.rb +0 -0
  13. data/{test → spec}/helpers/exception_helpers.rb +2 -2
  14. data/{test → spec}/rake_test_warning_false.rb +0 -0
  15. data/{test/test_helper.rb → spec/spec_helper.rb} +50 -39
  16. data/spec/unit/exception_handling/exception_catalog_spec.rb +85 -0
  17. data/spec/unit/exception_handling/exception_description_spec.rb +82 -0
  18. data/{test/unit/exception_handling/exception_info_test.rb → spec/unit/exception_handling/exception_info_spec.rb} +118 -99
  19. data/{test/unit/exception_handling/honeybadger_callbacks_test.rb → spec/unit/exception_handling/honeybadger_callbacks_spec.rb} +20 -20
  20. data/{test/unit/exception_handling/log_error_stub_test.rb → spec/unit/exception_handling/log_error_stub_spec.rb} +38 -22
  21. data/{test/unit/exception_handling/mailer_test.rb → spec/unit/exception_handling/mailer_spec.rb} +17 -17
  22. data/spec/unit/exception_handling/methods_spec.rb +84 -0
  23. data/spec/unit/exception_handling/sensu_spec.rb +51 -0
  24. data/{test/unit/exception_handling_test.rb → spec/unit/exception_handling_spec.rb} +325 -329
  25. metadata +29 -28
  26. data/test/unit/exception_handling/exception_catalog_test.rb +0 -85
  27. data/test/unit/exception_handling/exception_description_test.rb +0 -82
  28. data/test/unit/exception_handling/methods_test.rb +0 -84
  29. data/test/unit/exception_handling/sensu_test.rb +0 -52
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../spec_helper', __dir__)
4
+
5
+ module ExceptionHandling
6
+ describe ExceptionCatalog do
7
+
8
+ context "With stubbed yaml content" do
9
+ before do
10
+ filter_list = { exception1: { error: "my error message" },
11
+ exception2: { error: "some other message", session: "misc data" } }
12
+ allow(YAML).to receive(:load_file) { filter_list }
13
+
14
+ # bump modified time up to get the above filter loaded
15
+ allow(File).to receive(:mtime) { incrementing_mtime }
16
+ end
17
+
18
+ context "with loaded data" do
19
+ before do
20
+ allow(File).to receive(:mtime) { incrementing_mtime }
21
+ @exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
22
+ @exception_catalog.send :load_file
23
+ end
24
+
25
+ it "have loaded filters" do
26
+ expect(@exception_catalog.instance_eval("@filters").size).to eq(2)
27
+ end
28
+
29
+ it "find messages in the catalog" do
30
+ expect(!@exception_catalog.find(error: "Scott says unlikely to ever match")).to be_truthy
31
+ end
32
+
33
+ it "find matching data" do
34
+ exception_description = @exception_catalog.find(error: "this is my error message, which should match something")
35
+ expect(exception_description).to be_truthy
36
+ expect(exception_description.filter_name).to eq(:exception1)
37
+ end
38
+ end
39
+
40
+ it "write errors loading the yaml file directly to the log file" do
41
+ @exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
42
+
43
+ expect(ExceptionHandling).to receive(:log_error).never
44
+ expect(ExceptionHandling).to receive(:write_exception_to_log).with(anything, "ExceptionCatalog#refresh_filters: ./config/exception_filters.yml", anything)
45
+ expect(@exception_catalog).to receive(:load_file) { raise "noooooo" }
46
+
47
+ @exception_catalog.find({})
48
+ end
49
+ end
50
+
51
+ context "with live yaml content" do
52
+ before do
53
+ @filename = File.expand_path('../../../config/exception_filters.yml', __dir__)
54
+ @exception_catalog = ExceptionCatalog.new(@filename)
55
+ expect do
56
+ @exception_catalog.send :load_file
57
+ end.not_to raise_error
58
+ end
59
+
60
+ it "load the filter data" do
61
+ expect(!@exception_catalog.find(error: "Scott says unlikely to ever match")).to be_truthy
62
+ expect(!@exception_catalog.find(error: "Scott says unlikely to ever match")).to be_truthy
63
+ end
64
+ end
65
+
66
+ context "with no yaml content" do
67
+ before do
68
+ @exception_catalog = ExceptionCatalog.new(nil)
69
+ end
70
+
71
+ it "not load filter data" do
72
+ expect(ExceptionHandling).to receive(:write_exception_to_log).with(any_args).never
73
+ @exception_catalog.find(error: "Scott says unlikely to ever match")
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def incrementing_mtime
80
+ @mtime ||= Time.now
81
+ @mtime += 1.day
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../spec_helper', __dir__)
4
+
5
+ module ExceptionHandling
6
+ describe ExceptionDescription do
7
+
8
+ context "Filter" do
9
+ it "allow direct matching of strings" do
10
+ @f = ExceptionDescription.new(:filter1, error: "my error message")
11
+ expect(@f.match?('error' => "my error message")).to be_truthy
12
+ end
13
+
14
+ it "allow direct matching of strings on with symbol keys" do
15
+ @f = ExceptionDescription.new(:filter1, error: "my error message")
16
+ expect(@f.match?(error: "my error message")).to be_truthy
17
+ end
18
+
19
+ it "allow wildcards to cross line boundries" do
20
+ @f = ExceptionDescription.new(:filter1, error: "my error message.*with multiple lines")
21
+ expect(@f.match?(error: "my error message\nwith more than one, with multiple lines")).to be_truthy
22
+ end
23
+
24
+ it "complain when no regexps have a value" do
25
+ expect { ExceptionDescription.new(:filter1, error: nil) }.to raise_exception(ArgumentError, /has all blank regexes/)
26
+ end
27
+
28
+ it "report when an invalid key is passed" do
29
+ expect { ExceptionDescription.new(:filter1, error: "my error message", not_a_parameter: false) }.to raise_exception(ArgumentError, "Unknown section: not_a_parameter")
30
+ end
31
+
32
+ it "allow send_to_honeybadger to be specified and have it disabled by default" do
33
+ expect(!ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: false).send_to_honeybadger).to be_truthy
34
+ expect(ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: true).send_to_honeybadger).to be_truthy
35
+ expect(!ExceptionDescription.new(:filter1, error: "my error message").send_to_honeybadger).to be_truthy
36
+ end
37
+
38
+ it "allow send_metric to be configured" do
39
+ expect(!ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).send_metric).to be_truthy
40
+ expect(ExceptionDescription.new(:filter1, error: "my error message").send_metric).to be_truthy
41
+ end
42
+
43
+ it "provide metric name" do
44
+ expect(ExceptionDescription.new(:filter1, error: "my error message").metric_name).to eq("filter1")
45
+ expect(ExceptionDescription.new(:filter1, error: "my error message", metric_name: :some_other_metric_name).metric_name).to eq("some_other_metric_name")
46
+ end
47
+
48
+ it "replace spaces in metric name" do
49
+ @f = ExceptionDescription.new(:"filter has spaces", error: "my error message")
50
+ expect(@f.metric_name).to eq( "filter_has_spaces")
51
+ end
52
+
53
+ it "allow notes to be recorded" do
54
+ expect(ExceptionDescription.new(:filter1, error: "my error message").notes).to be_nil
55
+ expect(ExceptionDescription.new(:filter1, error: "my error message", notes: "a long string").notes).to eq("a long string")
56
+ end
57
+
58
+ it "not consider config options in the filter set" do
59
+ expect(ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).match?(error: "my error message")).to be_truthy
60
+ expect(ExceptionDescription.new(:filter1, error: "my error message", metric_name: "false").match?(error: "my error message")).to be_truthy
61
+ expect(ExceptionDescription.new(:filter1, error: "my error message", notes: "hey").match?(error: "my error message")).to be_truthy
62
+ end
63
+
64
+ it "provide exception details" do
65
+ exception_description = ExceptionDescription.new(:filter1, error: "my error message", notes: "hey")
66
+
67
+ expected = { "send_metric" => true, "metric_name" => "filter1", "notes" => "hey" }
68
+
69
+ expect(exception_description.exception_data).to eq( expected)
70
+ end
71
+
72
+ it "match multiple email addresses" do
73
+ mobi = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'mcc@mobistreak.com'"
74
+ credit = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'damon@thecreditpros.com'"
75
+
76
+ exception_description = ExceptionDescription.new(:filter1, error: "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for '(mcc\@mobistreak|damon\@thecreditpros).com'")
77
+ expect(exception_description.match?(error: mobi)).to be_truthy
78
+ expect(exception_description.match?(error: credit)).to be_truthy
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,58 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.expand_path('../../test_helper', __dir__)
3
+ require File.expand_path('../../spec_helper', __dir__)
4
4
  require_test_helper 'controller_helpers'
5
5
  require_test_helper 'exception_helpers'
6
6
 
7
7
  module ExceptionHandling
8
- class ExceptionInfoTest < ActiveSupport::TestCase
8
+ describe ExceptionInfo do
9
9
  include ControllerHelpers
10
10
  include ExceptionHelpers
11
11
 
12
12
  context "initialize" do
13
- setup do
13
+ before do
14
14
  @exception = StandardError.new("something went wrong")
15
15
  @timestamp = Time.now
16
16
  @controller = Object.new
17
17
  end
18
18
 
19
19
  context "controller_from_context" do
20
- should "extract controller from context when not specified explicitly" do
20
+ it "extract controller from context when not specified explicitly" do
21
21
  exception_context = {
22
22
  "action_controller.instance" => @controller
23
23
  }
24
24
  exception_info = ExceptionInfo.new(@exception, exception_context, @timestamp)
25
- assert_equal @controller, exception_info.controller
25
+ expect(exception_info.controller).to eq(@controller)
26
26
  end
27
27
 
28
- should "prefer the explicit controller over the one from context" do
28
+ it "prefer the explicit controller over the one from context" do
29
29
  exception_context = {
30
30
  "action_controller.instance" => Object.new
31
31
  }
32
32
  exception_info = ExceptionInfo.new(@exception, exception_context, @timestamp, controller: @controller)
33
- assert_equal @controller, exception_info.controller
34
- assert_not_equal exception_context["action_controller.instance"], exception_info.controller
33
+ expect(exception_info.controller).to eq(@controller)
34
+ expect(exception_info.controller).not_to eq(exception_context["action_controller.instance"])
35
35
  end
36
36
 
37
- should "leave controller unset when not included in the context hash" do
37
+ it "leave controller unset when not included in the context hash" do
38
38
  exception_info = ExceptionInfo.new(@exception, {}, @timestamp)
39
- assert_nil exception_info.controller
39
+ expect(exception_info.controller).to be_nil
40
40
  end
41
41
 
42
- should "leave controller unset when context is not in hash format" do
42
+ it "leave controller unset when context is not in hash format" do
43
43
  exception_info = ExceptionInfo.new(@exception, "string context", @timestamp)
44
- assert_nil exception_info.controller
44
+ expect(exception_info.controller).to be_nil
45
45
  end
46
46
  end
47
47
  end
48
48
 
49
49
  context "data" do
50
- setup do
50
+ before do
51
51
  @exception = StandardError.new("something went wrong")
52
52
  @timestamp = Time.now
53
53
  end
54
54
 
55
- should "return a hash with exception specific data including context hash" do
55
+ it "return a hash with exception specific data including context hash" do
56
56
  exception_context = {
57
57
  "rack.session" => {
58
58
  user_id: 23,
@@ -73,17 +73,17 @@ module ExceptionHandling
73
73
  }
74
74
  }
75
75
 
76
- assert_equal_with_diff expected_data, exception_info.data
76
+ expect(exception_info.data).to eq(expected_data)
77
77
  end
78
78
 
79
- should "generate exception data appropriately if exception message is nil" do
79
+ it "generate exception data appropriately if exception message is nil" do
80
80
  exception_info = ExceptionInfo.new(exception_with_nil_message, "custom context data", @timestamp)
81
81
  exception_data = exception_info.data
82
- assert_equal "RuntimeError: ", exception_data["error_string"]
83
- assert_equal "RuntimeError: : custom context data", exception_data["error"]
82
+ expect(exception_data["error_string"]).to eq("RuntimeError: ")
83
+ expect(exception_data["error"]).to eq("RuntimeError: : custom context data")
84
84
  end
85
85
 
86
- should "return a hash with exception specific data including context string" do
86
+ it "return a hash with exception specific data including context string" do
87
87
  exception_context = "custom context data"
88
88
  exception_info = ExceptionInfo.new(@exception, exception_context, @timestamp)
89
89
  expected_data = {
@@ -96,11 +96,10 @@ module ExceptionHandling
96
96
  "message" => "custom context data"
97
97
  }
98
98
  }
99
-
100
- assert_equal_with_diff expected_data, exception_info.data
99
+ expect(exception_info.data).to eq(expected_data)
101
100
  end
102
101
 
103
- should "not include enhanced data from controller or custom data callback" do
102
+ it "not include enhanced data from controller or custom data callback" do
104
103
  env = { server: "fe98" }
105
104
  parameters = { advertiser_id: 435 }
106
105
  session = { username: "jsmith" }
@@ -109,8 +108,8 @@ module ExceptionHandling
109
108
  data_callback = ->(data) { data[:custom_section] = "value" }
110
109
  exception_info = ExceptionInfo.new(@exception, "custom context data", @timestamp, controller: controller, data_callback: data_callback)
111
110
 
112
- dont_allow(exception_info).extract_and_merge_controller_data
113
- dont_allow(exception_info).customize_from_data_callback
111
+ expect(exception_info).to_not receive(:extract_and_merge_controller_data)
112
+ expect(exception_info).to_not receive(:customize_from_data_callback)
114
113
  expected_data = {
115
114
  "error_class" => "StandardError",
116
115
  "error_string" => "StandardError: something went wrong",
@@ -122,12 +121,12 @@ module ExceptionHandling
122
121
  }
123
122
  }
124
123
 
125
- assert_equal_with_diff expected_data, exception_info.data
124
+ expect(exception_info.data).to eq(expected_data)
126
125
  end
127
126
  end
128
127
 
129
128
  context "enhanced_data" do
130
- setup do
129
+ before do
131
130
  @exception = StandardError.new("something went wrong")
132
131
  @timestamp = Time.now
133
132
  @exception_context = {
@@ -145,13 +144,13 @@ module ExceptionHandling
145
144
  @data_callback = ->(data) { data[:custom_section] = "check this out" }
146
145
  end
147
146
 
148
- should "not return a mutable object for the session" do
147
+ it "not return a mutable object for the session" do
149
148
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
150
149
  exception_info.enhanced_data["session"]["hello"] = "world"
151
- assert_nil @controller.session["hello"]
150
+ expect(@controller.session["hello"]).to be_nil
152
151
  end
153
152
 
154
- should "return a hash with generic exception attributes as well as context data" do
153
+ it "return a hash with generic exception attributes as well as context data" do
155
154
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
156
155
  expected_data = {
157
156
  "error_class" => "StandardError",
@@ -164,19 +163,19 @@ module ExceptionHandling
164
163
  "location" => { "file" => "<no backtrace>", "line" => nil }
165
164
  }
166
165
 
167
- assert_equal_with_diff expected_data, prepare_data(exception_info.enhanced_data)
166
+ expect(prepare_data(exception_info.enhanced_data)).to eq(expected_data)
168
167
  end
169
168
 
170
- should "generate exception data appropriately if exception message is nil" do
169
+ it "generate exception data appropriately if exception message is nil" do
171
170
  exception_with_nil_message = RuntimeError.new(nil)
172
- stub(exception_with_nil_message).message { nil }
171
+ allow(exception_with_nil_message).to receive(:message).and_return(nil)
173
172
  exception_info = ExceptionInfo.new(exception_with_nil_message, @exception_context, @timestamp)
174
173
  exception_data = exception_info.enhanced_data
175
- assert_equal "RuntimeError: ", exception_data["error_string"]
176
- assert_equal "RuntimeError: ", exception_data["error"]
174
+ expect(exception_data["error_string"]).to eq("RuntimeError: ")
175
+ expect(exception_data["error"]).to eq("RuntimeError: ")
177
176
  end
178
177
 
179
- should "include controller data when available" do
178
+ it "include controller data when available" do
180
179
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: @controller)
181
180
  expected_data = {
182
181
  "error_class" => "StandardError",
@@ -194,10 +193,10 @@ module ExceptionHandling
194
193
  "location" => { "controller" => "dummy", "action" => "fail", "file" => "<no backtrace>", "line" => nil }
195
194
  }
196
195
 
197
- assert_equal_with_diff expected_data, prepare_data(exception_info.enhanced_data)
196
+ expect(prepare_data(exception_info.enhanced_data)).to eq(expected_data)
198
197
  end
199
198
 
200
- should "extract controller from rack specific exception context when not provided explicitly" do
199
+ it "extract controller from rack specific exception context when not provided explicitly" do
201
200
  @exception_context["action_controller.instance"] = @controller
202
201
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
203
202
  expected_data = {
@@ -216,10 +215,10 @@ module ExceptionHandling
216
215
  "location" => { "controller" => "dummy", "action" => "fail", "file" => "<no backtrace>", "line" => nil }
217
216
  }
218
217
 
219
- assert_equal_with_diff expected_data, prepare_data(exception_info.enhanced_data)
218
+ expect(prepare_data(exception_info.enhanced_data)).to eq(expected_data)
220
219
  end
221
220
 
222
- should "add to_s attribute to specific sections that have their content in hash format" do
221
+ it "add to_s attribute to specific sections that have their content in hash format" do
223
222
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: @controller)
224
223
  expected_data = {
225
224
  "error_class" => "StandardError",
@@ -245,10 +244,10 @@ module ExceptionHandling
245
244
  "location" => { "controller" => "dummy", "action" => "fail", "file" => "<no backtrace>", "line" => nil }
246
245
  }
247
246
 
248
- assert_equal_with_diff expected_data, exception_info.enhanced_data
247
+ expect(exception_info.enhanced_data).to eq(expected_data)
249
248
  end
250
249
 
251
- should "filter out sensitive parameters like passwords" do
250
+ it "filter out sensitive parameters like passwords" do
252
251
  @controller.request.parameters[:password] = "super_secret"
253
252
  @controller.request.parameters[:user] = { "password" => "also super secret", "password_confirmation" => "also super secret" }
254
253
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: @controller)
@@ -261,10 +260,10 @@ module ExceptionHandling
261
260
  "password_confirmation" => "[FILTERED]"
262
261
  }
263
262
  }
264
- assert_equal_with_diff expected_params, exception_info.enhanced_data["request"]["params"]
263
+ expect(exception_info.enhanced_data["request"]["params"]).to eq(expected_params)
265
264
  end
266
265
 
267
- should "include the changes from the custom data callback" do
266
+ it "include the changes from the custom data callback" do
268
267
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: nil, data_callback: @data_callback)
269
268
  expected_data = {
270
269
  "error_class" => "StandardError",
@@ -278,11 +277,11 @@ module ExceptionHandling
278
277
  "location" => { "file" => "<no backtrace>", "line" => nil }
279
278
  }
280
279
 
281
- assert_equal_with_diff expected_data, prepare_data(exception_info.enhanced_data)
280
+ expect(prepare_data(exception_info.enhanced_data)).to eq(expected_data)
282
281
  end
283
282
 
284
- should "apply the custom_data_hook results" do
285
- stub(ExceptionHandling).custom_data_hook { ->(data) { data[:custom_hook] = "changes from custom hook" } }
283
+ it "apply the custom_data_hook results" do
284
+ allow(ExceptionHandling).to receive(:custom_data_hook).and_return(->(data) { data[:custom_hook] = "changes from custom hook" })
286
285
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
287
286
  expected_data = {
288
287
  "error_class" => "StandardError",
@@ -296,35 +295,35 @@ module ExceptionHandling
296
295
  "location" => { "file" => "<no backtrace>", "line" => nil }
297
296
  }
298
297
 
299
- assert_equal_with_diff expected_data, prepare_data(exception_info.enhanced_data)
298
+ expect(prepare_data(exception_info.enhanced_data)).to eq(expected_data)
300
299
  end
301
300
 
302
- should "log info if the custom data hook results in a nil message exception" do
301
+ it "log info if the custom data hook results in a nil message exception" do
303
302
  ExceptionHandling.custom_data_hook = ->(_data) do
304
303
  raise_exception_with_nil_message
305
304
  end
306
305
  log_info_messages = []
307
- stub(ExceptionHandling.logger).info.with_any_args do |message, _|
306
+ allow(ExceptionHandling.logger).to receive(:info).with(any_args) do |message, _|
308
307
  log_info_messages << message
309
308
  end
310
309
 
311
310
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
312
311
  exception_info.enhanced_data
313
- assert log_info_messages.find { |message| message =~ /Unable to execute custom custom_data_hook callback/ }
312
+ expect(log_info_messages.find { |message| message =~ /Unable to execute custom custom_data_hook callback/ }).to be_truthy
314
313
  ExceptionHandling.custom_data_hook = nil
315
314
  end
316
315
  end
317
316
 
318
317
  context "exception_description" do
319
- should "return the exception description from the global exception filter list" do
318
+ it "return the exception description from the global exception filter list" do
320
319
  exception = StandardError.new("No route matches")
321
320
  exception_info = ExceptionInfo.new(exception, {}, Time.now)
322
321
  description = exception_info.exception_description
323
- assert_not_nil description
324
- assert_equal :NoRoute, description.filter_name
322
+ expect(description).to_not be_nil
323
+ expect(description.filter_name).to eq(:NoRoute)
325
324
  end
326
325
 
327
- should "find the description when filter criteria includes section in hash format" do
326
+ it "find the description when filter criteria includes section in hash format" do
328
327
  env = { server: "fe98" }
329
328
  parameters = { advertiser_id: 435, controller: "sessions", action: "fail" }
330
329
  session = { username: "jsmith", id: "session_key" }
@@ -332,25 +331,25 @@ module ExceptionHandling
332
331
  controller = create_dummy_controller(env, parameters, session, request_uri)
333
332
  exception = StandardError.new("Request to click domain rejected")
334
333
  exception_info = ExceptionInfo.new(exception, nil, Time.now, controller: controller)
335
- assert_equal true, exception_info.enhanced_data[:request].is_a?(Hash)
334
+ expect(exception_info.enhanced_data[:request].is_a?(Hash)).to eq(true)
336
335
  description = exception_info.exception_description
337
- assert_not_nil description
338
- assert_equal :"Click Request Rejected", description.filter_name
336
+ expect(description).to_not be_nil
337
+ expect(description.filter_name).to eq(:"Click Request Rejected")
339
338
  end
340
339
 
341
- should "return same description object for related errors (avoid reloading exception catalog from disk)" do
340
+ it "return same description object for related errors (avoid reloading exception catalog from disk)" do
342
341
  exception = StandardError.new("No route matches")
343
342
  exception_info = ExceptionInfo.new(exception, nil, Time.now)
344
343
  description = exception_info.exception_description
345
344
 
346
345
  repeat_ex = StandardError.new("No route matches 2")
347
346
  repeat_ex_info = ExceptionInfo.new(repeat_ex, nil, Time.now)
348
- assert_equal description.object_id, repeat_ex_info.exception_description.object_id
347
+ expect(repeat_ex_info.exception_description.object_id).to eq(description.object_id)
349
348
  end
350
349
  end
351
350
 
352
351
  context "controller_name" do
353
- setup do
352
+ before do
354
353
  @exception = StandardError.new('something went wrong')
355
354
  @timestamp = Time.now
356
355
  @exception_context = {
@@ -362,7 +361,7 @@ module ExceptionHandling
362
361
  }
363
362
  end
364
363
 
365
- should "return controller_name when controller is present" do
364
+ it "return controller_name when controller is present" do
366
365
  env = { server: 'fe98' }
367
366
  parameters = { controller: 'some_controller' }
368
367
  session = { username: 'smith' }
@@ -370,65 +369,85 @@ module ExceptionHandling
370
369
  controller = create_dummy_controller(env, parameters, session, request_uri)
371
370
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller: controller)
372
371
 
373
- assert_equal 'some_controller', exception_info.controller_name
372
+ expect(exception_info.controller_name).to eq('some_controller')
374
373
  end
375
374
 
376
- should "return an empty string when controller is not present" do
375
+ it "return an empty string when controller is not present" do
377
376
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
378
377
 
379
- assert_equal '', exception_info.controller_name
378
+ expect(exception_info.controller_name).to eq('')
380
379
  end
381
380
  end
382
381
 
383
382
  context "send_to_honeybadger?" do
384
- should "be enabled when Honeybadger is defined and exception is not in the filter list" do
385
- stub(ExceptionHandling).honeybadger_defined? { true }
383
+ it "be enabled when Honeybadger is defined and exception is not in the filter list" do
384
+ allow(ExceptionHandling).to receive(:honeybadger_defined?).and_return(true)
386
385
  exception = StandardError.new("something went wrong")
387
386
  exception_info = ExceptionInfo.new(exception, nil, Time.now)
388
- assert_nil exception_info.exception_description
389
- assert_equal true, exception_info.send_to_honeybadger?
387
+ expect(exception_info.exception_description).to be_nil
388
+ expect(exception_info.send_to_honeybadger?).to eq(true)
390
389
  end
391
390
 
392
- should "be enabled when Honeybadger is defined and exception is on the filter list with the flag turned on" do
393
- stub(ExceptionHandling).honeybadger_defined? { true }
391
+ it "be enabled when Honeybadger is defined and exception is on the filter list with the flag turned on" do
392
+ allow(ExceptionHandling).to receive(:honeybadger_defined?).and_return(true)
394
393
  exception = StandardError.new("No route matches")
395
394
  exception_info = ExceptionInfo.new(exception, nil, Time.now)
396
- assert_not_nil exception_info.exception_description
397
- assert_equal true, exception_info.exception_description.send_to_honeybadger
398
- assert_equal true, exception_info.send_to_honeybadger?
395
+ expect(exception_info.exception_description).to_not be_nil
396
+ expect(exception_info.exception_description.send_to_honeybadger).to eq(true)
397
+ expect(exception_info.send_to_honeybadger?).to eq(true)
399
398
  end
400
399
 
401
- should "be disabled when Honeybadger is defined and exception is on the filter list with the flag turned off" do
402
- stub(ExceptionHandling).honeybadger_defined? { true }
400
+ it "be disabled when Honeybadger is defined and exception is on the filter list with the flag turned off" do
401
+ allow(ExceptionHandling).to receive(:honeybadger_defined?).and_return(true)
403
402
  exception = StandardError.new("No route matches")
404
403
  exception_info = ExceptionInfo.new(exception, nil, Time.now)
405
- assert_not_nil exception_info.exception_description
406
- stub(exception_info.exception_description).send_to_honeybadger { false }
407
- assert_equal false, exception_info.send_to_honeybadger?
404
+ expect(exception_info.exception_description).to_not be_nil
405
+ allow(exception_info.exception_description).to receive(:send_to_honeybadger).and_return(false)
406
+ expect(exception_info.send_to_honeybadger?).to eq(false)
408
407
  end
409
408
 
410
- should "be disabled when Honeybadger is not defined" do
411
- stub(ExceptionHandling).honeybadger_defined? { false }
409
+ it "be disabled when Honeybadger is not defined" do
410
+ allow(ExceptionHandling).to receive(:honeybadger_defined?).and_return(false)
412
411
  exception = StandardError.new("something went wrong")
413
412
  exception_info = ExceptionInfo.new(exception, nil, Time.now)
414
- assert_nil exception_info.exception_description
415
- assert_equal false, exception_info.send_to_honeybadger?
413
+ expect(exception_info.exception_description).to be_nil
414
+ expect(exception_info.send_to_honeybadger?).to eq(false)
416
415
  end
417
416
  end
418
417
 
419
418
  context "honeybadger_context_data" do
420
- should "return the error details and relevant context data to be used as honeybadger notification context while filtering sensitive data" do
419
+ before do
420
+ allow(ExceptionHandling.logger).to receive(:current_context_for_thread).and_return({ cuid: 'ABCD' })
421
+ end
422
+
423
+ it "include thread_context when log_context: is nil" do
424
+ exception_with_nil_message = RuntimeError.new(nil)
425
+ allow(exception_with_nil_message).to receive(:message).and_return(nil)
426
+ exception_info = ExceptionInfo.new(exception_with_nil_message, @exception_context, @timestamp)
427
+ honeybadger_context_data = exception_info.honeybadger_context_data
428
+ expect(honeybadger_context_data[:log_context]).to eq({ "cuid" => 'ABCD' })
429
+ end
430
+
431
+ it "include thread context merged with log_context:" do
432
+ exception_with_nil_message = RuntimeError.new(nil)
433
+ allow(exception_with_nil_message).to receive(:message).and_return(nil)
434
+ exception_info = ExceptionInfo.new(exception_with_nil_message, @exception_context, @timestamp, log_context: { url: 'http://example.com' })
435
+ honeybadger_context_data = exception_info.honeybadger_context_data
436
+ expect(honeybadger_context_data[:log_context]).to eq({ "cuid" => 'ABCD', "url" => 'http://example.com' })
437
+ end
438
+
439
+ it "return the error details and relevant context data to be used as honeybadger notification context while filtering sensitive data" do
421
440
  env = { server: "fe98" }
422
441
  parameters = { advertiser_id: 435 }
423
442
  session = { username: "jsmith" }
424
443
  request_uri = "host/path"
425
444
  controller = create_dummy_controller(env, parameters, session, request_uri)
426
- stub(ExceptionHandling).server_name { "invoca_fe98" }
445
+ allow(ExceptionHandling).to receive(:server_name).and_return("invoca_fe98")
427
446
 
428
447
  exception = StandardError.new("Some Exception")
429
448
  exception.set_backtrace([
430
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
431
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
449
+ "spec/unit/exception_handling_test.rb:847:in `exception_1'",
450
+ "spec/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
432
451
  ])
433
452
  exception_context = { "SERVER_NAME" => "exceptional.com" }
434
453
  data_callback = ->(data) do
@@ -446,7 +465,6 @@ module ExceptionHandling
446
465
  exception_context: { "SERVER_NAME" => "exceptional.com" },
447
466
  server: "invoca_fe98",
448
467
  scm_revision: "5b24eac37aaa91f5784901e9aabcead36fd9df82",
449
- notes: "this is used by a test",
450
468
  user_details: { "username" => "jsmith" },
451
469
  request: {
452
470
  "params" => { "advertiser_id" => 435 },
@@ -461,28 +479,30 @@ module ExceptionHandling
461
479
  "SERVER_NAME" => "exceptional.com"
462
480
  },
463
481
  backtrace: [
464
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
465
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
482
+ "spec/unit/exception_handling_test.rb:847:in `exception_1'",
483
+ "spec/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
466
484
  ],
467
- event_response: "Event successfully received"
485
+ event_response: "Event successfully received",
486
+ log_context: { "cuid" => "ABCD" },
487
+ notes: "this is used by a test"
468
488
  }
469
- assert_equal_with_diff expected_data, exception_info.honeybadger_context_data
489
+ expect(exception_info.honeybadger_context_data).to eq(expected_data)
470
490
  end
471
491
 
472
492
  [['Hash', { 'cookie' => 'cookie_context' }],
473
493
  ['String', 'Entering Error State'],
474
494
  ['Array', ['Error1', 'Error2']]].each do |klass, value|
475
- should "extract context from exception_context when it is a #{klass}" do
495
+ it "extract context from exception_context when it is a #{klass}" do
476
496
  exception = StandardError.new("Exception")
477
497
  exception_context = value
478
498
  exception_info = ExceptionInfo.new(exception, exception_context, Time.now)
479
499
 
480
- assert_equal klass, value.class.name
481
- assert_equal value, exception_info.honeybadger_context_data[:exception_context]
500
+ expect(value.class.name).to eq(klass)
501
+ expect(exception_info.honeybadger_context_data[:exception_context]).to eq(value)
482
502
  end
483
503
  end
484
504
 
485
- should "filter out sensitive data from exception context such as [password, password_confirmation, oauth_token]" do
505
+ it "filter out sensitive data from exception context such as [password, password_confirmation, oauth_token]" do
486
506
  sensitive_data = {
487
507
  "password" => "super_secret",
488
508
  "password_confirmation" => "super_secret_confirmation",
@@ -517,15 +537,14 @@ module ExceptionHandling
517
537
  }
518
538
  }.merge(expected_sensitive_data)
519
539
 
520
- assert_equal_with_diff expected_exception_context, exception_info.honeybadger_context_data[:exception_context]
540
+ expect(exception_info.honeybadger_context_data[:exception_context]).to eq(expected_exception_context)
521
541
  end
522
542
 
523
- should "omit context if exception_context is empty" do
543
+ it "omit context if exception_context is empty" do
524
544
  exception = StandardError.new("Exception")
525
545
  exception_context = ""
526
546
  exception_info = ExceptionInfo.new(exception, exception_context, Time.now)
527
-
528
- assert_nil exception_info.honeybadger_context_data[:exception_context]
547
+ expect(exception_info.honeybadger_context_data[:exception_context]).to be_nil
529
548
  end
530
549
  end
531
550