airbrake 3.1.12 → 3.1.13

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 +61 -0
  2. data/README.md +36 -17
  3. data/Rakefile +14 -8
  4. data/TESTED_AGAINST +1 -0
  5. data/airbrake.gemspec +3 -3
  6. data/features/metal.feature +1 -1
  7. data/features/rails.feature +1 -0
  8. data/features/rake.feature +4 -0
  9. data/features/sinatra.feature +72 -1
  10. data/features/support/rake/Rakefile +14 -4
  11. data/generators/airbrake/airbrake_generator.rb +5 -5
  12. data/lib/airbrake.rb +2 -9
  13. data/lib/airbrake/backtrace.rb +8 -13
  14. data/lib/airbrake/capistrano.rb +58 -2
  15. data/lib/airbrake/cli/runner.rb +1 -0
  16. data/lib/airbrake/configuration.rb +31 -11
  17. data/lib/airbrake/notice.rb +52 -61
  18. data/lib/airbrake/rails/controller_methods.rb +7 -3
  19. data/lib/airbrake/rails/javascript_notifier.rb +56 -31
  20. data/lib/airbrake/rake_handler.rb +3 -2
  21. data/lib/airbrake/response.rb +6 -8
  22. data/lib/airbrake/sender.rb +1 -1
  23. data/lib/airbrake/sinatra.rb +9 -2
  24. data/lib/airbrake/user_informer.rb +1 -1
  25. data/lib/airbrake/version.rb +1 -1
  26. data/lib/airbrake_tasks.rb +2 -2
  27. data/lib/rails/generators/airbrake/airbrake_generator.rb +5 -5
  28. data/lib/templates/javascript_notifier_configuration +12 -0
  29. data/lib/templates/javascript_notifier_loader +6 -0
  30. data/resources/notice.xml +2 -1
  31. data/test/airbrake_tasks_test.rb +2 -2
  32. data/test/backtrace_test.rb +19 -0
  33. data/test/capistrano_test.rb +9 -1
  34. data/test/configuration_test.rb +49 -2
  35. data/test/controller_methods_test.rb +22 -0
  36. data/test/helper.rb +29 -155
  37. data/test/integration.rb +15 -0
  38. data/test/{catcher_test.rb → integration/catcher_test.rb} +130 -19
  39. data/test/{javascript_notifier_test.rb → integration/javascript_notifier_test.rb} +0 -1
  40. data/test/logger_test.rb +11 -11
  41. data/test/notice_test.rb +8 -2
  42. data/test/notifier_test.rb +6 -6
  43. data/test/sender_test.rb +1 -1
  44. metadata +34 -31
  45. data/lib/templates/javascript_notifier +0 -20
@@ -1,147 +1,39 @@
1
- require 'test/unit'
2
- require 'rubygems'
1
+ $VERBOSE = ENV["VERBOSE"]
3
2
 
4
- $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
5
-
6
- require 'thread'
7
-
8
- require 'mocha'
9
-
10
- require 'abstract_controller'
11
- require 'action_controller'
12
- require 'action_dispatch'
13
- require 'active_support/dependencies'
14
- require 'active_model'
15
- require 'active_record'
16
- require 'active_support/core_ext/kernel/reporting'
17
-
18
- require 'nokogiri'
19
- require 'rack'
20
- require 'bourne'
21
- require 'sham_rack'
22
- require 'json-schema'
23
-
24
- require "airbrake"
25
-
26
- require "shoulda-matchers"
27
- require "shoulda-context"
28
-
29
- begin require 'redgreen'; rescue LoadError; end
30
-
31
- # Show backtraces for deprecated behavior for quicker cleanup.
32
- ActiveSupport::Deprecation.debug = true
33
-
34
- FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
35
- FIXTURES = Pathname.new(FIXTURE_LOAD_PATH)
36
-
37
- SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
38
-
39
- class RoutedRackApp
40
- attr_reader :routes
41
-
42
- def initialize(routes, &blk)
43
- @routes = routes
44
- @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
3
+ module Kernel
4
+ def silence_warnings
5
+ with_warnings(nil) { yield }
45
6
  end
46
7
 
47
- def call(env)
48
- @stack.call(env)
8
+ def with_warnings(flag)
9
+ old_verbose, $VERBOSE = $VERBOSE, flag
10
+ yield
11
+ ensure
12
+ $VERBOSE = old_verbose
49
13
  end
50
14
  end
51
15
 
