airbrake 3.1.6 → 3.1.7

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 (58) hide show
  1. data/CHANGELOG +116 -0
  2. data/LICENSE +61 -0
  3. data/README.md +28 -478
  4. data/README_FOR_HEROKU_ADDON.md +13 -5
  5. data/Rakefile +26 -103
  6. data/TESTED_AGAINST +6 -0
  7. data/airbrake.gemspec +13 -14
  8. data/features/metal.feature +27 -12
  9. data/features/rack.feature +59 -59
  10. data/features/rails.feature +79 -100
  11. data/features/rails_with_js_notifier.feature +9 -21
  12. data/features/rake.feature +6 -4
  13. data/features/sinatra.feature +32 -6
  14. data/features/step_definitions/file_steps.rb +4 -0
  15. data/features/step_definitions/rack_steps.rb +9 -5
  16. data/features/step_definitions/rails_application_steps.rb +46 -278
  17. data/features/step_definitions/rake_steps.rb +16 -11
  18. data/features/support/airbrake_shim.rb.template +0 -2
  19. data/features/support/aruba.rb +5 -0
  20. data/features/support/env.rb +12 -6
  21. data/features/support/rails.rb +30 -73
  22. data/features/support/rake/Rakefile +1 -2
  23. data/features/user_informer.feature +12 -19
  24. data/generators/airbrake/airbrake_generator.rb +1 -1
  25. data/lib/airbrake.rb +9 -8
  26. data/lib/airbrake/cli/project_factory.rb +6 -3
  27. data/lib/airbrake/configuration.rb +7 -0
  28. data/lib/airbrake/notice.rb +52 -3
  29. data/lib/airbrake/rack.rb +16 -7
  30. data/lib/airbrake/rails/action_controller_catcher.rb +5 -3
  31. data/lib/airbrake/rails/controller_methods.rb +6 -6
  32. data/lib/airbrake/rails/error_lookup.rb +4 -2
  33. data/lib/airbrake/rails/javascript_notifier.rb +7 -3
  34. data/lib/airbrake/rails/middleware.rb +65 -0
  35. data/lib/airbrake/rails3_tasks.rb +16 -21
  36. data/lib/airbrake/railtie.rb +9 -16
  37. data/lib/airbrake/rake_handler.rb +2 -2
  38. data/lib/airbrake/sender.rb +57 -6
  39. data/lib/airbrake/shared_tasks.rb +24 -11
  40. data/lib/airbrake/sinatra.rb +34 -0
  41. data/lib/airbrake/user_informer.rb +9 -0
  42. data/lib/airbrake/version.rb +1 -1
  43. data/lib/rails/generators/airbrake/airbrake_generator.rb +10 -10
  44. data/{test/airbrake_2_3.xsd → resources/airbrake_2_4.xsd} +1 -0
  45. data/resources/airbrake_3_0.json +52 -0
  46. data/test/catcher_test.rb +198 -240
  47. data/test/configuration_test.rb +2 -0
  48. data/test/helper.rb +123 -53
  49. data/test/notice_test.rb +45 -1
  50. data/test/sender_test.rb +63 -32
  51. metadata +60 -79
  52. data/MIT-LICENSE +0 -22
  53. data/SUPPORTED_RAILS_VERSIONS +0 -38
  54. data/TESTING.md +0 -41
  55. data/features/step_definitions/metal_steps.rb +0 -23
  56. data/features/support/terminal.rb +0 -107
  57. data/lib/airbrake/extensions/blank.rb +0 -73
  58. data/lib/airbrake/rails/middleware/exceptions_catcher.rb +0 -33
@@ -14,11 +14,11 @@ namespace :airbrake do
14
14
  end
15
15
 
16
16
  AirbrakeTasks.deploy(:rails_env => ENV['TO'],
17
- :scm_revision => ENV['REVISION'],
18
- :scm_repository => ENV['REPO'],
19
- :local_username => ENV['USER'],
20
- :api_key => ENV['API_KEY'],
21
- :dry_run => ENV['DRY_RUN'])
17
+ :scm_revision => ENV['REVISION'],
18
+ :scm_repository => ENV['REPO'],
19
+ :local_username => ENV['USER'],
20
+ :api_key => ENV['API_KEY'],
21
+ :dry_run => ENV['DRY_RUN'])
22
22
  end
