exception_handling 2.7.0.pre.1 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) 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 +2 -2
  6. data/Gemfile +4 -4
  7. data/Gemfile.lock +65 -56
  8. data/Rakefile +7 -6
  9. data/gemfiles/rails_4.gemfile +4 -4
  10. data/gemfiles/rails_5.gemfile +4 -4
  11. data/gemfiles/rails_6.gemfile +4 -4
  12. data/lib/exception_handling/log_stub_error.rb +2 -1
  13. data/lib/exception_handling/logging_methods.rb +1 -7
  14. data/lib/exception_handling/version.rb +1 -1
  15. data/{test → spec}/helpers/controller_helpers.rb +0 -0
  16. data/{test → spec}/helpers/exception_helpers.rb +2 -2
  17. data/{test → spec}/rake_test_warning_false.rb +0 -0
  18. data/{test/test_helper.rb → spec/spec_helper.rb} +50 -39
  19. data/spec/unit/exception_handling/exception_catalog_spec.rb +85 -0
  20. data/spec/unit/exception_handling/exception_description_spec.rb +82 -0
  21. data/{test/unit/exception_handling/exception_info_test.rb → spec/unit/exception_handling/exception_info_spec.rb} +105 -107
  22. data/{test/unit/exception_handling/honeybadger_callbacks_test.rb → spec/unit/exception_handling/honeybadger_callbacks_spec.rb} +20 -20
  23. data/{test/unit/exception_handling/log_error_stub_test.rb → spec/unit/exception_handling/log_error_stub_spec.rb} +38 -22
  24. data/{test/unit/exception_handling/logging_methods_test.rb → spec/unit/exception_handling/logging_methods_spec.rb} +8 -7
  25. data/{test/unit/exception_handling/mailer_test.rb → spec/unit/exception_handling/mailer_spec.rb} +17 -17
  26. data/spec/unit/exception_handling/methods_spec.rb +105 -0
  27. data/spec/unit/exception_handling/sensu_spec.rb +51 -0
  28. data/{test/unit/exception_handling_test.rb → spec/unit/exception_handling_spec.rb} +325 -329
  29. metadata +36 -35
  30. data/test/unit/exception_handling/exception_catalog_test.rb +0 -85
  31. data/test/unit/exception_handling/exception_description_test.rb +0 -82
  32. data/test/unit/exception_handling/methods_test.rb +0 -105
  33. data/test/unit/exception_handling/sensu_test.rb +0 -52
@@ -1,17 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support'
4
- require 'active_support/time'
5
- require 'active_support/test_case'
6
- require 'action_mailer'
7
- require 'action_dispatch'
8
- require 'shoulda'
9
- require 'rr'
10
- require 'minitest/autorun'
11
- require "minitest/reporters"
12
-
13
- junit_ouptut_dir = ENV["JUNIT_OUTPUT_DIR"].presence || "test/reports"
14
- Minitest::Reporters.use!([Minitest::Reporters::DefaultReporter.new, Minitest::Reporters::JUnitReporter.new(junit_ouptut_dir)])
3
+ require 'rspec'
4
+ require 'rspec/mocks'
5
+ require 'rspec_junit_formatter'
15
6
 
16
7
  require 'pry'
17
8
  require 'honeybadger'
@@ -20,8 +11,6 @@ require 'contextual_logger'
20
11
  require 'exception_handling'
21
12
  require 'exception_handling/testing'
22
13
 
23
- ActiveSupport::TestCase.test_order = :sorted
24
-
25
14
  class LoggerStub
26
15
  include ContextualLogger::LoggerMixin
27
16
  attr_accessor :logged, :level
@@ -87,27 +76,17 @@ end
87
76
 
88
77
  ActionMailer::Base.delivery_method = :test
89
78
 
90
- _ = ActiveSupport
91
- _ = ActiveSupport::TestCase
92
79
 
93
- class ActiveSupport::TestCase
94
- @@constant_overrides = []
80
+ module TestHelper
81
+ @constant_overrides = []
82
+ class << self
83
+ attr_accessor :constant_overrides
84
+ end
95
85
 
96
- setup do
97
- unless @@constant_overrides.nil? || @@constant_overrides.empty?
98
- raise "Uh-oh! constant_overrides left over: #{@@constant_overrides.inspect}"
99
- end
100
86
 
