riscfuture-hoptoad_notifier 2.3.6

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 (47) hide show
  1. data/CHANGELOG +218 -0
  2. data/INSTALL +25 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +394 -0
  5. data/Rakefile +217 -0
  6. data/SUPPORTED_RAILS_VERSIONS +10 -0
  7. data/TESTING.rdoc +8 -0
  8. data/generators/hoptoad/hoptoad_generator.rb +63 -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.rb +148 -0
  15. data/lib/hoptoad_notifier/backtrace.rb +99 -0
  16. data/lib/hoptoad_notifier/capistrano.rb +20 -0
  17. data/lib/hoptoad_notifier/configuration.rb +236 -0
  18. data/lib/hoptoad_notifier/notice.rb +334 -0
  19. data/lib/hoptoad_notifier/rack.rb +40 -0
  20. data/lib/hoptoad_notifier/rails.rb +39 -0
  21. data/lib/hoptoad_notifier/rails/action_controller_catcher.rb +29 -0
  22. data/lib/hoptoad_notifier/rails/controller_methods.rb +60 -0
  23. data/lib/hoptoad_notifier/rails/error_lookup.rb +33 -0
  24. data/lib/hoptoad_notifier/rails/javascript_notifier.rb +43 -0
  25. data/lib/hoptoad_notifier/rails3_tasks.rb +91 -0
  26. data/lib/hoptoad_notifier/railtie.rb +29 -0
  27. data/lib/hoptoad_notifier/sender.rb +63 -0
  28. data/lib/hoptoad_notifier/tasks.rb +97 -0
  29. data/lib/hoptoad_notifier/version.rb +3 -0
  30. data/lib/hoptoad_tasks.rb +44 -0
  31. data/lib/rails/generators/hoptoad/hoptoad_generator.rb +69 -0
  32. data/lib/templates/javascript_notifier.erb +6 -0
  33. data/lib/templates/rescue.erb +91 -0
  34. data/rails/init.rb +1 -0
  35. data/script/integration_test.rb +38 -0
  36. data/test/backtrace_test.rb +118 -0
  37. data/test/catcher_test.rb +329 -0
  38. data/test/configuration_test.rb +209 -0
  39. data/test/helper.rb +239 -0
  40. data/test/hoptoad_tasks_test.rb +152 -0
  41. data/test/logger_test.rb +85 -0
  42. data/test/notice_test.rb +457 -0
  43. data/test/notifier_test.rb +222 -0
  44. data/test/rack_test.rb +58 -0
  45. data/test/rails_initializer_test.rb +36 -0
  46. data/test/sender_test.rb +123 -0
  47. metadata +197 -0
