exception_notification 5.0.0 → 5.0.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +14 -0
  3. data/exception_notification.gemspec +9 -2
  4. data/lib/exception_notification/version.rb +1 -1
  5. metadata +2 -31
  6. data/Gemfile +0 -5
  7. data/Gemfile.lock +0 -346
  8. data/gemfiles/pinned_dependencies.gemfile +0 -8
  9. data/gemfiles/rails7_1.gemfile +0 -5
  10. data/gemfiles/rails7_2.gemfile +0 -5
  11. data/gemfiles/rails8_0.gemfile +0 -5
  12. data/test/exception_notification/rack_test.rb +0 -106
  13. data/test/exception_notification/rake_test.rb +0 -38
  14. data/test/exception_notification/resque_test.rb +0 -54
  15. data/test/exception_notifier/datadog_notifier_test.rb +0 -154
  16. data/test/exception_notifier/email_notifier_test.rb +0 -342
  17. data/test/exception_notifier/google_chat_notifier_test.rb +0 -185
  18. data/test/exception_notifier/hipchat_notifier_test.rb +0 -220
  19. data/test/exception_notifier/irc_notifier_test.rb +0 -139
  20. data/test/exception_notifier/mattermost_notifier_test.rb +0 -251
  21. data/test/exception_notifier/modules/error_grouping_test.rb +0 -167
  22. data/test/exception_notifier/modules/formatter_test.rb +0 -154
  23. data/test/exception_notifier/sidekiq_test.rb +0 -41
  24. data/test/exception_notifier/slack_notifier_test.rb +0 -228
  25. data/test/exception_notifier/sns_notifier_test.rb +0 -181
  26. data/test/exception_notifier/teams_notifier_test.rb +0 -92
  27. data/test/exception_notifier/webhook_notifier_test.rb +0 -98
  28. data/test/exception_notifier_test.rb +0 -298
  29. data/test/support/exception_notifier_helper.rb +0 -14
  30. data/test/support/views/exception_notifier/_new_bkg_section.html.erb +0 -1
  31. data/test/support/views/exception_notifier/_new_bkg_section.text.erb +0 -1
  32. data/test/support/views/exception_notifier/_new_section.html.erb +0 -1
  33. data/test/support/views/exception_notifier/_new_section.text.erb +0 -1
  34. data/test/test_helper.rb +0 -16
