##// END OF EJS Templates
Default status per tracker (#5991)....
Jean-Philippe Lang -
r13153:dfc594c33702
parent child
Show More
@@ -0,0 +1,15
1 class AddTrackersDefaultStatusId < ActiveRecord::Migration
2 def up
3 add_column :trackers, :default_status_id, :integer
4
5 status_id = IssueStatus.where(:is_default => true).pluck(:id).first
6 status_id ||= IssueStatus.order(:position).pluck(:id).first
7 if status_id
8 Tracker.update_all :default_status_id => status_id
9 end
10 end
11
12 def down
13 remove_column :trackers, :default_status_id
14 end
15 end
@@ -0,0 +1,12
1 class RemoveIssueStatusesIsDefault < ActiveRecord::Migration
2 def up
3 remove_column :issue_statuses, :is_default
4 end
5
6 def down
7 add_column :issue_statuses, :is_default, :boolean, :null => false, :default => false
8 # Restores the first status as default
9 default_status_id = IssueStatus.order("position").first.pluck(:id)
10 IssueStatus.where(:id => default_status_id).update_all(:is_default => true)
11 end
12 end
@@ -24,7 +24,6 class IssuesController < ApplicationController
24 24 before_filter :find_project, :only => [:new, :create, :update_form]
25 25 before_filter :authorize, :except => [:index]
26 26 before_filter :find_optional_project, :only => [:index]
27 before_filter :check_for_default_issue_status, :only => [:new, :create]
28 27 before_filter :build_new_issue_from_params, :only => [:new, :create, :update_form]
29 28 accept_rss_auth :index, :show
30 29 accept_api_auth :index, :show, :create, :update, :destroy
@@ -234,7 +233,8 class IssuesController < ApplicationController
234 233 target_projects ||= @projects
235 234
236 235 if @copy
237 @available_statuses = [IssueStatus.default]
236 # Copied issues will get their default statuses
237 @available_statuses = []
238 238 else
239 239 @available_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
240 240 end
@@ -425,12 +425,21 class IssuesController < ApplicationController
425 425 @issue = @project.issues.visible.find(params[:id])
426 426 end
427 427
428 @issue.safe_attributes = params[:issue]
428 if attrs = params[:issue].deep_dup
429 if params[:was_default_status] == attrs[:status_id]
430 attrs.delete(:status_id)
431 end
432 @issue.safe_attributes = attrs
433 end
429 434 @issue.tracker ||= @project.trackers.first
430 435 if @issue.tracker.nil?
431 436 render_error l(:error_no_tracker_in_project)
432 437 return false
433 438 end
439 if @issue.status.nil?
440 render_error l(:error_no_default_issue_status)
441 return false
442 end
434 443
435 444 @priorities = IssuePriority.active
436 445 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, @issue.new_record?)
@@ -440,13 +449,6 class IssuesController < ApplicationController
440 449 end
441 450 end
442 451
443 def check_for_default_issue_status
444 if IssueStatus.default.nil?
445 render_error l(:error_no_default_issue_status)
446 return false
447 end
448 end
449
450 452 def parse_params_for_bulk_issue_attributes(params)
451 453 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
452 454 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
@@ -162,7 +162,6 class Issue < ActiveRecord::Base
162 162 super
163 163 if new_record?
164 164 # set default values for new records only
165 self.status ||= IssueStatus.default
166 165 self.priority ||= IssuePriority.default
167 166 self.watcher_user_ids = []
168 167 end
@@ -273,11 +272,19 class Issue < ActiveRecord::Base
273 272 issue.save ? issue : false
274 273 end
275 274
276 def status_id=(sid)
277 self.status = nil
278 result = write_attribute(:status_id, sid)
279 @workflow_rule_by_attribute = nil
280 result
275 def status_id=(status_id)
276 if status_id.to_s != self.status_id.to_s
277 self.status = (status_id.present? ? IssueStatus.find_by_id(status_id) : nil)
278 end
279 self.status_id
280 end
281
282 # Sets the status.
283 def self.status=(status)
284 if status != self.status
285 @workflow_rule_by_attribute = nil
286 end
287 association(:status).writer(status)
281 288 end
282 289
283 290 def priority_id=(pid)
@@ -302,12 +309,24 class Issue < ActiveRecord::Base
302 309 self.tracker_id
303 310 end
304 311
312 # Sets the tracker.
313 # This will set the status to the default status of the new tracker if:
314 # * the status was the default for the previous tracker
315 # * or if the status was not part of the new tracker statuses
316 # * or the status was nil
305 317 def tracker=(tracker)
306 318 if tracker != self.tracker
319 if status == default_status
320 self.status = nil
321 elsif status && tracker && !tracker.issue_status_ids.include?(status.id)
322 self.status = nil
323 end
307 324 @custom_field_values = nil
308 325 @workflow_rule_by_attribute = nil
309 326 end
310 327 association(:tracker).writer(tracker)
328 self.status ||= default_status
329 self.tracker
311 330 end
312 331
313 332 def project_id=(project_id)
@@ -317,6 +336,14 class Issue < ActiveRecord::Base
317 336 self.project_id
318 337 end
319 338
339 # Sets the project.
340 # Unless keep_tracker argument is set to true, this will change the tracker
341 # to the first tracker of the new project if the previous tracker is not part
342 # of the new project trackers.
343 # This will clear the fixed_version is it's no longer valid for the new project.
344 # This will clear the parent issue if it's no longer valid for the new project.
345 # This will set the category to the category with the same name in the new
346 # project if it exists, or clear it if it doesn't.
320 347 def project=(project, keep_tracker=false)
321 348 project_was = self.project
322 349 association(:project).writer(project)
@@ -339,7 +366,9 class Issue < ActiveRecord::Base
339 366 self.parent_issue_id = nil
340 367 end
341 368 @custom_field_values = nil
369 @workflow_rule_by_attribute = nil
342 370 end
371 self.project
343 372 end
344 373
345 374 def description=(arg)
@@ -776,14 +805,28 class Issue < ActiveRecord::Base
776 805 !relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
777 806 end
778 807
808 # Returns the default status of the issue based on its tracker
809 # Returns nil if tracker is nil
810 def default_status
811 tracker.try(:default_status)
812 end
813
779 814 # Returns an array of statuses that user is able to apply
780 815 def new_statuses_allowed_to(user=User.current, include_default=false)
781 816 if new_record? && @copied_from
782 [IssueStatus.default, @copied_from.status].compact.uniq.sort
817 [default_status, @copied_from.status].compact.uniq.sort
783 818 else
784 819 initial_status = nil
785 820 if new_record?
786 initial_status = IssueStatus.default
821 initial_status = default_status
822 elsif tracker_id_changed?
823 if Tracker.where(:id => tracker_id_was, :default_status_id => status_id_was).any?
824 initial_status = default_status
825 elsif tracker.issue_status_ids.include?(status_id_was)
826 initial_status = IssueStatus.find_by_id(status_id_was)
827 else
828 initial_status = default_status
829 end
787 830 else
788 831 initial_status = status_was
789 832 end
@@ -802,7 +845,7 class Issue < ActiveRecord::Base
802 845 )
803 846 end
804 847 statuses << initial_status unless statuses.empty?
805 statuses << IssueStatus.default if include_default
848 statuses << default_status if include_default
806 849 statuses = statuses.compact.uniq.sort
807 850 if blocked?
808 851 statuses.reject!(&:is_closed?)
@@ -22,7 +22,6 class IssueStatus < ActiveRecord::Base
22 22 acts_as_list
23 23
24 24 before_destroy :delete_workflow_rules
25 after_save :update_default
26 25
27 26 validates_presence_of :name
28 27 validates_uniqueness_of :name
@@ -33,15 +32,6 class IssueStatus < ActiveRecord::Base
33 32 scope :sorted, lambda { order(:position) }
34 33 scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
35 34
36 def update_default
37 IssueStatus.where(['id <> ?', id]).update_all({:is_default => false}) if self.is_default?
38 end
39
40 # Returns the default status for new issues
41 def self.default
42 where(:is_default => true).first
43 end
44
45 35 # Update all the +Issues+ setting their done_ratio to the value of their +IssueStatus+
46 36 def self.update_issue_done_ratios
47 37 if Issue.use_status_for_done_ratio?
@@ -100,7 +90,11 class IssueStatus < ActiveRecord::Base
100 90 private
101 91
102 92 def check_integrity
103 raise "Can't delete status" if Issue.where(:status_id => id).any?
93 if Issue.where(:status_id => id).any?
94 raise "This status is used by some issues"
95 elsif Tracker.where(:default_status_id => id).any?
96 raise "This status is used as the default status by some trackers"
97 end
104 98 end
105 99
106 100 # Deletes associated workflows
@@ -24,6 +24,7 class Tracker < ActiveRecord::Base
24 24 CORE_FIELDS_ALL = (CORE_FIELDS_UNDISABLABLE + CORE_FIELDS).freeze
25 25
26 26 before_destroy :check_integrity
27 belongs_to :default_status, :class_name => 'IssueStatus'
27 28 has_many :issues
28 29 has_many :workflow_rules, :dependent => :delete_all do
29 30 def copy(source_tracker)
@@ -37,6 +38,7 class Tracker < ActiveRecord::Base
37 38
38 39 attr_protected :fields_bits
39 40
41 validates_presence_of :default_status
40 42 validates_presence_of :name
41 43 validates_uniqueness_of :name
42 44 validates_length_of :name, :maximum => 30
@@ -53,14 +55,15 class Tracker < ActiveRecord::Base
53 55 # Returns an array of IssueStatus that are used
54 56 # in the tracker's workflows
55 57 def issue_statuses
56 if @issue_statuses
57 return @issue_statuses
58 elsif new_record?
59 return []
60 end
58 @issue_statuses ||= IssueStatus.where(:id => issue_status_ids).to_a.sort
59 end
61 60
62 status_ids = WorkflowTransition.where(:tracker_id => id).uniq.pluck(:old_status_id, :new_status_id).flatten.uniq
63 @issue_statuses = IssueStatus.where(:id => status_ids).to_a.sort
61 def issue_status_ids
62 if new_record?
63 []
64 else
65 @issue_status_ids ||= WorkflowTransition.where(:tracker_id => id).uniq.pluck(:old_status_id, :new_status_id).flatten.uniq
66 end
64 67 end
65 68
66 69 def disabled_core_fields
@@ -6,7 +6,6
6 6 <p><%= f.select :default_done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), :include_blank => true, :label => :field_done_ratio %></p>
7 7 <% end %>
8 8 <p><%= f.check_box :is_closed %></p>
9 <p><%= f.check_box :is_default %></p>
10 9
11 10 <%= call_hook(:view_issue_statuses_form, :issue_status => @issue_status) %>
12 11 </div>
@@ -3,7 +3,6 api.array :issue_statuses do
3 3 api.issue_status do
4 4 api.id status.id
5 5 api.name status.name
6 api.is_default status.is_default
7 6 api.is_closed status.is_closed
8 7 end
9 8 end
@@ -11,7 +11,6
11 11 <% if Issue.use_status_for_done_ratio? %>
12 12 <th><%=l(:field_done_ratio)%></th>
13 13 <% end %>
14 <th><%=l(:field_is_default)%></th>
15 14 <th><%=l(:field_is_closed)%></th>
16 15 <th><%=l(:button_sort)%></th>
17 16 <th></th>
@@ -23,7 +22,6
23 22 <% if Issue.use_status_for_done_ratio? %>
24 23 <td><%= h status.default_done_ratio %></td>
25 24 <% end %>
26 <td><%= checked_image status.is_default? %></td>
27 25 <td><%= checked_image status.is_closed? %></td>
28 26 <td class="reorder"><%= reorder_links('issue_status', {:action => 'update', :id => status}, :put) %></td>
29 27 <td class="buttons">
@@ -5,9 +5,9
5 5 <% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
6 6 <p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), {:required => true},
7 7 :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p>
8
8 <%= hidden_field_tag 'was_default_status', @issue.status_id, :id => nil if @issue.status == @issue.default_status %>
9 9 <% else %>
10 <p><label><%= l(:field_status) %></label> <%= h(@issue.status.name) %></p>
10 <p><label><%= l(:field_status) %></label> <%= @issue.status %></p>
11 11 <% end %>
12 12
13 13 <% if @issue.safe_attribute? 'priority_id' %>
@@ -4,8 +4,12
4 4 <div class="box tabular">
5 5 <!--[form:tracker]-->
6 6 <p><%= f.text_field :name, :required => true %></p>
7 <p><%= f.select :default_status_id,
8 IssueStatus.sorted.map {|s| [s.name, s.id]},
9 :include_blank => @tracker.default_status.nil?,
10 :required => true %>
11 </p>
7 12 <p><%= f.check_box :is_in_roadmap %></p>
8
9 13 <p>
10 14 <label><%= l(:field_core_fields) %></label>
11 15 <% Tracker::CORE_FIELDS.each do |field| %>
@@ -3,6 +3,7 api.array :trackers do
3 3 api.tracker do
4 4 api.id tracker.id
5 5 api.name tracker.name
6 api.default_status(:id => tracker.default_status.id, :name => tracker.default_status.name) unless tracker.default_status.nil?
6 7 end
7 8 end
8 9 end
@@ -337,6 +337,7 en:
337 337 field_inherit_members: Inherit members
338 338 field_generate_password: Generate password
339 339 field_must_change_passwd: Must change password at next logon
340 field_default_status: Default status
340 341
341 342 setting_app_title: Application title
342 343 setting_app_subtitle: Application subtitle
@@ -357,6 +357,7 fr:
357 357 field_inherit_members: Hériter les membres
358 358 field_generate_password: Générer un mot de passe
359 359 field_must_change_passwd: Doit changer de mot de passe à la prochaine connexion
360 field_default_status: Statut par défaut
360 361
361 362 setting_app_title: Titre de l'application
362 363 setting_app_subtitle: Sous-titre de l'application
@@ -125,18 +125,18 module Redmine
125 125 :browse_repository,
126 126 :view_changesets]
127 127
128 # Trackers
129 Tracker.create!(:name => l(:default_tracker_bug), :is_in_chlog => true, :is_in_roadmap => false, :position => 1)
130 Tracker.create!(:name => l(:default_tracker_feature), :is_in_chlog => true, :is_in_roadmap => true, :position => 2)
131 Tracker.create!(:name => l(:default_tracker_support), :is_in_chlog => false, :is_in_roadmap => false, :position => 3)
132
133 128 # Issue statuses
134 new = IssueStatus.create!(:name => l(:default_issue_status_new), :is_closed => false, :is_default => true, :position => 1)
135 in_progress = IssueStatus.create!(:name => l(:default_issue_status_in_progress), :is_closed => false, :is_default => false, :position => 2)
136 resolved = IssueStatus.create!(:name => l(:default_issue_status_resolved), :is_closed => false, :is_default => false, :position => 3)
137 feedback = IssueStatus.create!(:name => l(:default_issue_status_feedback), :is_closed => false, :is_default => false, :position => 4)
138 closed = IssueStatus.create!(:name => l(:default_issue_status_closed), :is_closed => true, :is_default => false, :position => 5)
139 rejected = IssueStatus.create!(:name => l(:default_issue_status_rejected), :is_closed => true, :is_default => false, :position => 6)
129 new = IssueStatus.create!(:name => l(:default_issue_status_new), :is_closed => false, :position => 1)
130 in_progress = IssueStatus.create!(:name => l(:default_issue_status_in_progress), :is_closed => false, :position => 2)
131 resolved = IssueStatus.create!(:name => l(:default_issue_status_resolved), :is_closed => false, :position => 3)
132 feedback = IssueStatus.create!(:name => l(:default_issue_status_feedback), :is_closed => false, :position => 4)
133 closed = IssueStatus.create!(:name => l(:default_issue_status_closed), :is_closed => true, :position => 5)
134 rejected = IssueStatus.create!(:name => l(:default_issue_status_rejected), :is_closed => true, :position => 6)
135
136 # Trackers
137 Tracker.create!(:name => l(:default_tracker_bug), :default_status_id => new.id, :is_in_chlog => true, :is_in_roadmap => false, :position => 1)
138 Tracker.create!(:name => l(:default_tracker_feature), :default_status_id => new.id, :is_in_chlog => true, :is_in_roadmap => true, :position => 2)
139 Tracker.create!(:name => l(:default_tracker_support), :default_status_id => new.id, :is_in_chlog => false, :is_in_roadmap => false, :position => 3)
140 140
141 141 # Workflow
142 142 Tracker.all.each { |t|
@@ -25,15 +25,15 task :migrate_from_mantis => :environment do
25 25
26 26 module MantisMigrate
27 27
28 DEFAULT_STATUS = IssueStatus.default
28 new_status = IssueStatus.find_by_position(1)
29 29 assigned_status = IssueStatus.find_by_position(2)
30 30 resolved_status = IssueStatus.find_by_position(3)
31 31 feedback_status = IssueStatus.find_by_position(4)
32 32 closed_status = IssueStatus.where(:is_closed => true).first
33 STATUS_MAPPING = {10 => DEFAULT_STATUS, # new
33 STATUS_MAPPING = {10 => new_status, # new
34 34 20 => feedback_status, # feedback
35 30 => DEFAULT_STATUS, # acknowledged
36 40 => DEFAULT_STATUS, # confirmed
35 30 => new_status, # acknowledged
36 40 => new_status, # confirmed
37 37 50 => assigned_status, # assigned
38 38 80 => resolved_status, # resolved
39 39 90 => closed_status # closed
@@ -317,8 +317,8 task :migrate_from_mantis => :environment do
317 317 i.author = User.find_by_id(users_map[bug.reporter_id])
318 318 i.category = IssueCategory.find_by_project_id_and_name(i.project_id, bug.category[0,30]) unless bug.category.blank?
319 319 i.fixed_version = Version.find_by_project_id_and_name(i.project_id, bug.fixed_in_version) unless bug.fixed_in_version.blank?
320 i.status = STATUS_MAPPING[bug.status] || DEFAULT_STATUS
321 320 i.tracker = (bug.severity == 10 ? TRACKER_FEATURE : TRACKER_BUG)
321 i.status = STATUS_MAPPING[bug.status] || i.status
322 322 i.id = bug.id if keep_bug_ids
323 323 next unless i.save
324 324 issues_map[bug.id] = i.id
@@ -25,12 +25,12 namespace :redmine do
25 25 module TracMigrate
26 26 TICKET_MAP = []
27 27
28 DEFAULT_STATUS = IssueStatus.default
28 new_status = IssueStatus.find_by_position(1)
29 29 assigned_status = IssueStatus.find_by_position(2)
30 30 resolved_status = IssueStatus.find_by_position(3)
31 31 feedback_status = IssueStatus.find_by_position(4)
32 32 closed_status = IssueStatus.where(:is_closed => true).first
33 STATUS_MAPPING = {'new' => DEFAULT_STATUS,
33 STATUS_MAPPING = {'new' => new_status,
34 34 'reopened' => feedback_status,
35 35 'assigned' => assigned_status,
36 36 'closed' => closed_status
@@ -476,8 +476,8 namespace :redmine do
476 476 i.author = find_or_create_user(ticket.reporter)
477 477 i.category = issues_category_map[ticket.component] unless ticket.component.blank?
478 478 i.fixed_version = version_map[ticket.milestone] unless ticket.milestone.blank?
479 i.status = STATUS_MAPPING[ticket.status] || DEFAULT_STATUS
480 479 i.tracker = TRACKER_MAPPING[ticket.ticket_type] || DEFAULT_TRACKER
480 i.status = STATUS_MAPPING[ticket.status] || i.default_status
481 481 i.id = ticket.id unless Issue.exists?(ticket.id)
482 482 next unless Time.fake(ticket.changetime) { i.save }
483 483 TICKET_MAP[ticket.id] = i.id
@@ -2,36 +2,30
2 2 issue_statuses_001:
3 3 id: 1
4 4 name: New
5 is_default: true
6 5 is_closed: false
7 6 position: 1
8 7 issue_statuses_002:
9 8 id: 2
10 9 name: Assigned
11 is_default: false
12 10 is_closed: false
13 11 position: 2
14 12 issue_statuses_003:
15 13 id: 3
16 14 name: Resolved
17 is_default: false
18 15 is_closed: false
19 16 position: 3
20 17 issue_statuses_004:
21 18 name: Feedback
22 19 id: 4
23 is_default: false
24 20 is_closed: false
25 21 position: 4
26 22 issue_statuses_005:
27 23 id: 5
28 24 name: Closed
29 is_default: false
30 25 is_closed: true
31 26 position: 5
32 27 issue_statuses_006:
33 28 id: 6
34 29 name: Rejected
35 is_default: false
36 30 is_closed: true
37 31 position: 6
@@ -3,14 +3,17 trackers_001:
3 3 name: Bug
4 4 id: 1
5 5 is_in_chlog: true
6 default_status_id: 1
6 7 position: 1
7 8 trackers_002:
8 9 name: Feature request
9 10 id: 2
10 11 is_in_chlog: true
12 default_status_id: 1
11 13 position: 2
12 14 trackers_003:
13 15 name: Support request
14 16 id: 3
15 17 is_in_chlog: false
18 default_status_id: 1
16 19 position: 3
@@ -86,7 +86,8 class IssueStatusesControllerTest < ActionController::TestCase
86 86 end
87 87
88 88 def test_destroy
89 Issue.delete_all("status_id = 1")
89 Issue.where(:status_id => 1).delete_all
90 Tracker.where(:default_status_id => 1).delete_all
90 91
91 92 assert_difference 'IssueStatus.count', -1 do
92 93 delete :destroy, :id => '1'
@@ -96,7 +97,19 class IssueStatusesControllerTest < ActionController::TestCase
96 97 end
97 98
98 99 def test_destroy_should_block_if_status_in_use
99 assert_not_nil Issue.find_by_status_id(1)
100 assert Issue.where(:status_id => 1).any?
101 Tracker.where(:default_status_id => 1).delete_all
102
103 assert_no_difference 'IssueStatus.count' do
104 delete :destroy, :id => '1'
105 end
106 assert_redirected_to :action => 'index'
107 assert_not_nil IssueStatus.find_by_id(1)
108 end
109
110 def test_destroy_should_block_if_status_in_use
111 Issue.where(:status_id => 1).delete_all
112 assert Tracker.where(:default_status_id => 1).any?
100 113
101 114 assert_no_difference 'IssueStatus.count' do
102 115 delete :destroy, :id => '1'
@@ -1511,6 +1511,30 class IssuesControllerTest < ActionController::TestCase
1511 1511 end
1512 1512 end
1513 1513
1514 def test_new_should_select_default_status
1515 @request.session[:user_id] = 2
1516
1517 get :new, :project_id => 1
1518 assert_response :success
1519 assert_template 'new'
1520 assert_select 'select[name=?]', 'issue[status_id]' do
1521 assert_select 'option[value=1][selected=selected]'
1522 end
1523 assert_select 'input[name=was_default_status][value=1]'
1524 end
1525
1526 def test_new_should_select_default_status
1527 @request.session[:user_id] = 2
1528
1529 get :new, :project_id => 1
1530 assert_response :success
1531 assert_template 'new'
1532 assert_select 'select[name=?]', 'issue[status_id]' do
1533 assert_select 'option[value=1][selected=selected]'
1534 end
1535 assert_select 'input[name=was_default_status][value=1]'
1536 end
1537
1514 1538 def test_get_new_with_list_custom_field
1515 1539 @request.session[:user_id] = 2
1516 1540 get :new, :project_id => 1, :tracker_id => 1
@@ -1731,6 +1755,20 class IssuesControllerTest < ActionController::TestCase
1731 1755 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
1732 1756 end
1733 1757
1758 def test_update_form_with_default_status_should_ignore_submitted_status_id_if_equals
1759 @request.session[:user_id] = 2
1760 tracker = Tracker.find(2)
1761 tracker.update! :default_status_id => 2
1762 tracker.generate_transitions! 2, 1, :clear => true
1763
1764 xhr :post, :update_form, :project_id => 1,
1765 :issue => {:tracker_id => 2,
1766 :status_id => 1},
1767 :was_default_status => 1
1768
1769 assert_equal 2, assigns(:issue).status_id
1770 end
1771
1734 1772 def test_post_create
1735 1773 @request.session[:user_id] = 2
1736 1774 assert_difference 'Issue.count' do
@@ -2266,13 +2304,17 class IssuesControllerTest < ActionController::TestCase
2266 2304 get :new, :project_id => 1
2267 2305 assert_response :success
2268 2306 assert_template 'new'
2307
2308 issue = assigns(:issue)
2309 assert_not_nil issue.default_status
2310
2269 2311 assert_select 'select[name=?]', 'issue[status_id]' do
2270 2312 assert_select 'option', 1
2271 assert_select 'option[value=?]', IssueStatus.default.id.to_s
2313 assert_select 'option[value=?]', issue.default_status.id.to_s
2272 2314 end
2273 2315 end
2274 2316
2275 test "without workflow privilege #new should accept default status" do
2317 test "without workflow privilege #create should accept default status" do
2276 2318 setup_without_workflow_privilege
2277 2319 assert_difference 'Issue.count' do
2278 2320 post :create, :project_id => 1,
@@ -2281,10 +2323,11 class IssuesControllerTest < ActionController::TestCase
2281 2323 :status_id => 1}
2282 2324 end
2283 2325 issue = Issue.order('id').last
2284 assert_equal IssueStatus.default, issue.status
2326 assert_not_nil issue.default_status
2327 assert_equal issue.default_status, issue.status
2285 2328 end
2286 2329
2287 test "without workflow privilege #new should ignore unauthorized status" do
2330 test "without workflow privilege #create should ignore unauthorized status" do
2288 2331 setup_without_workflow_privilege
2289 2332 assert_difference 'Issue.count' do
2290 2333 post :create, :project_id => 1,
@@ -2293,7 +2336,8 class IssuesControllerTest < ActionController::TestCase
2293 2336 :status_id => 3}
2294 2337 end
2295 2338 issue = Issue.order('id').last
2296 assert_equal IssueStatus.default, issue.status
2339 assert_not_nil issue.default_status
2340 assert_equal issue.default_status, issue.status
2297 2341 end
2298 2342
2299 2343 test "without workflow privilege #update should ignore status change" do
@@ -18,7 +18,7
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class TrackersControllerTest < ActionController::TestCase
21 fixtures :trackers, :projects, :projects_trackers, :users, :issues, :custom_fields
21 fixtures :trackers, :projects, :projects_trackers, :users, :issues, :custom_fields, :issue_statuses
22 22
23 23 def setup
24 24 User.current = nil
@@ -51,7 +51,7 class TrackersControllerTest < ActionController::TestCase
51 51
52 52 def test_create
53 53 assert_difference 'Tracker.count' do
54 post :create, :tracker => { :name => 'New tracker', :project_ids => ['1', '', ''], :custom_field_ids => ['1', '6', ''] }
54 post :create, :tracker => { :name => 'New tracker', :default_status_id => 1, :project_ids => ['1', '', ''], :custom_field_ids => ['1', '6', ''] }
55 55 end
56 56 assert_redirected_to :action => 'index'
57 57 tracker = Tracker.order('id DESC').first
@@ -62,9 +62,9 class TrackersControllerTest < ActionController::TestCase
62 62 assert_equal 0, tracker.workflow_rules.count
63 63 end
64 64
65 def create_with_disabled_core_fields
65 def test_create_with_disabled_core_fields
66 66 assert_difference 'Tracker.count' do
67 post :create, :tracker => { :name => 'New tracker', :core_fields => ['assigned_to_id', 'fixed_version_id', ''] }
67 post :create, :tracker => { :name => 'New tracker', :default_status_id => 1, :core_fields => ['assigned_to_id', 'fixed_version_id', ''] }
68 68 end
69 69 assert_redirected_to :action => 'index'
70 70 tracker = Tracker.order('id DESC').first
@@ -74,7 +74,7 class TrackersControllerTest < ActionController::TestCase
74 74
75 75 def test_create_new_with_workflow_copy
76 76 assert_difference 'Tracker.count' do
77 post :create, :tracker => { :name => 'New tracker' }, :copy_workflow_from => 1
77 post :create, :tracker => { :name => 'New tracker', :default_status_id => 1 }, :copy_workflow_from => 1
78 78 end
79 79 assert_redirected_to :action => 'index'
80 80 tracker = Tracker.find_by_name('New tracker')
@@ -164,7 +164,7 class TrackersControllerTest < ActionController::TestCase
164 164 end
165 165
166 166 def test_destroy
167 tracker = Tracker.create!(:name => 'Destroyable')
167 tracker = Tracker.generate!(:name => 'Destroyable')
168 168 assert_difference 'Tracker.count', -1 do
169 169 delete :destroy, :id => tracker.id
170 170 end
@@ -45,11 +45,22 module ObjectHelpers
45 45 project
46 46 end
47 47
48 def IssueStatus.generate!(attributes={})
49 @generated_status_name ||= 'Status 0'
50 @generated_status_name.succ!
51 status = IssueStatus.new(attributes)
52 status.name = @generated_status_name.dup if status.name.blank?
53 yield status if block_given?
54 status.save!
55 status
56 end
57
48 58 def Tracker.generate!(attributes={})
49 59 @generated_tracker_name ||= 'Tracker 0'
50 60 @generated_tracker_name.succ!
51 61 tracker = Tracker.new(attributes)
52 62 tracker.name = @generated_tracker_name.dup if tracker.name.blank?
63 tracker.default_status ||= IssueStatus.order('position').first || IssueStatus.generate!
53 64 yield tracker if block_given?
54 65 tracker.save!
55 66 tracker
@@ -188,6 +199,27 module ObjectHelpers
188 199 end
189 200 end
190 201
202 module TrackerObjectHelpers
203 def generate_transitions!(*args)
204 options = args.last.is_a?(Hash) ? args.pop : {}
205 if args.size == 1
206 args << args.first
207 end
208 if options[:clear]
209 WorkflowTransition.where(:tracker_id => id).delete_all
210 end
211 args.each_cons(2) do |old_status_id, new_status_id|
212 WorkflowTransition.create!(
213 :tracker => self,
214 :role_id => (options[:role_id] || 1),
215 :old_status_id => old_status_id,
216 :new_status_id => new_status_id
217 )
218 end
219 end
220 end
221 Tracker.send :include, TrackerObjectHelpers
222
191 223 module IssueObjectHelpers
192 224 def close!
193 225 self.status = IssueStatus.where(:is_closed => true).first
@@ -198,5 +230,4 module IssueObjectHelpers
198 230 Issue.generate!(attributes.merge(:parent_issue_id => self.id))
199 231 end
200 232 end
201
202 233 Issue.send :include, IssueObjectHelpers
@@ -28,7 +28,6 class IssueStatusTest < ActiveSupport::TestCase
28 28
29 29 status.name = "Test Status"
30 30 assert status.save
31 assert !status.is_default
32 31 end
33 32
34 33 def test_destroy
@@ -46,29 +45,6 class IssueStatusTest < ActiveSupport::TestCase
46 45 assert_raise(RuntimeError, "Can't delete status") { status.destroy }
47 46 end
48 47
49 def test_default
50 status = IssueStatus.default
51 assert_kind_of IssueStatus, status
52 end
53
54 def test_change_default
55 status = IssueStatus.find(2)
56 assert !status.is_default
57 status.is_default = true
58 assert status.save
59 status.reload
60
61 assert_equal status, IssueStatus.default
62 assert !IssueStatus.find(1).is_default
63 end
64
65 def test_reorder_should_not_clear_default_status
66 status = IssueStatus.default
67 status.move_to_bottom
68 status.reload
69 assert status.is_default?
70 end
71
72 48 def test_new_statuses_allowed_to
73 49 WorkflowTransition.delete_all
74 50
@@ -40,11 +40,11 class IssueTest < ActiveSupport::TestCase
40 40
41 41 assert_nil issue.project_id
42 42 assert_nil issue.tracker_id
43 assert_nil issue.status_id
43 44 assert_nil issue.author_id
44 45 assert_nil issue.assigned_to_id
45 46 assert_nil issue.category_id
46 47
47 assert_equal IssueStatus.default, issue.status
48 48 assert_equal IssuePriority.default, issue.priority
49 49 end
50 50
@@ -59,10 +59,9 class IssueTest < ActiveSupport::TestCase
59 59 end
60 60
61 61 def test_create_minimal
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
63 :status_id => 1, :priority => IssuePriority.all.first,
64 :subject => 'test_create')
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create')
65 63 assert issue.save
64 assert_equal issue.tracker.default_status, issue.status
66 65 assert issue.description.nil?
67 66 assert_nil issue.estimated_hours
68 67 end
@@ -908,7 +907,7 class IssueTest < ActiveSupport::TestCase
908 907
909 908 def test_copy_should_copy_status
910 909 orig = Issue.find(8)
911 assert orig.status != IssueStatus.default
910 assert orig.status != orig.default_status
912 911
913 912 issue = Issue.new.copy_from(orig)
914 913 assert issue.save
@@ -2480,4 +2479,67 class IssueTest < ActiveSupport::TestCase
2480 2479 issue.save!
2481 2480 assert_equal false, issue.reopening?
2482 2481 end
2482
2483 def test_default_status_without_tracker_should_be_nil
2484 issue = Issue.new
2485 assert_nil issue.tracker
2486 assert_nil issue.default_status
2487 end
2488
2489 def test_default_status_should_be_tracker_default_status
2490 issue = Issue.new(:tracker_id => 1)
2491 assert_not_nil issue.status
2492 assert_equal issue.tracker.default_status, issue.default_status
2493 end
2494
2495 def test_initializing_with_tracker_should_set_default_status
2496 issue = Issue.new(:tracker => Tracker.find(1))
2497 assert_not_nil issue.status
2498 assert_equal issue.default_status, issue.status
2499 end
2500
2501 def test_initializing_with_tracker_id_should_set_default_status
2502 issue = Issue.new(:tracker_id => 1)
2503 assert_not_nil issue.status
2504 assert_equal issue.default_status, issue.status
2505 end
2506
2507 def test_setting_tracker_should_set_default_status
2508 issue = Issue.new
2509 issue.tracker = Tracker.find(1)
2510 assert_not_nil issue.status
2511 assert_equal issue.default_status, issue.status
2512 end
2513
2514 def test_changing_tracker_should_set_default_status_if_status_was_default
2515 WorkflowTransition.delete_all
2516 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1
2517 Tracker.find(2).update! :default_status_id => 2
2518
2519 issue = Issue.new(:tracker_id => 1, :status_id => 1)
2520 assert_equal IssueStatus.find(1), issue.status
2521 issue.tracker = Tracker.find(2)
2522 assert_equal IssueStatus.find(2), issue.status
2523 end
2524
2525 def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker
2526 WorkflowTransition.delete_all
2527 Tracker.find(2).update! :default_status_id => 2
2528
2529 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2530 assert_equal IssueStatus.find(3), issue.status
2531 issue.tracker = Tracker.find(2)
2532 assert_equal IssueStatus.find(2), issue.status
2533 end
2534
2535 def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker
2536 WorkflowTransition.delete_all
2537 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3
2538 Tracker.find(2).update! :default_status_id => 2
2539
2540 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2541 assert_equal IssueStatus.find(3), issue.status
2542 issue.tracker = Tracker.find(2)
2543 assert_equal IssueStatus.find(3), issue.status
2544 end
2483 2545 end
@@ -412,7 +412,7 class MailHandlerTest < ActiveSupport::TestCase
412 412
413 413 def test_add_issue_with_japanese_keywords
414 414 ja_dev = "\xe9\x96\x8b\xe7\x99\xba".force_encoding('UTF-8')
415 tracker = Tracker.create!(:name => ja_dev)
415 tracker = Tracker.generate!(:name => ja_dev)
416 416 Project.find(1).trackers << tracker
417 417 issue = submit_email(
418 418 'japanese_keywords_iso_2022_jp.eml',
@@ -32,7 +32,7 class TrackerTest < ActiveSupport::TestCase
32 32 source = Tracker.find(1)
33 33 assert_equal 89, source.workflow_rules.size
34 34
35 target = Tracker.new(:name => 'Target')
35 target = Tracker.new(:name => 'Target', :default_status_id => 1)
36 36 assert target.save
37 37 target.workflow_rules.copy(source)
38 38 target.reload
General Comments 0
You need to be logged in to leave comments. Login now