23
23
 
24
24
  task :log_stdout do
@@ -30,15 +30,28 @@ namespace :airbrake do
30
30
  desc "Install Heroku deploy notifications addon"
31
31
  task :add_deploy_notification => [:environment] do
32
32
 
33
- def heroku_var(var)
34
- `heroku config | grep -E "#{var.upcase}" | awk '{ print $3; }'`.strip
33
+ def get_heroku_vars
34
+ config = `heroku config --shell`
35
+ array_of_vars = config.split.map do |var|
36
+ var.partition("=").tap {|part| part.delete_at(1)}
37
+ end.flatten
38
+ @heroku_vars = Hash[*array_of_vars]
35
39
  end
36
40
 
37
- heroku_rails_env = heroku_var("rails_env")
38
- heroku_api_key = heroku_var("(hoptoad|airbrake)_api_key").split.find {|x| x unless x.blank?} ||
39
- Airbrake.configuration.api_key
41
+ get_heroku_vars
40
42
 
41
- command = %Q(heroku addons:add deployhooks:http --url="http://airbrake.io/deploys.txt?deploy[rails_env]=#{heroku_rails_env}&api_key=#{heroku_api_key}")
43
+ heroku_rails_env = @heroku_vars["RAILS_ENV"] || ENV["RAILS_ENV"] || "production"
44
+ heroku_api_key = @heroku_vars["AIRBRAKE_API_KEY"] || Airbrake.configuration.api_key || ENV["AIRBRAKE_API_KEY"]
45
+ heroku_app = ENV["HEROKU_APP"]
46
+ repo = `git config --get remote.origin.url` || ENV["REPO"]
47
+
48
+ command = %Q(heroku addons:add deployhooks:http --url="http://airbrake.io/deploys.txt?api_key=#{heroku_api_key})
49
+ command << "&deploy[local_username]={{user}}"
50
+ command << "&deploy[scm_revision]={{head_long}}"
51
+ command << "&deploy[rails_env]=#{heroku_rails_env}" if heroku_rails_env
52
+ command << "&deploy[scm_repository]=#{repo}" if repo
53
+ command << '"'
54
+ command << " --app=#{heroku_app}" if heroku_app
42
55
 
43
56
  puts "\nRunning:\n#{command}\n"
44
57
  puts `#{command}`
@@ -0,0 +1,34 @@
1
+ module Airbrake
2
+ # Middleware for Sinatra applications. Any errors raised by the upstream
3
+ # application will be delivered to Airbrake and re-raised.
4
+
5
+ # Synopsis:
6
+
7
+ # require 'sinatra'
8
+ # require 'airbrake'
9
+
10
+ # Airbrake.configure do |config|
11
+ # config.api_key = 'my api key'
12
+ # end
13
+
14
+ # use Airbrake::Sinatra
15
+
16
+ # get '/' do
17
+ # raise "Sinatra has left the building"
18
+ # end
19
+ #
20
+ # Use a standard Airbrake.configure call to configure your api key.
21
+ class Sinatra < Rack
22
+
23
+ def initialize(app)
24
+ super
25
+ Airbrake.configuration.environment_name = "#{app.settings.environment}"
26
+ Airbrake.configuration.framework = "Sinatra: #{::Sinatra::VERSION}"
27
+ end
28
+
29
+ def framework_exception
30
+ @env['sinatra.error']
31
+ end
32
+
33
+ end
34
+ end
@@ -9,7 +9,12 @@ module Airbrake
9
9
  end
10
10
 
11
11
  def call(env)
12
+ dup._call(env)
13
+ end
14
+
15
+ def _call(env)
12
16
  status, headers, body = @app.call(env)
17
+
13
18
  if env['airbrake.error_id'] && Airbrake.configuration.user_information
14
19
  new_body = []
15
20
  replace = replacement(env['airbrake.error_id'])
@@ -20,7 +25,11 @@ module Airbrake
20
25
  headers['Content-Length'] = new_body.sum(&:bytesize).to_s
21
26
  body = new_body
22
27
  end
28
+
23
29
  [status, headers, body]
30
+
31
+ ensure
32
+ body.close if body && body.respond_to?(:close) && $!
24
33
  end
25
34
  end
26
35
  end
@@ -1,3 +1,3 @@
1
1
  module Airbrake
2
- VERSION = "3.1.6".freeze
2
+ VERSION = "3.1.7"
3
3
  end
@@ -49,7 +49,7 @@ class AirbrakeGenerator < Rails::Generators::Base
49
49
  s = if options[:api_key]
50
50
  "'#{options[:api_key]}'"
51
51
  elsif options[:heroku]
52
- "ENV['HOPTOAD_API_KEY']"
52
+ "ENV['AIRBRAKE_API_KEY']"
53
53
  end
54
54
  end
55
55
 
@@ -59,31 +59,31 @@ class AirbrakeGenerator < Rails::Generators::Base
59
59
 
60
60
  def determine_api_key
61
61
  puts "Attempting to determine your API Key from Heroku..."
62
- ENV['HOPTOAD_API_KEY'] = heroku_api_key
63
- if ENV['HOPTOAD_API_KEY'].blank?
62
+ ENV['AIRBRAKE_API_KEY'] = heroku_api_key
63
+ if ENV['AIRBRAKE_API_KEY'].blank?
64
64
  puts "... Failed."
65
65
  puts "WARNING: We were unable to detect the Airbrake API Key from your Heroku environment."
66
66
  puts "Your Heroku application environment may not be configured correctly."
67
67
  exit 1
68
68
  else
69
69
  puts "... Done."
70
- puts "Heroku's Airbrake API Key is '#{ENV['HOPTOAD_API_KEY']}'"
70
+ puts "Heroku's Airbrake API Key is '#{ENV['AIRBRAKE_API_KEY']}'"
71
71
  end
72
72
  end
73
73
 
74
74
  def heroku_var(var,app_name = nil)
75
- app = app_name ? "--app #{app_name}" : ''
76
- `heroku config #{app} | grep -E "#{var.upcase}" | awk '{ print $3; }'`.strip
75
+ app = app_name ? "-a #{app_name}" : ''
76
+ `heroku config:get #{var} #{app}`
77
77
  end
78
78
 
79
79
  def heroku_api_key
80
- heroku_var("(hoptoad|airbrake)_api_key",options[:app]).split.find {|x| x unless x.blank?}
80
+ heroku_var("AIRBRAKE_API_KEY",options[:app]).split.find {|x| x unless x.blank?}
81
81
  end
82
82
 
83
83
  def heroku?
84
84
  options[:heroku] ||
85
- system("grep HOPTOAD_API_KEY config/initializers/airbrake.rb") ||
86
- system("grep HOPTOAD_API_KEY config/environment.rb")
85
+ system("grep AIRBRAKE_API_KEY config/initializers/airbrake.rb") ||
86
+ system("grep AIRBRAKE_API_KEY config/environment.rb")
87
87
  end
88
88
 
89
89
  def api_key_configured?
@@ -91,7 +91,7 @@ class AirbrakeGenerator < Rails::Generators::Base
91
91
  end
92
92
 
93
93
  def test_airbrake
94
- puts run("rake airbrake:test --trace")
94
+ puts run("rake airbrake:test")
95
95
  end
96
96
 
97
97
  def plugin_is_present?
@@ -10,6 +10,7 @@
10
10
  <xs:element name="request" type="request" minOccurs="0"/>
11
11
  <xs:element name="server-environment" type="serverEnvironment"/>
12
12
  <xs:element name="current-user" type="current-user" minOccurs="0"/>
13
+ <xs:element name="framework" type="xs:string" minOccurs="0"/>
13
14
  </xs:all>
14
15
  <xs:attribute name="version" type="xs:string" use="required"/>
15
16
  </xs:complexType>
@@ -0,0 +1,52 @@
1
+ {
2
+ "type" : "object",
3
+ "additionalProperties" : false,
4
+ "properties" : {
5
+ "notifier" : {
6
+ "type" : "hash",
7
+ "required" : true,
8
+ "additionalProperties" : false,
9
+ "properties" : {
10
+ "name" : {"type" : "string", "required" : true},
11
+ "version" : {"type" : "string", "required" : true},
12
+ "url" : {"type" : "string", "required" : true}
13
+ }
14
+ },
15
+ "errors" : {
16
+ "type" : "array",
17
+ "required" : true,
18
+ "items" : {
19
+ "type" : [{
20
+ "type" : "hash",
21
+ "additionalProperties" : false,
22
+ "properties" : {
23
+ "backtrace" : {"type" : "array", "required" : true},
24
+ "type" : {"type" : "string", "required" : true},
25
+ "message" : {"type" : "string", "required" : true}
26
+ }
27
+ }]
28
+ }
29
+ },
30
+ "context" : {
31
+ "type" : "hash",
32
+ "additionalProperties" : false,
33
+ "properties" : {
34
+ "os" : {"type" : "string"},
35
+ "language" : {"type" : "string"},
36
+ "environment" : {"type" : "string"},
37
+ "version" : {"type" : "string"},
38
+ "url" : {"type" : "string"},
39
+ "rootDirectory" : {"type" : "string"},
40
+ "userId" : {"type" : "string"},
41
+ "userName" : {"type" : "string"},
42
+ "userEmail" : {"type" : "string"},
43
+ "component" : {"type" : "string"},
44
+ "action" : {"type" : "string"}
45
+ }
46
+ },
47
+ "environment" : {"type" : "hash"},
48
+ "session" : {"type" : "hash"},
49
+ "params" : {"type" : "hash"}
50
+ }
51
+ }
52
+
data/test/catcher_test.rb CHANGED
@@ -1,6 +1,23 @@
1
1
  require File.expand_path '../helper', __FILE__
2
2
 
3
- class ActionControllerCatcherTest < Test::Unit::TestCase
3
+ require 'airbrake/rails/controller_methods'
4
+ require 'airbrake/rails/middleware'
5
+
6
+ module ActionDispatch
7
+ class ShowExceptions
8
+ private
9
+ def public_path
10
+ "/null"
11
+ end
12
+
13
+ # Silence logger
14
+ def logger
15
+ nil
16
+ end
17
+ end
18
+ end
19
+
20
+ class ActionControllerCatcherTest < ActionDispatch::IntegrationTest
4
21
 
5
22
  include DefinesConstants
6
23
 
@@ -8,6 +25,7 @@ class ActionControllerCatcherTest < Test::Unit::TestCase
8
25
  super
9
26
  reset_config
10
27
  Airbrake.sender = CollectingSender.new
28
+ Airbrake.configuration.development_environments = []
11
29
  define_constant('RAILS_ROOT', '/path/to/rails/root')
12
30
  end
13
31
 
@@ -15,22 +33,17 @@ class ActionControllerCatcherTest < Test::Unit::TestCase
15
33
  Airbrake.configuration.ignore << exception_class
16
34
  end
17
35
 
18
- def build_controller_class(&definition)
19
- Class.new(ActionController::Base).tap do |klass|
20
- klass.__send__(:include, Airbrake::Rails::ActionControllerCatcher)
21
- klass.class_eval(&definition) if definition
22
- define_constant('AirbrakeTestController', klass)
23
- end
24
- end
25
-
26
36
  def assert_sent_hash(hash, xpath)
27
37
  hash.each do |key, value|
28
- next if key.match(/^airbrake\./) # We added this key.
38
+ next if key.match(/^airbrake\./) || # We added this key.
39
+ hash[key].blank?
29
40
 
30
41
  element_xpath = "#{xpath}/var[@key = '#{key}']"
31
42
  if value.respond_to?(:to_hash)
32
43
  assert_sent_hash value.to_hash, element_xpath
33
44
  else
45
+ next if key == "action_dispatch.exception" # TODO: Rails 3.2 only - review
46
+ value.gsub!(/\d/,"") if key == "PATH_INFO" # TODO: Rails 3.2 only - review
34
47
  assert_sent_element value, element_xpath
35
48
  end
36
49
  end
@@ -66,7 +79,8 @@ class ActionControllerCatcherTest < Test::Unit::TestCase
66
79
  url << ":#{request.port}"
67
80
  end
68
81
 
69
- url << request.request_uri
82
+ url << request.fullpath.gsub(%r{\d},"") # TODO: Rails 3.2 only - review
83
+
70
84
  url
71
85
  end
72
86
 
@@ -83,251 +97,195 @@ class ActionControllerCatcherTest < Test::Unit::TestCase
83
97
  Nokogiri::XML.parse(xml)
84
98
  end
85
99
 
86
- def process_action(opts = {}, &action)
87
- opts[:request] ||= ActionController::TestRequest.new
88
- opts[:response] ||= ActionController::TestResponse.new
89
- klass = build_controller_class do
90
- cattr_accessor :local
91
- define_method(:index, &action)
92
- def local_request?
93
- local
94
- end
95
- end
96
- if opts[:filters]
97
- klass.filter_parameter_logging *opts[:filters]
98
- end
99
- if opts[:user_agent]
100
- if opts[:request].respond_to?(:user_agent=)
101
- opts[:request].user_agent = opts[:user_agent]
102
- else
103
- opts[:request].env["HTTP_USER_AGENT"] = opts[:user_agent]
104
- end
105
- end
106
- if opts[:port]
107
- opts[:request].port = opts[:port]
108
- end
109
- klass.consider_all_requests_local = opts[:all_local]
110
- klass.local = opts[:local]
111
- controller = klass.new
112
- controller.stubs(:rescue_action_in_public_without_airbrake)
113
- opts[:request].query_parameters = opts[:request].query_parameters.merge(opts[:params] || {})
114
- opts[:request].session = ActionController::TestSession.new(opts[:session] || {})
115
- # Prevents request.fullpath from crashing Rails in tests
116
- opts[:request].env['REQUEST_URI'] = opts[:request].request_uri
117
- controller.process(opts[:request], opts[:response])
118
- controller
119
- end
120
-
121
- def process_action_with_manual_notification(args = {})
122
- process_action(args) do
123
- notify_airbrake(:error_message => 'fail')
124
- # Rails will raise a template error if we don't render something
125
- render :nothing => true
100
+ class AirbrakeTestController < ActionController::Base
101
+ begin
102
+ use ActionDispatch::ShowExceptions, ActionDispatch::PublicExceptions.new("/null")
103
+ rescue NameError
104
+ use ActionDispatch::ShowExceptions
126
105
  end
127
- end
128
-
129
- def process_action_with_automatic_notification(args = {})
130
- process_action(args) { raise "Hello" }
131
- end
132
-
133
- should "deliver notices from exceptions raised in public requests" do
134
- process_action_with_automatic_notification
135
- assert_caught_and_sent
136
- end
137
-
138
- should "not deliver notices from exceptions in local requests" do
139
- process_action_with_automatic_notification(:local => true)
140
- assert_caught_and_not_sent
141
- end
142
-
143
- should "not deliver notices from exceptions when all requests are local" do
144
- process_action_with_automatic_notification(:all_local => true)
145
- assert_caught_and_not_sent
146
- end
147
-
148
- should "not deliver notices from actions that don't raise" do
149
- controller = process_action { render :text => 'Hello' }
150
- assert_caught_and_not_sent
151
- assert_equal 'Hello', controller.response.body
152
- end
153
-
154
- should "not deliver ignored exceptions raised by actions" do
155
- ignore(RuntimeError)
156
- process_action_with_automatic_notification
157
- assert_caught_and_not_sent
158
- end
159
-
160
- should "deliver ignored exception raised manually" do
161
- ignore(RuntimeError)
162
- process_action_with_manual_notification
163
- assert_caught_and_sent
164
- end
165
-
166
- should "deliver manually sent notices in public requests" do
167
- process_action_with_manual_notification
168
- assert_caught_and_sent
169
- end
170
-
171
- should "not deliver manually sent notices in local requests" do
172
- process_action_with_manual_notification(:local => true)
173
- assert_caught_and_not_sent
174
- end
175
-
176
- should "not deliver manually sent notices when all requests are local" do
177
- process_action_with_manual_notification(:all_local => true)
178
- assert_caught_and_not_sent
179
- end
180
-
181
- should "continue with default behavior after delivering an exception" do
182
- controller = process_action_with_automatic_notification(:public => true)
183
- # TODO: can we test this without stubbing?
184
- assert_received(controller, :rescue_action_in_public_without_airbrake)
185
- end
186
-
187
- should "not create actions from Airbrake methods" do
188
- controller = build_controller_class.new
189
- assert_equal [], Airbrake::Rails::ActionControllerCatcher.instance_methods
190
- end
191
-
192
- should "ignore exceptions when user agent is being ignored by regular expression" do
193
- Airbrake.configuration.ignore_user_agent_only = [/Ignored/]
194
- process_action_with_automatic_notification(:user_agent => 'ShouldBeIgnored')
195
- assert_caught_and_not_sent
196
- end
197
-
198
- should "ignore exceptions when user agent is being ignored by string" do
199
- Airbrake.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
200
- process_action_with_automatic_notification(:user_agent => 'IgnoredUserAgent')
201
- assert_caught_and_not_sent
202
- end
203
-
204
- should "not ignore exceptions when user agent is not being ignored" do
205
- Airbrake.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
206
- process_action_with_automatic_notification(:user_agent => 'NonIgnoredAgent')
207
- assert_caught_and_sent
208
- end
209
-
210
- should "send session data for manual notifications" do
211
- data = { 'one' => 'two' }
212
- process_action_with_manual_notification(:session => data)
213
- assert_sent_hash data, "/notice/request/session"
214
- end
215
-
216
- should "send session data for automatic notification" do
217
- data = { 'one' => 'two' }
218
- process_action_with_automatic_notification(:session => data)
219
- assert_sent_hash data, "/notice/request/session"
220
- end
221
-
222
- should "send request data for manual notification" do
223
- params = { 'controller' => "airbrake_test", 'action' => "index" }
224
- controller = process_action_with_manual_notification(:params => params)
225
- assert_sent_request_info_for controller.request
226
- end
227
106
 
228
- should "send request data for manual notification with non-standard port" do
229
- params = { 'controller' => "airbrake_test", 'action' => "index" }
230
- controller = process_action_with_manual_notification(:params => params, :port => 81)
231
- assert_sent_request_info_for controller.request
232
- end
107
+ use Airbrake::Rails::Middleware
233
108
 
234
- should "send request data for automatic notification" do
235
- params = { 'controller' => "airbrake_test", 'action' => "index" }
236
- controller = process_action_with_automatic_notification(:params => params)
237
- assert_sent_request_info_for controller.request
238
- end
109
+ include Airbrake::Rails::ControllerMethods
239
110
 
240
- should "send request data for automatic notification with non-standard port" do
241
- params = { 'controller' => "airbrake_test", 'action' => "index" }
242
- controller = process_action_with_automatic_notification(:params => params, :port => 81)
243
- assert_sent_request_info_for controller.request
244
- end
245
-
246
- should "use standard rails logging filters on params and session and env" do
247
- filtered_params = { "abc" => "123",
248
- "def" => "456",
249
- "ghi" => "[FILTERED]" }
250
- filtered_session = { "abc" => "123",
251
- "ghi" => "[FILTERED]" }
252
- ENV['ghi'] = 'abc'
253
- filtered_env = { 'ghi' => '[FILTERED]' }
254
- filtered_cgi = { 'REQUEST_METHOD' => '[FILTERED]' }
255
-
256
- process_action_with_automatic_notification(:filters => [:ghi, :request_method],
257
- :params => { "abc" => "123",
258
- "def" => "456",
259
- "ghi" => "789" },
260
- :session => { "abc" => "123",
261
- "ghi" => "789" })
262
- assert_sent_hash filtered_params, '/notice/request/params'
263
- assert_sent_hash filtered_cgi, '/notice/request/cgi-data'
264
- assert_sent_hash filtered_session, '/notice/request/session'
265
- end
111
+ cattr_accessor :local
266
112
 
267
- context "for a local error with development lookup enabled" do
268
- setup do
269
- Airbrake.configuration.development_lookup = true
270
- Airbrake.stubs(:build_lookup_hash_for).returns({ :awesome => 2 })
113
+ before_filter :set_session
271
114
 
272
- @controller = process_action_with_automatic_notification(:local => true)
273
- @response = @controller.response
115
+ def set_session
116
+ unless params.empty?
117
+ request.session = ActionController::TestSession.new(params[:session] || {})
118
+ end
274
119
  end
275
120
 
276
- should "append custom CSS and JS to response body for a local error" do
277
- assert_match /text\/css/, @response.body
278
- assert_match /text\/javascript/, @response.body
121
+ def boom
122
+ raise "boom"
123
+ render :nothing => true
279
124
  end
280
125
 
281
- should "contain host, API key and notice JSON" do
282
- assert_match Airbrake.configuration.host.to_json, @response.body
283
- assert_match Airbrake.configuration.api_key.to_json, @response.body
284
- assert_match ({ :awesome => 2 }).to_json, @response.body
126
+ def hello
127
+ render :text => "hello"
285
128
  end
286
- end
287
129
 
288
- context "for a local error with development lookup disabled" do
289
- setup do
290
- Airbrake.configuration.development_lookup = false
291
-
292
- @controller = process_action_with_automatic_notification(:local => true)
293
- @response = @controller.response
294
- end
295
-
296
- should "not append custom CSS and JS to response for a local error" do
297
- assert_no_match /text\/css/, @response.body
298
- assert_no_match /text\/javascript/, @response.body
130
+ def manual_airbrake
131
+ notify_airbrake(:error_message => "fail")
132
+ render :nothing => true
299
133
  end
300
- end
301
134
 
302
- should "call session.to_hash if available" do
303
- hash_data = {:key => :value}
135
+ protected
304
136
 
305
- session = ActionController::TestSession.new
306
- ActionController::TestSession.stubs(:new).returns(session)
307
- session.stubs(:to_hash).returns(hash_data)
308
-
309
- process_action_with_automatic_notification
310
- assert_received(session, :to_hash)
311
- assert_received(session, :data) { |expect| expect.never }
312
- assert_caught_and_sent
313
- end
314
-
315
- should "call session.data if session.to_hash is undefined" do
316
- hash_data = {:key => :value}
317
-
318
- session = ActionController::TestSession.new
319
- ActionController::TestSession.stubs(:new).returns(session)
320
- session.stubs(:data).returns(hash_data)
321
- if session.respond_to?(:to_hash)
322
- class << session
323
- undef to_hash
324
- end
137
+ def airbrake_local_request?
138
+ @@local
325
139
  end
326
-
327
- process_action_with_automatic_notification
328
- assert_received(session, :to_hash) { |expect| expect.never }
329
- assert_received(session, :data) { |expect| expect.at_least_once }
330
- assert_caught_and_sent
331
140
  end
332
141
 
142
+ setup do
143
+ Airbrake.configuration.development_environments = []
144
+ end
145
+
146
+
147
+ should "deliver notices from exceptions raised in public requests" do
148
+ @app = AirbrakeTestController.action(:boom)
149
+ get '/'
150
+ assert_caught_and_sent
151
+ end
152
+
153
+ should "not deliver notices from exceptions in development environments" do
154
+ Airbrake.configuration.development_environments = ["test"]
155
+ Airbrake.configuration.environment_name = "test"
156
+ @app = AirbrakeTestController.action(:boom)
157
+ get '/'
158
+ assert_caught_and_not_sent
159
+ end
160
+
161
+ should "not deliver notices from actions that don't raise" do
162
+ @app = AirbrakeTestController.action(:hello)
163
+ get '/'
164
+ assert_caught_and_not_sent
165
+ assert_equal 'hello', response.body
166
+ end
167
+
168
+ should "not deliver ignored exceptions raised by actions" do
169
+ @app = AirbrakeTestController.action(:boom)
170
+ ignore(RuntimeError)
171
+ get '/'
172
+ assert_caught_and_not_sent
173
+ end
174
+
175
+ should "deliver ignored exception raised manually" do
176
+ @app = AirbrakeTestController.action(:manual_airbrake)
177
+ ignore(RuntimeError)
178
+ get '/'
179
+ assert_caught_and_sent
180
+ end
181
+
182
+ should "not deliver manually sent notices in local requests" do
183
+ AirbrakeTestController.local = true
184
+ @app = AirbrakeTestController.action(:manual_airbrake)
185
+ get '/'
186
+ assert_caught_and_not_sent
187
+ AirbrakeTestController.local = false
188
+ end
189
+
190
+ should "not create actions from Airbrake methods" do
191
+ Airbrake::Rails::ControllerMethods.instance_methods.each do |method|
192
+ assert !(AirbrakeTestController.new.action_methods.include?(method))
193
+ end
194
+ end
195
+
196
+ should "ignore exceptions when user agent is being ignored by regular expression" do
197
+ Airbrake.configuration.ignore_user_agent_only = [/Ignored/]
198
+ @app = AirbrakeTestController.action(:boom)
199
+ get "/", {}, {"HTTP_USER_AGENT" => "ShouldBeIgnored"}
200
+ assert_caught_and_not_sent
201
+ end
202
+
203
+ should "ignore exceptions when user agent is being ignored by string" do
204
+ Airbrake.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
205
+ @app = AirbrakeTestController.action(:boom)
206
+ get "/", {}, {"HTTP_USER_AGENT" => "IgnoredUserAgent"}
207
+ assert_caught_and_not_sent
208
+ end
209
+
210
+ should "not ignore exceptions when user agent is not being ignored" do
211
+ Airbrake.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
212
+ @app = AirbrakeTestController.action(:boom)
213
+ get "/", {}, {"HTTP_USER_AGENT" => "NonIgnoredAgent"}
214
+ assert_caught_and_sent
215
+ end
216
+
217
+ should "send session data for manual notifications" do
218
+ @app = AirbrakeTestController.action(:manual_airbrake)
219
+ data = { 'one' => 'two' }
220
+ get "/", :session => data
221
+ assert_sent_hash data, "/notice/request/session"
222
+ end
223
+
224
+ should "send request data for manual notification" do
225
+ params = { 'controller' => "airbrake_test", 'action' => "index" }
226
+ @app = AirbrakeTestController.action(:manual_airbrake)
227
+ get "/", params
228
+ assert_sent_request_info_for @request
229
+ end
230
+
231
+ should "send request data for manual notification with non-standard port" do
232
+ params = { 'controller' => "airbrake_test", 'action' => "index" }
233
+ @app = AirbrakeTestController.action(:manual_airbrake)
234
+ get "/", params, {"SERVER_PORT" => 81}
235
+ assert_sent_request_info_for @request
236
+ end
237
+
238
+ should "send request data for automatic notification" do
239
+ params = { 'controller' => "airbrake_test", 'action' => "index" }
240
+ @app = AirbrakeTestController.action(:boom)
241
+ get "/", params
242
+ assert_sent_request_info_for @request
243
+ end
244
+
245
+ should "send request data for automatic notification with non-standard port" do
246
+ params = { 'controller' => "airbrake_test", 'action' => "index" }
247
+ @app = AirbrakeTestController.action(:boom)
248
+ get "/", params, {"SERVER_PORT" => 81}
249
+ assert_sent_request_info_for @request
250
+ assert_sent_element 81, "/notice/request/cgi-data/var[@key = 'SERVER_PORT']"
251
+ end
252
+
253
+ # should "call session.to_hash if available" do
254
+ # hash_data = {:key => :value}
255
+
256
+ # session = ActionController::TestSession.new
257
+ # ActionController::TestSession.stubs(:new).returns(session)
258
+ # session.stubs(:to_hash).returns(hash_data)
259
+
260
+ # Airbrake.configuration.environment_name = "production"
261
+
262
+ # @app = AirbrakeTestController.action(:boom)
263
+ # get '/'
264
+
265
+ # assert_received(session, :to_hash)
266
+ # assert_received(session, :data) { |expect| expect.never }
267
+ # assert_caught_and_sent
268
+ # end
269
+
270
+ # should "call session.data if session.to_hash is undefined" do
271
+ # hash_data = {:key => :value}
272
+
273
+ # session = ActionController::TestSession.new
274
+ # ActionController::TestSession.stubs(:new).returns(session)
275
+ # session.stubs(:data).returns(hash_data)
276
+ # if session.respond_to?(:to_hash)
277
+ # class << session
278
+ # undef to_hash
279
+ # end
280
+ # end
281
+
282
+ # Airbrake.configuration.environment_name = "production"
283
+
284
+ # @app = AirbrakeTestController.action(:boom)
285
+ # get '/'
286
+
287
+ # assert_received(session, :to_hash) { |expect| expect.never }
288
+ # assert_received(session, :data) { |expect| expect.at_least_once }
289
+ # assert_caught_and_sent
290
+ # end
333
291
  end