52
- unless defined?(ActionDispatch::IntegrationTest)
53
- class ActionController::IntegrationTest < ActiveSupport::TestCase
54
- def self.build_app(routes = nil)
55
- RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
56
- yield(middleware) if block_given?
57
- end
58
- end
59
-
60
- self.app = build_app
61
-
62
- # Stub Rails dispatcher so it does not get controller references and
63
- # simply return the controller#action as Rack::Body.
64
- class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
65
- protected
66
- def controller_reference(controller_param)
67
- controller_param
68
- end
69
-
70
- def dispatch(controller, action, env)
71
- [200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
72
- end
73
- end
74
-
75
- def self.stub_controllers
76
- old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher
77
- ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
78
- ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher }
79
- yield ActionDispatch::Routing::RouteSet.new
80
- ensure
81
- ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
82
- ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher }
83
- end
84
-
85
- def with_routing(&block)
86
- temporary_routes = ActionDispatch::Routing::RouteSet.new
87
- old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
88
- old_routes = SharedTestRoutes
89
- silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
90
-
91
- yield temporary_routes
92
- ensure
93
- self.class.app = old_app
94
- silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
95
- end
96
-
97
- def with_autoload_path(path)
98
- path = File.join(File.dirname(__FILE__), "fixtures", path)
99
- if ActiveSupport::Dependencies.autoload_paths.include?(path)
100
- yield
101
- else
102
- begin
103
- ActiveSupport::Dependencies.autoload_paths << path
104
- yield
105
- ensure
106
- ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
107
- ActiveSupport::Dependencies.clear
108
- end
109
- end
110
- end
111
- end
112
- end
113
-
114
- class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
115
- setup do
116
- @routes = SharedTestRoutes
117
- end
16
+ silence_warnings do
17
+ require 'test/unit'
18
+ require 'rubygems'
19
+
20
+ require 'thread'
21
+
22
+ require 'mocha/setup'
23
+ require 'nokogiri'
24
+ require 'rack'
25
+ require 'bourne'
26
+ require 'sham_rack'
27
+ require 'json-schema'
28
+ require "shoulda-matchers"
29
+ require "shoulda-context"
30
+ begin require 'redgreen'; rescue LoadError; end
118
31
  end
119
32
 
33
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
120
34
 
121
35
 
122
- module ActionController
123
- class Base
124
- include ActionController::Testing
125
- end
126
-
127
- Base.view_paths = FIXTURE_LOAD_PATH
128
-
129
- class TestCase
130
- include ActionDispatch::TestProcess
131
-
132
- setup do
133
- @routes = SharedTestRoutes
134
- end
135
- end
136
- end
137
-
138
- # This stub emulates the Railtie including the URL helpers from a Rails application
139
- module ActionController
140
- class Base
141
- include SharedTestRoutes.url_helpers
142
- end
143
- end
144
-
36
+ require "airbrake"
145
37
 
146
38
  module TestMethods
147
39
  def rescue_action e
@@ -287,27 +179,6 @@ module DefinesConstants
287
179
  end
288
180
  end
289
181
 
290
- # Also stolen from AS 2.3.2
291
- class Array
292
- # Wraps the object in an Array unless it's an Array. Converts the
293
- # object to an Array using #to_ary if it implements that.
294
- def self.wrap(object)
295
- case object
296
- when nil
297
- []
298
- when self
299
- object
300
- else
301
- if object.respond_to?(:to_ary)
302
- object.to_ary
303
- else
304
- [object]
305
- end
306
- end
307
- end
308
-
309
- end
310
-
311
182
  class CollectingSender
312
183
  attr_reader :collected
313
184
 
@@ -322,12 +193,15 @@ end
322
193
 
323
194
  class BacktracedException < Exception
324
195
  attr_accessor :backtrace
196
+
325
197
  def initialize(opts)
326
198
  @backtrace = opts[:backtrace]
327
199
  end
200
+
328
201
  def set_backtrace(bt)
329
202
  @backtrace = bt
330
203
  end
204
+
331
205
  def message
332
206
  "Something went wrong. Did you press the red button?"
333
207
  end
@@ -0,0 +1,15 @@
1
+ require File.expand_path '../helper', __FILE__
2
+
3
+ silence_warnings do
4
+ require 'abstract_controller'
5
+ require 'action_controller'
6
+ require 'action_dispatch'
7
+ require 'active_support/dependencies'
8
+ require 'active_support/core_ext/kernel/reporting'
9
+
10
+ require "erb"
11
+ require "action_view"
12
+ end
13
+
14
+ require File.expand_path "../integration/javascript_notifier_test", __FILE__
15
+ require File.expand_path "../integration/catcher_test", __FILE__
@@ -1,8 +1,119 @@
1
- require File.expand_path '../helper', __FILE__
2
-
3
1
  require 'airbrake/rails/controller_methods'
4
2
  require 'airbrake/rails/middleware'
5
3
 
