party_foul 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.md +74 -4
  2. data/Rakefile +0 -19
  3. data/lib/generators/party_foul/install_generator.rb +74 -0
  4. data/lib/party_foul/exception_handler.rb +118 -0
  5. data/lib/party_foul/middleware.rb +32 -0
  6. data/lib/party_foul/version.rb +1 -1
  7. data/lib/party_foul.rb +22 -0
  8. data/test/party_foul/configure_test.rb +25 -0
  9. data/test/party_foul/exception_handler_test.rb +102 -0
  10. data/test/party_foul/middleware_test.rb +106 -0
  11. data/test/test_helper.rb +22 -11
  12. metadata +112 -66
  13. data/lib/tasks/party_foul_tasks.rake +0 -4
  14. data/test/dummy/README.rdoc +0 -261
  15. data/test/dummy/Rakefile +0 -7
  16. data/test/dummy/app/assets/javascripts/application.js +0 -15
  17. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  18. data/test/dummy/app/controllers/application_controller.rb +0 -3
  19. data/test/dummy/app/helpers/application_helper.rb +0 -2
  20. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  21. data/test/dummy/config/application.rb +0 -59
  22. data/test/dummy/config/boot.rb +0 -10
  23. data/test/dummy/config/database.yml +0 -25
  24. data/test/dummy/config/environment.rb +0 -5
  25. data/test/dummy/config/environments/development.rb +0 -37
  26. data/test/dummy/config/environments/production.rb +0 -67
  27. data/test/dummy/config/environments/test.rb +0 -37
  28. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  29. data/test/dummy/config/initializers/inflections.rb +0 -15
  30. data/test/dummy/config/initializers/mime_types.rb +0 -5
  31. data/test/dummy/config/initializers/secret_token.rb +0 -7
  32. data/test/dummy/config/initializers/session_store.rb +0 -8
  33. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  34. data/test/dummy/config/locales/en.yml +0 -5
  35. data/test/dummy/config/routes.rb +0 -58
  36. data/test/dummy/config.ru +0 -4
  37. data/test/dummy/public/404.html +0 -26
  38. data/test/dummy/public/422.html +0 -26
  39. data/test/dummy/public/500.html +0 -25
  40. data/test/dummy/public/favicon.ico +0 -0
  41. data/test/dummy/script/rails +0 -6
  42. data/test/party_foul_test.rb +0 -7
data/README.md CHANGED
@@ -6,25 +6,96 @@
6
6
 
7
7
  Rails exceptions automatically opened as issues on Github
8
8
 
9
+ ## About ##
10
+
11
+ `PartyFoul` will capture exceptions in your application and will do the
12
+ following:
13
+
14
+ 1. Will attempt to find a matching issue in your Github repo
15
+ 2. If no matching issue is found an new issue will be created with a
16
+ unique title, session information, and stack trace. The issue will be
17
+ tagged as a `bug`
18
+ 3. If an open issue is found the occurance count and time stamp will be
19
+ updated
20
+ 4. If a closed issue is found the occurance count and time stamp will be
21
+ updated. The issue will be reopened and a `regression` tag will be
22
+ added.
23
+ 5. If the issue is marked as `wontfix` the issue is not updated nor is
24
+ a new issue created.
25
+
9
26
  ## Installation ##
10
27
 
28
+ Prior to installing the gem you will need to set up an OAuth application
29
+ on Github to provide access to your repository. Once this OAuth
30
+ application is setup you will have a `ClientID` and `ClientSecret` that
31
+ you will need to complete the installation.
32
+
33
+ **Note** We highly recommend that you create a new Github account that is
34
+ a collaborator on your repository. Use this new account's credentials
35
+ for the installation below. If you use your own account you will
36
+ not receive emails when issues are created, updated, reopened, etc...
37
+ because all of the work will be done as your account.
38
+
11
39
  In your Gemfile add the following:
12
40
 
13
41
  ```ruby
14
42
  gem 'party_foul'
15
43
  ```
16
44
 
45
+ ### Rails ###
46
+ If you are using Rails you can run the install generator.
17
47
 
