party_fouls 1.5.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.
- checksums.yaml +7 -0
- data/README.md +268 -0
- data/Rakefile +19 -0
- data/lib/generators/party_foul/install_generator.rb +38 -0
- data/lib/generators/party_foul/templates/party_foul.rb +39 -0
- data/lib/party_foul/exception_handler.rb +106 -0
- data/lib/party_foul/issue_renderers/base.rb +187 -0
- data/lib/party_foul/issue_renderers/rack.rb +54 -0
- data/lib/party_foul/issue_renderers/rackless.rb +25 -0
- data/lib/party_foul/issue_renderers/rails.rb +35 -0
- data/lib/party_foul/issue_renderers.rb +5 -0
- data/lib/party_foul/middleware.rb +32 -0
- data/lib/party_foul/processors/base.rb +11 -0
- data/lib/party_foul/processors/delayed_job.rb +16 -0
- data/lib/party_foul/processors/resque.rb +16 -0
- data/lib/party_foul/processors/sidekiq.rb +17 -0
- data/lib/party_foul/processors/sync.rb +11 -0
- data/lib/party_foul/processors.rb +2 -0
- data/lib/party_foul/rackless_exception_handler.rb +17 -0
- data/lib/party_foul/version.rb +3 -0
- data/lib/party_foul.rb +92 -0
- data/test/generator_test.rb +26 -0
- data/test/party_foul/configure_test.rb +37 -0
- data/test/party_foul/exception_handler_test.rb +205 -0
- data/test/party_foul/issue_renderers/base_test.rb +210 -0
- data/test/party_foul/issue_renderers/rack_test.rb +80 -0
- data/test/party_foul/issue_renderers/rackless_test.rb +29 -0
- data/test/party_foul/issue_renderers/rails_test.rb +83 -0
- data/test/party_foul/middleware_test.rb +48 -0
- data/test/party_foul/rackless_exception_handler_test.rb +33 -0
- data/test/test_helper.rb +42 -0
- data/test/tmp/config/initializers/party_foul.rb +39 -0
- metadata +214 -0
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'action_dispatch/http/parameter_filter'
|
4
|
+
|
5
|
+
describe 'Party Foul Issue Renderer Base' do
|
6
|
+
before do
|
7
|
+
Time.stubs(:now).returns(Time.new(1970, 1, 1, 0, 0, 0, '-05:00'))
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
clean_up_party
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#body' do
|
15
|
+
describe 'updating issue body' do
|
16
|
+
before do
|
17
|
+
@rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
18
|
+
@rendered_issue.stubs(:exception).returns('Test Exception')
|
19
|
+
@rendered_issue.stubs(:fingerprint).returns('abcdefg1234567890')
|
20
|
+
@rendered_issue.stubs(:stack_trace)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'updates count and timestamp' do
|
24
|
+
body = <<-BODY.gsub(/\n/, '')
|
25
|
+
<table>
|
26
|
+
<tr><th>Exception</th><td>Test Exception</td></tr>
|
27
|
+
<tr><th>Last Occurrence</th><td>January 01, 1970 00:00:00 -0500</td></tr>
|
28
|
+
<tr><th>Count</th><td>1</td></tr>
|
29
|
+
</table>
|
30
|
+
|
31
|
+
## Stack Trace
|
32
|
+
<pre></pre>
|
33
|
+
Fingerprint: `abcdefg1234567890`
|
34
|
+
BODY
|
35
|
+
|
36
|
+
Time.stubs(:now).returns(Time.new(1985, 10, 25, 1, 22, 0, '-05:00'))
|
37
|
+
|
38
|
+
expected_body = <<-BODY.gsub(/\n/, '')
|
39
|
+
<table>
|
40
|
+
<tr><th>Exception</th><td>Test Exception</td></tr>
|
41
|
+
<tr><th>Last Occurrence</th><td>October 25, 1985 01:22:00 -0500</td></tr>
|
42
|
+
<tr><th>Count</th><td>2</td></tr>
|
43
|
+
</table>
|
44
|
+
|
45
|
+
## Stack Trace
|
46
|
+
<pre></pre>
|
47
|
+
Fingerprint: `abcdefg1234567890`
|
48
|
+
BODY
|
49
|
+
|
50
|
+
@rendered_issue.update_body(body).must_equal expected_body
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'empty body' do
|
55
|
+
before do
|
56
|
+
@rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
57
|
+
@rendered_issue.stubs(:exception).returns('Test Exception')
|
58
|
+
@rendered_issue.stubs(:fingerprint).returns('abcdefg1234567890')
|
59
|
+
@rendered_issue.stubs(:stack_trace)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'resets body' do
|
63
|
+
expected_body = <<-BODY
|
64
|
+
<table><tr><th>Exception</th><td>Test Exception</td></tr><tr><th>Last Occurrence</th><td>January 01, 1970 00:00:00 -0500</td></tr><tr><th>Count</th><td>1</td></tr></table>
|
65
|
+
|
66
|
+
## Stack Trace
|
67
|
+
<pre></pre>
|
68
|
+
Fingerprint: `abcdefg1234567890`
|
69
|
+
BODY
|
70
|
+
@rendered_issue.update_body(nil).must_equal expected_body
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#build_table_from_hash' do
|
76
|
+
it 'builds an HTML table from a hash' do
|
77
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
78
|
+
hash = { 'Value 1' => 'abc', 'Value 2' => { 'Value A' => 123, 'Value B' => 456 } }
|
79
|
+
expected = '<table><tr><th>Value 1</th><td>abc</td></tr><tr><th>Value 2</th><td><table><tr><th>Value A</th><td>123</td></tr><tr><th>Value B</th><td>456</td></tr></table></td></tr></table>'
|
80
|
+
rendered_issue.build_table_from_hash(hash).must_equal expected
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'escapes HTML entities' do
|
84
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
85
|
+
hash = { 'Value 1' => 'Error in #<Foo>' }
|
86
|
+
expected = '<table><tr><th>Value 1</th><td>Error in #<Foo></td></tr></table>'
|
87
|
+
rendered_issue.build_table_from_hash(hash).must_equal expected
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#fingerprint' do
|
92
|
+
it 'SHA1s the title' do
|
93
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
94
|
+
rendered_issue.stubs(:title).returns('abcdefg1234567890')
|
95
|
+
rendered_issue.fingerprint.must_equal Digest::SHA1.hexdigest(rendered_issue.title)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#occurred_at' do
|
100
|
+
it 'memoizes the time' do
|
101
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
102
|
+
expected = rendered_issue.occurred_at
|
103
|
+
Time.stubs(:now).returns(Time.new(1970, 1, 1, 0, 0, 1, '-05:00'))
|
104
|
+
rendered_issue.occurred_at.must_equal expected
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#title' do
|
109
|
+
context 'when no title prefix is configured' do
|
110
|
+
before do
|
111
|
+
PartyFoul.configure do |config|
|
112
|
+
config.title_prefix = nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'masks the object ids in the raw_title' do
|
117
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
118
|
+
rendered_issue.stubs(:raw_title).returns('Error for #<ClassName:0xabcdefg1234567>')
|
119
|
+
rendered_issue.title.must_equal 'Error for #<ClassName:0xXXXXXX>'
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'masks the extended object ids in the raw_title' do
|
123
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
124
|
+
rendered_issue.stubs(:raw_title).returns('Error for #<#<ClassName:0x007fbddbdcd340>:0x007fbddf6be0a0>')
|
125
|
+
rendered_issue.title.must_equal 'Error for #<#<ClassName:0xXXXXXX>:0xXXXXXX>'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when a custom title prefix is configured' do
|
130
|
+
before do
|
131
|
+
PartyFoul.configure do |config|
|
132
|
+
config.title_prefix = 'PRODUCTION'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'adds a custom prefix' do
|
137
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
138
|
+
rendered_issue.stubs(:raw_title).returns('Error')
|
139
|
+
rendered_issue.title.must_equal '[PRODUCTION] Error'
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'generated unique fingerprints' do
|
143
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
144
|
+
rendered_issue.stubs(:raw_title).returns('Error')
|
145
|
+
fingerprint = rendered_issue.fingerprint
|
146
|
+
|
147
|
+
PartyFoul.configure do |config|
|
148
|
+
config.title_prefix = 'STAGING'
|
149
|
+
end
|
150
|
+
|
151
|
+
fingerprint.wont_equal rendered_issue.fingerprint
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'title length limit' do
|
156
|
+
before do
|
157
|
+
PartyFoul.configure do |config|
|
158
|
+
config.title_prefix = 'PRODUCTION'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'at most 256 chars' do
|
163
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(nil, nil)
|
164
|
+
rendered_issue.stubs(:raw_title).returns('F'*300)
|
165
|
+
rendered_issue.title.size.must_equal 256
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#stack_trace' do
|
171
|
+
# it 'returns the stack trace' do
|
172
|
+
# exception = mock do
|
173
|
+
# stubs backtrace: ['/path/to/gems/gem-name/lib/some/file.rb:123 in `method`']
|
174
|
+
# end
|
175
|
+
# rendered_issue = PartyFoul::IssueRenderers::Base.new(exception, nil)
|
176
|
+
# rendered_issue.stack_trace.must_equal exception.backtrace.first
|
177
|
+
# end
|
178
|
+
|
179
|
+
it 'formats the stack trace with shortened bundle paths' do
|
180
|
+
exception = mock do
|
181
|
+
stubs backtrace: ["#{Bundler.bundle_path}/some_gem/lib/some/file.rb:123 in `method`"]
|
182
|
+
end
|
183
|
+
|
184
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(exception, nil)
|
185
|
+
rendered_issue.stack_trace.must_equal '[bundle].../some_gem/lib/some/file.rb:123 in `method`'
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'formats the stack trace with link to shortened application path' do
|
189
|
+
clean_up_party
|
190
|
+
exception = mock do
|
191
|
+
stubs backtrace: ['/path/to/app/lib/some/file.rb:123 in `method`']
|
192
|
+
end
|
193
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(exception, nil)
|
194
|
+
rendered_issue.stubs app_root: '/path/to/app'
|
195
|
+
rendered_issue.stack_trace.must_match "<a href='https://github.com///blob//lib/some/file.rb#L123'>[app].../lib/some/file.rb:123 in `method`</a>"
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'does not link to bundled resources on Heroku' do
|
199
|
+
Bundler.stub(:bundle_path, '/app/vendor/bundle/ruby/2.0.0') do
|
200
|
+
exception = mock do
|
201
|
+
stubs backtrace: ["#{Bundler.bundle_path}/some_gem/lib/some/file.rb:123 in `method`"]
|
202
|
+
end
|
203
|
+
|
204
|
+
rendered_issue = PartyFoul::IssueRenderers::Base.new(exception, nil)
|
205
|
+
rendered_issue.stubs app_root: '/app'
|
206
|
+
rendered_issue.stack_trace.must_equal '[bundle].../some_gem/lib/some/file.rb:123 in `method`'
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe 'Rack Issue Renderer' do
|
4
|
+
describe '#params' do
|
5
|
+
before do
|
6
|
+
@issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil, ::Rack::MockRequest.env_for("/?status=ok"))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'returns the value of the query param' do
|
10
|
+
@issue_renderer.params['status'].must_equal 'ok'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#raw_title' do
|
15
|
+
before do
|
16
|
+
@exception = Exception.new('message')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'constructs the title with the class and instance method' do
|
20
|
+
@issue_renderer = PartyFoul::IssueRenderers::Rack.new(@exception, {})
|
21
|
+
@issue_renderer.send(:raw_title).must_equal %{(Exception) "message"}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#request' do
|
26
|
+
it 'builds a rack request' do
|
27
|
+
issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil, {})
|
28
|
+
assert issue_renderer.request.is_a?(::Rack::Request)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#ip_address_geolocator' do
|
33
|
+
# we are delegating to rack, see
|
34
|
+
# https://github.com/rack/rack/blob/master/test/spec_request.rb
|
35
|
+
|
36
|
+
it 'returns the link to geolocation IP address when REMOTE_ADDR is set' do
|
37
|
+
issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil, { 'REMOTE_ADDR' => '1.2.3.4' })
|
38
|
+
ip_addr = "<a href='http://ipinfo.io/1.2.3.4'>1.2.3.4</a>"
|
39
|
+
issue_renderer.ip_address_locator.must_equal ip_addr
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'return the link to geolocation IP address when HTTP_X_FORWARDED_FOR is set' do
|
43
|
+
issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil, { 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6' })
|
44
|
+
ip_addr = "<a href='http://ipinfo.io/3.4.5.6'>3.4.5.6</a>"
|
45
|
+
issue_renderer.ip_address_locator.must_equal ip_addr
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#url' do
|
50
|
+
it 'returns the method and uri' do
|
51
|
+
issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil, { 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/something' })
|
52
|
+
issue_renderer.url.must_equal '[GET] /something'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#session' do
|
57
|
+
it 'returns the session' do
|
58
|
+
issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil, { 'rack.session' => 'abc:123' })
|
59
|
+
issue_renderer.session.must_equal 'abc:123'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#http_headers' do
|
64
|
+
it 'returns http headers' do
|
65
|
+
issue_renderer = PartyFoul::IssueRenderers::Rack.new(nil,
|
66
|
+
{
|
67
|
+
'HTTP_VERSION' => 'version',
|
68
|
+
'HTTP_USER_AGENT' => 'user agent',
|
69
|
+
'HTTP_ACCEPT_ENCODING' => 'accept encoding',
|
70
|
+
'HTTP_ACCEPT' => 'accept'
|
71
|
+
})
|
72
|
+
|
73
|
+
issue_renderer.http_headers[:Version].must_equal 'version'
|
74
|
+
issue_renderer.http_headers['User Agent'].must_equal 'user agent'
|
75
|
+
issue_renderer.http_headers['Accept Encoding'].must_equal 'accept encoding'
|
76
|
+
issue_renderer.http_headers[:Accept].must_equal 'accept'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe 'Rackless Issue Renderer' do
|
4
|
+
before do
|
5
|
+
@env = { :params => { :val1 => '1', :val2 => '2' }, :class => 'Worker', :method => 'perform' }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#params' do
|
9
|
+
before do
|
10
|
+
@rendered_issue = PartyFoul::IssueRenderers::Rackless.new(nil, @env)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns the parameters' do
|
14
|
+
@rendered_issue.params[:val1].must_equal '1'
|
15
|
+
@rendered_issue.params[:val2].must_equal '2'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#raw_title' do
|
20
|
+
before do
|
21
|
+
@exception = Exception.new('message')
|
22
|
+
@rendered_issue = PartyFoul::IssueRenderers::Rackless.new(@exception, @env)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'constructs the title with the controller and action' do
|
26
|
+
@rendered_issue.send(:raw_title).must_equal %{Worker#perform (Exception) "message"}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe 'Rails Issue Renderer' do
|
4
|
+
describe '#params' do
|
5
|
+
let(:request_parameters) { { 'status' => 'ok', 'password' => 'test' } }
|
6
|
+
before do
|
7
|
+
@rendered_issue = PartyFoul::IssueRenderers::Rails.new(nil, {'action_dispatch.parameter_filter' => ['password'], 'action_dispatch.request.parameters' => request_parameters, 'QUERY_STRING' => { 'status' => 'fail' } })
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'returns ok' do
|
11
|
+
@rendered_issue.params['status'].must_equal 'ok'
|
12
|
+
@rendered_issue.params['password'].must_equal '[FILTERED]'
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'without request parameters' do
|
16
|
+
let(:request_parameters) { nil }
|
17
|
+
|
18
|
+
it 'returns empty hash' do
|
19
|
+
@rendered_issue.params.must_equal({})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#occurred_at' do
|
25
|
+
it 'uses current when possible' do
|
26
|
+
Time.stubs(:now).returns(Time.new(1970, 1, 1, 0, 0, 1, '-08:00'))
|
27
|
+
Time.stubs(:current).returns(Time.new(1970, 1, 1, 0, 0, 1, '-05:00'))
|
28
|
+
current_as_string = Time.current.strftime('%B %d, %Y %H:%M:%S %z')
|
29
|
+
rendered_issue = PartyFoul::IssueRenderers::Rails.new(nil, nil)
|
30
|
+
rendered_issue.occurred_at.must_equal current_as_string
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#session' do
|
35
|
+
let(:params) { {'action_dispatch.parameter_filter' => ['password'], 'rack.session' => { 'status' => 'ok', 'password' => 'test' }, 'QUERY_STRING' => { 'status' => 'fail' } } }
|
36
|
+
|
37
|
+
before do
|
38
|
+
@rendered_issue = PartyFoul::IssueRenderers::Rails.new(nil, params)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns ok' do
|
42
|
+
@rendered_issue.session['status'].must_equal 'ok'
|
43
|
+
@rendered_issue.session['password'].must_equal '[FILTERED]'
|
44
|
+
end
|
45
|
+
|
46
|
+
context "without session" do
|
47
|
+
|
48
|
+
let(:params) { {'action_dispatch.parameter_filter' => ['password'], 'QUERY_STRING' => { 'status' => 'fail' } } }
|
49
|
+
|
50
|
+
it 'returns empty hash' do
|
51
|
+
@rendered_issue.session.must_be_empty
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#raw_title' do
|
59
|
+
let(:request_parameters) { { 'controller' => 'landing', 'action' => 'index' } }
|
60
|
+
before do
|
61
|
+
@exception = Exception.new('message')
|
62
|
+
controller_instance = mock('Controller')
|
63
|
+
controller_instance.stubs(:class).returns('LandingController')
|
64
|
+
env = {
|
65
|
+
'action_dispatch.request.parameters' => request_parameters,
|
66
|
+
'action_controller.instance' => controller_instance
|
67
|
+
}
|
68
|
+
@rendered_issue = PartyFoul::IssueRenderers::Rails.new(@exception, env)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'constructs the title with the controller and action' do
|
72
|
+
@rendered_issue.send(:raw_title).must_equal %{LandingController#index (Exception) "message"}
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'without request parameters' do
|
76
|
+
let(:request_parameters) { nil }
|
77
|
+
|
78
|
+
it 'leaves action blank' do
|
79
|
+
@rendered_issue.send(:raw_title).must_equal %{LandingController# (Exception) "message"}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe 'Party Foul Middleware' do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
after do
|
7
|
+
clean_up_party
|
8
|
+
end
|
9
|
+
|
10
|
+
def error_to_raise
|
11
|
+
Exception
|
12
|
+
end
|
13
|
+
|
14
|
+
def app
|
15
|
+
_self = self
|
16
|
+
Rack::Builder.new {
|
17
|
+
map '/' do
|
18
|
+
use PartyFoul::Middleware
|
19
|
+
run lambda { |env| raise _self.error_to_raise }
|
20
|
+
end
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'handling an exception' do
|
25
|
+
it 'does not handle exception' do
|
26
|
+
PartyFoul::ExceptionHandler.stubs(:handle)
|
27
|
+
PartyFoul::ExceptionHandler.expects(:handle)
|
28
|
+
lambda {
|
29
|
+
get '/'
|
30
|
+
}.must_raise(Exception)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'filtering based upon exception' do
|
35
|
+
before do
|
36
|
+
PartyFoul.blacklisted_exceptions = ['StandardError']
|
37
|
+
self.stubs(:error_to_raise).returns(StandardError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not handle exception' do
|
41
|
+
PartyFoul::ExceptionHandler.stubs(:handle)
|
42
|
+
PartyFoul::ExceptionHandler.expects(:handle).never
|
43
|
+
lambda {
|
44
|
+
get '/'
|
45
|
+
}.must_raise(StandardError)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe 'Party Foul Rackless Exception Handler' do
|
4
|
+
before do
|
5
|
+
PartyFoul.configure do |config|
|
6
|
+
config.oauth_token = 'abcdefg1234567890'
|
7
|
+
config.owner = 'test_owner'
|
8
|
+
config.repo = 'test_repo'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#handle' do
|
13
|
+
it 'will call run on itself' do
|
14
|
+
PartyFoul::RacklessExceptionHandler.any_instance.expects(:run)
|
15
|
+
PartyFoul::RacklessExceptionHandler.handle(nil, {})
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should pass parameters required by the renderer to the initializer' do
|
19
|
+
params = {:class => Object, :method => :to_s, :params => {:one => "One", :two => "Two"}}
|
20
|
+
expected_exception_handler = PartyFoul::RacklessExceptionHandler.new(nil, params)
|
21
|
+
expected_exception_handler.expects(:run)
|
22
|
+
PartyFoul::RacklessExceptionHandler.expects(:new).with(nil, params).returns(expected_exception_handler)
|
23
|
+
PartyFoul::RacklessExceptionHandler.handle(nil, params)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#initialize' do
|
28
|
+
it 'should use PartyFoul::IssueRenderers::Rackless for rendering issues' do
|
29
|
+
issue_renderer = PartyFoul::RacklessExceptionHandler.new(nil, {}).rendered_issue
|
30
|
+
assert_kind_of(PartyFoul::IssueRenderers::Rackless, issue_renderer)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
|
3
|
+
if defined?(M)
|
4
|
+
require 'minitest/spec'
|
5
|
+
else
|
6
|
+
require 'minitest/autorun'
|
7
|
+
end
|
8
|
+
begin
|
9
|
+
require 'byebug'
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
require 'rack/test'
|
13
|
+
require 'mocha/setup'
|
14
|
+
require 'active_support'
|
15
|
+
require 'party_foul'
|
16
|
+
|
17
|
+
ActiveSupport.test_order = :random
|
18
|
+
|
19
|
+
class MiniTest::Spec
|
20
|
+
class << self
|
21
|
+
alias :context :describe
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module MiniTest::Expectations
|
26
|
+
infect_an_assertion :assert_received, :must_have_received
|
27
|
+
end
|
28
|
+
|
29
|
+
def clean_up_party
|
30
|
+
%w{github oauth_token api_endpoint owner repo blacklisted_exceptions processor web_url branch additional_labels comment_limit}.each do |attr|
|
31
|
+
PartyFoul.send("#{attr}=", nil)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def sawyer_resource(attrs)
|
36
|
+
agent = Sawyer::Agent.new(PartyFoul.api_endpoint)
|
37
|
+
Sawyer::Resource.new(agent, attrs)
|
38
|
+
end
|
39
|
+
|
40
|
+
def no_search_results
|
41
|
+
sawyer_resource(total_count: 0, incomplete_results: false, items: [])
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
PartyFoul.configure do |config|
|
2
|
+
# The collection of exceptions PartyFoul should not be allowed to handle
|
3
|
+
# The constants here *must* be represented as strings
|
4
|
+
config.blacklisted_exceptions = ['ActiveRecord::RecordNotFound', 'ActionController::RoutingError']
|
5
|
+
|
6
|
+
# The OAuth token for the account that is opening the issues on GitHub
|
7
|
+
config.oauth_token = 'test_token'
|
8
|
+
|
9
|
+
# The API endpoint for GitHub. Unless you are hosting a private
|
10
|
+
# instance of Enterprise GitHub you do not need to include this
|
11
|
+
config.api_endpoint = 'http://api.example.com'
|
12
|
+
|
13
|
+
# The Web URL for GitHub. Unless you are hosting a private
|
14
|
+
# instance of Enterprise GitHub you do not need to include this
|
15
|
+
config.web_url = 'http://example.com'
|
16
|
+
|
17
|
+
# The organization or user that owns the target repository
|
18
|
+
config.owner = 'test_owner'
|
19
|
+
|
20
|
+
# The repository for this application
|
21
|
+
config.repo = 'test_repo'
|
22
|
+
|
23
|
+
# The branch for your deployed code
|
24
|
+
# config.branch = 'master'
|
25
|
+
|
26
|
+
# Additional labels to add to issues created
|
27
|
+
# config.additional_labels = ['production']
|
28
|
+
# or
|
29
|
+
# config.additional_labels = Proc.new do |exception, env|
|
30
|
+
# []
|
31
|
+
# end
|
32
|
+
|
33
|
+
# Limit the number of comments per issue
|
34
|
+
# config.comment_limit = 10
|
35
|
+
|
36
|
+
# Setting your title prefix can help with
|
37
|
+
# distinguishing the issue between environments
|
38
|
+
# config.title_prefix = Rails.env
|
39
|
+
end
|