101
- unless defined?(Rails) && defined?(Rails.env)
102
- module ::Rails
103
- class << self
104
- attr_writer :env
105
-
106
- def env
107
- @env ||= 'test'
108
- end
109
- end
110
- end
87
+ def setup_constant_overrides
88
+ unless TestHelper.constant_overrides.nil? || TestHelper.constant_overrides.empty?
89
+ raise "Uh-oh! constant_overrides left over: #{TestHelper.constant_overrides.inspect}"
111
90
  end
112
91
 
113
92
  Time.now_override = nil
@@ -127,8 +106,8 @@ class ActiveSupport::TestCase
127
106
  ExceptionHandling.sensu_prefix = ""
128
107
  end
129
108
 
130
- teardown do
131
- @@constant_overrides&.reverse&.each do |parent_module, k, v|
109
+ def teardown_constant_overrides
110
+ TestHelper.constant_overrides&.reverse&.each do |parent_module, k, v|
132
111
  ExceptionHandling.ensure_safe "constant cleanup #{k.inspect}, #{parent_module}(#{parent_module.class})::#{v.inspect}(#{v.class})" do
133
112
  silence_warnings do
134
113
  if v == :never_defined
@@ -139,7 +118,7 @@ class ActiveSupport::TestCase
139
118
  end
140
119
  end
141
120
  end
142
- @@constant_overrides = []
121
+ TestHelper.constant_overrides = []
143
122
  end
144
123
 
145
124
  def set_test_const(const_name, value)
@@ -159,7 +138,7 @@ class ActiveSupport::TestCase
159
138
  end
160
139
  end
161
140
 
162
- @@constant_overrides << [final_parent_module, final_const_name, original_value]
141
+ TestHelper.constant_overrides << [final_parent_module, final_const_name, original_value]
163
142
 
164
143
  silence_warnings { final_parent_module.const_set(final_const_name, value) }
165
144
  end
@@ -171,15 +150,15 @@ class ActiveSupport::TestCase
171
150
  else
172
151
  original_count = 0
173
152
  end
174
- assert_equal expected, ActionMailer::Base.deliveries.size - original_count, "wrong number of emails#{': ' + message.to_s if message}"
153
+ expect(ActionMailer::Base.deliveries.size - original_count).to eq(expected), "wrong number of emails#{': ' + message.to_s if message}"
175
154
  end
176
155
  end
177
156
 
178
157
  def assert_equal_with_diff(arg1, arg2, msg = '')
179
158
  if arg1 == arg2
180
- assert true # To keep the assertion count accurate
159
+ expect(true).to be_truthy # To keep the assertion count accurate
181
160
  else
182
- assert_equal arg1, arg2, "#{msg}\n#{Diff.compare(arg1, arg2)}"
161
+ expect(arg1).to eq(arg2), "#{msg}\n#{Diff.compare(arg1, arg2)}"
183
162
  end
184
163
  end
185
164
 
@@ -210,3 +189,35 @@ class Time
210
189
  end
211
190
  end
212
191
  end
192
+
193
+ RSpec.configure do |config|
194
+ config.add_formatter(RspecJunitFormatter, 'spec/reports/rspec.xml')
195
+ config.include TestHelper
196
+
197
+ config.before(:each) do
198
+ setup_constant_overrides
199
+ unless defined?(Rails) && defined?(Rails.env)
200
+ module Rails
201
+ class << self
202
+ attr_writer :env
203
+
204
+ def env
205
+ @env ||= 'test'
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ config.after(:each) do
213
+ teardown_constant_overrides
214
+ end
215
+
216
+ config.mock_with :rspec do |mocks|
217
+ mocks.verify_partial_doubles = true
218
+ end
219
+
220
+ config.expect_with(:rspec, :test_unit)
221
+
222
+ RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 2_000
223
+ end
@@ -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,85 +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
- setup do
421
- stub(ExceptionHandling.logger).current_context_for_thread { { cuid: 'ABCD' } }
419
+ before do
420
+ allow(ExceptionHandling.logger).to receive(:current_context_for_thread).and_return({ cuid: 'ABCD' })
422
421
  end
423
422
 
424
- should "include thread_context when log_context: is nil" do
423
+ it "include thread_context when log_context: is nil" do
425
424
  exception_with_nil_message = RuntimeError.new(nil)
426
- stub(exception_with_nil_message).message { nil }
425
+ allow(exception_with_nil_message).to receive(:message).and_return(nil)
427
426
  exception_info = ExceptionInfo.new(exception_with_nil_message, @exception_context, @timestamp)
428
427
  honeybadger_context_data = exception_info.honeybadger_context_data