18
- ## Usage ##
48
+ ```
49
+ rails g party_foul:install
50
+ ```
51
+
52
+ This will prompt you for the Github credentials of the account that will
53
+ be opening the issues. The OAuth token for that account will be stored
54
+ in `config/initializers/party_foul.rb`. You may want to remove the token
55
+ string and store in an environment variable. It is best not to store the
56
+ token in version control.
57
+
58
+ Add as the very last middleware in your production `Rack` stack in `config/environments/production.rb`
59
+
60
+ ```ruby
61
+ config.middleware.insert_before(-1, 'PartyFoul::Middleware')
62
+ ```
63
+ ### Other ###
19
64
 
65
+ You will need to initialize `PartyFoul`, you can use the following to do
66
+ so:
20
67
 
21
- ## What you get ##
68
+ ```ruby
69
+ PartyFoul.configure do |config|
70
+ # the collection of exceptions to be ignored by PartyFoul
71
+ # The constants here *must* be represented as strings
72
+ config.ignored_exceptions = ['ActiveRecord::RecordNotFound']
73
+
74
+ # The OAuth token for the account that will be opening the issues on Github
75
+ config.oauth_token = 'abcdefgh1234567890'
76
+
77
+ # The API endpoint for Github. Unless you are hosting a private
78
+ # instance of Enterprise Github you do not need to include this
79
+ config.endpoint = 'https://api.github.com'
80
+
81
+ # The organization or user that owns the target repository
82
+ config.owner = 'owner_name'
83
+
84
+ # The repository for this application
85
+ config.repo = 'repo_name'
86
+ end
87
+ ```
88
+
89
+ Add as the very last middleware in your production `Rack` stack.
90
+
91
+ ## Usage ##
22
92
 
23
93
 
24
94
  ## Authors ##
25
95
 