@@ -1,228 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "slack-notifier"
5
-
6
- class SlackNotifierTest < ActiveSupport::TestCase
7
- def setup
8
- @exception = fake_exception
9
- @exception.stubs(:backtrace).returns(fake_backtrace)
10
- @exception.stubs(:message).returns("exception message")
11
- ExceptionNotifier::SlackNotifier.any_instance.stubs(:clean_backtrace).returns(fake_cleaned_backtrace)
12
- Socket.stubs(:gethostname).returns("example.com")
13
- end
14
-
15
- test "should send a slack notification if properly configured" do
16
- options = {
17
- webhook_url: "http://slack.webhook.url"
18
- }
19
-
20
- Slack::Notifier.any_instance.expects(:ping).with("", fake_notification)
21
-
22
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
23
- slack_notifier.call(@exception)
24
- end
25
-
26
- test "should send a slack notification without backtrace info if properly configured" do
27
- options = {
28
- webhook_url: "http://slack.webhook.url"
29
- }
30
-
31
- Slack::Notifier.any_instance.expects(:ping).with("", fake_notification(fake_exception_without_backtrace))
32
-
33
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
34
- slack_notifier.call(fake_exception_without_backtrace)
35
- end
36
-
37
- test "should send the notification to the specified channel" do
38
- options = {
39
- webhook_url: "http://slack.webhook.url",
40
- channel: "channel"
41
- }
42
-
43
- Slack::Notifier.any_instance.expects(:ping).with("", fake_notification)
44
-
45
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
46
- slack_notifier.call(@exception)
47
-
48
- channel = slack_notifier.notifier.config.defaults[:channel]
49
- assert_equal channel, options[:channel]
50
- end
51
-
52
- test "should send the notification to the specified username" do
53
- options = {
54
- webhook_url: "http://slack.webhook.url",
55
- username: "username"
56
- }
57
-
58
- Slack::Notifier.any_instance.expects(:ping).with("", fake_notification)
59
-
60
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
61
- slack_notifier.call(@exception)
62
-
63
- username = slack_notifier.notifier.config.defaults[:username]
64
- assert_equal username, options[:username]
65
- end
66
-
67
- test "should send the notification with specific backtrace lines" do
68
- options = {
69
- webhook_url: "http://slack.webhook.url",
70
- backtrace_lines: 1
71
- }
72
-
73
- Slack::Notifier.any_instance.expects(:ping).with("", fake_notification(@exception, {}, nil, 1))
74
-
75
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
76
- slack_notifier.call(@exception)
77
- end
78
-
79
- test "should send the notification with additional fields" do
80
- field = {title: "Branch", value: "master", short: true}
81
- options = {
82
- webhook_url: "http://slack.webhook.url",
83
- additional_fields: [field]
84
- }
85
-
86
- Slack::Notifier.any_instance.expects(:ping).with("", fake_notification(@exception, {}, nil, 10, [field]))
87
-
88
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
89
- slack_notifier.call(@exception)
90
-
91
- additional_fields = slack_notifier.notifier.config.defaults[:additional_fields]
92
- assert_equal additional_fields, options[:additional_fields]
93
- end
94
-
95
- test "should pass the additional parameters to Slack::Notifier.ping" do
96
- options = {
97
- webhook_url: "http://slack.webhook.url",
98
- username: "test",
99
- custom_hook: "hook",
100
- additional_parameters: {
101
- icon_url: "icon"
102
- }
103
- }
104
-
105
- Slack::Notifier.any_instance.expects(:ping).with("", options[:additional_parameters].merge(fake_notification))
106
-
107
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
108
- slack_notifier.call(@exception)
109
- end
110
-
111
- test "shouldn't send a slack notification if webhook url is missing" do
112
- options = {}
113
-
114
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
115
-
116
- assert_nil slack_notifier.notifier
117
- assert_nil slack_notifier.call(@exception)
118
- end
119
-
120
- test "should pass along environment data" do
121
- options = {
122
- webhook_url: "http://slack.webhook.url",
123
- ignore_data_if: lambda { |k, v|
124
- k.to_s == "key_to_be_ignored" || v.is_a?(Hash)
125
- }
126
- }
127
-
128
- notification_options = {
129
- env: {
130
- "exception_notifier.exception_data" => {foo: "bar", john: "doe"}
131
- },
132
- data: {
133
- "user_id" => 5,
134
- "key_to_be_ignored" => "whatever",
135
- "ignore_as_well" => {what: "ever"}
136
- }
137
- }
138
-
139
- expected_data_string = "foo: bar\njohn: doe\nuser_id: 5"
140
-
141
- Slack::Notifier.any_instance
142
- .expects(:ping)
143
- .with("", fake_notification(@exception, notification_options, expected_data_string))
144
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
145
- slack_notifier.call(@exception, notification_options)
146
- end
147
-
148
- test "should call pre/post_callback proc if specified" do
149
- post_callback_called = 0
150
- options = {
151
- webhook_url: "http://slack.webhook.url",
152
- username: "test",
153
- custom_hook: "hook",
154
- pre_callback: proc { |_opts, _notifier, backtrace, _message, message_opts|
155
- (message_opts[:attachments] = []) << {text: backtrace.join("\n").to_s, color: "danger"}
156
- },
157
- post_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts|
158
- post_callback_called = 1
159
- },
160
- additional_parameters: {
161
- icon_url: "icon"
162
- }
163
- }
164
-
165
- Slack::Notifier.any_instance.expects(:ping).with("",
166
- {icon_url: "icon",
167
- attachments: [{
168
- text: fake_backtrace.join("\n"),
169
- color: "danger"
170
- }]})
171
-
172
- slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
173
- slack_notifier.call(@exception)
174
- assert_equal(post_callback_called, 1)
175
- end
176
-
177
- private
178
-
179
- def fake_exception
180
- 5 / 0
181
- rescue => e
182
- e
183
- end
184
-
185
- def fake_exception_without_backtrace
186
- StandardError.new("my custom error")
187
- end
188
-
189
- def fake_backtrace
190
- [
191
- "backtrace line 1", "backtrace line 2", "backtrace line 3",
192
- "backtrace line 4", "backtrace line 5", "backtrace line 6"
193
- ]
194
- end
195
-
196
- def fake_cleaned_backtrace
197
- fake_backtrace[2..-1] # standard:disable Style/SlicingWithRange
198
- end
199
-
200
- def fake_notification(exception = @exception, notification_options = {},
201
- data_string = nil, expected_backtrace_lines = 10, additional_fields = [])
202
- exception_name = "*#{/^[aeiou]/i.match?(exception.class.to_s) ? "An" : "A"}* `#{exception.class}`"
203
- if notification_options[:env].nil?
204
- text = "#{exception_name} *occured in background*"
205
- else
206
- env = notification_options[:env]
207
-
208
- kontroller = env["action_controller.instance"]
209
- request = "#{env["REQUEST_METHOD"]} <#{env["REQUEST_URI"]}>"
210
-
211
- text = "#{exception_name} *occurred while* `#{request}`"
212
- text += " *was processed by* `#{kontroller.controller_name}##{kontroller.action_name}`" if kontroller
213
- end
214
-
215
- text += "\n"
216
-
217
- fields = [{title: "Exception", value: exception.message}]
218
- fields.push(title: "Hostname", value: "example.com")
219
- if exception.backtrace
220
- formatted_backtrace = "```#{fake_cleaned_backtrace.first(expected_backtrace_lines).join("\n")}```"
221
- fields.push(title: "Backtrace", value: formatted_backtrace)
222
- end
223
- fields.push(title: "Data", value: "```#{data_string}```") if data_string
224
- additional_fields.each { |f| fields.push(f) }
225
-
226
- {attachments: [color: "danger", text: text, fields: fields, mrkdwn_in: %w[text fields]]}
227
- end
228
- end
@@ -1,181 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "aws-sdk-sns"
5
-
6
- class SnsNotifierTest < ActiveSupport::TestCase
7
- def setup
8
- @exception = fake_exception
9
- @exception.stubs(:class).returns("MyException")
10
- @exception.stubs(:backtrace).returns(fake_backtrace)
11
- @exception.stubs(:message).returns("undefined method 'method=' for Empty")
12
- @options = {
13
- access_key_id: "my-access_key_id",
14
- secret_access_key: "my-secret_access_key",
15
- region: "us-east",
16
- topic_arn: "topicARN",
17
- sns_prefix: "[App Exception]"
18
- }
19
- Socket.stubs(:gethostname).returns("example.com")
20
- end
21
-
22
- # initialize
23
-
24
- test "should initialize aws notifier with received params" do
25
- Aws::SNS::Client.expects(:new).with(
26
- region: "us-east",
27
- access_key_id: "my-access_key_id",
28
- secret_access_key: "my-secret_access_key"
29
- )
30
-
31
- ExceptionNotifier::SnsNotifier.new(@options)
32
- end
33
-
34
- test "should raise an exception if region is not received" do
35
- @options[:region] = nil
36
-
37
- error = assert_raises ArgumentError do
38
- ExceptionNotifier::SnsNotifier.new(@options)
39
- end
40
- assert_equal "You must provide 'region' option", error.message
41
- end
42
-
43
- test "should raise an exception on publish if access_key_id is not received" do
44
- @options[:access_key_id] = nil
45
- error = assert_raises ArgumentError do
46
- ExceptionNotifier::SnsNotifier.new(@options)
47
- end
48
-
49
- assert_equal "You must provide 'access_key_id' option", error.message
50
- end
51
-
52
- test "should raise an exception on publish if secret_access_key is not received" do
53
- @options[:secret_access_key] = nil
54
- error = assert_raises ArgumentError do
55
- ExceptionNotifier::SnsNotifier.new(@options)
56
- end
57
-
58
- assert_equal "You must provide 'secret_access_key' option", error.message
59
- end
60
-
61
- # call
62
-
63
- test "should send a sns notification in background" do
64
- Aws::SNS::Client.any_instance.expects(:publish).with(
65
- topic_arn: "topicARN",
66
- message: "3 MyException occured in background\n" \
67
- "Exception: undefined method 'method=' for Empty\n" \
68
- "Hostname: example.com\n" \
69
- "Data: {}\n" \
70
- "Backtrace:\n#{fake_backtrace.join("\n")}\n",
71
- subject: "[App Exception] - 3 MyException occurred"
72
- )
73
-
74
- sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
75
- sns_notifier.call(@exception, accumulated_errors_count: 3)
76
- end
77
-
78
- test "should send a sns notification with controller#action information" do
79
- controller = mock("controller")
80
- controller.stubs(:action_name).returns("index")
81
- controller.stubs(:controller_name).returns("examples")
82
-
83
- Aws::SNS::Client.any_instance.expects(:publish).with(
84
- topic_arn: "topicARN",
85
- message: "A MyException occurred while GET </examples> " \
86
- "was processed by examples#index\n" \
87
- "Exception: undefined method 'method=' for Empty\n" \
88
- "Hostname: example.com\n" \
89
- "Data: {}\n" \
90
- "Backtrace:\n#{fake_backtrace.join("\n")}\n",
91
- subject: "[App Exception] - A MyException occurred"
92
- )
93
-
94
- sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
95
- sns_notifier.call(@exception,
96
- env: {
97
- "REQUEST_METHOD" => "GET",
98
- "REQUEST_URI" => "/examples",
99
- "action_controller.instance" => controller
100
- })
101
- end
102
-
103
- test 'should put data from env["exception_notifier.exception_data"] into text' do
104
- controller = mock("controller")
105
- controller.stubs(:action_name).returns("index")
106
- controller.stubs(:controller_name).returns("examples")
107
-
108
- # standard:disable Lint/LiteralInInterpolation
109
- Aws::SNS::Client.any_instance.expects(:publish).with(
110
- topic_arn: "topicARN",
111
- message: "A MyException occurred while GET </examples> " \
112
- "was processed by examples#index\n" \
113
- "Exception: undefined method 'method=' for Empty\n" \
114
- "Hostname: example.com\n" \
115
- "Data: #{{current_user: 12}}\n" \
116
- "Backtrace:\n#{fake_backtrace.join("\n")}\n",
117
- subject: "[App Exception] - A MyException occurred"
118
- )
119
- # standard:enable Lint/LiteralInInterpolation
120
- sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
121
- sns_notifier.call(@exception,
122
- env: {
123
- "REQUEST_METHOD" => "GET",
124
- "REQUEST_URI" => "/examples",
125
- "action_controller.instance" => controller,
126
- "exception_notifier.exception_data" => {current_user: 12}
127
- })
128
- end
129
-
130
- test "should put optional data into text" do
131
- controller = mock("controller")
132
- controller.stubs(:action_name).returns("index")
133
- controller.stubs(:controller_name).returns("examples")
134
-
135
- # standard:disable Lint/LiteralInInterpolation
136
- Aws::SNS::Client.any_instance.expects(:publish).with(
137
- topic_arn: "topicARN",
138
- message: "A MyException occurred while GET </examples> " \
139
- "was processed by examples#index\n" \
140
- "Exception: undefined method 'method=' for Empty\n" \
141
- "Hostname: example.com\n" \
142
- "Data: #{{current_user: 12}}\n" \
143
- "Backtrace:\n#{fake_backtrace.join("\n")}\n",
144
- subject: "[App Exception] - A MyException occurred"
145
- )
146
- # standard:enable Lint/LiteralInInterpolation
147
- sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
148
- sns_notifier.call(@exception,
149
- env: {
150
- "REQUEST_METHOD" => "GET",
151
- "REQUEST_URI" => "/examples",
152
- "action_controller.instance" => controller
153
- },
154
- data: {
155
- current_user: 12
156
- })
157
- end
158
-
159
- private
160
-
161
- def fake_exception
162
- 1 / 0
163
- rescue => e
164
- e
165
- end
166
-
167
- def fake_exception_without_backtrace
168
- StandardError.new("my custom error")
169
- end
170
-
171
- def fake_backtrace
172
- [
173
- "backtrace line 1",
174
- "backtrace line 2",
175
- "backtrace line 3",
176
- "backtrace line 4",
177
- "backtrace line 5",
178
- "backtrace line 6"
179
- ]
180
- end
181
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "httparty"
5
-
6
- class TeamsNotifierTest < ActiveSupport::TestCase
7
- test "should send notification if properly configured" do
8
- options = {
9
- webhook_url: "http://localhost:8000"
10
- }
11
- teams_notifier = ExceptionNotifier::TeamsNotifier.new
12
- teams_notifier.httparty = FakeHTTParty.new
13
-
14
- options = teams_notifier.call ArgumentError.new("foo"), options
15
-
16
- body = ActiveSupport::JSON.decode options[:body]
17
- assert body.key? "title"
18
- assert body.key? "sections"
19
-
20
- sections = body["sections"]
21
- header = sections[0]
22
-
23
- assert_equal 2, sections.size
24
- assert_equal "A *ArgumentError* occurred.", header["activityTitle"]
25
- assert_equal "foo", header["activitySubtitle"]
26
- end
27
-
28
- test "should send notification with create gitlab issue link if specified" do
29
- options = {
30
- webhook_url: "http://localhost:8000",
31
- git_url: "github.com/aschen"
32
- }
33
- teams_notifier = ExceptionNotifier::TeamsNotifier.new
34
- teams_notifier.httparty = FakeHTTParty.new
35
-
36
- options = teams_notifier.call ArgumentError.new("foo"), options
37
-
38
- body = ActiveSupport::JSON.decode options[:body]
39
-
40
- potential_action = body["potentialAction"]
41
- assert_equal 2, potential_action.size
42
- assert_equal "🦊 View in GitLab", potential_action[0]["name"]
43
- assert_equal "🦊 Create Issue in GitLab", potential_action[1]["name"]
44
- end
45
-
46
- test "should add other HTTParty options to params" do
47
- options = {
48
- webhook_url: "http://localhost:8000",
49
- username: "Test Bot",
50
- avatar: "http://site.com/icon.png",
51
- basic_auth: {
52
- username: "clara",
53
- password: "password"
54
- }
55
- }
56
- teams_notifier = ExceptionNotifier::TeamsNotifier.new
57
- teams_notifier.httparty = FakeHTTParty.new
58
-
59
- options = teams_notifier.call ArgumentError.new("foo"), options
60
-
61
- assert options.key? :basic_auth
62
- assert "clara", options[:basic_auth][:username]
63
- assert "password", options[:basic_auth][:password]
64
- end
65
-
66
- test "should use 'A' for exceptions count if :accumulated_errors_count option is nil" do
67
- teams_notifier = ExceptionNotifier::TeamsNotifier.new
68
- exception = ArgumentError.new("foo")
69
- teams_notifier.instance_variable_set(:@exception, exception)
70
- teams_notifier.instance_variable_set(:@options, {})
71
-
72
- message_text = teams_notifier.send(:message_text)
73
- header = message_text["sections"][0]
74
- assert_equal "A *ArgumentError* occurred.", header["activityTitle"]
75
- end
76
-
77
- test "should use direct errors count if :accumulated_errors_count option is 5" do
78
- teams_notifier = ExceptionNotifier::TeamsNotifier.new
79
- exception = ArgumentError.new("foo")
80
- teams_notifier.instance_variable_set(:@exception, exception)
81
- teams_notifier.instance_variable_set(:@options, accumulated_errors_count: 5)
82
- message_text = teams_notifier.send(:message_text)
83
- header = message_text["sections"][0]
84
- assert_equal "5 *ArgumentError* occurred.", header["activityTitle"]
85
- end
86
- end
87
-
88
- class FakeHTTParty
89
- def post(_url, options)
90
- options
91
- end
92
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "httparty"
5
-
6
- class WebhookNotifierTest < ActiveSupport::TestCase
7
- test "should send webhook notification if properly configured" do
8
- ExceptionNotifier::WebhookNotifier.stubs(:new).returns(Object.new)
9
- webhook = ExceptionNotifier::WebhookNotifier.new(url: "http://localhost:8000")
10
- webhook.stubs(:call).returns(fake_response)
11
- response = webhook.call(fake_exception)
12
-
13
- refute_nil response
14
- assert_equal response[:status], 200
15
- assert_equal response[:body][:exception][:error_class], "ZeroDivisionError"
16
- assert_includes response[:body][:exception][:message], "divided by 0"
17
- assert_includes response[:body][:exception][:backtrace], "/exception_notification/test/webhook_notifier_test.rb:48"
18
-
19
- assert response[:body][:request][:cookies].key?(:cookie_item1)
20
- assert_equal response[:body][:request][:url], "http://example.com/example"
21
- assert_equal response[:body][:request][:ip_address], "192.168.1.1"
22
- assert response[:body][:request][:environment].key?(:env_item1)
23
- assert_equal response[:body][:request][:controller], "#<ControllerName:0x007f9642a04d00>"
24
- assert response[:body][:request][:session].key?(:session_item1)
25
- assert response[:body][:request][:parameters].key?(:controller)
26
- assert response[:body][:data][:extra_data].key?(:data_item1)
27
- end
28
-
29
- test "should send webhook notification with correct params data" do
30
- url = "http://localhost:8000"
31
- fake_exception.stubs(:backtrace).returns("the backtrace")
32
- webhook = ExceptionNotifier::WebhookNotifier.new(url: url)
33
-
34
- HTTParty.expects(:send).with(:post, url, fake_params)
35
-
36
- webhook.call(fake_exception)
37
- end
38
-
39
- test "should call pre/post_callback if specified" do
40
- HTTParty.expects(:send).returns(fake_response)
41
- webhook = ExceptionNotifier::WebhookNotifier.new(url: "http://localhost:8000")
42
- webhook.call(fake_exception)
43
- end
44
-
45
- private
46
-
47
- def fake_response
48
- {
49
- status: 200,
50
- body: {
51
- exception: {
52
- error_class: "ZeroDivisionError",
53
- message: "divided by 0",
54
- backtrace: "/exception_notification/test/webhook_notifier_test.rb:48:in `/"
55
- },
56
- data: {
57
- extra_data: {data_item1: "datavalue1", data_item2: "datavalue2"}
58
- },
59
- request: {
60
- cookies: {cookie_item1: "cookieitemvalue1", cookie_item2: "cookieitemvalue2"},
61
- url: "http://example.com/example",
62
- ip_address: "192.168.1.1",
63
- environment: {env_item1: "envitem1", env_item2: "envitem2"},
64
- controller: "#<ControllerName:0x007f9642a04d00>",
65
- session: {session_item1: "sessionitem1", session_item2: "sessionitem2"},
66
- parameters: {action: "index", controller: "projects"}
67
- }
68
- }
69
- }
70
- end
71
-
72
- def fake_params
73
- params = {
74
- body: {
75
- server: Socket.gethostname,
76
- process: $PROCESS_ID,
77
- exception: {
78
- error_class: "ZeroDivisionError",
79
- message: "divided by 0".inspect,
80
- backtrace: "the backtrace"
81
- },
82
- data: {}
83
- }
84
- }
85
-
86
- params[:body][:rails_root] = Rails.root if defined?(::Rails) && Rails.respond_to?(:root)
87
-
88
- params
89
- end
90
-
91
- def fake_exception
92
- @fake_exception ||= begin
93
- 5 / 0
94
- rescue => e
95
- e
96
- end
97
- end
98
- end