@@ -0,0 +1,209 @@
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
+ assert_config_default :js_notifier, false
33
+ end
34
+
35
+ should "provide default values for secure connections" do
36
+ config = HoptoadNotifier::Configuration.new
37
+ config.secure = true
38
+ assert_equal 443, config.port
39
+ assert_equal 'https', config.protocol
40
+ end
41
+
42
+ should "provide default values for insecure connections" do
43
+ config = HoptoadNotifier::Configuration.new
44
+ config.secure = false
45
+ assert_equal 80, config.port
46
+ assert_equal 'http', config.protocol
47
+ end
48
+
49
+ should "not cache inferred ports" do
50
+ config = HoptoadNotifier::Configuration.new
51
+ config.secure = false
52
+ config.port
53
+ config.secure = true
54
+ assert_equal 443, config.port
55
+ end
56
+
57
+ should "allow values to be overwritten" do
58
+ assert_config_overridable :proxy_host
59
+ assert_config_overridable :proxy_port
60
+ assert_config_overridable :proxy_user
61
+ assert_config_overridable :proxy_pass
62
+ assert_config_overridable :secure
63
+ assert_config_overridable :host
64
+ assert_config_overridable :port
65
+ assert_config_overridable :http_open_timeout
66
+ assert_config_overridable :http_read_timeout
67
+ assert_config_overridable :project_root
68
+ assert_config_overridable :notifier_version
69
+ assert_config_overridable :notifier_name
70
+ assert_config_overridable :notifier_url
71
+ assert_config_overridable :environment_name
72
+ assert_config_overridable :development_lookup
73
+ assert_config_overridable :logger
74
+ end
75
+
76
+ should "have an api key" do
77
+ assert_config_overridable :api_key
78
+ end
79
+
80
+ should "act like a hash" do
81
+ config = HoptoadNotifier::Configuration.new
82
+ hash = config.to_hash
83
+ [:api_key, :backtrace_filters, :development_environments,
84
+ :environment_name, :host, :http_open_timeout,
85
+ :http_read_timeout, :ignore, :ignore_by_filters, :ignore_user_agent,
86
+ :notifier_name, :notifier_url, :notifier_version, :params_filters,
87
+ :project_root, :port, :protocol, :proxy_host, :proxy_pass, :proxy_port,
88
+ :proxy_user, :secure, :development_lookup, :js_notifier].each do |option|
89
+ assert_equal config[option], hash[option], "Wrong value for #{option}"
90
+ end
91
+ end
92
+
93
+ should "be mergable" do
94
+ config = HoptoadNotifier::Configuration.new
95
+ hash = config.to_hash
96
+ assert_equal hash.merge(:key => 'value'), config.merge(:key => 'value')
97
+ end
98
+
99
+ should "allow param filters to be appended" do
100
+ assert_appends_value :params_filters
101
+ end
102
+
103
+ should "warn when attempting to read environment filters" do
104
+ config = HoptoadNotifier::Configuration.new
105
+ config.
106
+ expects(:warn).
107
+ with(regexp_matches(/deprecated/i))
108
+ assert_equal [], config.environment_filters
109
+ end
110
+
111
+ should "allow ignored user agents to be appended" do
112
+ assert_appends_value :ignore_user_agent
113
+ end
114
+
115
+ should "allow backtrace filters to be appended" do
116
+ assert_appends_value(:backtrace_filters) do |config|
117
+ new_filter = lambda {}
118
+ config.filter_backtrace(&new_filter)
119
+ new_filter
120
+ end
121
+ end
122
+
123
+ should "allow ignore by filters to be appended" do
124
+ assert_appends_value(:ignore_by_filters) do |config|
125
+ new_filter = lambda {}
126
+ config.ignore_by_filter(&new_filter)
127
+ new_filter
128
+ end
129
+ end
130
+
131
+ should "allow ignored exceptions to be appended" do
132
+ config = HoptoadNotifier::Configuration.new
133
+ original_filters = config.ignore.dup
134
+ new_filter = 'hello'
135
+ config.ignore << new_filter
136
+ assert_same_elements original_filters + [new_filter], config.ignore
137
+ end
138
+
139
+ should "allow ignored exceptions to be replaced" do
140
+ assert_replaces(:ignore, :ignore_only=)
141
+ end
142
+
143
+ should "allow ignored user agents to be replaced" do
144
+ assert_replaces(:ignore_user_agent, :ignore_user_agent_only=)
145
+ end
146
+
147
+ should "use development and test as development environments by default" do
148
+ config = HoptoadNotifier::Configuration.new
149
+ assert_same_elements %w(development test cucumber), config.development_environments
150
+ end
151
+
152
+ should "be public in a public environment" do
153
+ config = HoptoadNotifier::Configuration.new
154
+ config.development_environments = %w(development)
155
+ config.environment_name = 'production'
156
+ assert config.public?
157
+ end
158
+
159
+ should "not be public in a development environment" do
160
+ config = HoptoadNotifier::Configuration.new
161
+ config.development_environments = %w(staging)
162
+ config.environment_name = 'staging'
163
+ assert !config.public?
164
+ end
165
+
166
+ should "be public without an environment name" do
167
+ config = HoptoadNotifier::Configuration.new
168
+ assert config.public?
169
+ end
170
+
171
+ should "use the assigned logger if set" do
172
+ config = HoptoadNotifier::Configuration.new
173
+ config.logger = "CUSTOM LOGGER"
174
+ assert_equal "CUSTOM LOGGER", config.logger
175
+ end
176
+
177
+ def assert_config_default(option, default_value, config = nil)
178
+ config ||= HoptoadNotifier::Configuration.new
179
+ assert_equal default_value, config.send(option)
180
+ end
181
+
182
+ def assert_config_overridable(option, value = 'a value')
183
+ config = HoptoadNotifier::Configuration.new
184
+ config.send(:"#{option}=", value)
185
+ assert_equal value, config.send(option)
186
+ end
187
+
188
+ def assert_appends_value(option, &block)
189
+ config = HoptoadNotifier::Configuration.new
190
+ original_values = config.send(option).dup
191
+ block ||= lambda do |config|
192
+ new_value = 'hello'
193
+ config.send(option) << new_value
194
+ new_value
195
+ end
196
+ new_value = block.call(config)
197
+ assert_same_elements original_values + [new_value], config.send(option)
198
+ end
199
+
200
+ def assert_replaces(option, setter)
201
+ config = HoptoadNotifier::Configuration.new
202
+ new_value = 'hello'
203
+ config.send(setter, [new_value])
204
+ assert_equal [new_value], config.send(option)
205
+ config.send(setter, new_value)
206
+ assert_equal [new_value], config.send(option)
207
+ end
208
+
209
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,239 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+
4
+ gem 'jferris-mocha', '>= 0.9.5.0.1241126838'
5
+
6
+ $LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. vendor ginger lib])
7
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
8
+
9
+ require 'shoulda'
10
+ require 'mocha'
11
+
12
+ require 'ginger'
13
+
14
+ require 'action_controller'
15
+ require 'action_controller/test_process'
16
+ require 'active_record'
17
+ require 'active_record/base'
18
+ require 'active_support'
19
+ require 'nokogiri'
20
+ require 'rack'
21
+
22
+ require "hoptoad_notifier"
23
+
24
+ begin require 'redgreen'; rescue LoadError; end
25
+
26
+ module TestMethods
27
+ def rescue_action e
28
+ raise e
29
+ end
30
+
31
+ def do_raise
32
+ raise "Hoptoad"
33
+ end
34
+
35
+ def do_not_raise
36
+ render :text => "Success"
37
+ end
38
+
39
+ def do_raise_ignored
40
+ raise ActiveRecord::RecordNotFound.new("404")
41
+ end
42
+
43
+ def do_raise_not_ignored
44
+ raise ActiveRecord::StatementInvalid.new("Statement invalid")
45
+ end
46
+
47
+ def manual_notify
48
+ notify_hoptoad(Exception.new)
49
+ render :text => "Success"
50
+ end
51
+
52
+ def manual_notify_ignored
53
+ notify_hoptoad(ActiveRecord::RecordNotFound.new("404"))
54
+ render :text => "Success"
55
+ end
56
+ end
57
+
58
+ class HoptoadController < ActionController::Base
59
+ include TestMethods
60
+ end
61
+
62
+ class Test::Unit::TestCase
63
+ def request(action = nil, method = :get, user_agent = nil, params = {})
64
+ @request = ActionController::TestRequest.new
65
+ @request.action = action ? action.to_s : ""
66
+
67
+ if user_agent
68
+ if @request.respond_to?(:user_agent=)
69
+ @request.user_agent = user_agent
70
+ else
71
+ @request.env["HTTP_USER_AGENT"] = user_agent
72
+ end
73
+ end
74
+ @request.query_parameters = @request.query_parameters.merge(params)
75
+ @response = ActionController::TestResponse.new
76
+ @controller.process(@request, @response)
77
+ end
78
+
79
+ # Borrowed from ActiveSupport 2.3.2
80
+ def assert_difference(expression, difference = 1, message = nil, &block)
81
+ b = block.send(:binding)
82
+ exps = Array.wrap(expression)
83
+ before = exps.map { |e| eval(e, b) }
84
+
85
+ yield
86
+
87
+ exps.each_with_index do |e, i|
88
+ error = "#{e.inspect} didn't change by #{difference}"
89
+ error = "#{message}.\n#{error}" if message
90
+ assert_equal(before[i] + difference, eval(e, b), error)
91
+ end
92
+ end
93
+
94
+ def assert_no_difference(expression, message = nil, &block)
95
+ assert_difference expression, 0, message, &block
96
+ end
97
+
98
+ def stub_sender
99
+ stub('sender', :send_to_hoptoad => nil)
100
+ end
101
+
102
+ def stub_sender!
103
+ HoptoadNotifier.sender = stub_sender
104
+ end
105
+
106
+ def stub_notice
107
+ stub('notice', :to_xml => 'some yaml', :ignore? => false)
108
+ end
109
+
110
+ def stub_notice!
111
+ returning stub_notice do |notice|
112
+ HoptoadNotifier::Notice.stubs(:new => notice)
113
+ end
114
+ end
115
+
116
+ def create_dummy
117
+ HoptoadNotifier::DummySender.new
118
+ end
119
+
120
+ def reset_config
121
+ HoptoadNotifier.configuration = nil
122
+ HoptoadNotifier.configure do |config|
123
+ config.api_key = 'abc123'
124
+ end
125
+ end
126
+
127
+ def clear_backtrace_filters
128
+ HoptoadNotifier.configuration.backtrace_filters.clear
129
+ end
130
+
131
+ def build_exception
132
+ raise
133
+ rescue => caught_exception
134
+ caught_exception
135
+ end
136
+
137
+ def build_notice_data(exception = nil)
138
+ exception ||= build_exception
139
+ {
140
+ :api_key => 'abc123',
141
+ :error_class => exception.class.name,
142
+ :error_message => "#{exception.class.name}: #{exception.message}",
143
+ :backtrace => exception.backtrace,
144
+ :environment => { 'PATH' => '/bin', 'REQUEST_URI' => '/users/1' },
145
+ :request => {
146
+ :params => { 'controller' => 'users', 'action' => 'show', 'id' => '1' },
147
+ :rails_root => '/path/to/application',
148
+ :url => "http://test.host/users/1"
149
+ },
150
+ :session => {
151
+ :key => '123abc',
152
+ :data => { 'user_id' => '5', 'flash' => { 'notice' => 'Logged in successfully' } }
153
+ }
154
+ }
155
+ end
156
+
157
+ def assert_caught_and_sent
158
+ assert !HoptoadNotifier.sender.collected.empty?
159
+ end
160
+
161
+ def assert_caught_and_not_sent
162
+ assert HoptoadNotifier.sender.collected.empty?
163
+ end
164
+
165
+ def assert_array_starts_with(expected, actual)
166
+ assert_respond_to actual, :to_ary
167
+ array = actual.to_ary.reverse
168
+ expected.reverse.each_with_index do |value, i|
169
+ assert_equal value, array[i]
170
+ end
171
+ end
172
+
173
+ def assert_valid_node(document, xpath, content)
174
+ nodes = document.xpath(xpath)
175
+ assert nodes.any?{|node| node.content == content },
176
+ "Expected xpath #{xpath} to have content #{content}, " +
177
+ "but found #{nodes.map { |n| n.content }} in #{nodes.size} matching nodes." +
178
+ "Document:\n#{document.to_s}"
179
+ end
180
+ end
181
+
182
+ module DefinesConstants
183
+ def setup
184
+ @defined_constants = []
185
+ end
186
+
187
+ def teardown
188
+ @defined_constants.each do |constant|
189
+ Object.__send__(:remove_const, constant)
190
+ end
191
+ end
192
+
193
+ def define_constant(name, value)
194
+ Object.const_set(name, value)
195
+ @defined_constants << name
196
+ end
197
+ end
198
+
199
+ # Also stolen from AS 2.3.2
200
+ class Array
201
+ # Wraps the object in an Array unless it's an Array. Converts the
202
+ # object to an Array using #to_ary if it implements that.
203
+ def self.wrap(object)
204
+ case object
205
+ when nil
206
+ []
207
+ when self
208
+ object
209
+ else
210
+ if object.respond_to?(:to_ary)
211
+ object.to_ary
212
+ else
213
+ [object]
214
+ end
215
+ end
216
+ end
217
+
218
+ end
219
+
220
+ class CollectingSender
221
+ attr_reader :collected
222
+
223
+ def initialize
224
+ @collected = []
225
+ end
226
+
227
+ def send_to_hoptoad(data)
228
+ @collected << data
229
+ end
230
+ end
231
+
232
+ class FakeLogger
233
+ def info(*args); end
234
+ def debug(*args); end
235
+ def warn(*args); end
236
+ def error(*args); end
237
+ def fatal(*args); end
238
+ end
239
+
@@ -0,0 +1,152 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+ require 'rubygems'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/hoptoad_tasks'
5
+ require 'fakeweb'
6
+
7
+ FakeWeb.allow_net_connect = false
8
+
9
+ class HoptoadTasksTest < Test::Unit::TestCase
10
+ def successful_response(body = "")
11
+ response = Net::HTTPSuccess.new('1.2', '200', 'OK')
12
+ response.stubs(:body).returns(body)
13
+ return response
14
+ end
15
+
16
+ def unsuccessful_response(body = "")
17
+ response = Net::HTTPClientError.new('1.2', '200', 'OK')
18
+ response.stubs(:body).returns(body)
19
+ return response
20
+ end
21
+
22
+ context "being quiet" do
23
+ setup { HoptoadTasks.stubs(:puts) }
24
+
25
+ context "in a configured project" do
26
+ setup { HoptoadNotifier.configure { |config| config.api_key = "1234123412341234" } }
27
+
28
+ context "on deploy({})" do
29
+ setup { @output = HoptoadTasks.deploy({}) }
30
+
31
+ before_should "complain about missing rails env" do
32
+ HoptoadTasks.expects(:puts).with(regexp_matches(/rails environment/i))
33
+ end
34
+
35
+ should "return false" do
36
+ assert !@output
37
+ end
38
+ end
39
+
40
+ context "given an optional HTTP proxy and valid options" do
41
+ setup do
42
+ @response = stub("response", :body => "stub body")
43
+ @http_proxy = stub("proxy", :post_form => @response)
44
+
45
+ Net::HTTP.expects(:Proxy).
46
+ with(HoptoadNotifier.configuration.proxy_host,
47
+ HoptoadNotifier.configuration.proxy_port,
48
+ HoptoadNotifier.configuration.proxy_user,
49
+ HoptoadNotifier.configuration.proxy_pass).
50
+ returns(@http_proxy)
51
+
52
+ @options = { :rails_env => "staging" }
53
+ end
54
+
55
+ context "on deploy(options)" do
56
+ setup do
57
+ @output = HoptoadTasks.deploy(@options)
58
+ end
59
+
60
+ before_should "post to http://hoptoadapp.com/deploys.txt" do
61
+ URI.stubs(:parse).with('http://hoptoadapp.com/deploys.txt').returns(:uri)
62
+ @http_proxy.expects(:post_form).with(:uri, kind_of(Hash)).returns(successful_response)
63
+ end
64
+
65
+ before_should "use the project api key" do
66
+ @http_proxy.expects(:post_form).
67
+ with(kind_of(URI), has_entries('api_key' => "1234123412341234")).
68
+ returns(successful_response)
69
+ end
70
+
71
+ before_should "use send the rails_env param" do
72
+ @http_proxy.expects(:post_form).
73
+ with(kind_of(URI), has_entries("deploy[rails_env]" => "staging")).
74
+ returns(successful_response)
75
+ end
76
+
77
+ [:local_username, :scm_repository, :scm_revision].each do |key|
78
+ before_should "use send the #{key} param if it's passed in." do
79
+ @options[key] = "value"
80
+ @http_proxy.expects(:post_form).
81
+ with(kind_of(URI), has_entries("deploy[#{key}]" => "value")).
82
+ returns(successful_response)
83
+ end
84
+ end
85
+
86
+ before_should "use the :api_key param if it's passed in." do
87
+ @options[:api_key] = "value"
88
+ @http_proxy.expects(:post_form).
89
+ with(kind_of(URI), has_entries("api_key" => "value")).
90
+ returns(successful_response)
91
+ end
92
+
93
+ before_should "puts the response body on success" do
94
+ HoptoadTasks.expects(:puts).with("body")
95
+ @http_proxy.expects(:post_form).with(any_parameters).returns(successful_response('body'))
96
+ end
97
+
98
+ before_should "puts the response body on failure" do
99
+ HoptoadTasks.expects(:puts).with("body")
100
+ @http_proxy.expects(:post_form).with(any_parameters).returns(unsuccessful_response('body'))
101
+ end
102
+
103
+ should "return false on failure", :before => lambda {
104
+ @http_proxy.expects(:post_form).with(any_parameters).returns(unsuccessful_response('body'))
105
+ } do
106
+ assert !@output
107
+ end
108
+
109
+ should "return true on success", :before => lambda {
110
+ @http_proxy.expects(:post_form).with(any_parameters).returns(successful_response('body'))
111
+ } do
112
+ assert @output
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ context "in a configured project with custom host" do
119
+ setup do
120
+ HoptoadNotifier.configure do |config|
121
+ config.api_key = "1234123412341234"
122
+ config.host = "custom.host"
123
+ end
124
+ end
125
+
126
+ context "on deploy(:rails_env => 'staging')" do
127
+ setup { @output = HoptoadTasks.deploy(:rails_env => "staging") }
128
+
129
+ before_should "post to the custom host" do
130
+ URI.stubs(:parse).with('http://custom.host/deploys.txt').returns(:uri)
131
+ Net::HTTP.expects(:post_form).with(:uri, kind_of(Hash)).returns(successful_response)
132
+ end
133
+ end
134
+ end
135
+
136
+ context "when not configured" do
137
+ setup { HoptoadNotifier.configure { |config| config.api_key = "" } }
138
+
139
+ context "on deploy(:rails_env => 'staging')" do
140
+ setup { @output = HoptoadTasks.deploy(:rails_env => "staging") }
141
+
142
+ before_should "complain about missing api key" do
143
+ HoptoadTasks.expects(:puts).with(regexp_matches(/api key/i))
144
+ end
145
+
146
+ should "return false" do
147
+ assert !@output
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end