PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/gems/hoptoad_notifier-2.4.4/test/catcher_test.rb

https://bitbucket.org/resumenothing/expertiza
Ruby | 331 lines | 307 code | 23 blank | 1 comment | 10 complexity | fa36034abff9cc3c44bcaf26a14086d8 MD5 | raw file
  1. require File.dirname(__FILE__) + '/helper'
  2. class ActionControllerCatcherTest < Test::Unit::TestCase
  3. include DefinesConstants
  4. def setup
  5. super
  6. reset_config
  7. HoptoadNotifier.sender = CollectingSender.new
  8. define_constant('RAILS_ROOT', '/path/to/rails/root')
  9. end
  10. def ignore(exception_class)
  11. HoptoadNotifier.configuration.ignore << exception_class
  12. end
  13. def build_controller_class(&definition)
  14. returning Class.new(ActionController::Base) do |klass|
  15. klass.__send__(:include, HoptoadNotifier::Rails::ActionControllerCatcher)
  16. klass.class_eval(&definition) if definition
  17. define_constant('HoptoadTestController', klass)
  18. end
  19. end
  20. def assert_sent_hash(hash, xpath)
  21. hash.each do |key, value|
  22. next if key.match(/^hoptoad\./) # We added this key.
  23. element_xpath = "#{xpath}/var[@key = '#{key}']"
  24. if value.respond_to?(:to_hash)
  25. assert_sent_hash value.to_hash, element_xpath
  26. else
  27. assert_sent_element value, element_xpath
  28. end
  29. end
  30. end
  31. def assert_sent_element(value, xpath)
  32. assert_valid_node last_sent_notice_document, xpath, stringify_array_elements(value).to_s
  33. end
  34. def stringify_array_elements(data)
  35. if data.respond_to?(:to_ary)
  36. data.collect do |value|
  37. stringify_array_elements(value)
  38. end
  39. else
  40. data.to_s
  41. end
  42. end
  43. def assert_sent_request_info_for(request)
  44. params = request.parameters.to_hash
  45. assert_sent_hash params, '/notice/request/params'
  46. assert_sent_element params['controller'], '/notice/request/component'
  47. assert_sent_element params['action'], '/notice/request/action'
  48. assert_sent_element url_from_request(request), '/notice/request/url'
  49. assert_sent_hash request.env, '/notice/request/cgi-data'
  50. end
  51. def url_from_request(request)
  52. url = "#{request.protocol}#{request.host}"
  53. unless [80, 443].include?(request.port)
  54. url << ":#{request.port}"
  55. end
  56. url << request.request_uri
  57. url
  58. end
  59. def sender
  60. HoptoadNotifier.sender
  61. end
  62. def last_sent_notice_xml
  63. sender.collected.last
  64. end
  65. def last_sent_notice_document
  66. assert_not_nil xml = last_sent_notice_xml, "No xml was sent"
  67. Nokogiri::XML.parse(xml)
  68. end
  69. def process_action(opts = {}, &action)
  70. opts[:request] ||= ActionController::TestRequest.new
  71. opts[:response] ||= ActionController::TestResponse.new
  72. klass = build_controller_class do
  73. cattr_accessor :local
  74. define_method(:index, &action)
  75. def local_request?
  76. local
  77. end
  78. end
  79. if opts[:filters]
  80. klass.filter_parameter_logging *opts[:filters]
  81. end
  82. if opts[:user_agent]
  83. if opts[:request].respond_to?(:user_agent=)
  84. opts[:request].user_agent = opts[:user_agent]
  85. else
  86. opts[:request].env["HTTP_USER_AGENT"] = opts[:user_agent]
  87. end
  88. end
  89. if opts[:port]
  90. opts[:request].port = opts[:port]
  91. end
  92. klass.consider_all_requests_local = opts[:all_local]
  93. klass.local = opts[:local]
  94. controller = klass.new
  95. controller.stubs(:rescue_action_in_public_without_hoptoad)
  96. opts[:request].query_parameters = opts[:request].query_parameters.merge(opts[:params] || {})
  97. opts[:request].session = ActionController::TestSession.new(opts[:session] || {})
  98. controller.process(opts[:request], opts[:response])
  99. controller
  100. end
  101. def process_action_with_manual_notification(args = {})
  102. process_action(args) do
  103. notify_hoptoad(:error_message => 'fail')
  104. # Rails will raise a template error if we don't render something
  105. render :nothing => true
  106. end
  107. end
  108. def process_action_with_automatic_notification(args = {})
  109. process_action(args) { raise "Hello" }
  110. end
  111. should "deliver notices from exceptions raised in public requests" do
  112. process_action_with_automatic_notification
  113. assert_caught_and_sent
  114. end
  115. should "not deliver notices from exceptions in local requests" do
  116. process_action_with_automatic_notification(:local => true)
  117. assert_caught_and_not_sent
  118. end
  119. should "not deliver notices from exceptions when all requests are local" do
  120. process_action_with_automatic_notification(:all_local => true)
  121. assert_caught_and_not_sent
  122. end
  123. should "not deliver notices from actions that don't raise" do
  124. controller = process_action { render :text => 'Hello' }
  125. assert_caught_and_not_sent
  126. assert_equal 'Hello', controller.response.body
  127. end
  128. should "not deliver ignored exceptions raised by actions" do
  129. ignore(RuntimeError)
  130. process_action_with_automatic_notification
  131. assert_caught_and_not_sent
  132. end
  133. should "deliver ignored exception raised manually" do
  134. ignore(RuntimeError)
  135. process_action_with_manual_notification
  136. assert_caught_and_sent
  137. end
  138. should "deliver manually sent notices in public requests" do
  139. process_action_with_manual_notification
  140. assert_caught_and_sent
  141. end
  142. should "not deliver manually sent notices in local requests" do
  143. process_action_with_manual_notification(:local => true)
  144. assert_caught_and_not_sent
  145. end
  146. should "not deliver manually sent notices when all requests are local" do
  147. process_action_with_manual_notification(:all_local => true)
  148. assert_caught_and_not_sent
  149. end
  150. should "continue with default behavior after delivering an exception" do
  151. controller = process_action_with_automatic_notification(:public => true)
  152. # TODO: can we test this without stubbing?
  153. assert_received(controller, :rescue_action_in_public_without_hoptoad)
  154. end
  155. should "not create actions from Hoptoad methods" do
  156. controller = build_controller_class.new
  157. assert_equal [], HoptoadNotifier::Rails::ActionControllerCatcher.instance_methods
  158. end
  159. should "ignore exceptions when user agent is being ignored by regular expression" do
  160. HoptoadNotifier.configuration.ignore_user_agent_only = [/Ignored/]
  161. process_action_with_automatic_notification(:user_agent => 'ShouldBeIgnored')
  162. assert_caught_and_not_sent
  163. end
  164. should "ignore exceptions when user agent is being ignored by string" do
  165. HoptoadNotifier.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
  166. process_action_with_automatic_notification(:user_agent => 'IgnoredUserAgent')
  167. assert_caught_and_not_sent
  168. end
  169. should "not ignore exceptions when user agent is not being ignored" do
  170. HoptoadNotifier.configuration.ignore_user_agent_only = ['IgnoredUserAgent']
  171. process_action_with_automatic_notification(:user_agent => 'NonIgnoredAgent')
  172. assert_caught_and_sent
  173. end
  174. should "send session data for manual notifications" do
  175. data = { 'one' => 'two' }
  176. process_action_with_manual_notification(:session => data)
  177. assert_sent_hash data, "/notice/request/session"
  178. end
  179. should "send session data for automatic notification" do
  180. data = { 'one' => 'two' }
  181. process_action_with_automatic_notification(:session => data)
  182. assert_sent_hash data, "/notice/request/session"
  183. end
  184. should "send request data for manual notification" do
  185. params = { 'controller' => "hoptoad_test", 'action' => "index" }
  186. controller = process_action_with_manual_notification(:params => params)
  187. assert_sent_request_info_for controller.request
  188. end
  189. should "send request data for manual notification with non-standard port" do
  190. params = { 'controller' => "hoptoad_test", 'action' => "index" }
  191. controller = process_action_with_manual_notification(:params => params, :port => 81)
  192. assert_sent_request_info_for controller.request
  193. end
  194. should "send request data for automatic notification" do
  195. params = { 'controller' => "hoptoad_test", 'action' => "index" }
  196. controller = process_action_with_automatic_notification(:params => params)
  197. assert_sent_request_info_for controller.request
  198. end
  199. should "send request data for automatic notification with non-standard port" do
  200. params = { 'controller' => "hoptoad_test", 'action' => "index" }
  201. controller = process_action_with_automatic_notification(:params => params, :port => 81)
  202. assert_sent_request_info_for controller.request
  203. end
  204. should "use standard rails logging filters on params and session and env" do
  205. filtered_params = { "abc" => "123",
  206. "def" => "456",
  207. "ghi" => "[FILTERED]" }
  208. filtered_session = { "abc" => "123",
  209. "ghi" => "[FILTERED]" }
  210. ENV['ghi'] = 'abc'
  211. filtered_env = { 'ghi' => '[FILTERED]' }
  212. filtered_cgi = { 'REQUEST_METHOD' => '[FILTERED]' }
  213. process_action_with_automatic_notification(:filters => [:ghi, :request_method],
  214. :params => { "abc" => "123",
  215. "def" => "456",
  216. "ghi" => "789" },
  217. :session => { "abc" => "123",
  218. "ghi" => "789" })
  219. assert_sent_hash filtered_params, '/notice/request/params'
  220. assert_sent_hash filtered_cgi, '/notice/request/cgi-data'
  221. assert_sent_hash filtered_session, '/notice/request/session'
  222. end
  223. context "for a local error with development lookup enabled" do
  224. setup do
  225. HoptoadNotifier.configuration.development_lookup = true
  226. HoptoadNotifier.stubs(:build_lookup_hash_for).returns({ :awesome => 2 })
  227. @controller = process_action_with_automatic_notification(:local => true)
  228. @response = @controller.response
  229. end
  230. should "append custom CSS and JS to response body for a local error" do
  231. assert_match /text\/css/, @response.body
  232. assert_match /text\/javascript/, @response.body
  233. end
  234. should "contain host, API key and notice JSON" do
  235. assert_match HoptoadNotifier.configuration.host.to_json, @response.body
  236. assert_match HoptoadNotifier.configuration.api_key.to_json, @response.body
  237. assert_match ({ :awesome => 2 }).to_json, @response.body
  238. end
  239. end
  240. context "for a local error with development lookup disabled" do
  241. setup do
  242. HoptoadNotifier.configuration.development_lookup = false
  243. @controller = process_action_with_automatic_notification(:local => true)
  244. @response = @controller.response
  245. end
  246. should "not append custom CSS and JS to response for a local error" do
  247. assert_no_match /text\/css/, @response.body
  248. assert_no_match /text\/javascript/, @response.body
  249. end
  250. end
  251. should "call session.to_hash if available" do
  252. hash_data = {:key => :value}
  253. session = ActionController::TestSession.new
  254. ActionController::TestSession.stubs(:new).returns(session)
  255. session.stubs(:to_hash).returns(hash_data)
  256. process_action_with_automatic_notification
  257. assert_received(session, :to_hash)
  258. assert_received(session, :data) { |expect| expect.never }
  259. assert_caught_and_sent
  260. end
  261. should "call session.data if session.to_hash is undefined" do
  262. hash_data = {:key => :value}
  263. session = ActionController::TestSession.new
  264. ActionController::TestSession.stubs(:new).returns(session)
  265. session.stubs(:data).returns(hash_data)
  266. if session.respond_to?(:to_hash)
  267. class << session
  268. undef to_hash
  269. end
  270. end
  271. process_action_with_automatic_notification
  272. assert_received(session, :to_hash) { |expect| expect.never }
  273. assert_received(session, :data) { |expect| expect.at_least_once }
  274. assert_caught_and_sent
  275. end
  276. end