This repository has been archived by the owner on Nov 11, 2017. It is now read-only.
/
controller_test.rb
389 lines (339 loc) · 12.8 KB
/
controller_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
require File.dirname(__FILE__) + '/helper'
def expect_session_data_for(controller)
# NOTE: setting expectations on the controller is not a good idea here,
# because the controller is the unit we're trying to test. However, as all
# exception-related behavior is mixed into the controller itsef, we have
# little choice. Delegating notifier methods from the controller to a
# Sender could make this easier to maintain and test.
@controller.expects(:send_to_hoptoad).with do |params|
assert params.respond_to?(:to_hash), "The notifier needs a hash"
notice = params[:notice]
assert_not_nil notice, "No notice passed to the notifier"
assert_not_nil notice[:session][:key], "No session key was set"
assert_not_nil notice[:session][:data], "No session data was set"
true
end
@controller.stubs(:rescue_action_in_public_without_hoptoad)
end
def should_notify_normally
should "have inserted its methods into the controller" do
assert @controller.respond_to?(:notify_hoptoad)
end
should "prevent raises and send the error to hoptoad" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise")
end
end
should "allow a non-raising action to complete" do
assert_nothing_raised do
request("do_not_raise")
end
end
should "allow manual sending of exceptions" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad).never
assert_nothing_raised do
request("manual_notify")
end
end
should "disable manual sending of exceptions in a non-public (development or test) environment" do
@controller.stubs(:public_environment?).returns(false)
@controller.expects(:send_to_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad).never
assert_nothing_raised do
request("manual_notify")
end
end
should "send even ignored exceptions if told manually" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad).never
assert_nothing_raised do
request("manual_notify_ignored")
end
end
should "ignore default exceptions" do
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise_ignored")
end
end
should "convert non-serializable data to strings" do
klass = Class.new
File.open(__FILE__) do |file|
data = { :ghi => "789", :klass => klass, :file => file }
assert_equal({ :ghi => "789", :file => file.to_s, :klass => klass.to_s },
@controller.send(:clean_non_serializable_data, data))
end
end
should "apply all params, environment and technical filters" do
params_hash = {:abc => 123}
environment_hash = {:def => 456}
backtrace_data = :backtrace_data
raw_notice = {:request => {:params => params_hash},
:environment => environment_hash,
:backtrace => backtrace_data}
processed_notice = {:backtrace => :backtrace_data,
:request => {:params => :params_data},
:environment => :environment_data}
@controller.expects(:clean_hoptoad_backtrace).with(backtrace_data).returns(:backtrace_data)
@controller.expects(:clean_hoptoad_params).with(params_hash).returns(:params_data)
@controller.expects(:clean_hoptoad_environment).with(environment_hash).returns(:environment_data)
@controller.expects(:clean_non_serializable_data).with(processed_notice).returns(:serializable_data)
assert_equal(:serializable_data, @controller.send(:clean_notice, raw_notice))
end
should "send session data to hoptoad when the session has @data" do
expect_session_data_for(@controller)
@request = ActionController::TestRequest.new
@request.action = 'do_raise'
@request.session.instance_variable_set("@data", { :message => 'Hello' })
@response = ActionController::TestResponse.new
@controller.process(@request, @response)
end
should "send session data to hoptoad when the session responds to to_hash" do
expect_session_data_for(@controller)
@request = ActionController::TestRequest.new
@request.action = 'do_raise'
@request.session.stubs(:to_hash).returns(:message => 'Hello')
@response = ActionController::TestResponse.new
@controller.process(@request, @response)
end
end
def should_auto_include_catcher
should "auto-include for ApplicationController" do
assert ApplicationController.include?(HoptoadNotifier::Catcher)
end
end
class ControllerTest < Test::Unit::TestCase
context "Hoptoad inclusion" do
should "be able to occur even outside Rails controllers" do
assert_nothing_raised do
class MyHoptoad
include HoptoadNotifier::Catcher
end
end
my = MyHoptoad.new
assert my.respond_to?(:notify_hoptoad)
end
context "when auto-included" do
setup do
class ::ApplicationController < ActionController::Base
end
class ::AutoIncludeController < ::ApplicationController
include TestMethods
def rescue_action e
rescue_action_in_public e
end
end
HoptoadNotifier.ignore_only = HoptoadNotifier::IGNORE_DEFAULT
@controller = ::AutoIncludeController.new
@controller.stubs(:public_environment?).returns(true)
@controller.stubs(:send_to_hoptoad)
HoptoadNotifier.configure do |config|
config.api_key = "1234567890abcdef"
end
end
context "when included through the configure block" do
should_auto_include_catcher
should_notify_normally
end
context "when included both through configure and normally" do
setup do
class ::AutoIncludeController < ::ApplicationController
include HoptoadNotifier::Catcher
end
end
should_auto_include_catcher
should_notify_normally
end
end
end
context "when the logger is overridden for an action" do
setup do
class ::IgnoreActionController < ::ActionController::Base
include TestMethods
include HoptoadNotifier::Catcher
def rescue_action e
rescue_action_in_public e
end
def logger
super unless action_name == "do_raise"
end
end
::ActionController::Base.logger = Logger.new(STDOUT)
@controller = ::IgnoreActionController.new
@controller.stubs(:public_environment?).returns(true)
@controller.stubs(:rescue_action_in_public_without_hoptoad)
HoptoadNotifier.stubs(:environment_info)
# stubbing out Net::HTTP as well
@body = 'body'
@http = stub(:post => @response, :read_timeout= => nil, :open_timeout= => nil, :use_ssl= => nil)
Net::HTTP.stubs(:new).returns(@http)
HoptoadNotifier.port = nil
HoptoadNotifier.host = nil
HoptoadNotifier.proxy_host = nil
end
should "work when action is called and request works" do
@response = stub(:body => @body, :class => Net::HTTPSuccess)
assert_nothing_raised do
request("do_raise")
end
end
should "work when action is called and request doesn't work" do
@response = stub(:body => @body, :class => Net::HTTPError)
assert_nothing_raised do
request("do_raise")
end
end
should "work when action is called and hoptoad times out" do
@http.stubs(:post).raises(TimeoutError)
assert_nothing_raised do
request("do_raise")
end
end
end
context "The hoptoad test controller" do
setup do
@controller = ::HoptoadController.new
class ::HoptoadController
def rescue_action e
raise e
end
end
end
context "with no notifier catcher" do
should "not prevent raises" do
assert_raises RuntimeError do
request("do_raise")
end
end
should "allow a non-raising action to complete" do
assert_nothing_raised do
request("do_not_raise")
end
end
end
context "with the notifier installed" do
setup do
class ::HoptoadController
include HoptoadNotifier::Catcher
def rescue_action e
rescue_action_in_public e
end
end
HoptoadNotifier.ignore_only = HoptoadNotifier::IGNORE_DEFAULT
@controller.stubs(:public_environment?).returns(true)
@controller.stubs(:send_to_hoptoad)
end
should_notify_normally
context "and configured to ignore_by_filter" do
setup do
HoptoadNotifier.configure do |config|
config.ignore_by_filter do |exception_data|
if exception_data[:error_class] == "RuntimeError"
true if exception_data[:request][:params]['blah'] == 'skip'
end
end
end
end
should "ignore exceptions based on param data" do
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise", "get", nil, :blah => 'skip')
end
end
end
context "and configured to ignore additional exceptions" do
setup do
HoptoadNotifier.ignore << ActiveRecord::StatementInvalid
end
should "still ignore default exceptions" do
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise_ignored")
end
end
should "ignore specified exceptions" do
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise_not_ignored")
end
end
should "not ignore unspecified, non-default exceptions" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise")
end
end
end
context "and configured to ignore only certain exceptions" do
setup do
HoptoadNotifier.ignore_only = [ActiveRecord::StatementInvalid]
end
should "no longer ignore default exceptions" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise_ignored")
end
end
should "ignore specified exceptions" do
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise_not_ignored")
end
end
should "not ignore unspecified, non-default exceptions" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise")
end
end
end
context "and configured to ignore certain user agents" do
setup do
HoptoadNotifier.ignore_user_agent << /Ignored/
HoptoadNotifier.ignore_user_agent << 'IgnoredUserAgent'
end
should "ignore exceptions when user agent is being ignored" do
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise", :get, 'IgnoredUserAgent')
end
end
should "ignore exceptions when user agent is being ignored (regexp)" do
HoptoadNotifier.ignore_user_agent_only = [/Ignored/]
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise", :get, 'IgnoredUserAgent')
end
end
should "ignore exceptions when user agent is being ignored (string)" do
HoptoadNotifier.ignore_user_agent_only = ['IgnoredUserAgent']
@controller.expects(:notify_hoptoad).never
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise", :get, 'IgnoredUserAgent')
end
end
should "not ignore exceptions when user agent is not being ignored" do
@controller.expects(:notify_hoptoad)
@controller.expects(:rescue_action_in_public_without_hoptoad)
assert_nothing_raised do
request("do_raise")
end
end
end
end
end
end