From 90033270a10b952161d1e545993761516d5e8566 Mon Sep 17 00:00:00 2001 From: Cyril Mougel Date: Wed, 20 Nov 2013 11:02:17 +0100 Subject: [PATCH] Extract all IssueTracker system and migrate to errbit_plugin --- Gemfile | 31 ++++++------------------------- Gemfile.lock | 94 +++++++++++++++++++++++++++++----------------------------------------------------------------- app/controllers/apps_controller.rb | 2 +- app/controllers/problems_controller.rb | 3 +-- app/decorators/issue_tracker_decorator.rb | 21 ++++++++++++--------- app/decorators/issue_tracker_field_decorator.rb | 6 +++--- app/interactors/issue_creation.rb | 32 ++++++++++++++++++-------------- app/models/app.rb | 14 +++++++++++--- app/models/issue_tracker.rb | 56 +++++++++++++------------------------------------------- app/models/issue_trackers/bitbucket_issues_tracker.rb | 55 ------------------------------------------------------- app/models/issue_trackers/fogbugz_tracker.rb | 53 ----------------------------------------------------- app/models/issue_trackers/github_issues_tracker.rb | 61 ------------------------------------------------------------- app/models/issue_trackers/gitlab_tracker.rb | 53 ----------------------------------------------------- app/models/issue_trackers/jira_tracker.rb | 110 -------------------------------------------------------------------------------------------------------------- app/models/issue_trackers/lighthouse_tracker.rb | 53 ----------------------------------------------------- app/models/issue_trackers/mingle_tracker.rb | 71 ----------------------------------------------------------------------- app/models/issue_trackers/none.rb | 5 ----- app/models/issue_trackers/pivotal_labs_tracker.rb | 43 ------------------------------------------- app/models/issue_trackers/redmine_tracker.rb | 75 --------------------------------------------------------------------------- app/models/issue_trackers/unfuddle_tracker.rb | 69 --------------------------------------------------------------------- app/models/problem.rb | 2 +- app/views/apps/_issue_tracker_fields.html.haml | 23 ++++++++++++----------- db/migrate/20131011155638_extract_issue_tracker.rb | 19 +++++++++++++++++++ spec/acceptance/app_regenerate_api_key_spec.rb | 16 ++++++++-------- spec/controllers/apps_controller_spec.rb | 31 +++++++++++++++++-------------- spec/controllers/problems_controller_spec.rb | 67 +++++++++++++++++++++---------------------------------------------- spec/decorators/issue_tracker_decorator_spec.rb | 39 +++++++++++++++------------------------ spec/fabricators/issue_tracker_fabricator.rb | 38 -------------------------------------- spec/interactors/issue_creation_spec.rb | 25 +++++++++++++++++++++---- spec/interactors/problem_updater_cache_spec.rb | 2 +- spec/models/app_spec.rb | 22 ++++++++++++++++++++++ spec/models/issue_tracker_spec.rb | 20 ++++++++++++++++++++ spec/models/issue_trackers/bitbucket_issues_tracker_spec.rb | 40 ---------------------------------------- spec/models/issue_trackers/fogbugz_tracker_spec.rb | 23 ----------------------- spec/models/issue_trackers/github_issues_tracker_spec.rb | 47 ----------------------------------------------- spec/models/issue_trackers/gitlab_issues_tracker_spec.rb | 32 -------------------------------- spec/models/issue_trackers/lighthouse_tracker_spec.rb | 27 --------------------------- spec/models/issue_trackers/mingle_tracker_spec.rb | 28 ---------------------------- spec/models/issue_trackers/pivotal_labs_tracker_spec.rb | 46 ---------------------------------------------- spec/models/issue_trackers/redmine_tracker_spec.rb | 45 --------------------------------------------- spec/models/issue_trackers/unfuddle_issues_tracker_spec.rb | 92 -------------------------------------------------------------------------------------------- spec/models/problem_spec.rb | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 3 ++- spec/views/problems/show.html.haml_spec.rb | 44 +++++++++++++++++++++++++++++--------------- 44 files changed, 332 insertions(+), 1356 deletions(-) delete mode 100644 app/models/issue_trackers/bitbucket_issues_tracker.rb delete mode 100644 app/models/issue_trackers/fogbugz_tracker.rb delete mode 100644 app/models/issue_trackers/github_issues_tracker.rb delete mode 100644 app/models/issue_trackers/gitlab_tracker.rb delete mode 100644 app/models/issue_trackers/jira_tracker.rb delete mode 100644 app/models/issue_trackers/lighthouse_tracker.rb delete mode 100644 app/models/issue_trackers/mingle_tracker.rb delete mode 100644 app/models/issue_trackers/none.rb delete mode 100644 app/models/issue_trackers/pivotal_labs_tracker.rb delete mode 100644 app/models/issue_trackers/redmine_tracker.rb delete mode 100644 app/models/issue_trackers/unfuddle_tracker.rb create mode 100644 db/migrate/20131011155638_extract_issue_tracker.rb create mode 100644 spec/models/issue_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/bitbucket_issues_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/fogbugz_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/github_issues_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/gitlab_issues_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/lighthouse_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/mingle_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/pivotal_labs_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/redmine_tracker_spec.rb delete mode 100644 spec/models/issue_trackers/unfuddle_issues_tracker_spec.rb diff --git a/Gemfile b/Gemfile index 1dcda45..9fd2cd4 100644 --- a/Gemfile +++ b/Gemfile @@ -27,30 +27,13 @@ gem 'rails_autolink' gem 'hoptoad_notifier', "~> 2.4" gem 'draper', :require => false +gem 'errbit_plugin', + :git => 'https://github.com/errbit/errbit_plugin.git' + # :path => 'vendor/gems/errbit_plugin' +gem 'errbit_github_plugin', + :git => 'https://github.com/errbit/errbit_github_plugin.git' + # :path => 'vendor/gems/errbit_github_plugin' -# Remove / comment out any of the gems below if you want to disable -# a given issue tracker, notification service, or authentication. - -# Issue Trackers -# --------------------------------------- -# Lighthouse -gem 'lighthouse-api' -# Redmine -gem 'oruen_redmine_client', :require => 'redmine_client' -# Pivotal Tracker -gem 'pivotal-tracker' -# Fogbugz -gem 'ruby-fogbugz', :require => 'fogbugz' -# Github Issues -gem 'octokit', '~> 1.18' -# Gitlab -gem 'gitlab', '~> 3.0.0' - -# Bitbucket Issues -gem 'bitbucket_rest_api', :require => false - -# Jira -gem 'jira-ruby', :require => 'jira' # Notification services # --------------------------------------- @@ -80,7 +63,6 @@ group :development, :test do gem 'rspec-rails' gem 'webmock', :require => false gem 'airbrake', :require => false - gem 'ruby-debug', :platform => :mri_18 gem 'debugger', :platform => :mri_19 gem 'pry-rails' # gem 'rpm_contrib' @@ -117,7 +99,6 @@ group :heroku, :production do gem 'unicorn', :require => false end - # Gems used only for assets and not required # in production environments by default. group :assets do diff --git a/Gemfile.lock b/Gemfile.lock index ac35328..d20f390 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,15 @@ +PATH + remote: vendor/gems/errbit_github_plugin + specs: + errbit_github_plugin (0.0.1) + errbit_plugin + octokit + +PATH + remote: vendor/gems/errbit_plugin + specs: + errbit_plugin (0.0.1) + GEM remote: https://rubygems.org/ specs: @@ -44,13 +56,6 @@ GEM erubis (>= 2.6.6) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - bitbucket_rest_api (0.1.4) - faraday (~> 0.8.1) - faraday_middleware (~> 0.9.0) - hashie (~> 2.0.5) - multi_json (~> 1.3) - nokogiri (~> 1.5.2) - simple_oauth builder (3.0.4) callsite (0.0.11) campy (1.0.0) @@ -96,8 +101,9 @@ GEM warden (~> 1.2.3) diff-lcs (1.2.4) dotenv (0.9.0) - draper (1.2.1) + draper (1.3.0) actionpack (>= 3.0) + activemodel (>= 3.0) activesupport (>= 3.0) request_store (~> 1.0.3) email_spec (1.5.0) @@ -105,25 +111,19 @@ GEM mail (~> 2.2) erubis (2.7.0) execjs (2.0.2) - fabrication (2.8.1) + fabrication (2.9.0) faraday (0.8.8) multipart-post (~> 1.2.0) - faraday_middleware (0.9.0) - faraday (>= 0.7.4, < 0.9) flowdock (0.3.1) httparty (~> 0.7) multi_json foreman (0.63.0) dotenv (>= 0.7) thor (>= 0.13.6) - gitlab (3.0.0) - httparty haml (4.0.3) tilt - happymapper (0.4.1) - libxml-ruby (~> 2.0) hashie (2.0.5) - highline (1.6.19) + highline (1.6.20) hike (1.2.3) hipchat (0.12.0) httparty @@ -138,11 +138,7 @@ GEM json (~> 1.8) multi_xml (>= 0.5.2) httpauth (0.2.0) - i18n (0.6.9) - jira-ruby (0.1.2) - activesupport - oauth - railties + i18n (0.6.5) journey (1.0.4) jquery-rails (2.1.4) railties (>= 3.0, < 5.0) @@ -157,10 +153,6 @@ GEM launchy (2.3.0) addressable (~> 2.3) libv8 (3.16.14.3) - libxml-ruby (2.7.0) - lighthouse-api (2.0) - activeresource (>= 3.0.0) - activesupport (>= 3.0.0) linecache (0.46) rbx-require-relative (> 0.0.4) mail (2.5.4) @@ -197,24 +189,15 @@ GEM net-ssh (2.7.0) net-ssh-gateway (1.2.0) net-ssh (>= 2.6.5) - netrc (0.7.7) nokogiri (1.5.10) - nokogiri-happymapper (0.5.8) - nokogiri (~> 1.5) - oauth (0.4.7) oauth2 (0.8.1) faraday (~> 0.8) httpauth (~> 0.1) jwt (~> 0.1.4) multi_json (~> 1.0) rack (~> 1.2) - octokit (1.25.0) - addressable (~> 2.2) - faraday (~> 0.8) - faraday_middleware (~> 0.9) - hashie (~> 2.0) - multi_json (~> 1.3) - netrc (~> 0.7.7) + octokit (2.1.2) + sawyer (~> 0.5.0) omniauth (1.1.4) hashie (>= 1.2, < 3) rack @@ -226,18 +209,6 @@ GEM omniauth (~> 1.0) origin (1.1.0) orm_adapter (0.4.0) - oruen_redmine_client (0.0.1) - activeresource (>= 2.3.0) - pivotal-tracker (0.5.12) - builder - builder - crack - happymapper (>= 0.3.2) - nokogiri (>= 1.4.3) - nokogiri (>= 1.5.5) - nokogiri-happymapper (>= 0.5.4) - rest-client (~> 1.6.0) - rest-client (~> 1.6.0) pjax_rails (0.3.4) jquery-rails poltergeist (1.4.1) @@ -246,7 +217,7 @@ GEM multi_json (~> 1.0) websocket-driver (>= 0.2.0) polyglot (0.3.3) - premailer (1.7.3) + premailer (1.7.9) css_parser (>= 1.1.9) htmlentities (>= 4.0.0) pry (0.9.12.2) @@ -276,8 +247,7 @@ GEM activeresource (= 3.2.16) activesupport (= 3.2.16) bundler (~> 1.0) - railties (= 3.2.16) - rails_autolink (1.1.4) + rails_autolink (1.1.5) rails (> 3.1) railties (3.2.16) actionpack (= 3.2.16) @@ -316,13 +286,13 @@ GEM ruby-debug-base (~> 0.10.4.0) ruby-debug-base (0.10.4) linecache (>= 0.3) - ruby-fogbugz (0.1.1) - crack rushover (0.3.0) json rest-client safe_yaml (0.9.7) - simple_oauth (0.2.0) + sawyer (0.5.0) + addressable (~> 2.3.5) + faraday (~> 0.8, < 0.10) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) @@ -355,15 +325,15 @@ GEM railties (> 3.2.8, < 4.0.0) sprockets (>= 2.0.0) tzinfo (0.3.38) - uglifier (2.2.1) + uglifier (2.3.0) execjs (>= 0.3.0) - multi_json (~> 1.0, >= 1.0.2) + json (>= 1.8.0) underscore-rails (1.5.2) unicorn (4.6.3) kgio (~> 2.6) rack raindrops (~> 0.7) - useragent (0.8.3) + useragent (0.9.0) warden (1.2.3) rack (>= 1.0) webmock (1.15.0) @@ -385,7 +355,6 @@ DEPENDENCIES airbrake better_errors binding_of_caller - bitbucket_rest_api campy capistrano (~> 2.0) capybara @@ -396,30 +365,26 @@ DEPENDENCIES devise draper email_spec + errbit_github_plugin! + errbit_plugin! execjs fabrication flowdock foreman - gitlab (~> 3.0.0) haml hipchat hoi hoptoad_notifier (~> 2.4) htmlentities httparty - jira-ruby jquery-rails (~> 2.1.4) kaminari (>= 0.14.1) launchy - lighthouse-api meta_request mongoid mongoid-rspec mongoid_rails_migrations - octokit (~> 1.18) omniauth-github - oruen_redmine_client - pivotal-tracker pjax_rails poltergeist pry-rails @@ -432,7 +397,6 @@ DEPENDENCIES ri_cal rspec-rails ruby-debug - ruby-fogbugz rushover strong_parameters therubyracer diff --git a/app/controllers/apps_controller.rb b/app/controllers/apps_controller.rb index 7cebb18..bafee25 100644 --- a/app/controllers/apps_controller.rb +++ b/app/controllers/apps_controller.rb @@ -99,7 +99,7 @@ class AppsController < ApplicationController def plug_params app app.watchers.build if app.watchers.none? - app.issue_tracker = IssueTracker.new unless app.issue_tracker_configured? + app.issue_tracker ||= IssueTracker.new app.notification_service = NotificationService.new unless app.notification_service_configured? app.copy_attributes_from(params[:copy_attributes_from]) if params[:copy_attributes_from] end diff --git a/app/controllers/problems_controller.rb b/app/controllers/problems_controller.rb index 08e985f..c21c751 100644 --- a/app/controllers/problems_controller.rb +++ b/app/controllers/problems_controller.rb @@ -62,8 +62,7 @@ class ProblemsController < ApplicationController end def create_issue - IssueTracker.update_url_options(request) - issue_creation = IssueCreation.new(problem, current_user, params[:tracker]) + issue_creation = IssueCreation.new(problem, current_user, params[:tracker], request) unless issue_creation.execute flash[:error] = issue_creation.errors.full_messages.join(', ') diff --git a/app/decorators/issue_tracker_decorator.rb b/app/decorators/issue_tracker_decorator.rb index 4abea5c..82774ec 100644 --- a/app/decorators/issue_tracker_decorator.rb +++ b/app/decorators/issue_tracker_decorator.rb @@ -1,23 +1,26 @@ class IssueTrackerDecorator < Draper::Decorator + def initialize(object, key) + @object = object + @key = key + end + attr_reader :key + delegate_all def issue_trackers - @issue_trackers ||= [ - IssueTracker::None, - IssueTracker.subclasses.select{|klass| klass != IssueTracker::None } - ].flatten - @issue_trackers.each do |it| - yield IssueTrackerDecorator.new(it) + @issue_trackers ||= ErrbitPlugin::Register.issue_trackers + @issue_trackers.each do |key, it| + yield IssueTrackerDecorator.new(it.new(app, {}), key) end end def note - object::Note.html_safe + object.note.html_safe end def fields - object::Fields.each do |field, field_info| + object.fields.each do |field, field_info| yield IssueTrackerFieldDecorator.new(field, field_info) end end @@ -29,7 +32,7 @@ class IssueTrackerDecorator < Draper::Decorator private def choosen?(issue_tracker) - object.to_s == issue_tracker._type ? 'chosen' : '' + key == issue_tracker.type_tracker.to_s ? 'chosen' : '' end end diff --git a/app/decorators/issue_tracker_field_decorator.rb b/app/decorators/issue_tracker_field_decorator.rb index 46f16ec..bd6d508 100644 --- a/app/decorators/issue_tracker_field_decorator.rb +++ b/app/decorators/issue_tracker_field_decorator.rb @@ -13,10 +13,10 @@ class IssueTrackerFieldDecorator < Draper::Decorator end - def input(form) - form.send(input_field, object, + def input(form, issue_tracker) + form.send(input_field, key.to_s, :placeholder => field_info[:placeholder], - :value => form.object.send(object)) + :value => issue_tracker.options[key.to_s]) end private diff --git a/app/interactors/issue_creation.rb b/app/interactors/issue_creation.rb index ef0e70d..880524d 100644 --- a/app/interactors/issue_creation.rb +++ b/app/interactors/issue_creation.rb @@ -5,12 +5,24 @@ class IssueCreation delegate :app, :to => :problem - def initialize(problem, user, tracker_name) + def initialize(problem, user, tracker_name, request) @problem = problem @user = user @tracker_name = tracker_name + IssueTracker.update_url_options(request) end + def execute + tracker.create_issue(problem, user) if tracker + errors.empty? + rescue => ex + Rails.logger.error "Error during issue creation: " << ex.message + errors.add :base, "There was an error during issue creation: #{ex.message}" + false + end + + private + def tracker return @tracker if @tracker @@ -21,10 +33,11 @@ class IssueCreation elsif !user.github_account? errors.add :base, "You haven't linked your Github account." else - @tracker = GithubIssuesTracker.new( - :app => app, - :username => user.github_login, - :oauth_token => user.github_oauth_token + @tracker = ErrbitGithubPlugin::IssueTracker.new( + app, { + :username => user.github_login, + :oauth_token => user.github_oauth_token + } ) end @@ -39,13 +52,4 @@ class IssueCreation @tracker end - - def execute - tracker.create_issue problem, user if tracker - errors.empty? - rescue => ex - Rails.logger.error "Error during issue creation: " << ex.message - errors.add :base, "There was an error during issue creation: #{ex.message}" - false - end end diff --git a/app/models/app.rb b/app/models/app.rb index 043fcff..7617470 100644 --- a/app/models/app.rb +++ b/app/models/app.rb @@ -25,7 +25,7 @@ class App embeds_many :watchers embeds_many :deploys - embeds_one :issue_tracker + embeds_one :issue_tracker, :class_name => 'IssueTracker' embeds_one :notification_service has_many :problems, :inverse_of => :app, :dependent => :destroy @@ -43,7 +43,7 @@ class App accepts_nested_attributes_for :watchers, :allow_destroy => true, :reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? } accepts_nested_attributes_for :issue_tracker, :allow_destroy => true, - :reject_if => proc { |attrs| !IssueTracker.subclasses.map(&:to_s).include?(attrs[:type].to_s) } + :reject_if => proc { |attrs| !ErrbitPlugin::Register.issue_trackers.keys.map(&:to_s).include?(attrs[:type_tracker].to_s) } accepts_nested_attributes_for :notification_service, :allow_destroy => true, :reject_if => proc { |attrs| !NotificationService.subclasses.map(&:to_s).include?(attrs[:type].to_s) } @@ -119,7 +119,7 @@ class App def issue_tracker_configured? - !!(issue_tracker.class < IssueTracker && issue_tracker.configured?) + !!issue_tracker && !!(issue_tracker.configured?) end def notification_service_configured? @@ -174,6 +174,13 @@ class App set(:api_key, SecureRandom.hex) end + ## + # Check if comments can be allowed on this application + # + def comments_allowed? + !issue_tracker || issue_tracker.comments_allowed? + end + protected def store_cached_attributes_on_problems @@ -199,5 +206,6 @@ class App github_repo.sub!(/(git@|https?:\/\/)github\.com(\/|:)/, '') github_repo.sub!(/\.git$/, '') end + end diff --git a/app/models/issue_tracker.rb b/app/models/issue_tracker.rb index 5cf412a..02af2f4 100644 --- a/app/models/issue_tracker.rb +++ b/app/models/issue_tracker.rb @@ -1,55 +1,15 @@ class IssueTracker include Mongoid::Document include Mongoid::Timestamps - include HashHelper - include Rails.application.routes.url_helpers - Note = '' + include Rails.application.routes.url_helpers default_url_options[:host] = ActionMailer::Base.default_url_options[:host] embedded_in :app, :inverse_of => :issue_tracker - field :project_id, :type => String - field :alt_project_id, :type => String # Specify an alternative project id. e.g. for viewing files - field :api_token, :type => String - field :account, :type => String - field :username, :type => String - field :password, :type => String - field :ticket_properties, :type => String - field :subdomain, :type => String - field :milestone_id, :type => String - - # Is there any better way to enhance the props? Putting them into the subclass leads to - # an error while rendering the form fields -.- - field :base_url, :type => String - field :context_path, :type => String - field :issue_type, :type => String - field :issue_component, :type => String - field :issue_priority, :type => String - - validate :check_params - - # Subclasses are responsible for overwriting this method. - def check_params; true; end - - def issue_title(problem) - "[#{ problem.environment }][#{ problem.where }] #{problem.message.to_s.truncate(100)}" - end - - # Allows us to set the issue tracker class from a single form. - def type; self._type; end - def type=(t); self._type=t; end - - def url; nil; end - - # Retrieve tracker label from either class or instance. - def self.label; self::Label; end - def label; self.class.label; end - - def configured? - project_id.present? - end + field :type_tracker, :type => String + field :options, :type => Hash, :default => {} ## # Update default_url_option with valid data from the request information @@ -61,4 +21,14 @@ class IssueTracker IssueTracker.default_url_options[:port] = request.port IssueTracker.default_url_options[:protocol] = request.scheme end + + def tracker + @tracker ||= ErrbitPlugin::Register.issue_tracker(self.type_tracker).new(app, self.options) + rescue NameError + ErrbitPlugin::NoneIssueTracker.new(app, {}) + end + delegate :configured?, :to => :tracker + delegate :create_issue, :to => :tracker + delegate :label, :to => :tracker + delegate :comments_allowed?, :to => :tracker end diff --git a/app/models/issue_trackers/bitbucket_issues_tracker.rb b/app/models/issue_trackers/bitbucket_issues_tracker.rb deleted file mode 100644 index c28d3fe..0000000 --- a/app/models/issue_trackers/bitbucket_issues_tracker.rb +++ /dev/null @@ -1,55 +0,0 @@ -begin - require 'bitbucket_rest_api' -rescue LoadError -end - -if defined? BitBucket - class IssueTrackers::BitbucketIssuesTracker < IssueTracker - Label = "bitbucket" - Note = 'Please configure your Bitbucket repository in the BITBUCKET REPO field above.' - Fields = [ - [:api_token, { - :placeholder => "Your username on Bitbucket account", - :label => "Username" - }], - [:project_id, { - :placeholder => "Password for your Bitbucket account", - :label => "Password" - }] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? } - errors.add :base, 'You must specify your Bitbucket username and password' - end - end - - def repo_name - app.bitbucket_repo - end - - def create_issue(problem, reported_by = nil) - bitbucket = BitBucket.new :basic_auth => "#{api_token}:#{project_id}" - - begin - r_user = repo_name.split('/')[0] - r_name = repo_name.split('/')[1] - issue = bitbucket.issues.create r_user, r_name, :title => issue_title(problem), :content => body_template.result(binding), :priority => 'critical' - problem.update_attributes( - :issue_link => "https://bitbucket.org/#{repo_name}/issue/#{issue.local_id}/", - :issue_type => Label - ) - rescue BitBucket::Error::Unauthorized - raise IssueTrackers::AuthenticationError, "Could not authenticate with BitBucket. Please check your username and password." - end - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/bitbucket_issues_body.txt.erb")) - end - - def url - "https://www.bitbucket.org/#{repo_name}/issues" - end - end -end diff --git a/app/models/issue_trackers/fogbugz_tracker.rb b/app/models/issue_trackers/fogbugz_tracker.rb deleted file mode 100644 index 3ef9d44..0000000 --- a/app/models/issue_trackers/fogbugz_tracker.rb +++ /dev/null @@ -1,53 +0,0 @@ -if defined? Fogbugz - class IssueTrackers::FogbugzTracker < IssueTracker - Label = "fogbugz" - Fields = [ - [:project_id, { - :label => "Area Name" - }], - [:account, { - :label => "FogBugz URL", - :placeholder => "abc from http://abc.fogbugz.com/" - }], - [:username, { - :placeholder => "Username/Email for your account" - }], - [:password, { - :placeholder => "Password for your account" - }] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? } - errors.add :base, 'You must specify your FogBugz Area Name, FogBugz URL, Username, and Password' - end - end - - def create_issue(problem, reported_by = nil) - fogbugz = Fogbugz::Interface.new(:email => username, :password => password, :uri => "https://#{account}.fogbugz.com") - fogbugz.authenticate - - issue = {} - issue['sTitle'] = issue_title problem - issue['sArea'] = project_id - issue['sEvent'] = body_template.result(binding) - issue['sTags'] = ['errbit'].join(',') - issue['cols'] = ['ixBug'].join(',') - - fb_resp = fogbugz.command(:new, issue) - problem.update_attributes( - :issue_link => "https://#{account}.fogbugz.com/default.asp?#{fb_resp['case']['ixBug']}", - :issue_type => Label - ) - - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/fogbugz_body.txt.erb")) - end - - def url - "http://#{account}.fogbugz.com/" - end - end -end diff --git a/app/models/issue_trackers/github_issues_tracker.rb b/app/models/issue_trackers/github_issues_tracker.rb deleted file mode 100644 index c9aa0a5..0000000 --- a/app/models/issue_trackers/github_issues_tracker.rb +++ /dev/null @@ -1,61 +0,0 @@ -if defined? Octokit - class IssueTrackers::GithubIssuesTracker < IssueTracker - Label = "github" - Note = 'Please configure your github repository in the GITHUB REPO field above.
' << - 'Instead of providing your username & password, you can link your Github account ' << - 'to your user profile, and allow Errbit to create issues using your OAuth token.' - - Fields = [ - [:username, { - :placeholder => "Your username on GitHub" - }], - [:password, { - :placeholder => "Password for your account" - }] - ] - - attr_accessor :oauth_token - - def project_id - app.github_repo - end - - def check_params - if Fields.detect {|f| self[f[0]].blank? } - errors.add :base, 'You must specify your GitHub username and password' - end - end - - def create_issue(problem, reported_by = nil) - # Login using OAuth token, if given. - if oauth_token - client = Octokit::Client.new(:login => username, :oauth_token => oauth_token) - else - client = Octokit::Client.new(:login => username, :password => password) - end - - begin - issue = client.create_issue( - project_id, - issue_title(problem), - body_template.result(binding).unpack('C*').pack('U*') - ) - problem.update_attributes( - :issue_link => issue.html_url, - :issue_type => Label - ) - - rescue Octokit::Unauthorized - raise IssueTrackers::AuthenticationError, "Could not authenticate with GitHub. Please check your username and password." - end - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/github_issues_body.txt.erb").gsub(/^\s*/, '')) - end - - def url - "https://github.com/#{project_id}/issues" - end - end -end diff --git a/app/models/issue_trackers/gitlab_tracker.rb b/app/models/issue_trackers/gitlab_tracker.rb deleted file mode 100644 index 64d2a7d..0000000 --- a/app/models/issue_trackers/gitlab_tracker.rb +++ /dev/null @@ -1,53 +0,0 @@ -if defined? Gitlab - class IssueTrackers::GitlabTracker < IssueTracker - Label = "gitlab" - Fields = [ - [:account, { - :label => "Gitlab URL", - :placeholder => "e.g. https://example.net" - }], - [:api_token, { - :placeholder => "API Token for your account" - }], - [:project_id, { - :label => "Ticket Project ID (use Number)", - :placeholder => "Gitlab Project where issues will be created" - }], - [:alt_project_id, { - :label => "Project Name (namespace/project)", - :placeholder => "Gitlab Project where issues will be created" - }] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank?} - errors.add :base, 'You must specify your Gitlab URL, API token, Project ID and Project Name' - end - end - - def create_issue(problem, reported_by = nil) - Gitlab.configure do |config| - config.endpoint = "#{account}/api/v3" - config.private_token = api_token - config.user_agent = 'Errbit User Agent' - end - title = issue_title problem - description_summary = summary_template.result(binding) - description_body = body_template.result(binding) - ticket = Gitlab.create_issue(project_id, title, { :description => description_summary, :labels => "errbit" } ) - Gitlab.create_issue_note(project_id, ticket.id, description_body) - end - - def summary_template - @@summary_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/gitlab_summary.txt.erb").gsub(/^\s*/, '')) - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/gitlab_body.txt.erb").gsub(/^\s*/, '')) - end - - def url - "#{account}/#{alt_project_id}/issues" - end - end -end diff --git a/app/models/issue_trackers/jira_tracker.rb b/app/models/issue_trackers/jira_tracker.rb deleted file mode 100644 index 2c9f68a..0000000 --- a/app/models/issue_trackers/jira_tracker.rb +++ /dev/null @@ -1,110 +0,0 @@ -if defined? JIRA - class IssueTrackers::JiraTracker < IssueTracker - Label = 'jira' - - Fields = [ - [:base_url, { - :label => 'Jira URL without trailing slash', - :placeholder => 'https://jira.example.org/' - }], - [:context_path, { - :optional => true, - :label => 'Context Path (Just "/" if empty otherwise with leading slash)', - :placeholder => "/jira" - }], - [:username, { - :optional => true, - :label => 'HTTP Basic Auth User', - :placeholder => 'johndoe' - }], - [:password, { - :optional => true, - :label => 'HTTP Basic Auth Password', - :placeholder => 'p@assW0rd' - }], - [:project_id, { - :label => 'Project Key', - :placeholder => 'The project Key where the issue will be created' - }], - [:account, { - :optional => true, - :label => 'Assign to this user. If empty, Jira takes the project default.', - :placeholder => "username" - }], - [:issue_component, { - :label => 'Issue category', - :placeholder => 'Website - Other' - }], - [:issue_type, { - :label => 'Issue type', - :placeholder => 'Bug' - }], - [:issue_priority, { - :label => 'Priority', - :placeholder => 'Normal' - }] - ] - - def check_params - if Fields.detect { |f| self[f[0]].blank? && !f[1][:optional] } - errors.add :base, 'You must specify all non optional values!' - end - end - - - # - # @param problem Problem - def create_issue(problem, reported_by = nil) - options = { - :username => username, - :password => password, - :site => base_url, - :context_path => context_path, - :auth_type => :basic, - :use_ssl => base_url.match(/^https/) ? true : false - } - client = JIRA::Client.new(options) - - issue = { - :fields => { - :project => { - :key => project_id - }, - :summary => issue_title(problem), - :description => body_template.result(binding), - :issuetype => { - :name => issue_type - }, - :priority => { - :name => issue_priority, - }, - - :components => [{:name => issue_component}] - } - } - - issue[:fields][:assignee] = {:name => account} if account - - issue_build = client.Issue.build - issue_build.save(issue) - issue_build.fetch - - problem.update_attributes( - :issue_link => "#{base_url}#{context_path}browse/#{issue_build.key}", - :issue_type => Label - ) - - # Maybe in a later version? - #remote_link = { - # :url => app_problem_url(problem.app, problem), - # :name => "Link to Errbit Issue" - #} - #remote_link_build = issue_build.remotelink.build - #remote_link_build.save(remote_link) - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/jira_body.txt.erb")) - end - end -end \ No newline at end of file diff --git a/app/models/issue_trackers/lighthouse_tracker.rb b/app/models/issue_trackers/lighthouse_tracker.rb deleted file mode 100644 index 21aaaeb..0000000 --- a/app/models/issue_trackers/lighthouse_tracker.rb +++ /dev/null @@ -1,53 +0,0 @@ -if defined? Lighthouse - class IssueTrackers::LighthouseTracker < IssueTracker - Label = "lighthouseapp" - Fields = [ - [:account, { - :label => "Subdomain", - :placeholder => "subdomain from http://{{subdomain}}.lighthouseapp.com" - }], - [:api_token, { - :label => "API Token", - :placeholder => "123456789abcdef123456789abcdef" - }], - [:project_id, { - :label => "Project ID", - :placeholder => "123456" - }] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? } - errors.add :base, 'You must specify your Lighthouseapp Subdomain, API token and Project ID' - end - end - - def create_issue(problem, reported_by = nil) - Lighthouse.account = account - Lighthouse.token = api_token - # updating lighthouse account - Lighthouse::Ticket.site - Lighthouse::Ticket.format = :xml - ticket = Lighthouse::Ticket.new(:project_id => project_id) - ticket.title = issue_title problem - - ticket.body = body_template.result(binding) - - ticket.tags << "errbit" - ticket.save! - problem.update_attributes( - :issue_link => "#{Lighthouse::Ticket.site.to_s.sub(/#{Lighthouse::Ticket.site.path}$/, '')}#{Lighthouse::Ticket.element_path(ticket.id, :project_id => project_id)}".sub(/\.xml$/, ''), - :issue_type => Label - ) - - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/lighthouseapp_body.txt.erb").gsub(/^\s*/, '')) - end - - def url - "http://#{account}.lighthouseapp.com" - end - end -end \ No newline at end of file diff --git a/app/models/issue_trackers/mingle_tracker.rb b/app/models/issue_trackers/mingle_tracker.rb deleted file mode 100644 index 2105148..0000000 --- a/app/models/issue_trackers/mingle_tracker.rb +++ /dev/null @@ -1,71 +0,0 @@ -class IssueTrackers::MingleTracker < IssueTracker - Label = "mingle" - Note = "Note: CARD PROPERTIES must be comma separated key = value pairs" - - Fields = [ - [:account, { - :label => "Mingle URL", - :placeholder => "http://mingle.example.com/" - }], - [:project_id, { - :placeholder => "Mingle project" - }], - [:ticket_properties, { - :label => "Card Properties", - :placeholder => "card_type = Defect, defect_status = Open, priority = Essential" - }], - [:username, { - :label => "Sign-in name", - :placeholder => "Sign-in name for your account" - }], - [:password, { - :placeholder => "Password for your account" - }] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? } or !ticket_properties_hash["card_type"] - errors.add :base, 'You must specify your Mingle URL, Project ID, Card Type (in default card properties), Sign-in name, and Password' - end - end - - def create_issue(problem, reported_by = nil) - properties = ticket_properties_hash - basic_auth = account.gsub(/https?:\/\//, "https://#{username}:#{password}@") - Mingle.set_site "#{basic_auth}/api/v1/projects/#{project_id}/" - - card = Mingle::Card.new - card.card_type_name = properties.delete("card_type") - card.name = issue_title(problem) - card.description = body_template.result(binding) - properties.each do |property, value| - card.send("cp_#{property}=", value) - end - - card.save! - problem.update_attributes( - :issue_link => URI.parse("#{account}/projects/#{project_id}/cards/#{card.id}").to_s, - :issue_type => Label - ) - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/textile_body.txt.erb")) - end - - def ticket_properties_hash - # Parses 'key=value, key2=value2' from ticket_properties into a ruby hash. - self.ticket_properties.to_s.split(",").inject({}) do |hash, pair| - key, value = pair.split("=").map(&:strip) - hash[key] = value - hash - end - end - - def url - acc_url = account.start_with?('http') ? account : "http://#{account}" - URI.parse("#{acc_url}/projects/#{project_id}").to_s - rescue URI::InvalidURIError - end -end - diff --git a/app/models/issue_trackers/none.rb b/app/models/issue_trackers/none.rb deleted file mode 100644 index 43e09d9..0000000 --- a/app/models/issue_trackers/none.rb +++ /dev/null @@ -1,5 +0,0 @@ -class IssueTrackers::None < IssueTracker - Fields = [] - Note = 'When no issue tracker has been configured, you will be able to leave comments on errors.' - Label = 'none' -end diff --git a/app/models/issue_trackers/pivotal_labs_tracker.rb b/app/models/issue_trackers/pivotal_labs_tracker.rb deleted file mode 100644 index cc014f9..0000000 --- a/app/models/issue_trackers/pivotal_labs_tracker.rb +++ /dev/null @@ -1,43 +0,0 @@ -if defined? PivotalTracker - class IssueTrackers::PivotalLabsTracker < IssueTracker - Label = "pivotal" - Fields = [ - [:api_token, { - :placeholder => "API Token for your account" - }], - [:project_id, {}] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? } - errors.add :base, 'You must specify your Pivotal Tracker API token and Project ID' - end - end - - def create_issue(problem, reported_by = nil) - PivotalTracker::Client.token = api_token - PivotalTracker::Client.use_ssl = true - project = PivotalTracker::Project.find project_id.to_i - story = project.stories.create :name => issue_title(problem), - :story_type => 'bug', :description => body_template.result(binding), - :requested_by => reported_by.name - - if story.errors.present? - raise IssueTrackers::IssueTrackerError, story.errors.first - else - problem.update_attributes( - :issue_link => "https://www.pivotaltracker.com/story/show/#{story.id}", - :issue_type => Label - ) - end - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/pivotal_body.txt.erb")) - end - - def url - "https://www.pivotaltracker.com/" - end - end -end \ No newline at end of file diff --git a/app/models/issue_trackers/redmine_tracker.rb b/app/models/issue_trackers/redmine_tracker.rb deleted file mode 100644 index fc178e4..0000000 --- a/app/models/issue_trackers/redmine_tracker.rb +++ /dev/null @@ -1,75 +0,0 @@ -if defined? RedmineClient - class IssueTrackers::RedmineTracker < IssueTracker - Label = "redmine" - Fields = [ - [:account, { - :label => "Redmine URL", - :placeholder => "http://www.redmine.org/" - }], - [:api_token, { - :placeholder => "API Token for your account" - }], - [:username, { - :placeholder => "Your username" - }], - [:password, { - :placeholder => "Your password" - }], - [:project_id, { - :label => "Ticket Project", - :placeholder => "Redmine Project where tickets will be created" - }], - [:alt_project_id, { - :optional => true, - :label => "App Project", - :placeholder => "Where app's files & revisions can be viewed. (Leave blank to use the above project by default)" - }] - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? && !f[1][:optional]} - errors.add :base, 'You must specify your Redmine URL, API token, Username, Password and Project ID' - end - end - - def create_issue(problem, reported_by = nil) - token = api_token - acc = account - user = username - passwd = password - RedmineClient::Base.configure do - self.token = token - self.user = user - self.password = passwd - self.site = acc - self.format = :xml - end - issue = RedmineClient::Issue.new(:project_id => project_id) - issue.subject = issue_title problem - issue.description = body_template.result(binding) - issue.save! - problem.update_attributes( - :issue_link => "#{RedmineClient::Issue.site.to_s.sub(/#{RedmineClient::Issue.site.path}$/, '')}#{RedmineClient::Issue.element_path(issue.id, :project_id => project_id)}".sub(/\.xml\?project_id=#{project_id}$/, "\?project_id=#{project_id}"), - :issue_type => Label - ) - end - - def url_to_file(file_path, line_number = nil) - # alt_project_id let's users specify a different project for tickets / app files. - project = self.alt_project_id.present? ? self.alt_project_id : self.project_id - url = "#{self.account.gsub(/\/$/, '')}/projects/#{project}/repository/revisions/#{app.repository_branch}/changes/#{file_path.sub(/\[PROJECT_ROOT\]/, '').sub(/^\//,'')}" - line_number ? url << "#L#{line_number}" : url - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/redmine_body.txt.erb")) - end - - def url - acc_url = account.start_with?('http') ? account : "http://#{account}" - acc_url = acc_url.gsub(/\/$/, '') - URI.parse("#{acc_url}/projects/#{project_id}").to_s - rescue URI::InvalidURIError - end - end -end diff --git a/app/models/issue_trackers/unfuddle_tracker.rb b/app/models/issue_trackers/unfuddle_tracker.rb deleted file mode 100644 index 243bc6d..0000000 --- a/app/models/issue_trackers/unfuddle_tracker.rb +++ /dev/null @@ -1,69 +0,0 @@ -class IssueTrackers::UnfuddleTracker < IssueTracker - Label = "unfuddle" - Fields = [ - - [:account, { - :placeholder => "Your domain" - }], - - - [:username, { - :placeholder => "Your username" - }], - - [:password, { - :placeholder => "Your password" - }], - - [:project_id, { - :label => "Ticket Project", - :placeholder => "Project where tickets will be created" - }], - - [:milestone_id, { - :optional => true, - :label => "Ticket Milestone", - :placeholder => "Milestone where tickets will be created" - }] - - - ] - - def check_params - if Fields.detect {|f| self[f[0]].blank? && !f[1][:optional]} - errors.add :base, 'You must specify your Account, Username, Password and Project ID' - end - end - - def create_issue(problem, reported_by = nil) - - Unfuddle.config(account, username, password) - begin - issue_options = {:project_id => project_id, - :summary => issue_title(problem), - :priority => '5', - :status => "new", - :description => body_template.result(binding), - 'description-format' => 'textile' } - - issue_options[:milestone_id] = milestone_id if milestone_id.present? - - issue = Unfuddle::Ticket.create(issue_options) - problem.update_attributes( - :issue_link => File.join("#{url}/tickets/#{issue.id}"), - :issue_type => Label - ) - rescue ActiveResource::UnauthorizedAccess - raise ActiveResource::UnauthorizedAccess, "Could not authenticate with Unfuddle. Please check your username and password." - end - - end - - def body_template - @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/textile_body.txt.erb")) - end - - def url - "https://#{account}.unfuddle.com/projects/#{project_id}" - end -end diff --git a/app/models/problem.rb b/app/models/problem.rb index 548dbbe..bc7a728 100644 --- a/app/models/problem.rb +++ b/app/models/problem.rb @@ -68,7 +68,7 @@ class Problem end def comments_allowed? - Errbit::Config.allow_comments_with_issue_tracker || !app.issue_tracker_configured? + Errbit::Config.allow_comments_with_issue_tracker || app.comments_allowed? end def resolve! diff --git a/app/views/apps/_issue_tracker_fields.html.haml b/app/views/apps/_issue_tracker_fields.html.haml index 0322d2c..36e9228 100644 --- a/app/views/apps/_issue_tracker_fields.html.haml +++ b/app/views/apps/_issue_tracker_fields.html.haml @@ -1,22 +1,23 @@ %fieldset %legend= t('.legend') - = f.fields_for :issue_tracker do |w| + = f.fields_for :issue_tracker do |issue_tracker_form| %div.issue_tracker.nested %div.choose - - w.object.issue_trackers do |tracker| - = w.label :type, :class => "label_radio #{tracker.label}", :value => tracker.name do - = w.radio_button :type, tracker.name, 'data-section' => tracker.label + - issue_tracker_form.object.issue_trackers do |tracker| + = issue_tracker_form.label :type_tracker, :class => "label_radio #{tracker.label}", :value => tracker.key do + = issue_tracker_form.radio_button :type_tracker, tracker.key, 'data-section' => tracker.label = tracker.label - - w.object.issue_trackers do |tracker| - %div.tracker_params{:class => tracker.params_class(w.object)} - %p= tracker.note - - tracker.fields do |field| - = w.label field.key, field.label - = field.input(w) + - issue_tracker_form.object.issue_trackers do |tracker| + %div.tracker_params{:class => tracker.params_class(issue_tracker_form.object)} + = issue_tracker_form.fields_for(:options) do |options_form| + %p= tracker.note + - tracker.fields do |field| + = options_form.label field.key, field.label + = field.input(options_form, issue_tracker_form.object) .image_preloader - - w.object.issue_trackers do |tracker| + - issue_tracker_form.object.issue_trackers do |tracker| = image_tag "#{tracker.label}_inactive.png" = image_tag "#{tracker.label}_create.png" diff --git a/db/migrate/20131011155638_extract_issue_tracker.rb b/db/migrate/20131011155638_extract_issue_tracker.rb new file mode 100644 index 0000000..7b50551 --- /dev/null +++ b/db/migrate/20131011155638_extract_issue_tracker.rb @@ -0,0 +1,19 @@ +class ExtractIssueTracker < Mongoid::Migration + + def self.up + App.collection.find.each do |app| + if app['issue_tracker'] && !app['issue_tracker'].empty? + it = app['issue_tracker'] + it['type_tracker'] = 'IssueTrackers::BitbucketIssuesTracker' + it['options'] = app['issue_tracker'].dup + it.delete('_type') + App.collection.find( + :_id => app['_id'] + ).update(app) + end + end + end + + def self.down + end +end diff --git a/spec/acceptance/app_regenerate_api_key_spec.rb b/spec/acceptance/app_regenerate_api_key_spec.rb index f82bcb1..70f5c40 100644 --- a/spec/acceptance/app_regenerate_api_key_spec.rb +++ b/spec/acceptance/app_regenerate_api_key_spec.rb @@ -72,17 +72,17 @@ feature "Create an application" do log_in admin click_on I18n.t('apps.index.new_app') fill_in 'app_name', :with => 'My new app' - find('.label_radio.bitbucket').click - within ".bitbucket.tracker_params" do - fill_in 'app_issue_tracker_attributes_api_token', :with => 'token' - fill_in 'app_issue_tracker_attributes_project_id', :with => 'pass' + find('.label_radio.github').click + within ".github.tracker_params" do + fill_in 'app_issue_tracker_attributes_options_username', :with => 'token' + fill_in 'app_issue_tracker_attributes_options_password', :with => 'pass' end click_on I18n.t('apps.new.add_app') expect(page.has_content?(I18n.t('controllers.apps.flash.create.success'))).to eql true app = App.where(:name => 'My new app').first - expect(app.issue_tracker).to be_a IssueTracker::BitbucketIssuesTracker - expect(app.issue_tracker.api_token).to eql 'token' - expect(app.issue_tracker.project_id).to eql 'pass' + expect(app.issue_tracker.type_tracker).to eql 'IssueTrackers::GithubIssuesTracker' + expect(app.issue_tracker.options['username']).to eql 'token' + expect(app.issue_tracker.options['password']).to eql 'pass' click_on I18n.t('shared.navigation.apps') click_on 'My new app' @@ -91,6 +91,6 @@ feature "Create an application" do click_on I18n.t('apps.edit.update') expect(page.has_content?(I18n.t('controllers.apps.flash.update.success'))).to eql true app = App.where(:name => 'My new app').first - expect(app.issue_tracker).to be_a IssueTracker::None + expect(app.issue_tracker.tracker).to be_a ErrbitPlugin::NoneIssueTracker end end diff --git a/spec/controllers/apps_controller_spec.rb b/spec/controllers/apps_controller_spec.rb index b001a29..97fc64b 100644 --- a/spec/controllers/apps_controller_spec.rb +++ b/spec/controllers/apps_controller_spec.rb @@ -289,7 +289,7 @@ describe AppsController do context "unknown tracker type" do before(:each) do put :update, :id => @app.id, :app => { :issue_tracker_attributes => { - :type => 'unknown', :project_id => '1234', :api_token => '123123', :account => 'myapp' + :type_tracker => 'unknown', :options => {:project_id => '1234', :api_token => '123123', :account => 'myapp'} } } @app.reload end @@ -299,24 +299,24 @@ describe AppsController do end end - IssueTracker.subclasses.each do |tracker_klass| - context tracker_klass do + ErrbitPlugin::Register.issue_trackers.each do |key, klass| + context key do it "should save tracker params" do - params = tracker_klass::Fields.inject({}){|hash,f| hash[f[0]] = "test_value"; hash } - params[:ticket_properties] = "card_type = defect" if tracker_klass == MingleTracker - params[:type] = tracker_klass.to_s + issue_tracker_klass = klass.new(@app, {}) + params = { + :options => issue_tracker_klass.fields.inject({}){|hash,f| hash[f[0]] = "test_value"; hash }, + :type_tracker => key.dup.to_s + } put :update, :id => @app.id, :app => {:issue_tracker_attributes => params} @app.reload tracker = @app.issue_tracker - expect(tracker).to be_a(tracker_klass) - tracker_klass::Fields.each do |field, field_info| + expect(tracker.tracker).to be_a(ErrbitPlugin::Register.issue_tracker(key)) + issue_tracker_klass.fields.each do |field, field_info| case field - when :ticket_properties - expect(tracker.send(field.to_sym)).to eq 'card_type = defect' - else - expect(tracker.send(field.to_sym)).to eq 'test_value' + when :ticket_properties; tracker.send(field.to_sym).should == 'card_type = defect' + else tracker.options[field.to_s].should == 'test_value' end end end @@ -324,8 +324,11 @@ describe AppsController do it "should show validation notice when sufficient params are not present" do # Leave out one required param # TODO. previous test was not relevant because one params can be enough. So put noone - params = {:type => tracker_klass.to_s } - put :update, :id => @app.id, :app => {:issue_tracker_attributes => params} + put :update, :id => @app.id, :app => { + :issue_tracker_attributes => { + :type_tracker => key.dup.to_s + } + } @app.reload expect(@app.issue_tracker_configured?).to eq false diff --git a/spec/controllers/problems_controller_spec.rb b/spec/controllers/problems_controller_spec.rb index 0885ae4..3cd4e97 100644 --- a/spec/controllers/problems_controller_spec.rb +++ b/spec/controllers/problems_controller_spec.rb @@ -8,15 +8,16 @@ describe ProblemsController do :params => {:app_id => 'dummyid', :id => 'dummyid'} let(:app) { Fabricate(:app) } - let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production")) } + let(:err) { Fabricate(:err, :problem => problem) } + let(:admin) { Fabricate(:admin) } + let(:problem) { Fabricate(:problem, :app => app, :environment => "production") } describe "GET /problems" do #render_views context 'when logged in as an admin' do before(:each) do - @user = Fabricate(:admin) - sign_in @user + sign_in admin @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem end @@ -31,7 +32,7 @@ describe ProblemsController do end it "should be able to override default per_page value" do - @user.update_attribute :per_page, 10 + admin.update_attribute :per_page, 10 get :index expect(controller.problems.to_a.size).to eq 10 end @@ -98,7 +99,7 @@ describe ProblemsController do describe "GET /problems - previously all" do context 'when logged in as an admin' do it "gets a paginated list of all problems" do - sign_in Fabricate(:admin) + sign_in admin problems = Kaminari.paginate_array((1..30).to_a) 3.times { problems << Fabricate(:err).problem } 3.times { problems << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem } @@ -128,7 +129,7 @@ describe ProblemsController do context 'when logged in as an admin' do before do - sign_in Fabricate(:admin) + sign_in admin end it "finds the app" do @@ -192,7 +193,7 @@ describe ProblemsController do describe "PUT /apps/:app_id/problems/:id/resolve" do before do - sign_in Fabricate(:admin) + sign_in admin @problem = Fabricate(:err) App.stub(:find).with(@problem.app.id.to_s).and_return(@problem.app) @@ -231,76 +232,50 @@ describe ProblemsController do end describe "POST /apps/:app_id/problems/:id/create_issue" do - #render_views before(:each) do - sign_in Fabricate(:admin) + sign_in admin end context "successful issue creation" do context "lighthouseapp tracker" do let(:notice) { Fabricate :notice } - let(:tracker) { Fabricate :lighthouse_tracker, :app => notice.app } let(:problem) { notice.problem } before(:each) do - number = 5 - @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml" - body = "#{number}" - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml"). - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) - + controller.stub(:problem).and_return(problem) + controller.stub(:current_user).and_return(admin) + IssueCreation.should_receive(:new).with(problem, admin, nil, request).and_return(double(:execute => true)) post :create_issue, :app_id => problem.app.id, :id => problem.id - problem.reload end it "should redirect to problem page" do expect(response).to redirect_to( app_problem_path(problem.app, problem) ) + expect(flash[:error]).to be_blank end end end - context "absent issue tracker" do - let(:problem) { Fabricate :problem } - + context "error during request to a tracker" do before(:each) do + IssueCreation.should_receive(:new).with(problem, admin, nil, request).and_return( + double(:execute => false, :errors => double(:full_messages => ['not create'])) + ) + controller.stub(:problem).and_return(problem) post :create_issue, :app_id => problem.app.id, :id => problem.id end it "should redirect to problem page" do expect(response).to redirect_to( app_problem_path(problem.app, problem) ) - end - - it "should set flash error message telling issue tracker of the app doesn't exist" do - expect(flash[:error]).to eq "This app has no issue tracker setup." + expect(flash[:error]).to eql 'not create' end end - context "error during request to a tracker" do - context "lighthouseapp tracker" do - let(:tracker) { Fabricate :lighthouse_tracker } - let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app)) } - - before(:each) do - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500) - - post :create_issue, :app_id => err.app.id, :id => err.problem.id - end - - it "should redirect to problem page" do - expect(response).to redirect_to( app_problem_path(err.app, err.problem) ) - end - - it "should notify of connection error" do - expect(flash[:error]).to include("There was an error during issue creation:") - end - end - end end describe "DELETE /apps/:app_id/problems/:id/unlink_issue" do before(:each) do - sign_in Fabricate(:admin) + sign_in admin end context "problem with issue" do @@ -336,7 +311,7 @@ describe ProblemsController do describe "Bulk Actions" do before(:each) do - sign_in Fabricate(:admin) + sign_in admin @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem end diff --git a/spec/decorators/issue_tracker_decorator_spec.rb b/spec/decorators/issue_tracker_decorator_spec.rb index ff3f50a..2567e3e 100644 --- a/spec/decorators/issue_tracker_decorator_spec.rb +++ b/spec/decorators/issue_tracker_decorator_spec.rb @@ -2,37 +2,28 @@ require 'spec_helper' describe IssueTrackerDecorator do - class Foo - Note = 'hello ' - Fields = [ - [:foo, :bar] - ] - Label = 'foo' - def self.label; Label; end - def _type - 'Foo' - end + let(:none_tracker) do + ErrbitPlugin::NoneIssueTracker.new(Object.new, 'none') end - class Bar - Label = 'bar' - def self.label; Label; end - def _type - 'Bar' - end + let(:tracker) do + ErrbitPlugin::FakeIssueTracker.new(Object.new, 'fake') end - describe "#note" do + let(:decorator) do + IssueTrackerDecorator.new(tracker, 'fake') + end + describe "#note" do it 'return the html_safe of Note' do - expect(IssueTrackerDecorator.new(Foo).note).to eql 'hello '.html_safe + expect(decorator.note).to eql tracker.note end end describe "#issue_trackers" do it 'return an array of IssueTrackerDecorator' do - IssueTrackerDecorator.new(Foo).issue_trackers do |it| + decorator.issue_trackers do |it| expect(it).to be_a(IssueTrackerDecorator) end end @@ -40,20 +31,20 @@ describe IssueTrackerDecorator do describe "#fields" do it 'return all Fields define decorate' do - IssueTrackerDecorator.new(Foo).fields do |itf| + decorator.fields do |itf| expect(itf).to be_a(IssueTrackerFieldDecorator) - expect(itf.object).to eql :foo - expect(itf.field_info).to eql :bar + expect([:foo, :bar]).to be_include(itf.object) + expect([{:label => 'foo'}, {:label => 'bar'}]).to be_include(itf.field_info) end end end describe "#params_class" do it 'add the label in class' do - expect(IssueTrackerDecorator.new(Bar).params_class(Foo.new)).to eql 'bar' + expect(decorator.params_class(IssueTracker.new(:type_tracker => 'none'))).to eql 'fake' end it 'add chosen class if _type is same' do - expect(IssueTrackerDecorator.new(Foo).params_class(Foo.new)).to eql 'chosen foo' + expect(decorator.params_class(IssueTracker.new(:type_tracker => 'fake'))).to eql 'chosen fake' end end end diff --git a/spec/fabricators/issue_tracker_fabricator.rb b/spec/fabricators/issue_tracker_fabricator.rb index b6b10d0..ff75151 100644 --- a/spec/fabricators/issue_tracker_fabricator.rb +++ b/spec/fabricators/issue_tracker_fabricator.rb @@ -1,41 +1,3 @@ Fabricator :issue_tracker do app - api_token { sequence :word } - project_id { sequence :word } - account { sequence :word } - username { sequence :word } - password { sequence :word } -end - -%w(lighthouse pivotal_labs fogbugz).each do |t| - Fabricator "#{t}_tracker".to_sym, :from => :issue_tracker, :class_name => "IssueTrackers::#{t.camelcase}Tracker" -end - -Fabricator :redmine_tracker, :from => :issue_tracker, :class_name => "IssueTrackers::RedmineTracker" do - account 'http://redmine.example.com' -end - -Fabricator :gitlab_tracker, :from => :issue_tracker, :class_name => "IssueTrackers::GitlabTracker" do - account 'http://gitlab.example.com' - alt_project_id 'foo' -end - -Fabricator :mingle_tracker, :from => :issue_tracker, :class_name => "IssueTrackers::MingleTracker" do - account 'https://mingle.example.com' - ticket_properties 'card_type = Defect, defect_status = open, priority = essential' -end - -Fabricator :github_issues_tracker, :from => :issue_tracker, :class_name => "IssueTrackers::GithubIssuesTracker" do - project_id 'test_account/test_project' - username 'test_username' -end - -Fabricator :bitbucket_issues_tracker, :from => :issue_tracker, :class_name => "IssueTrackers::BitbucketIssuesTracker" do - project_id 'password' - api_token 'test_username' -end - -Fabricator :unfuddle_issues_tracker, :from => :issue_tracker, :class_name => "IssueTrackers::UnfuddleTracker" do - account 'test' - project_id 15 end diff --git a/spec/interactors/issue_creation_spec.rb b/spec/interactors/issue_creation_spec.rb index ab74419..852d8d9 100644 --- a/spec/interactors/issue_creation_spec.rb +++ b/spec/interactors/issue_creation_spec.rb @@ -1,8 +1,22 @@ require 'spec_helper' describe IssueCreation do - subject(:issue_creation) { IssueCreation.new(problem, user, tracker_name) } + class FakeIssueTracker + def initialize(app, params); end + def configured?; true; end + def create_issue(problem,user) ; true; end + end + subject(:issue_creation) do + IssueCreation.new(problem, user, tracker_name, request) + end + let(:request) do + double(:request, + :host => 'github.com', + :port => '80', + :scheme => 'http' + ) + end let(:problem) { notice.problem } let(:notice) { Fabricate(:notice) } let(:user) { Fabricate(:admin) } @@ -15,8 +29,9 @@ describe IssueCreation do end it 'creates an issue if issue tracker is configured' do - tracker = Fabricate(:lighthouse_tracker, :app => notice.app) - expect(tracker).to receive(:create_issue) + a = problem.app + a.build_issue_tracker + expect(ErrbitPlugin::Register).to receive(:issue_tracker).and_return(FakeIssueTracker) issue_creation.execute expect(errors).to be_empty end @@ -44,7 +59,9 @@ describe IssueCreation do user.github_oauth_token = 'oauthtoken' user.save! - GithubIssuesTracker.any_instance.should_receive(:create_issue) + ErrbitGithubPlugin::IssueTracker.should_receive(:new).and_return( + double(:create_issue => true) + ) issue_creation.execute expect(errors).to be_empty end diff --git a/spec/interactors/problem_updater_cache_spec.rb b/spec/interactors/problem_updater_cache_spec.rb index dca8381..679a95b 100644 --- a/spec/interactors/problem_updater_cache_spec.rb +++ b/spec/interactors/problem_updater_cache_spec.rb @@ -74,7 +74,7 @@ describe ProblemUpdaterCache do end it 'update last_notice_at' do - expect(problem.last_notice_at.to_i).to be_within(1).of(notice.created_at.to_i) + expect(problem.last_notice_at.to_i).to be_within(2).of(notice.created_at.to_i) end it 'update stats messages' do diff --git a/spec/models/app_spec.rb b/spec/models/app_spec.rb index 0242175..0d57a51 100644 --- a/spec/models/app_spec.rb +++ b/spec/models/app_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe App do + context "Attributes" do it { should have_field(:_id).of_type(String) } it { should have_field(:name).of_type(String) } @@ -220,5 +221,26 @@ describe App do end end + describe "#comments_allowed?" do + context "without issue_tracker" do + it 'return true' do + expect(App.new.comments_allowed?).to be_true + end + end + + context "with issue_tracker" do + let(:issue_tracker) do + ist = IssueTracker.new + ist.stub(:comments_allowed?).and_return('foo') + ist + end + it 'delegate to issue_tracker' do + expect(App.new( + :issue_tracker => issue_tracker + ).comments_allowed?).to eql 'foo' + end + end + end + end diff --git a/spec/models/issue_tracker_spec.rb b/spec/models/issue_tracker_spec.rb new file mode 100644 index 0000000..9c4b7a7 --- /dev/null +++ b/spec/models/issue_tracker_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe IssueTracker do + describe "Association" do + it { should be_embedded_in(:app) } + end + + describe "Attributes" do + it { should have_field(:type_tracker).of_type(String) } + it { should have_field(:options).of_type(Hash).with_default_value_of({}) } + end + + describe "#tracker" do + context "with type_tracker class not exist" do + it 'return NullIssueTracker' do + expect(IssueTracker.new(:type_tracker => 'Foo').tracker).to be_a ErrbitPlugin::NoneIssueTracker + end + end + end +end diff --git a/spec/models/issue_trackers/bitbucket_issues_tracker_spec.rb b/spec/models/issue_trackers/bitbucket_issues_tracker_spec.rb deleted file mode 100644 index 12640f6..0000000 --- a/spec/models/issue_trackers/bitbucket_issues_tracker_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::BitbucketIssuesTracker do - it "should create an issue on BitBucket Issues with problem params, and set issue link for problem" do - repo = "test_user/test_repo" - notice = Fabricate :notice - notice.app.bitbucket_repo = repo - tracker = Fabricate :bitbucket_issues_tracker, :app => notice.app - problem = notice.problem - - number = 123 - @issue_link = "https://bitbucket.org/#{repo}/issue/#{number}/" - body = < 200, :headers => {}, :body => body ) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested = have_requested(:post, "https://#{tracker.api_token}:#{tracker.project_id}@bitbucket.org/api/1.0/repositories/test_user/test_repo/issues/") - expect(WebMock).to requested.with(:title => /[production][foo#bar] FooError: Too Much Bar/) - expect(WebMock).to requested.with(:content => /See this exception on Errbit/) - - expect(problem.issue_link).to eq @issue_link - end -end diff --git a/spec/models/issue_trackers/fogbugz_tracker_spec.rb b/spec/models/issue_trackers/fogbugz_tracker_spec.rb deleted file mode 100644 index cee2603..0000000 --- a/spec/models/issue_trackers/fogbugz_tracker_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::FogbugzTracker do - it "should create an issue on Fogbugz with problem params, and set issue link for problem" do - notice = Fabricate :notice - tracker = Fabricate :fogbugz_tracker, :app => notice.app - problem = notice.problem - - number = 123 - @issue_link = "https://#{tracker.account}.fogbugz.com/default.asp?#{number}" - response = "12345123" - http_mock = double - expect(http_mock).to receive(:new).and_return(http_mock) - expect(http_mock).to receive(:request).twice.and_return(response) - Fogbugz.adapter[:http] = http_mock - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - expect(problem.issue_link).to eq @issue_link - end -end - diff --git a/spec/models/issue_trackers/github_issues_tracker_spec.rb b/spec/models/issue_trackers/github_issues_tracker_spec.rb deleted file mode 100644 index 5fc0aec..0000000 --- a/spec/models/issue_trackers/github_issues_tracker_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::GithubIssuesTracker do - it "should create an issue on GitHub Issues with problem params, and set issue link for problem" do - repo = "test_user/test_repo" - notice = Fabricate :notice - notice.app.github_repo = repo - tracker = Fabricate :github_issues_tracker, :app => notice.app - problem = notice.problem - - number = 5 - @issue_link = "https://github.com/#{repo}/issues/#{number}" - body = < 201, - :headers => { - 'Location' => @issue_link, - 'Content-Type' => 'application/json', - }, - :body => body ) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested = have_requested(:post, "https://#{tracker.username}:#{tracker.password}@api.github.com/repos/#{repo}/issues") - expect(WebMock).to requested.with(:body => /[production][foo#bar] FooError: Too Much Bar/) - expect(WebMock).to requested.with(:body => /See this exception on Errbit/) - - expect(problem.issue_link).to eq @issue_link - end -end - diff --git a/spec/models/issue_trackers/gitlab_issues_tracker_spec.rb b/spec/models/issue_trackers/gitlab_issues_tracker_spec.rb deleted file mode 100644 index 45c5b9e..0000000 --- a/spec/models/issue_trackers/gitlab_issues_tracker_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::GitlabTracker do - it "should create an issue on Gitlab with problem params" do - notice = Fabricate :notice - tracker = Fabricate :gitlab_tracker, :app => notice.app - problem = notice.problem - - issue_id = 5 - note_id = 10 - issue_body = {:id => issue_id, :title => "[production][foo#bar] FooError: Too Much Bar", :description => "[See this exception on Errbit]"}.to_json - note_body = {:id => note_id, :body => "Example note body"}.to_json - - stub_request(:post, "#{tracker.account}/api/v3/projects/#{tracker.project_id}/issues?private_token=#{tracker.api_token}"). - with(:body => /.+/, :headers => {'Accept'=>'application/json'}). - to_return(:status => 200, :body => issue_body, :headers => {'Accept'=>'application/json'}) - - stub_request(:post, "#{tracker.account}/api/v3/projects/#{tracker.project_id}/issues/#{issue_id}/notes?private_token=#{tracker.api_token}"). - with(:body => /.+/, :headers => {'Accept'=>'application/json'}). - to_return(:status => 200, :body => note_body, :headers => {'Accept'=>'application/json'}) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested_issue = have_requested(:post, "#{tracker.account}/api/v3/projects/#{tracker.project_id}/issues?private_token=#{tracker.api_token}").with(:body => /.+/, :headers => {'Accept'=>'application/json'}) - requested_note = have_requested(:post, "#{tracker.account}/api/v3/projects/#{tracker.project_id}/issues/#{issue_id}/notes?private_token=#{tracker.api_token}") - expect(WebMock).to requested_issue.with(:body => /%5Bproduction%5D%5Bfoo%23bar%5D%20FooError%3A%20Too%20Much%20Bar/) - expect(WebMock).to requested_issue.with(:body => /See%20this%20exception%20on%20Errbit/) - - end -end - diff --git a/spec/models/issue_trackers/lighthouse_tracker_spec.rb b/spec/models/issue_trackers/lighthouse_tracker_spec.rb deleted file mode 100644 index 1bcbb99..0000000 --- a/spec/models/issue_trackers/lighthouse_tracker_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::LighthouseTracker do - it "should create an issue on Lighthouse with problem params, and set issue link for problem" do - notice = Fabricate :notice - tracker = Fabricate :lighthouse_tracker, :app => notice.app - problem = notice.problem - - number = 5 - @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml" - body = "#{number}" - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml"). - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested = have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml") - expect(WebMock).to requested.with(:headers => {'X-Lighthousetoken' => tracker.api_token}) - expect(WebMock).to requested.with(:body => /errbit<\/tag>/) - expect(WebMock).to requested.with(:body => /\[#{ problem.environment }\]\[#{problem.where}\] #{problem.message.to_s.truncate(100)}<\/title>/) - expect(WebMock).to requested.with(:body => /<body>.+<\/body>/m) - - expect(problem.issue_link).to eq @issue_link.sub(/\.xml$/, '') - end -end - diff --git a/spec/models/issue_trackers/mingle_tracker_spec.rb b/spec/models/issue_trackers/mingle_tracker_spec.rb deleted file mode 100644 index 7011f26..0000000 --- a/spec/models/issue_trackers/mingle_tracker_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::MingleTracker do - it "should create an issue on Mingle with problem params, and set issue link for problem" do - notice = Fabricate :notice - tracker = Fabricate :mingle_tracker, :app => notice.app - problem = notice.problem - - number = 5 - @issue_link = "#{tracker.account}/projects/#{tracker.project_id}/cards/#{number}.xml" - @basic_auth = tracker.account.gsub("://", "://#{tracker.username}:#{tracker.password}@") - body = "<card><id type=\"integer\">#{number}</id></card>" - stub_request(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml"). - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested = have_requested(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml") - expect(WebMock).to requested.with(:headers => {'Content-Type' => 'application/xml'}) - expect(WebMock).to requested.with(:body => /FooError: Too Much Bar/) - expect(WebMock).to requested.with(:body => /See this exception on Errbit/) - expect(WebMock).to requested.with(:body => /<card-type-name>Defect<\/card-type-name>/) - - expect(problem.issue_link).to eq @issue_link.sub(/\.xml$/, '') - end -end - diff --git a/spec/models/issue_trackers/pivotal_labs_tracker_spec.rb b/spec/models/issue_trackers/pivotal_labs_tracker_spec.rb deleted file mode 100644 index c27927a..0000000 --- a/spec/models/issue_trackers/pivotal_labs_tracker_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::PivotalLabsTracker do - - let(:user) { Fabricate(:user) } - let(:notice) { Fabricate(:notice) } - let(:tracker) { Fabricate :pivotal_labs_tracker, :app => notice.app, :project_id => 10 } - let(:problem) { notice.problem } - let(:story_id) { 5 } - let(:issue_link) { "https://www.pivotaltracker.com/story/show/#{story_id}" } - - it "creates an issue on Pivotal Tracker with problem params, and set issue link for problem" do - project_body = "<project><id>#{tracker.project_id}</id><name>TestProject</name></project>" - stub_request(:get, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}"). - to_return(:status => 200, :headers => {'Location' => issue_link}, :body => project_body ) - story_body = "<story><name>Test Story</name><id>#{story_id}</id></story>" - stub_request(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories"). - to_return(:status => 201, :headers => {'Location' => issue_link}, :body => story_body ) - - problem.app.issue_tracker.create_issue(problem, user) - problem.reload - - requested = have_requested(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories") - expect(WebMock).to requested.with(:headers => {'X-Trackertoken' => tracker.api_token}) - expect(WebMock).to requested.with(:body => /See this exception on Errbit/) - expect(WebMock).to requested.with(:body => /<name>\[#{ problem.environment }\]\[#{problem.where}\] #{problem.message.to_s.truncate(100)}<\/name>/) - expect(WebMock).to requested.with(:body => /<description>.+<\/description>/m) - - expect(problem.issue_link).to eq issue_link - end - - it "raises IssueTrackers::IssueTrackerError exception when invalid params and does not set issue link for problem" do - project_body = "<project><id>#{tracker.project_id}</id><name>TestProject</name></project>" - stub_request(:get, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}"). - to_return(:status => 200, :body => project_body ) - story_body = "<errors><error>Requested by can't be blank</error><error>Requested by can't be blank</error></errors>" - stub_request(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories"). - to_return(:status => 422, :body => story_body ) - - expect{ - problem.app.issue_tracker.create_issue(problem, user) - }.to raise_exception(IssueTrackers::IssueTrackerError, "Requested by can't be blank") - expect(problem.issue_link).to be_nil - end -end - diff --git a/spec/models/issue_trackers/redmine_tracker_spec.rb b/spec/models/issue_trackers/redmine_tracker_spec.rb deleted file mode 100644 index 399df99..0000000 --- a/spec/models/issue_trackers/redmine_tracker_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::RedmineTracker do - it "should create an issue on Redmine with problem params, and set issue link for problem" do - notice = Fabricate(:notice) - tracker = Fabricate(:redmine_tracker, :app => notice.app, :project_id => 10) - problem = notice.problem - number = 5 - @issue_link = "#{tracker.account}/issues/#{number}.xml?project_id=#{tracker.project_id}" - body = "<issue><subject>my subject</subject><id>#{number}</id></issue>" - - # Build base url with account URL, and username/password basic auth - base_url = tracker.account.gsub 'http://', "http://#{tracker.username}:#{tracker.password}@" - - stub_request(:post, "#{base_url}/issues.xml"). - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested = have_requested(:post, "#{base_url}/issues.xml") - expect(WebMock).to requested.with(:headers => {'X-Redmine-API-Key' => tracker.api_token}) - expect(WebMock).to requested.with(:body => /<project-id>#{tracker.project_id}<\/project-id>/) - expect(WebMock).to requested.with(:body => /<subject>\[#{ problem.environment }\]\[#{problem.where}\] #{problem.message.to_s.truncate(100)}<\/subject>/) - expect(WebMock).to requested.with(:body => /<description>.+<\/description>/m) - - expect(problem.issue_link).to eq @issue_link.sub(/\.xml/, '') - end - - it "should generate a url where a file with line number can be viewed" do - t = Fabricate(:redmine_tracker, :account => 'http://redmine.example.com', :project_id => "errbit") - expect(t.url_to_file("/example/file")). - to eq 'http://redmine.example.com/projects/errbit/repository/revisions/master/changes/example/file' - expect(t.url_to_file("/example/file", 25)). - to eq 'http://redmine.example.com/projects/errbit/repository/revisions/master/changes/example/file#L25' - end - - it "should use the alt_project_id to generate a file/linenumber url, if given" do - t = Fabricate(:redmine_tracker, :account => 'http://redmine.example.com', - :project_id => "errbit", - :alt_project_id => "actual_project") - expect(t.url_to_file("/example/file", 25)). - to eq 'http://redmine.example.com/projects/actual_project/repository/revisions/master/changes/example/file#L25' - end -end diff --git a/spec/models/issue_trackers/unfuddle_issues_tracker_spec.rb b/spec/models/issue_trackers/unfuddle_issues_tracker_spec.rb deleted file mode 100644 index c518c97..0000000 --- a/spec/models/issue_trackers/unfuddle_issues_tracker_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'spec_helper' - -describe IssueTrackers::UnfuddleTracker do - - let(:issue_link) { "https://test.unfuddle.com/projects/15/tickets/2436" } - let(:notice) { Fabricate :notice } - let(:tracker) { Fabricate :unfuddle_issues_tracker, :app => notice.app } - let(:problem) { notice.problem } - - it "should create an issue on Unfuddle Issues with problem params, and set issue link for problem" do -project_xml = <<EOF -<?xml version="1.0" encoding="UTF-8"?> -<project> - <account-id type="integer">1</account-id> - <archived type="boolean">false</archived> - <assignee-on-resolve>reporter</assignee-on-resolve> - <backup-frequency type="integer">0</backup-frequency> - <close-ticket-simultaneously-default type="boolean">false</close-ticket-simultaneously-default> - <default-ticket-report-id type="integer" nil="true"></default-ticket-report-id> - <description nil="true"></description> - <disk-usage type="integer">27932</disk-usage> - <enable-time-tracking type="boolean">true</enable-time-tracking> - <id type="integer">#{tracker.project_id}</id> - <s3-access-key-id></s3-access-key-id> - <s3-backup-enabled type="boolean">false</s3-backup-enabled> - <s3-bucket-name></s3-bucket-name> - <short-name>test-project</short-name> - <theme>blue</theme> - <ticket-field1-active type="boolean">false</ticket-field1-active> - <ticket-field1-disposition>text</ticket-field1-disposition> - <ticket-field1-title>Field 1</ticket-field1-title> - <ticket-field2-active type="boolean">false</ticket-field2-active> - <ticket-field2-disposition>text</ticket-field2-disposition> - <ticket-field2-title>Field 2</ticket-field2-title> - <ticket-field3-active type="boolean">false</ticket-field3-active> - <ticket-field3-disposition>text</ticket-field3-disposition> - <ticket-field3-title>Field 3</ticket-field3-title> - <title>test-project - 2011-04-25T09:21:43Z - 2013-03-08T08:03:02Z - -EOF - - ticket_xml =< - - 40 - - - markdown - - - - - 1268.7 - 0.0 - 2436 - 78 - 119 - 3 - 15 - 40 - - - markdown - - reopened - TEST-ticket. - - 2012-06-27T17:49:06Z - 2013-03-07T16:04:05Z - -EOF - - stub_request(:get, "https://#{tracker.username}:#{tracker.password}@test.unfuddle.com/api/v1/projects/#{tracker.project_id}.xml"). - to_return(:status => 200, :body => project_xml, :headers => {}) - - - stub_request(:post, "https://#{tracker.username}:#{tracker.password}@test.unfuddle.com/api/v1/projects/#{tracker.project_id}/tickets.xml"). - to_return(:status => 200, :body => ticket_xml, :headers => {}) - - problem.app.issue_tracker.create_issue(problem) - problem.reload - - requested = have_requested(:post,"https://#{tracker.username}:#{tracker.password}@test.unfuddle.com/api/v1/projects/#{tracker.project_id}/tickets.xml" ) - expect(WebMock).to requested.with(:title => /[production][foo#bar] FooError: Too Much Bar/) - expect(WebMock).to requested.with(:content => /See this exception on Errbit/) - - expect(problem.issue_link).to eq issue_link - expect(problem.issue_type).to eq IssueTrackers::UnfuddleTracker::Label - end -end diff --git a/spec/models/problem_spec.rb b/spec/models/problem_spec.rb index afbf12d..412f02a 100644 --- a/spec/models/problem_spec.rb +++ b/spec/models/problem_spec.rb @@ -370,6 +370,56 @@ describe Problem do end end + describe "#issue_type" do + context "without issue_type fill in Problem" do + let(:problem) do + Problem.new(:app => app) + end + + let(:app) do + App.new(:issue_tracker => issue_tracker) + end + + context "without issue_tracker associate to app" do + let(:issue_tracker) do + nil + end + it 'return nil' do + expect(problem.issue_type).to be_nil + end + end + + context "with issue_tracker valid associate to app" do + let(:issue_tracker) do + it = IssueTracker.new + it.stub(:tracker).and_return(double(:configured? => true, :label => 'foo')) + it + end + + it 'return the issue_tracker label' do + expect(problem.issue_type).to eql 'foo' + end + end + + context "with issue_tracker not valid associate to app" do + let(:issue_tracker) do + it = IssueTracker.new + it.stub(:tracker).and_return(double(:configured? => false)) + it + end + it 'return nil' do + expect(problem.issue_type).to be_nil + end + end + end + + context "with issue_type fill in Problem" do + it 'return the value associate' do + expect(Problem.new(:issue_type => 'foo').issue_type).to eql 'foo' + end + end + end + end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 47080d8..ea72e22 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,6 +24,7 @@ require 'webmock/rspec' require 'xmpp4r' require 'xmpp4r/muc' require 'mongoid-rspec' +require 'errbit_plugin/issue_trackers/fake' # Requires supporting files with custom matchers and macros, etc, @@ -54,7 +55,7 @@ RSpec.configure do |config| init_haml_helpers end - config.after(:all) do + config.before(:all) do WebMock.disable_net_connect! :allow => /coveralls\.io|127\.0\.0\.1/ end end diff --git a/spec/views/problems/show.html.haml_spec.rb b/spec/views/problems/show.html.haml_spec.rb index 90d87a1..4d70795 100644 --- a/spec/views/problems/show.html.haml_spec.rb +++ b/spec/views/problems/show.html.haml_spec.rb @@ -1,6 +1,20 @@ require 'spec_helper' describe "problems/show.html.haml" do + class PivotalLabsTracker + def initialize(app, params); end + def label; 'pivotal'; end + def configured?; true; end + def comments_allowed?; false; end + end + + class GithubIssuesTracker + def initialize(app, params); end + def label; 'github'; end + def configured?; true; end + def comments_allowed?; false; end + end + let(:problem) { Fabricate(:problem) } let(:comment) { Fabricate(:comment) } @@ -16,7 +30,8 @@ describe "problems/show.html.haml" do end def with_issue_tracker(tracker, problem) - problem.app.issue_tracker = tracker.new :api_token => "token token token", :project_id => "1234" + problem.app.issue_tracker = IssueTracker.new :type_tracker => tracker, :options => {:api_token => "token token token", :project_id => "1234"} + ErrbitPlugin::Register.stub(:issue_tracker).with(tracker).and_return(tracker.constantize) view.stub(:problem).and_return(problem) view.stub(:app).and_return(problem.app) end @@ -75,7 +90,7 @@ describe "problems/show.html.haml" do it 'should allow creating issue for github if application has a github tracker' do problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo")) - with_issue_tracker(GithubIssuesTracker, problem) + with_issue_tracker("GithubIssuesTracker", problem) view.stub(:problem).and_return(problem) view.stub(:app).and_return(problem.app) render @@ -96,16 +111,15 @@ describe "problems/show.html.haml" do end - context "with lighthouse tracker on app" do - let(:app) { App.new(:new_record => false, :issue_tracker => tracker ) } - let(:tracker) { - IssueTrackers::LighthouseTracker.new(:project_id => 'x') - } + context "with tracker associate on app" do + before do + with_issue_tracker("PivotalLabsTracker", problem) + end context "with problem without issue link" do - let(:problem){ Problem.new(:new_record => false, :app => app) } + before do + problem.issue_link = nil + end it 'not see link if no issue tracker' do - view.stub(:problem).and_return(problem) - view.stub(:app).and_return(problem.app) render expect(view.content_for(:action_bar)).to match(/create issue/) end @@ -113,11 +127,11 @@ describe "problems/show.html.haml" do end context "with problem with issue link" do - let(:problem){ Problem.new(:new_record => false, :app => app, :issue_link => 'http://foo') } + before do + problem.issue_link = 'http://foo' + end it 'not see link if no issue tracker' do - view.stub(:problem).and_return(problem) - view.stub(:app).and_return(problem.app) render expect(view.content_for(:action_bar)).to_not match(/create issue/) end @@ -147,7 +161,7 @@ describe "problems/show.html.haml" do context "with issue tracker" do it 'should not display the comments section' do problem = Fabricate(:problem) - with_issue_tracker(PivotalLabsTracker, problem) + with_issue_tracker("PivotalLabsTracker", problem) render expect(view.view_flow.get(:comments)).to be_blank end @@ -155,7 +169,7 @@ describe "problems/show.html.haml" do it 'should display existing comments' do problem = Fabricate(:problem_with_comments) problem.reload - with_issue_tracker(PivotalLabsTracker, problem) + with_issue_tracker("PivotalLabsTracker", problem) render expect(view.content_for(:comments)).to include('Test comment') -- libgit2 0.21.2