errornot_notifier 0.1.0
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.
- data/INSTALL +25 -0
- data/MIT-LICENSE +22 -0
- data/README.rdoc +289 -0
- data/Rakefile +124 -0
- data/SUPPORTED_RAILS_VERSIONS +8 -0
- data/TESTING.rdoc +8 -0
- data/generators/hoptoad/hoptoad_generator.rb +55 -0
- data/generators/hoptoad/lib/insert_commands.rb +34 -0
- data/generators/hoptoad/lib/rake_commands.rb +24 -0
- data/generators/hoptoad/templates/capistrano_hook.rb +6 -0
- data/generators/hoptoad/templates/hoptoad_notifier_tasks.rake +5 -0
- data/generators/hoptoad/templates/initializer.rb +7 -0
- data/lib/hoptoad_notifier/backtrace.rb +99 -0
- data/lib/hoptoad_notifier/capistrano.rb +20 -0
- data/lib/hoptoad_notifier/configuration.rb +232 -0
- data/lib/hoptoad_notifier/notice.rb +287 -0
- data/lib/hoptoad_notifier/rack.rb +40 -0
- data/lib/hoptoad_notifier/rails/action_controller_catcher.rb +29 -0
- data/lib/hoptoad_notifier/rails/controller_methods.rb +59 -0
- data/lib/hoptoad_notifier/rails/error_lookup.rb +33 -0
- data/lib/hoptoad_notifier/rails.rb +37 -0
- data/lib/hoptoad_notifier/sender.rb +85 -0
- data/lib/hoptoad_notifier/tasks.rb +97 -0
- data/lib/hoptoad_notifier/version.rb +3 -0
- data/lib/hoptoad_notifier.rb +146 -0
- data/lib/hoptoad_tasks.rb +37 -0
- data/lib/templates/rescue.erb +91 -0
- data/rails/init.rb +1 -0
- data/script/integration_test.rb +38 -0
- data/test/backtrace_test.rb +118 -0
- data/test/catcher_test.rb +300 -0
- data/test/configuration_test.rb +208 -0
- data/test/helper.rb +232 -0
- data/test/hoptoad_tasks_test.rb +138 -0
- data/test/logger_test.rb +85 -0
- data/test/notice_test.rb +395 -0
- data/test/notifier_test.rb +222 -0
- data/test/rack_test.rb +58 -0
- data/test/rails_initializer_test.rb +36 -0
- data/test/sender_test.rb +123 -0
- metadata +164 -0
data/test/helper.rb
ADDED
@@ -0,0 +1,232 @@
|
|
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
|
+
end
|
174
|
+
|
175
|
+
module DefinesConstants
|
176
|
+
def setup
|
177
|
+
@defined_constants = []
|
178
|
+
end
|
179
|
+
|
180
|
+
def teardown
|
181
|
+
@defined_constants.each do |constant|
|
182
|
+
Object.__send__(:remove_const, constant)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def define_constant(name, value)
|
187
|
+
Object.const_set(name, value)
|
188
|
+
@defined_constants << name
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Also stolen from AS 2.3.2
|
193
|
+
class Array
|
194
|
+
# Wraps the object in an Array unless it's an Array. Converts the
|
195
|
+
# object to an Array using #to_ary if it implements that.
|
196
|
+
def self.wrap(object)
|
197
|
+
case object
|
198
|
+
when nil
|
199
|
+
[]
|
200
|
+
when self
|
201
|
+
object
|
202
|
+
else
|
203
|
+
if object.respond_to?(:to_ary)
|
204
|
+
object.to_ary
|
205
|
+
else
|
206
|
+
[object]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
class CollectingSender
|
214
|
+
attr_reader :collected
|
215
|
+
|
216
|
+
def initialize
|
217
|
+
@collected = []
|
218
|
+
end
|
219
|
+
|
220
|
+
def send_to_hoptoad(data)
|
221
|
+
@collected << data
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class FakeLogger
|
226
|
+
def info(*args); end
|
227
|
+
def debug(*args); end
|
228
|
+
def warn(*args); end
|
229
|
+
def error(*args); end
|
230
|
+
def fatal(*args); end
|
231
|
+
end
|
232
|
+
|
@@ -0,0 +1,138 @@
|
|
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 valid options" do
|
41
|
+
setup { @options = {:rails_env => "staging"} }
|
42
|
+
|
43
|
+
context "on deploy(options)" do
|
44
|
+
setup { @output = HoptoadTasks.deploy(@options) }
|
45
|
+
|
46
|
+
before_should "post to http://hoptoadapp.com/deploys.txt" do
|
47
|
+
URI.stubs(:parse).with('http://hoptoadapp.com/deploys.txt').returns(:uri)
|
48
|
+
Net::HTTP.expects(:post_form).with(:uri, kind_of(Hash)).returns(successful_response)
|
49
|
+
end
|
50
|
+
|
51
|
+
before_should "use the project api key" do
|
52
|
+
Net::HTTP.expects(:post_form).
|
53
|
+
with(kind_of(URI), has_entries('api_key' => "1234123412341234")).
|
54
|
+
returns(successful_response)
|
55
|
+
end
|
56
|
+
|
57
|
+
before_should "use send the rails_env param" do
|
58
|
+
Net::HTTP.expects(:post_form).
|
59
|
+
with(kind_of(URI), has_entries("deploy[rails_env]" => "staging")).
|
60
|
+
returns(successful_response)
|
61
|
+
end
|
62
|
+
|
63
|
+
[:local_username, :scm_repository, :scm_revision].each do |key|
|
64
|
+
before_should "use send the #{key} param if it's passed in." do
|
65
|
+
@options[key] = "value"
|
66
|
+
Net::HTTP.expects(:post_form).
|
67
|
+
with(kind_of(URI), has_entries("deploy[#{key}]" => "value")).
|
68
|
+
returns(successful_response)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
before_should "use the :api_key param if it's passed in." do
|
73
|
+
@options[:api_key] = "value"
|
74
|
+
Net::HTTP.expects(:post_form).
|
75
|
+
with(kind_of(URI), has_entries("api_key" => "value")).
|
76
|
+
returns(successful_response)
|
77
|
+
end
|
78
|
+
|
79
|
+
before_should "puts the response body on success" do
|
80
|
+
HoptoadTasks.expects(:puts).with("body")
|
81
|
+
Net::HTTP.expects(:post_form).with(any_parameters).returns(successful_response('body'))
|
82
|
+
end
|
83
|
+
|
84
|
+
before_should "puts the response body on failure" do
|
85
|
+
HoptoadTasks.expects(:puts).with("body")
|
86
|
+
Net::HTTP.expects(:post_form).with(any_parameters).returns(unsuccessful_response('body'))
|
87
|
+
end
|
88
|
+
|
89
|
+
should "return false on failure", :before => lambda {
|
90
|
+
Net::HTTP.expects(:post_form).with(any_parameters).returns(unsuccessful_response('body'))
|
91
|
+
} do
|
92
|
+
assert !@output
|
93
|
+
end
|
94
|
+
|
95
|
+
should "return true on success", :before => lambda {
|
96
|
+
Net::HTTP.expects(:post_form).with(any_parameters).returns(successful_response('body'))
|
97
|
+
} do
|
98
|
+
assert @output
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "in a configured project with custom host" do
|
105
|
+
setup do
|
106
|
+
HoptoadNotifier.configure do |config|
|
107
|
+
config.api_key = "1234123412341234"
|
108
|
+
config.host = "custom.host"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "on deploy(:rails_env => 'staging')" do
|
113
|
+
setup { @output = HoptoadTasks.deploy(:rails_env => "staging") }
|
114
|
+
|
115
|
+
before_should "post to the custom host" do
|
116
|
+
URI.stubs(:parse).with('http://custom.host/deploys.txt').returns(:uri)
|
117
|
+
Net::HTTP.expects(:post_form).with(:uri, kind_of(Hash)).returns(successful_response)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when not configured" do
|
123
|
+
setup { HoptoadNotifier.configure { |config| config.api_key = "" } }
|
124
|
+
|
125
|
+
context "on deploy(:rails_env => 'staging')" do
|
126
|
+
setup { @output = HoptoadTasks.deploy(:rails_env => "staging") }
|
127
|
+
|
128
|
+
before_should "complain about missing api key" do
|
129
|
+
HoptoadTasks.expects(:puts).with(regexp_matches(/api key/i))
|
130
|
+
end
|
131
|
+
|
132
|
+
should "return false" do
|
133
|
+
assert !@output
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/test/logger_test.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class LoggerTest < Test::Unit::TestCase
|
4
|
+
def stub_http(response, body = nil)
|
5
|
+
response.stubs(:body => body) if body
|
6
|
+
@http = stub(:post => response,
|
7
|
+
:read_timeout= => nil,
|
8
|
+
:open_timeout= => nil,
|
9
|
+
:use_ssl= => nil)
|
10
|
+
Net::HTTP.stubs(:new).returns(@http)
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_notice
|
14
|
+
HoptoadNotifier.sender.send_to_hoptoad('data')
|
15
|
+
end
|
16
|
+
|
17
|
+
def stub_verbose_log
|
18
|
+
HoptoadNotifier.stubs(:write_verbose_log)
|
19
|
+
end
|
20
|
+
|
21
|
+
def assert_logged(expected)
|
22
|
+
assert_received(HoptoadNotifier, :write_verbose_log) do |expect|
|
23
|
+
expect.with {|actual| actual =~ expected }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def assert_not_logged(expected)
|
28
|
+
assert_received(HoptoadNotifier, :write_verbose_log) do |expect|
|
29
|
+
expect.with {|actual| actual =~ expected }.never
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def configure
|
34
|
+
HoptoadNotifier.configure { |config| }
|
35
|
+
end
|
36
|
+
|
37
|
+
should "report that notifier is ready when configured" do
|
38
|
+
stub_verbose_log
|
39
|
+
configure
|
40
|
+
assert_logged /Notifier (.*) ready/
|
41
|
+
end
|
42
|
+
|
43
|
+
should "not report that notifier is ready when internally configured" do
|
44
|
+
stub_verbose_log
|
45
|
+
HoptoadNotifier.configure(true) { |config| }
|
46
|
+
assert_not_logged /.*/
|
47
|
+
end
|
48
|
+
|
49
|
+
should "print environment info a successful notification without a body" do
|
50
|
+
reset_config
|
51
|
+
stub_verbose_log
|
52
|
+
stub_http(Net::HTTPSuccess)
|
53
|
+
send_notice
|
54
|
+
assert_logged /Environment Info:/
|
55
|
+
assert_not_logged /Response from Hoptoad:/
|
56
|
+
end
|
57
|
+
|
58
|
+
should "print environment info on a failed notification without a body" do
|
59
|
+
reset_config
|
60
|
+
stub_verbose_log
|
61
|
+
stub_http(Net::HTTPError)
|
62
|
+
send_notice
|
63
|
+
assert_logged /Environment Info:/
|
64
|
+
assert_not_logged /Response from Hoptoad:/
|
65
|
+
end
|
66
|
+
|
67
|
+
should "print environment info and response on a success with a body" do
|
68
|
+
reset_config
|
69
|
+
stub_verbose_log
|
70
|
+
stub_http(Net::HTTPSuccess, 'test')
|
71
|
+
send_notice
|
72
|
+
assert_logged /Environment Info:/
|
73
|
+
assert_logged /Response from Hoptoad:/
|
74
|
+
end
|
75
|
+
|
76
|
+
should "print environment info and response on a failure with a body" do
|
77
|
+
reset_config
|
78
|
+
stub_verbose_log
|
79
|
+
stub_http(Net::HTTPError, 'test')
|
80
|
+
send_notice
|
81
|
+
assert_logged /Environment Info:/
|
82
|
+
assert_logged /Response from Hoptoad:/
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|