4
+ unless defined?(ActionDispatch::IntegrationTest) # Rails 3.0
5
+ # what follows is a dirty hack which makes
6
+ # AD::IntegrationTest possible in Rails 3.0
7
+ ActiveSupport::Deprecation.debug = true
8
+
9
+ FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
10
+ FIXTURES = Pathname.new(FIXTURE_LOAD_PATH)
11
+
12
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
13
+
14
+ class RoutedRackApp
15
+ attr_reader :routes
16
+
17
+ def initialize(routes, &blk)
18
+ @routes = routes
19
+ @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
20
+ end
21
+
22
+ def call(env)
23
+ @stack.call(env)
24
+ end
25
+ end
26
+
27
+ class ActionController::IntegrationTest < ActiveSupport::TestCase
28
+ def self.build_app(routes = nil)
29
+ RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
30
+ yield(middleware) if block_given?
31
+ end
32
+ end
33
+
34
+ self.app = build_app
35
+
36
+ # Stub Rails dispatcher so it does not get controller references and
37
+ # simply return the controller#action as Rack::Body.
38
+ class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
39
+ protected
40
+ def controller_reference(controller_param)
41
+ controller_param
42
+ end
43
+
44
+ def dispatch(controller, action, env)
45
+ [200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
46
+ end
47
+ end
48
+
49
+ def self.stub_controllers
50
+ old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher
51
+ ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
52
+ ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher }
53
+ yield ActionDispatch::Routing::RouteSet.new
54
+ ensure
55
+ ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
56
+ ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher }
57
+ end
58
+
59
+ def with_routing(&block)
60
+ temporary_routes = ActionDispatch::Routing::RouteSet.new
61
+ old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
62
+ old_routes = SharedTestRoutes
63
+ silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
64
+
65
+ yield temporary_routes
66
+ ensure
67
+ self.class.app = old_app
68
+ silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
69
+ end
70
+
71
+ def with_autoload_path(path)
72
+ path = File.join(File.dirname(__FILE__), "fixtures", path)
73
+ if ActiveSupport::Dependencies.autoload_paths.include?(path)
74
+ yield
75
+ else
76
+ begin
77
+ ActiveSupport::Dependencies.autoload_paths << path
78
+ yield
79
+ ensure
80
+ ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
81
+ ActiveSupport::Dependencies.clear
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
88
+ setup do
89
+ @routes = SharedTestRoutes
90
+ end
91
+ end
92
+
93
+ module ActionController
94
+ class Base
95
+ include ActionController::Testing
96
+ end
97
+
98
+ Base.view_paths = FIXTURE_LOAD_PATH
99
+
100
+ class TestCase
101
+ include ActionDispatch::TestProcess
102
+
103
+ setup do
104
+ @routes = SharedTestRoutes
105
+ end
106
+ end
107
+ end
108
+
109
+ # This stub emulates the Railtie including the URL helpers from a Rails application
110
+ module ActionController
111
+ class Base
112
+ include SharedTestRoutes.url_helpers
113
+ end
114
+ end
115
+ end # end Rails 3.0 hack
116
+
6
117
  module ActionDispatch
7
118
  class ShowExceptions
8
119
  private
@@ -36,9 +147,9 @@ class ActionControllerCatcherTest < ActionDispatch::IntegrationTest
36
147
  def assert_sent_hash(hash, xpath)
37
148
  hash.each do |key, value|
38
149
  next if key.match(/^airbrake\./) || # We added this key.
39
- hash[key].blank?
150
+ hash[key] !~ /\S/
40
151
 
41
- element_xpath = "#{xpath}/var[@key = '#{key}']"
152
+ element_xpath = "#{xpath}/var[@key = '#{key}']"
42
153
  if value.respond_to?(:to_hash)
43
154
  assert_sent_hash value.to_hash, element_xpath
44
155
  else
@@ -144,13 +255,13 @@ class ActionControllerCatcherTest < ActionDispatch::IntegrationTest
144
255
  end
145
256
 
146
257
 
147
- def deliver_notices_from_exceptions_raised_in_public_requests
258
+ def test_deliver_notices_from_exceptions_raised_in_public_requests
148
259
  @app = AirbrakeTestController.action(:boom)
149
260
  get '/'
150
261
  assert_caught_and_sent
151
262
  end
152
263
 
153
- def not_deliver_notices_from_exceptions_in_development_environments
264
+ def test_not_deliver_notices_from_exceptions_in_development_environments
154
265
  Airbrake.configuration.development_environments = ["test"]
155
266
  Airbrake.configuration.environment_name = "test"
156
267
  @app = AirbrakeTestController.action(:boom)
@@ -158,28 +269,28 @@ class ActionControllerCatcherTest < ActionDispatch::IntegrationTest
158
269
  assert_caught_and_not_sent
159
270
  end
160
271
 
161
- def not_deliver_notices_from_actions_that_dont_raise
272
+ def test_not_deliver_notices_from_actions_that_dont_raise
162
273
  @app = AirbrakeTestController.action(:hello)
163
274
  get '/'
164
275
  assert_caught_and_not_sent
165
276
  assert_equal 'hello', response.body
