hatless-hoptoad_notifier 2.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +149 -0
  2. data/INSTALL +25 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +382 -0
  5. data/Rakefile +217 -0
  6. data/SUPPORTED_RAILS_VERSIONS +9 -0
  7. data/TESTING.rdoc +8 -0
  8. data/generators/hoptoad/hoptoad_generator.rb +54 -0
  9. data/generators/hoptoad/lib/insert_commands.rb +34 -0
  10. data/generators/hoptoad/lib/rake_commands.rb +24 -0
  11. data/generators/hoptoad/templates/capistrano_hook.rb +6 -0
  12. data/generators/hoptoad/templates/hoptoad_notifier_tasks.rake +25 -0
  13. data/generators/hoptoad/templates/initializer.rb +6 -0
  14. data/lib/hoptoad_notifier/backtrace.rb +99 -0
  15. data/lib/hoptoad_notifier/capistrano.rb +20 -0
  16. data/lib/hoptoad_notifier/configuration.rb +232 -0
  17. data/lib/hoptoad_notifier/notice.rb +318 -0
  18. data/lib/hoptoad_notifier/rack.rb +40 -0
  19. data/lib/hoptoad_notifier/rails/action_controller_catcher.rb +29 -0
  20. data/lib/hoptoad_notifier/rails/controller_methods.rb +58 -0
  21. data/lib/hoptoad_notifier/rails/error_lookup.rb +33 -0
  22. data/lib/hoptoad_notifier/rails.rb +37 -0
  23. data/lib/hoptoad_notifier/rails3_tasks.rb +90 -0
  24. data/lib/hoptoad_notifier/railtie.rb +23 -0
  25. data/lib/hoptoad_notifier/sender.rb +63 -0
  26. data/lib/hoptoad_notifier/tasks.rb +97 -0
  27. data/lib/hoptoad_notifier/version.rb +3 -0
  28. data/lib/hoptoad_notifier.rb +148 -0
  29. data/lib/hoptoad_tasks.rb +40 -0
  30. data/lib/rails/generators/hoptoad/hoptoad_generator.rb +64 -0
  31. data/lib/templates/rescue.erb +91 -0
  32. data/rails/init.rb +1 -0
  33. data/script/integration_test.rb +38 -0
  34. data/test/backtrace_test.rb +118 -0
  35. data/test/catcher_test.rb +324 -0
  36. data/test/configuration_test.rb +208 -0
  37. data/test/helper.rb +239 -0
  38. data/test/hoptoad_tasks_test.rb +138 -0
  39. data/test/logger_test.rb +85 -0
  40. data/test/notice_test.rb +443 -0
  41. data/test/notifier_test.rb +222 -0
  42. data/test/rack_test.rb +58 -0
  43. data/test/rails_initializer_test.rb +36 -0
  44. data/test/sender_test.rb +123 -0
  45. metadata +204 -0
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'hoptoad_notifier/rails'
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'logger'
4
+ require 'fileutils'
5
+
6
+ RAILS_ENV = "production"
7
+ RAILS_ROOT = FileUtils.pwd
8
+ RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
9
+
10
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ require 'hoptoad_notifier'
12
+ require 'rails/init'
13
+
14
+ fail "Please supply an API Key as the first argument" if ARGV.empty?
15
+
16
+ host = ARGV[1]
17
+ host ||= "hoptoadapp.com"
18
+
19
+ secure = (ARGV[2] == "secure")
20
+
21
+ exception = begin
22
+ raise "Testing hoptoad notifier with secure = #{secure}. If you can see this, it works."
23
+ rescue => foo
24
+ foo
25
+ end
26
+
27
+ HoptoadNotifier.configure do |config|
28
+ config.secure = secure
29
+ config.host = host
30
+ config.api_key = ARGV.first
31
+ end
32
+ puts "Configuration:"
33
+ HoptoadNotifier.configuration.to_hash.each do |key, value|
34
+ puts sprintf("%25s: %s", key.to_s, value.inspect.slice(0, 55))
35
+ end
36
+ puts "Sending #{secure ? "" : "in"}secure notification to project with key #{ARGV.first}"
37
+ HoptoadNotifier.notify(exception)
38
+
@@ -0,0 +1,118 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class BacktraceTest < Test::Unit::TestCase
4
+
5
+ should "parse a backtrace into lines" do
6
+ array = [
7
+ "app/models/user.rb:13:in `magic'",
8
+ "app/controllers/users_controller.rb:8:in `index'"
9
+ ]
10
+
11
+ backtrace = HoptoadNotifier::Backtrace.parse(array)
12
+
13
+ line = backtrace.lines.first
14
+ assert_equal '13', line.number
15
+ assert_equal 'app/models/user.rb', line.file
16
+ assert_equal 'magic', line.method
17
+
18
+ line = backtrace.lines.last
19
+ assert_equal '8', line.number
20
+ assert_equal 'app/controllers/users_controller.rb', line.file
21
+ assert_equal 'index', line.method
22
+ end
23
+
24
+ should "be equal with equal lines" do
25
+ one = build_backtrace_array
26
+ two = one.dup
27
+ assert_equal one, two
28
+
29
+ assert_equal HoptoadNotifier::Backtrace.parse(one), HoptoadNotifier::Backtrace.parse(two)
30
+ end
31
+
32
+ should "parse massive one-line exceptions into multiple lines" do
33
+ original_backtrace = HoptoadNotifier::Backtrace.
34
+ parse(["one:1:in `one'\n two:2:in `two'\n three:3:in `three`"])
35
+ expected_backtrace = HoptoadNotifier::Backtrace.
36
+ parse(["one:1:in `one'", "two:2:in `two'", "three:3:in `three`"])
37
+
38
+ assert_equal expected_backtrace, original_backtrace
39
+ end
40
+
41
+ context "with a project root" do
42
+ setup do
43
+ @project_root = '/some/path'
44
+ HoptoadNotifier.configure {|config| config.project_root = @project_root }
45
+ end
46
+
47
+ teardown do
48
+ reset_config
49
+ end
50
+
51
+ should "filter out the project root" do
52
+ backtrace_with_root = HoptoadNotifier::Backtrace.parse(
53
+ ["#{@project_root}/app/models/user.rb:7:in `latest'",
54
+ "#{@project_root}/app/controllers/users_controller.rb:13:in `index'",
55
+ "/lib/something.rb:41:in `open'"],
56
+ :filters => default_filters)
57
+ backtrace_without_root = HoptoadNotifier::Backtrace.parse(
58
+ ["[PROJECT_ROOT]/app/models/user.rb:7:in `latest'",
59
+ "[PROJECT_ROOT]/app/controllers/users_controller.rb:13:in `index'",
60
+ "/lib/something.rb:41:in `open'"])
61
+
62
+ assert_equal backtrace_without_root, backtrace_with_root
63
+ end
64
+ end
65
+
66
+ context "with a blank project root" do
67
+ setup do
68
+ HoptoadNotifier.configure {|config| config.project_root = '' }
69
+ end
70
+
71
+ teardown do
72
+ reset_config
73
+ end
74
+
75
+ should "not filter line numbers with respect to any project root" do
76
+ backtrace = ["/app/models/user.rb:7:in `latest'",
77
+ "/app/controllers/users_controller.rb:13:in `index'",
78
+ "/lib/something.rb:41:in `open'"]
79
+
80
+ backtrace_with_root =
81
+ HoptoadNotifier::Backtrace.parse(backtrace, :filters => default_filters)
82
+
83
+ backtrace_without_root =
84
+ HoptoadNotifier::Backtrace.parse(backtrace)
85
+
86
+ assert_equal backtrace_without_root, backtrace_with_root
87
+ end
88
+ end
89
+
90
+ should "remove notifier trace" do
91
+ inside_notifier = ['lib/hoptoad_notifier.rb:13:in `voodoo`']
92
+ outside_notifier = ['users_controller:8:in `index`']
93
+
94
+ without_inside = HoptoadNotifier::Backtrace.parse(outside_notifier)
95
+ with_inside = HoptoadNotifier::Backtrace.parse(inside_notifier + outside_notifier,
96
+ :filters => default_filters)
97
+
98
+ assert_equal without_inside, with_inside
99
+ end
100
+
101
+ should "run filters on the backtrace" do
102
+ filters = [lambda { |line| line.sub('foo', 'bar') }]
103
+ input = HoptoadNotifier::Backtrace.parse(["foo:13:in `one'", "baz:14:in `two'"],
104
+ :filters => filters)
105
+ expected = HoptoadNotifier::Backtrace.parse(["bar:13:in `one'", "baz:14:in `two'"])
106
+ assert_equal expected, input
107
+ end
108
+
109
+ def build_backtrace_array
110
+ ["app/models/user.rb:13:in `magic'",
111
+ "app/controllers/users_controller.rb:8:in `index'"]
112
+ end
113
+
114
+ def default_filters
115
+ HoptoadNotifier::Configuration::DEFAULT_BACKTRACE_FILTERS
116
+ end
117
+
118
+ end
@@ -0,0 +1,324 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class ActionControllerCatcherTest < Test::Unit::TestCase
4
+
5
+ include DefinesConstants
6
+
7
+ def setup
8
+ super
9
+ reset_config
10
+ HoptoadNotifier.sender = CollectingSender.new
11
+ define_constant('RAILS_ROOT', '/path/to/rails/root')
12
+ end
13
+
14
+ def ignore(exception_class)
15
+ HoptoadNotifier.configuration.ignore << exception_class
16
+ end
17
+
18
+ def build_controller_class(&definition)
19
+ returning Class.new(ActionController::Base) do |klass|
20
+ klass.__send__(:include, HoptoadNotifier::Rails::ActionControllerCatcher)
21
+ klass.class_eval(&definition) if definition
22
+ define_constant('HoptoadTestController', klass)
23
+ end
24
+ end
25
+
26
+ def assert_sent_hash(hash, xpath)
27
+ hash.each do |key, value|
28
+ element_xpath = "#{xpath}/var[@key = '#{key}']"
29
+ if value.respond_to?(:to_hash)
30
+ assert_sent_hash value.to_hash, element_xpath
31
+ else
32
+ assert_sent_element value, element_xpath
33
+ end
34
+ end
35
+ end
36
+
37
+ def assert_sent_element(value, xpath)
38
+ assert_valid_node last_sent_notice_document, xpath, stringify_array_elements(value).to_s
39
+ end
40
+
41
+ def stringify_array_elements(data)
42
+ if data.respond_to?(:to_ary)
43
+ data.collect do |value|
44
+ stringify_array_elements(value)
45
+ end
46
+ else
47
+ data.to_s
48
+ end
49
+ end
50
+
51
+ def assert_sent_request_info_for(request)
52
+ params = request.parameters.to_hash
53
+ assert_sent_hash params, '/notice/request/params'
54
+ assert_sent_element params['controller'], '/notice/request/component'
55
+ assert_sent_element params['action'], '/notice/request/action'
56
+ assert_sent_element url_from_request(request), '/notice/request/url'
57
+ assert_sent_hash request.env, '/notice/request/cgi-data'
58
+ end
59
+
60
+ def url_from_request(request)
61
+ url = "#{request.protocol}#{request.host}"
62
+
63
+ unless [80, 443].include?(request.port)
64
+ url << ":#{request.port}"
65
+ end
66
+
67
+ url << request.request_uri
68
+ url
69
+ end
70
+
71
+ def sender
72
+ HoptoadNotifier.sender
73
+ end
74
+
75
+ def last_sent_notice_xml
76
+ sender.collected.last
77
+ end
78
+
79
+ def last_sent_notice_document
80
+ assert_not_nil xml = last_sent_notice_xml, "No xml was sent"
81
+ Nokogiri::XML.parse(xml)
82
+ end
83
+
84
+ def process_action(opts = {}, &action)
85
+ opts[:request] ||= ActionController::TestRequest.new
86
+ opts[:response] ||= ActionController::TestResponse.new
87
+ klass = build_controller_class do
88
+ cattr_accessor :local
89
+ define_method(:index, &action)
90
+ def local_request?
91
+ local
92
+ end
93
+ end
94
+ if opts[:filters]
95
+ klass.filter_parameter_logging *opts[:filters]
96
+ end
97
+ if opts[:user_agent]
98
+ if opts[:request].respond_to?(:user_agent=)
99
+ opts[:request].user_agent = opts[:user_agent]
100
+ else
101
+ opts[:request].env["HTTP_USER_AGENT"] = opts[:user_agent]
102
+ end
103
+ end
104
+ if opts[:port]
105
+ opts[:request].port = opts[:port]
106
+ end
107
+ klass.consider_all_requests_local = opts[:all_local]
108
+ klass.local = opts[:local]
109
+ controller = klass.new
110
+ controller.stubs(:rescue_action_in_public_without_hoptoad)
111
+ opts[:request].query_parameters = opts[:request].query_parameters.merge(opts[:params] || {})
112
+ opts[:request].session = ActionController::TestSession.new(opts[:session] || {})
113
+ controller.process(opts[:request], opts[:response])
114
+ controller
115
+ end
116
+
117
+ def process_action_with_manual_notification(args = {})
118
+ process_action(args) do
119
+ notify_hoptoad(:error_message => 'fail')
120
+ # Rails will raise a template error if we don't render something
121
+ render :nothing => true
122
+ end
123
+ end
124
+
125
+ def process_action_with_automatic_notification(args = {})
126
+ process_action(args) { raise "Hello" }
127
+ end
128
+
129
+ should "deliver notices from exceptions raised in public requests" do
130
+ process_action_with_automatic_notification
131
+ assert_caught_and_sent
132
+ end
133
+
134
+ should "not deliver notices from exceptions in local requests" do
135
+ process_action_with_automatic_notification(:local => true)
136
+ assert_caught_and_not_sent
137
+ end
138
+
139
+ should "not deliver notices from exceptions when all requests are local" do
140
+ process_action_with_automatic_notification(:all_local => true)
141
+ assert_caught_and_not_sent
142
+ end
143
+
144
+ should "not deliver notices from actions that don't raise" do
145
+ controller = process_action { render :text => 'Hello' }
146
+ assert_caught_and_not_sent
147
+ assert_equal 'Hello', controller.response.body
148
+ end
149
+
150
+ should "not deliver ignored exceptions raised by actions" do
151
+ ignore(RuntimeError)
152
+ process_action_with_automatic_notification
153
+ assert_caught_and_not_sent
154
+ end
155
+
156
+ should "deliver ignored exception raised manually" do
157
+ ignore(RuntimeError)
158
+ process_action_with_manual_notification
159
+ assert_caught_and_sent
160
+ end
161
+
162
+ should "deliver manually sent notices in public requests" do
163
+ process_action_with_manual_notification
164
+ assert_caught_and_sent
165
+ end
166
+
167
+ should "not deliver manually sent notices in local requests" do
168
+ process_action_with_manual_notification(:local => true)
169
+ assert_caught_and_not_sent
170
+ end
171
+
172
+ should "not deliver manually sent notices when all requests are local" do
173
+ process_action_with_manual_notification(:all_local => true)
174
+ assert_caught_and_not_sent
175
+ end
176
+
177
+ should "continue with default behavior after delivering an exception" do
178
+ controller = process_action_with_automatic_notification(:public => true)
179
+ # TODO: can we test this without stubbing?
180
+ assert_received(controller, :rescue_action_in_public_without_hoptoad)
181
+ end
182
+
183
+ should "not create actions from Hoptoad methods" do
184
+ controller = build_controller_class.new
185
+ assert_equal [], HoptoadNotifier::Rails::ActionControllerCatcher.instance_methods
186
+ end
187
+
188
+ should "ignore exceptions when user agent is being ignored by regular expression" do
189
+ HoptoadNotifier.configuration.ignore_user_agent_only = [/Ignored/]
190
+ process_action_with_automatic_notification(:user_agent => 'ShouldBeIgnored')
191
+ assert_caught_and_not_sent
192
+ end
193
+
194
+ should "ignore exceptions when user agent is being ignored by string" do
195
+ HoptoadNotifier.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
196
+ process_action_with_automatic_notification(:user_agent => 'IgnoredUserAgent')
197
+ assert_caught_and_not_sent
198
+ end
199
+
200
+ should "not ignore exceptions when user agent is not being ignored" do
201
+ HoptoadNotifier.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
202
+ process_action_with_automatic_notification(:user_agent => 'NonIgnoredAgent')
203
+ assert_caught_and_sent
204
+ end
205
+
206
+ should "send session data for manual notifications" do
207
+ data = { 'one' => 'two' }
208
+ process_action_with_manual_notification(:session => data)
209
+ assert_sent_hash data, "/notice/request/session"
210
+ end
211
+
212
+ should "send session data for automatic notification" do
213
+ data = { 'one' => 'two' }
214
+ process_action_with_automatic_notification(:session => data)
215
+ assert_sent_hash data, "/notice/request/session"
216
+ end
217
+
218
+ should "send request data for manual notification" do
219
+ params = { 'controller' => "hoptoad_test", 'action' => "index" }
220
+ controller = process_action_with_manual_notification(:params => params)
221
+ assert_sent_request_info_for controller.request
222
+ end
223
+
224
+ should "send request data for manual notification with non-standard port" do
225
+ params = { 'controller' => "hoptoad_test", 'action' => "index" }
226
+ controller = process_action_with_manual_notification(:params => params, :port => 81)
227
+ assert_sent_request_info_for controller.request
228
+ end
229
+
230
+ should "send request data for automatic notification" do
231
+ params = { 'controller' => "hoptoad_test", 'action' => "index" }
232
+ controller = process_action_with_automatic_notification(:params => params)
233
+ assert_sent_request_info_for controller.request
234
+ end
235
+
236
+ should "send request data for automatic notification with non-standard port" do
237
+ params = { 'controller' => "hoptoad_test", 'action' => "index" }
238
+ controller = process_action_with_automatic_notification(:params => params, :port => 81)
239
+ assert_sent_request_info_for controller.request
240
+ end
241
+
242
+ should "use standard rails logging filters on params and env" do
243
+ filtered_params = { "abc" => "123",
244
+ "def" => "456",
245
+ "ghi" => "[FILTERED]" }
246
+ ENV['ghi'] = 'abc'
247
+ filtered_env = { 'ghi' => '[FILTERED]' }
248
+ filtered_cgi = { 'REQUEST_METHOD' => '[FILTERED]' }
249
+
250
+ process_action_with_automatic_notification(:filters => [:ghi, :request_method],
251
+ :params => { "abc" => "123",
252
+ "def" => "456",
253
+ "ghi" => "789" })
254
+ assert_sent_hash filtered_params, '/notice/request/params'
255
+ assert_sent_hash filtered_cgi, '/notice/request/cgi-data'
256
+ end
257
+
258
+ context "for a local error with development lookup enabled" do
259
+ setup do
260
+ HoptoadNotifier.configuration.development_lookup = true
261
+ HoptoadNotifier.stubs(:build_lookup_hash_for).returns({ :awesome => 2 })
262
+
263
+ @controller = process_action_with_automatic_notification(:local => true)
264
+ @response = @controller.response
265
+ end
266
+
267
+ should "append custom CSS and JS to response body for a local error" do
268
+ assert_match /text\/css/, @response.body
269
+ assert_match /text\/javascript/, @response.body
270
+ end
271
+
272
+ should "contain host, API key and notice JSON" do
273
+ assert_match HoptoadNotifier.configuration.host.to_json, @response.body
274
+ assert_match HoptoadNotifier.configuration.api_key.to_json, @response.body
275
+ assert_match ({ :awesome => 2 }).to_json, @response.body
276
+ end
277
+ end
278
+
279
+ context "for a local error with development lookup disabled" do
280
+ setup do
281
+ HoptoadNotifier.configuration.development_lookup = false
282
+
283
+ @controller = process_action_with_automatic_notification(:local => true)
284
+ @response = @controller.response
285
+ end
286
+
287
+ should "not append custom CSS and JS to response for a local error" do
288
+ assert_no_match /text\/css/, @response.body
289
+ assert_no_match /text\/javascript/, @response.body
290
+ end
291
+ end
292
+
293
+ should "call session.to_hash if available" do
294
+ hash_data = {:key => :value}
295
+
296
+ session = ActionController::TestSession.new
297
+ ActionController::TestSession.stubs(:new).returns(session)
298
+ session.stubs(:to_hash).returns(hash_data)
299
+
300
+ process_action_with_automatic_notification
301
+ assert_received(session, :to_hash)
302
+ assert_received(session, :data) { |expect| expect.never }
303
+ assert_caught_and_sent
304
+ end
305
+
306
+ should "call session.data if session.to_hash is undefined" do
307
+ hash_data = {:key => :value}
308
+
309
+ session = ActionController::TestSession.new
310
+ ActionController::TestSession.stubs(:new).returns(session)
311
+ session.stubs(:data).returns(hash_data)
312
+ if session.respond_to?(:to_hash)
313
+ class << session
314
+ undef to_hash
315
+ end
316
+ end
317
+
318
+ process_action_with_automatic_notification
319
+ assert_received(session, :to_hash) { |expect| expect.never }
320
+ assert_received(session, :data) { |expect| expect.at_least_once }
321
+ assert_caught_and_sent
322
+ end
323
+
324
+ end
@@ -0,0 +1,208 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class ConfigurationTest < Test::Unit::TestCase
4
+
5
+ include DefinesConstants
6
+
7
+ should "provide default values" do
8
+ assert_config_default :proxy_host, nil
9
+ assert_config_default :proxy_port, nil
10
+ assert_config_default :proxy_user, nil
11
+ assert_config_default :proxy_pass, nil
12
+ assert_config_default :project_root, nil
13
+ assert_config_default :environment_name, nil
14
+ assert_config_default :logger, nil
15
+ assert_config_default :notifier_version, HoptoadNotifier::VERSION
16
+ assert_config_default :notifier_name, 'Hoptoad Notifier'
17
+ assert_config_default :notifier_url, 'http://hoptoadapp.com'
18
+ assert_config_default :secure, false
19
+ assert_config_default :host, 'hoptoadapp.com'
20
+ assert_config_default :http_open_timeout, 2
21
+ assert_config_default :http_read_timeout, 5
22
+ assert_config_default :ignore_by_filters, []
23
+ assert_config_default :ignore_user_agent, []
24
+ assert_config_default :params_filters,
25
+ HoptoadNotifier::Configuration::DEFAULT_PARAMS_FILTERS
26
+ assert_config_default :backtrace_filters,
27
+ HoptoadNotifier::Configuration::DEFAULT_BACKTRACE_FILTERS
28
+ assert_config_default :ignore,
29
+ HoptoadNotifier::Configuration::IGNORE_DEFAULT
30
+ assert_config_default :development_lookup, true
31
+ assert_config_default :framework, 'Standalone'
32
+ end
33
+
34
+ should "provide default values for secure connections" do
35
+ config = HoptoadNotifier::Configuration.new
36
+ config.secure = true
37
+ assert_equal 443, config.port
38
+ assert_equal 'https', config.protocol
39
+ end
40
+
41
+ should "provide default values for insecure connections" do
42
+ config = HoptoadNotifier::Configuration.new
43
+ config.secure = false
44
+ assert_equal 80, config.port
45
+ assert_equal 'http', config.protocol
46
+ end
47
+
48
+ should "not cache inferred ports" do
49
+ config = HoptoadNotifier::Configuration.new
50
+ config.secure = false
51
+ config.port
52
+ config.secure = true
53
+ assert_equal 443, config.port
54
+ end
55
+
56
+ should "allow values to be overwritten" do
57
+ assert_config_overridable :proxy_host
58
+ assert_config_overridable :proxy_port
59
+ assert_config_overridable :proxy_user
60
+ assert_config_overridable :proxy_pass
61
+ assert_config_overridable :secure
62
+ assert_config_overridable :host
63
+ assert_config_overridable :port
64
+ assert_config_overridable :http_open_timeout
65
+ assert_config_overridable :http_read_timeout
66
+ assert_config_overridable :project_root
67
+ assert_config_overridable :notifier_version
68
+ assert_config_overridable :notifier_name
69
+ assert_config_overridable :notifier_url
70
+ assert_config_overridable :environment_name
71
+ assert_config_overridable :development_lookup
72
+ assert_config_overridable :logger
73
+ end
74
+
75
+ should "have an api key" do
76
+ assert_config_overridable :api_key
77
+ end
78
+
79
+ should "act like a hash" do
80
+ config = HoptoadNotifier::Configuration.new
81
+ hash = config.to_hash
82
+ [:api_key, :backtrace_filters, :development_environments,
83
+ :environment_name, :host, :http_open_timeout,
84
+ :http_read_timeout, :ignore, :ignore_by_filters, :ignore_user_agent,
85
+ :notifier_name, :notifier_url, :notifier_version, :params_filters,
86
+ :project_root, :port, :protocol, :proxy_host, :proxy_pass, :proxy_port,
87
+ :proxy_user, :secure, :development_lookup].each do |option|
88
+ assert_equal config[option], hash[option], "Wrong value for #{option}"
89
+ end
90
+ end
91
+
92
+ should "be mergable" do
93
+ config = HoptoadNotifier::Configuration.new
94
+ hash = config.to_hash
95
+ assert_equal hash.merge(:key => 'value'), config.merge(:key => 'value')
96
+ end
97
+
98
+ should "allow param filters to be appended" do
99
+ assert_appends_value :params_filters
100
+ end
101
+
102
+ should "warn when attempting to read environment filters" do
103
+ config = HoptoadNotifier::Configuration.new
104
+ config.
105
+ expects(:warn).
106
+ with(regexp_matches(/deprecated/i))
107
+ assert_equal [], config.environment_filters
108
+ end
109
+
110
+ should "allow ignored user agents to be appended" do
111
+ assert_appends_value :ignore_user_agent
112
+ end
113
+
114
+ should "allow backtrace filters to be appended" do
115
+ assert_appends_value(:backtrace_filters) do |config|
116
+ new_filter = lambda {}
117
+ config.filter_backtrace(&new_filter)
118
+ new_filter
119
+ end
120
+ end
121
+
122
+ should "allow ignore by filters to be appended" do
123
+ assert_appends_value(:ignore_by_filters) do |config|
124
+ new_filter = lambda {}
125
+ config.ignore_by_filter(&new_filter)
126
+ new_filter
127
+ end
128
+ end
129
+
130
+ should "allow ignored exceptions to be appended" do
131
+ config = HoptoadNotifier::Configuration.new
132
+ original_filters = config.ignore.dup
133
+ new_filter = 'hello'
134
+ config.ignore << new_filter
135
+ assert_same_elements original_filters + [new_filter], config.ignore
136
+ end
137
+
138
+ should "allow ignored exceptions to be replaced" do
139
+ assert_replaces(:ignore, :ignore_only=)
140
+ end
141
+
142
+ should "allow ignored user agents to be replaced" do
143
+ assert_replaces(:ignore_user_agent, :ignore_user_agent_only=)
144
+ end
145
+
146
+ should "use development and test as development environments by default" do
147
+ config = HoptoadNotifier::Configuration.new
148
+ assert_same_elements %w(development test cucumber), config.development_environments
149
+ end
150
+
151
+ should "be public in a public environment" do
152
+ config = HoptoadNotifier::Configuration.new
153
+ config.development_environments = %w(development)
154
+ config.environment_name = 'production'
155
+ assert config.public?
156
+ end
157
+
158
+ should "not be public in a development environment" do
159
+ config = HoptoadNotifier::Configuration.new
160
+ config.development_environments = %w(staging)
161
+ config.environment_name = 'staging'
162
+ assert !config.public?
163
+ end
164
+
165
+ should "be public without an environment name" do
166
+ config = HoptoadNotifier::Configuration.new
167
+ assert config.public?
168
+ end
169
+
170
+ should "use the assigned logger if set" do
171
+ config = HoptoadNotifier::Configuration.new
172
+ config.logger = "CUSTOM LOGGER"
173
+ assert_equal "CUSTOM LOGGER", config.logger
174
+ end
175
+
176
+ def assert_config_default(option, default_value, config = nil)
177
+ config ||= HoptoadNotifier::Configuration.new
178
+ assert_equal default_value, config.send(option)
179
+ end
180
+
181
+ def assert_config_overridable(option, value = 'a value')
182
+ config = HoptoadNotifier::Configuration.new
183
+ config.send(:"#{option}=", value)
184
+ assert_equal value, config.send(option)
185
+ end
186
+
187
+ def assert_appends_value(option, &block)
188
+ config = HoptoadNotifier::Configuration.new
189
+ original_values = config.send(option).dup
190
+ block ||= lambda do |config|
191
+ new_value = 'hello'
192
+ config.send(option) << new_value
193
+ new_value
194
+ end
195
+ new_value = block.call(config)
196
+ assert_same_elements original_values + [new_value], config.send(option)
197
+ end
198
+
199
+ def assert_replaces(option, setter)
200
+ config = HoptoadNotifier::Configuration.new
201
+ new_value = 'hello'
202
+ config.send(setter, [new_value])
203
+ assert_equal [new_value], config.send(option)
204
+ config.send(setter, new_value)
205
+ assert_equal [new_value], config.send(option)
206
+ end
207
+
208
+ end