26
96
  [Brian Cardarella](http://twitter.com/bcardarella)
27
- [Dan McClain](http://twitter.com/danmcclain)
97
+
98
+ [Dan McClain](http://twitter.com/_danmcclain)
28
99
 
29
100
  [We are very thankful for the many contributors](https://github.com/dockyard/party_foul/graphs/contributors)
30
101
 
@@ -45,4 +116,3 @@ on how to properly submit issues and pull requests.
45
116
  [@dockyard](http://twitter.com/dockyard)
46
117
 
47
118
  [Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php)
48
-
data/Rakefile CHANGED
@@ -4,24 +4,6 @@ begin
4
4
  rescue LoadError
5
5
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
6
  end
7
- begin
8
- require 'rdoc/task'
9
- rescue LoadError
10
- require 'rdoc/rdoc'
11
- require 'rake/rdoctask'
12
- RDoc::Task = Rake::RDocTask
13
- end
14
-
15
- RDoc::Task.new(:rdoc) do |rdoc|
16
- rdoc.rdoc_dir = 'rdoc'
17
- rdoc.title = 'PartyFoul'
18
- rdoc.options << '--line-numbers'
19
- rdoc.rdoc_files.include('README.rdoc')
20
- rdoc.rdoc_files.include('lib/**/*.rb')
21
- end
22
-
23
-
24
-
25
7
 
26
8
  Bundler::GemHelper.install_tasks
27
9
 
@@ -34,5 +16,4 @@ Rake::TestTask.new(:test) do |t|
34
16
  t.verbose = false
35
17
  end
36
18
 
37
-
38
19
  task :default => :test
@@ -0,0 +1,74 @@
1
+ require 'rails/generators'
2
+ require 'io/console'
3
+ require 'net/http'
4
+
5
+ module PartyFoul
6
+ class InstallGenerator < Rails::Generators::Base
7
+
8
+ def create_initializer_file
9
+ puts 'A Github Application is required'
10
+
11
+ client_id = ask 'Github App Client ID:'
12
+ client_secret = ask 'Github App Client Secret:'
13
+ username = ask 'Github username:'
14
+ password = STDIN.noecho do
15
+ ask 'Github password:'
16
+ end
17
+ say ''
18
+
19
+ owner = ask 'Repository owner:'
20
+ repo = ask 'Repository name:'
21
+ auth_uri = URI("https://api.github.com/authorizations")
22
+
23
+ response = nil
24
+ Net::HTTP.start(auth_uri.host, auth_uri.port, :use_ssl => auth_uri.scheme == 'https') do |http|
25
+ request = Net::HTTP::Post.new auth_uri.request_uri
26
+ body = { :scopes => ['repo'], :client_id => client_id, :client_secret => client_secret }
27
+ request.body = body.to_json
28
+
29
+ request.basic_auth username, password
30
+
31
+ response = http.request request
32
+ end
33
+
34
+ if response.code == '201'
35
+ oauth_token = JSON.parse(response.body)['token']
36
+
37
+ File.open('config/initializers/party_foul.rb', 'w') do |f|
38
+ f.puts <<-CONTENTS
39
+ PartyFoul.configure do |config|
40
+ # the collection of exceptions to be ignored by PartyFoul
41
+ # The constants here *must* be represented as strings
42
+ config.ignored_exceptions = ['ActiveRecord::RecordNotFound']
43
+
44
+ # The OAuth token for the account that will be opening the issues on Github
45
+ config.oauth_token = '#{oauth_token}'
46
+
47
+ # The API endpoint for Github. Unless you are hosting a private
48
+ # instance of Enterprise Github you do not need to include this
49
+ config.endpoint = 'https://api.github.com'
50
+
51
+ # The organization or user that owns the target repository
52
+ config.owner = '#{owner}'
53
+
54
+ # The repository for this application
55
+ config.repo = '#{repo}'
56
+ end
57
+ CONTENTS
58
+ end
59
+ else
60
+ say 'There was an error retrieving your Github OAuth token'
61
+ end
62
+
63
+ say 'Done'
64
+ end
65
+
66
+ private
67
+
68
+ def self.installation_message
69
+ 'Generates the configuration file'
70
+ end
71
+
72
+ desc installation_message
73
+ end
74
+ end
@@ -0,0 +1,118 @@
1
+ class PartyFoul::ExceptionHandler
2
+ attr_accessor :exception, :env
3
+
4
+ def self.handle(exception, env)
5
+ handler = self.new(exception, env)
6
+ handler.run
7
+ end
8
+
9
+ def initialize(exception, env)
10
+ self.exception = exception
11
+ self.env = env
12
+ end
13
+
14
+ def run
15
+ if issue = find_issue
16
+ update_issue(issue)
17
+ else
18
+ create_issue
19
+ end
20
+ end
21
+
22
+ def find_issue
23
+ unless issue = PartyFoul.github.search.issues(owner: PartyFoul.owner, repo: PartyFoul.repo, state: 'open', keyword: fingerprint).issues.first
24
+ issue = PartyFoul.github.search.issues(owner: PartyFoul.owner, repo: PartyFoul.repo, state: 'closed', keyword: fingerprint).issues.first
25
+ end
26
+
27
+ issue
28
+ end
29
+
30
+ def stack_trace
31
+ exception.backtrace.map do |line|
32
+ if matches = extract_file_name_and_line_number(line)
33
+ "<a href='../tree/master/#{matches[2]}#L#{matches[3]}'>#{line}</a>"
34
+ else
35
+ line
36
+ end
37
+ end.join("\n")
38
+ end
39
+
40
+ def create_issue
41
+ PartyFoul.github.issues.create(PartyFoul.owner, PartyFoul.repo, title: issue_title, body: issue_body, labels: ['bug'])
42
+ end
43
+
44
+ def update_issue(issue)
45
+ unless issue.key?('labels') && issue['labels'].include?('wontfix')
46
+ params = {body: update_body(issue['body']), state: 'open'}
47
+
48
+ if issue['state'] == 'closed'
49
+ params[:labels] = ['bug', 'regression']
50
+ end
51
+
52
+ PartyFoul.github.issues.edit(PartyFoul.owner, PartyFoul.repo, issue['number'], params)
53
+ end
54
+ end
55
+
56
+ def issue_title
57
+ line = exception.backtrace.select {|p| p =~ /#{app_root}/ }.first
58
+ name_and_number = extract_file_name_and_line_number(line)[1]
59
+ "#{exception} - #{name_and_number}"
60
+ end
61
+
62
+ def fingerprint
63
+ Digest::SHA1.hexdigest(issue_title)
64
+ end
65
+
66
+ def update_body(body)
67
+ begin
68
+ current_count = body.match(/<th>Count<\/th><td>(\d+)<\/td>/)[1].to_i
69
+ body.sub!("<th>Count</th><td>#{current_count}</td>", "<th>Count</th><td>#{current_count + 1}</td>")
70
+ body.sub!(/<th>Last Occurance<\/th><td>.+<\/td>/, "<th>Last Occurance</th><td>#{Time.now}</td>")
71
+ body
72
+ rescue
73
+ issue_body
74
+ end
75
+ end
76
+
77
+ def params
78
+ if env["action_dispatch.parameter_filter"]
79
+ parameter_filter = ActionDispatch::Http::ParameterFilter.new(env["action_dispatch.parameter_filter"])
80
+ parameter_filter.filter(env['action_dispatch.request.path_parameters'])
81
+ else
82
+ env['QUERY_STRING']
83
+ end
84
+ end
85
+
86
+ def issue_body
87
+ <<-BODY
88
+ <table>
89
+ <tr><th>Count</th><td>1</td></tr>
90
+ <tr><th>Last Occurance</th><td>#{Time.now}</td></tr>
91
+ <tr><th>Params</th><td>#{params}</td></tr>
92
+ <tr><th>Exception</th><td>#{exception}</td></tr>
93
+ </table>
94
+
95
+ ## Stack Trace
96
+ <pre>#{stack_trace}</pre>
97
+ Fingerprint: `#{fingerprint}`
98
+ BODY
99
+ end
100
+
101
+ private
102
+
103
+ def app_root
104
+ if defined?(Rails)
105
+ Rails.root
106
+ else
107
+ Dir.pwd
108
+ end
109
+ end
110
+
111
+ def file_and_line_regex
112
+ /#{app_root}\/((.+?):(\d+))/
113
+ end
114
+
115
+ def extract_file_name_and_line_number(backtrace_line)
116
+ backtrace_line.match(file_and_line_regex)
117
+ end
118
+ end
@@ -0,0 +1,32 @@
1
+ module PartyFoul
2
+ class Middleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ @app.call(env)
9
+ rescue Exception => captured_exception
10
+ if allow_handling?(captured_exception)
11
+ PartyFoul::ExceptionHandler.handle(captured_exception, env)
12
+ end
13
+ raise captured_exception
14
+ end
15
+
16
+ private
17
+
18
+ def allow_handling?(captured_exception)
19
+ !PartyFoul.ignored_exceptions.find do |ignored_exception|
20
+ names = ignored_exception.split('::')
21
+ names.shift if names.empty? || names.first.empty?
22
+
23
+ constant = Object
24
+ names.each do |name|
25
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
26
+ end
27
+
28
+ constant === captured_exception
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
1
  module PartyFoul
2
- VERSION = "0.0.0"
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/party_foul.rb CHANGED
@@ -1,2 +1,24 @@
1
+ require 'github_api'
2
+
1
3
  module PartyFoul
4
+ class << self
5
+ attr_accessor :github, :oauth_token, :endpoint, :owner, :repo, :ignored_exceptions
6
+ end
7
+
8
+ def self.ignored_exceptions
9
+ @ignored_exceptions || []
10
+ end
11
+
12
+ def self.configure(&block)
13
+ yield self
14
+ _self = self
15
+ self.github ||= Github.new do |config|
16
+ %w{endpoint oauth_token}.each do |option|
17
+ config.send("#{option}=", _self.send(option)) if !_self.send(option).nil?
18
+ end
19
+ end
20
+ end
2
21
  end
22
+
23
+ require 'party_foul/exception_handler'
24
+ require 'party_foul/middleware'
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ describe 'Party Foul Confg' do
4
+
5
+ after do
6
+ clean_up_party
7
+ end
8
+
9
+ it 'sets the proper config variables' do
10
+ PartyFoul.configure do |config|
11
+ config.ignored_exceptions = ['StandardError']
12
+ config.oauth_token = 'test_token'
13
+ config.endpoint = 'test_endpoint'
14
+ config.owner = 'test_owner'
15
+ config.repo = 'test_repo'
16
+ end
17
+
18
+ PartyFoul.ignored_exceptions.must_equal ['StandardError']
19
+ PartyFoul.github.must_be_instance_of Github::Client
20
+ PartyFoul.github.oauth_token.must_equal 'test_token'
21
+ PartyFoul.github.endpoint.must_equal 'test_endpoint'
22
+ PartyFoul.owner.must_equal 'test_owner'
23
+ PartyFoul.repo.must_equal 'test_repo'
24
+ end
25
+ end
@@ -0,0 +1,102 @@
1
+ require 'test_helper'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'action_dispatch/http/parameter_filter'
4
+
5
+ describe 'Party Foul Exception Handler' do
6
+ before do
7
+ Time.stubs(:now).returns(Time.at(0))
8
+ end
9
+
10
+ describe '#body' do
11
+ describe 'updating issue body' do
12
+ before do
13
+ @handler = PartyFoul::ExceptionHandler.new(nil, nil)
14
+ @handler.stubs(:fingerprint).returns('abcdefg1234567890')
15
+ @handler.stubs(:stack_trace)
16
+ @handler.stubs(:params)
17
+ @handler.stubs(:exception)
18
+ end
19
+
20
+ it 'updates count and timestamp' do
21
+ body = <<-BODY
22
+ <table>
23
+ <tr><th>Count</th><td>1</td></tr>
24
+ <tr><th>Last Occurance</th><td>#{Time.now}</td></tr>
25
+ <tr><th>Params</th><td></td></tr>
26
+ <tr><th>Exception</th><td></td></tr>
27
+ </table>
28
+
29
+ ## Stack Trace
30
+ <pre></pre>
31
+ Fingerprint: `abcdefg1234567890`
32
+ BODY
33
+
34
+ Time.stubs(:now).returns(Time.new(1985, 10, 25, 1, 22, 0, '-05:00'))
35
+
36
+ expected_body = <<-BODY
37
+ <table>
38
+ <tr><th>Count</th><td>2</td></tr>
39
+ <tr><th>Last Occurance</th><td>#{Time.now}</td></tr>
40
+ <tr><th>Params</th><td></td></tr>
41
+ <tr><th>Exception</th><td></td></tr>
42
+ </table>
43
+
44
+ ## Stack Trace
45
+ <pre></pre>
46
+ Fingerprint: `abcdefg1234567890`
47
+ BODY
48
+
49
+ @handler.update_body(body).must_equal expected_body
50
+ end
51
+ end
52
+
53
+ describe 'empty body' do
54
+ before do
55
+ @handler = PartyFoul::ExceptionHandler.new(nil, nil)
56
+ @handler.stubs(:fingerprint).returns('abcdefg1234567890')
57
+ @handler.stubs(:stack_trace)
58
+ @handler.stubs(:params)
59
+ @handler.stubs(:exception)
60
+ end
61
+
62
+ it 'resets body' do
63
+ expected_body = <<-BODY
64
+ <table>
65
+ <tr><th>Count</th><td>1</td></tr>
66
+ <tr><th>Last Occurance</th><td>#{Time.now}</td></tr>
67
+ <tr><th>Params</th><td></td></tr>
68
+ <tr><th>Exception</th><td></td></tr>
69
+ </table>
70
+
71
+ ## Stack Trace
72
+ <pre></pre>
73
+ Fingerprint: `abcdefg1234567890`
74
+ BODY
75
+ @handler.update_body(nil).must_equal expected_body
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#params' do
81
+ context 'with Rails' do
82
+ before do
83
+ @handler = PartyFoul::ExceptionHandler.new(nil, {'action_dispatch.parameter_filter' => ['password'], 'action_dispatch.request.path_parameters' => { 'status' => 'ok', 'password' => 'test' }, 'QUERY_STRING' => { 'status' => 'fail' } })
84
+ end
85
+
86
+ it 'returns ok' do
87
+ @handler.params['status'].must_equal 'ok'
88
+ @handler.params['password'].must_equal '[FILTERED]'
89
+ end
90
+ end
91
+
92
+ context 'without Rails' do
93
+ before do
94
+ @handler = PartyFoul::ExceptionHandler.new(nil, {'QUERY_STRING' => { 'status' => 'ok' } })
95
+ end
96
+
97
+ it 'returns ok' do
98
+ @handler.params['status'].must_equal 'ok'
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,106 @@
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
+ before do
25
+ PartyFoul.configure do |config|
26
+ config.oauth_token = 'abcdefg1234567890'
27
+ config.owner = 'test_owner'
28
+ config.repo = 'test_repo'
29
+ end
30
+ PartyFoul.github.stubs(:issues).returns(mock('Issues'))
31
+ PartyFoul.github.stubs(:search).returns(mock('Search'))
32
+ PartyFoul.github.issues.stubs(:create)
33
+ PartyFoul.github.issues.stubs(:edit)
34
+ PartyFoul::ExceptionHandler.any_instance.stubs(:issue_title).returns('Test Title')
35
+ PartyFoul::ExceptionHandler.any_instance.stubs(:fingerprint).returns('test_fingerprint')
36
+ end
37
+
38
+ context 'when error is new' do
39
+ it 'will open a new error on Github' do
40
+ PartyFoul::ExceptionHandler.any_instance.stubs(:issue_body).returns('Test Body')
41
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
42
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: []))
43
+ PartyFoul.github.issues.expects(:create).with('test_owner', 'test_repo', title: 'Test Title', body: 'Test Body', :labels => ['bug'])
44
+ lambda {
45
+ get '/'
46
+ }.must_raise(Exception)
47
+ end
48
+ end
49
+
50
+ context 'when error is not new' do
51
+ before do
52
+ PartyFoul::ExceptionHandler.any_instance.stubs(:update_body).returns('New Body')
53
+ end
54
+
55
+ context 'and open' do
56
+ it 'will update the issue' do
57
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: [{title: 'Test Title', body: 'Test Body', state: 'open', number: 1}]))
58
+ PartyFoul.github.issues.expects(:edit).with('test_owner', 'test_repo', 1, body: 'New Body', state: 'open')
59
+ lambda {
60
+ get '/'
61
+ }.must_raise(Exception)
62
+ end
63
+ end
64
+
65
+ context 'and closed' do
66
+ it 'will update the count on the body and re-open the issue' do
67
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
68
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: [{title: 'Test Title', body: 'Test Body', state: 'closed', number: 1}]))
69
+ PartyFoul.github.issues.expects(:edit).with('test_owner', 'test_repo', 1, body: 'New Body', state: 'open', labels: ['bug', 'regression'])
70
+ lambda {
71
+ get '/'
72
+ }.must_raise(Exception)
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'when issue is marked as "wontfix"' do
78
+ it 'does nothing' do
79
+ PartyFoul::ExceptionHandler.any_instance.stubs(:issue_body).returns('Test Body')
80
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
81
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: [{title: 'Test Title', body: 'Test Body', state: 'closed', number: 1, 'labels' => ['wontfix']}]))
82
+ PartyFoul.github.issues.expects(:create).never
83
+ PartyFoul.github.issues.expects(:edit).never
84
+ lambda {
85
+ get '/'
86
+ }.must_raise(Exception)
87
+ end
88
+ end
89
+
90
+ context 'filtering based upon exception' do
91
+ before do
92
+ PartyFoul.ignored_exceptions = ['StandardError']
93
+ self.stubs(:error_to_raise).returns(StandardError)
94
+ end
95
+
96
+ it 'does not handle exception' do
97
+ PartyFoul::ExceptionHandler.any_instance.stubs(:issue_body).returns('Test Body')
98
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
99
+ PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: []))
100
+ PartyFoul.github.issues.expects(:create).never
101
+ lambda {
102
+ get '/'
103
+ }.must_raise(StandardError)
104
+ end
105
+ end
106
+ end
data/test/test_helper.rb CHANGED
@@ -1,15 +1,26 @@
1
- # Configure Rails Environment
2
- ENV["RAILS_ENV"] = "test"
3
-
4
- require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
- require "rails/test_help"
1
+ if defined?(M)
2
+ require 'minitest/spec'
3
+ else
4
+ require 'minitest/autorun'
5
+ end
6
+ require 'rack/test'
7
+ require 'mocha/setup'
8
+ require 'bourne'
9
+ require 'debugger'
10
+ require 'party_foul'
6
11
 
7
- Rails.backtrace_cleaner.remove_silencers!
12
+ class MiniTest::Spec
13
+ class << self
14
+ alias :context :describe
15
+ end
16
+ end
8
17
 
9
- # Load support files
10
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
18
+ module MiniTest::Expectations
19
+ infect_an_assertion :assert_received, :must_have_received
20
+ end
11
21
 
12
- # Load fixtures from the engine
13
- if ActiveSupport::TestCase.method_defined?(:fixture_path=)
14
- ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
22
+ def clean_up_party
23
+ %w{github oauth_token endpoint owner repo ignored_exceptions}.each do |attr|
24
+ PartyFoul.send("#{attr}=", nil)
25
+ end
15
26
  end