429
- assert_equal({ "cuid" => 'ABCD' }, honeybadger_context_data[:log_context])
428
+ expect(honeybadger_context_data[:log_context]).to eq({ "cuid" => 'ABCD' })
430
429
  end
431
430
 
432
- should "include thread context merged with log_context:" do
431
+ it "include thread context merged with log_context:" do
433
432
  exception_with_nil_message = RuntimeError.new(nil)
434
- stub(exception_with_nil_message).message { nil }
433
+ allow(exception_with_nil_message).to receive(:message).and_return(nil)
435
434
  exception_info = ExceptionInfo.new(exception_with_nil_message, @exception_context, @timestamp, log_context: { url: 'http://example.com' })
436
435
  honeybadger_context_data = exception_info.honeybadger_context_data
437
- assert_equal({ "cuid" => 'ABCD', "url" => 'http://example.com' }, honeybadger_context_data[:log_context])
436
+ expect(honeybadger_context_data[:log_context]).to eq({ "cuid" => 'ABCD', "url" => 'http://example.com' })
438
437
  end
439
438
 
440
- should "return the error details and relevant context data to be used as honeybadger notification context while filtering sensitive data" do
439
+ it "return the error details and relevant context data to be used as honeybadger notification context while filtering sensitive data" do
441
440
  env = { server: "fe98" }
442
441
  parameters = { advertiser_id: 435 }
443
442
  session = { username: "jsmith" }
444
443
  request_uri = "host/path"
445
444
  controller = create_dummy_controller(env, parameters, session, request_uri)
446
- stub(ExceptionHandling).server_name { "invoca_fe98" }
445
+ allow(ExceptionHandling).to receive(:server_name).and_return("invoca_fe98")
447
446
 
448
447
  exception = StandardError.new("Some Exception")
449
448
  exception.set_backtrace([
450
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
451
- "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>'"
452
451
  ])
453
452
  exception_context = { "SERVER_NAME" => "exceptional.com" }
454
453
  data_callback = ->(data) do
@@ -466,7 +465,6 @@ module ExceptionHandling
466
465
  exception_context: { "SERVER_NAME" => "exceptional.com" },
467
466
  server: "invoca_fe98",
468
467
  scm_revision: "5b24eac37aaa91f5784901e9aabcead36fd9df82",
469
- notes: "this is used by a test",
470
468
  user_details: { "username" => "jsmith" },
471
469
  request: {
472
470
  "params" => { "advertiser_id" => 435 },
@@ -481,29 +479,30 @@ module ExceptionHandling
481
479
  "SERVER_NAME" => "exceptional.com"
482
480
  },
483
481
  backtrace: [
484
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
485
- "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>'"
486
484
  ],
487
485
  event_response: "Event successfully received",
488
- log_context: { "cuid" => "ABCD" }
486
+ log_context: { "cuid" => "ABCD" },
487
+ notes: "this is used by a test"
489
488
  }
490
- assert_equal_with_diff expected_data, exception_info.honeybadger_context_data
489
+ expect(exception_info.honeybadger_context_data).to eq(expected_data)
491
490
  end
492
491
 
493
492
  [['Hash', { 'cookie' => 'cookie_context' }],
494
493
  ['String', 'Entering Error State'],
495
494
  ['Array', ['Error1', 'Error2']]].each do |klass, value|
496
- 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
497
496
  exception = StandardError.new("Exception")
498
497
  exception_context = value
499
498
  exception_info = ExceptionInfo.new(exception, exception_context, Time.now)
500
499
 
501
- assert_equal klass, value.class.name
502
- 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)
503
502
  end
504
503
  end
505
504
 
506
- 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
507
506
  sensitive_data = {
508
507
  "password" => "super_secret",
509
508
  "password_confirmation" => "super_secret_confirmation",
@@ -538,15 +537,14 @@ module ExceptionHandling
538
537
  }
539
538
  }.merge(expected_sensitive_data)
540
539
 
541
- 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)
542
541
  end
543
542
 
544
- should "omit context if exception_context is empty" do
543
+ it "omit context if exception_context is empty" do
545
544
  exception = StandardError.new("Exception")
546
545
  exception_context = ""
547
546
  exception_info = ExceptionInfo.new(exception, exception_context, Time.now)
548
-
549
- assert_nil exception_info.honeybadger_context_data[:exception_context]
547
+ expect(exception_info.honeybadger_context_data[:exception_context]).to be_nil
550
548
  end
551
549
  end
552
550