166
277
  end
167
278
 
168
- def not_deliver_ignored_exceptions_raised_by_actions
279
+ def test_not_deliver_ignored_exceptions_raised_by_actions
169
280
  @app = AirbrakeTestController.action(:boom)
170
281
  ignore(RuntimeError)
171
282
  get '/'
172
283
  assert_caught_and_not_sent
173
284
  end
174
285
 
175
- def deliver_ignored_exception_raised_manually
286
+ def test_deliver_ignored_exception_raised_manually
176
287
  @app = AirbrakeTestController.action(:manual_airbrake)
177
288
  ignore(RuntimeError)
178
289
  get '/'
179
290
  assert_caught_and_sent
180
291
  end
181
292
 
182
- def not_deliver_manually_sent_notices_in_local_requests
293
+ def test_not_deliver_manually_sent_notices_in_local_requests
183
294
  AirbrakeTestController.local = true
184
295
  @app = AirbrakeTestController.action(:manual_airbrake)
185
296
  get '/'
@@ -187,62 +298,62 @@ class ActionControllerCatcherTest < ActionDispatch::IntegrationTest
187
298
  AirbrakeTestController.local = false
188
299
  end
189
300
 
190
- def not_create_actions_from_airbrake_methods
301
+ def test_not_create_actions_from_airbrake_methods
191
302
  Airbrake::Rails::ControllerMethods.instance_methods.each do |method|
192
303
  assert !(AirbrakeTestController.new.action_methods.include?(method))
193
304
  end
194
305
  end
195
306
 
196
- def ignore_exceptions_when_user_agent_is_being_ignored_by_regular_expression
307
+ def test_ignore_exceptions_when_user_agent_is_being_ignored_by_regular_expression
197
308
  Airbrake.configuration.ignore_user_agent_only = [/Ignored/]
198
309
  @app = AirbrakeTestController.action(:boom)
199
310
  get "/", {}, {"HTTP_USER_AGENT" => "ShouldBeIgnored"}
200
311
  assert_caught_and_not_sent
201
312
  end
202
313
 
203
- def ignore_exceptions_when_user_agent_is_being_ignored_by_string
314
+ def test_ignore_exceptions_when_user_agent_is_being_ignored_by_string
204
315
  Airbrake.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
205
316
  @app = AirbrakeTestController.action(:boom)
206
317
  get "/", {}, {"HTTP_USER_AGENT" => "IgnoredUserAgent"}
207
318
  assert_caught_and_not_sent
208
319
  end
209
320
 
210
- def not_ignore_exceptions_when_user_agent_is_not_being_ignored
321
+ def test_not_ignore_exceptions_when_user_agent_is_not_being_ignored
211
322
  Airbrake.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
212
323
  @app = AirbrakeTestController.action(:boom)
213
324
  get "/", {}, {"HTTP_USER_AGENT" => "NonIgnoredAgent"}
214
325
  assert_caught_and_sent
215
326
  end
216
327
 
217
- def send_session_data_for_manual_notifications
328
+ def test_send_session_data_for_manual_notifications
218
329
  @app = AirbrakeTestController.action(:manual_airbrake)
219
330
  data = { 'one' => 'two' }
220
331
  get "/", :session => data
221
332
  assert_sent_hash data, "/notice/request/session"
222
333
  end
223
334
 
224
- def send_request_data_for_manual_notification
335
+ def test_send_request_data_for_manual_notification
225
336
  params = { 'controller' => "airbrake_test", 'action' => "index" }
226
337
  @app = AirbrakeTestController.action(:manual_airbrake)
227
338
  get "/", params
228
339
  assert_sent_request_info_for @request
229
340
  end
230
341
 
231
- def send_request_data_for_manual_notification_with_non_standard_port
342
+ def test_send_request_data_for_manual_notification_with_non_standard_port
232
343
  params = { 'controller' => "airbrake_test", 'action' => "index" }
233
344
  @app = AirbrakeTestController.action(:manual_airbrake)
234
345
  get "/", params, {"SERVER_PORT" => 81}
235
346
  assert_sent_request_info_for @request
236
347
  end
237
348
 
238
- def send_request_data_for_automatic_notification
349
+ def test_send_request_data_for_automatic_notification
239
350
  params = { 'controller' => "airbrake_test", 'action' => "index" }
240
351
  @app = AirbrakeTestController.action(:boom)
241
352
  get "/", params
242
353
  assert_sent_request_info_for @request
243
354
  end
244
355
 
245
- def send_request_data_for_automatic_notification_with_non_standard_port
356
+ def test_send_request_data_for_automatic_notification_with_non_standard_port
246
357
  params = { 'controller' => "airbrake_test", 'action' => "index" }
247
358
  @app = AirbrakeTestController.action(:boom)
248
359
  get "/", params, {"SERVER_PORT" => 81}