##// END OF EJS Templates
Merged r4354 from trunk....
Jean-Philippe Lang -
r4241:f1f0704ef82f
parent child
Show More
@@ -1,155 +1,159
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class VersionsController < ApplicationController
18 class VersionsController < ApplicationController
19 menu_item :roadmap
19 menu_item :roadmap
20 model_object Version
20 model_object Version
21 before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
21 before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
22 before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
22 before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
23 before_filter :find_project, :only => [:index, :new, :create, :close_completed]
23 before_filter :find_project, :only => [:index, :new, :create, :close_completed]
24 before_filter :authorize
24 before_filter :authorize
25
25
26 helper :custom_fields
26 helper :custom_fields
27 helper :projects
27 helper :projects
28
28
29 def index
29 def index
30 @trackers = @project.trackers.find(:all, :order => 'position')
30 @trackers = @project.trackers.find(:all, :order => 'position')
31 retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
31 retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
32 @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
32 @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
33 project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
33 project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
34
34
35 @versions = @project.shared_versions || []
35 @versions = @project.shared_versions || []
36 @versions += @project.rolled_up_versions.visible if @with_subprojects
36 @versions += @project.rolled_up_versions.visible if @with_subprojects
37 @versions = @versions.uniq.sort
37 @versions = @versions.uniq.sort
38 @versions.reject! {|version| version.closed? || version.completed? } unless params[:completed]
38 @versions.reject! {|version| version.closed? || version.completed? } unless params[:completed]
39
39
40 @issues_by_version = {}
40 @issues_by_version = {}
41 unless @selected_tracker_ids.empty?
41 unless @selected_tracker_ids.empty?
42 @versions.each do |version|
42 @versions.each do |version|
43 issues = version.fixed_issues.visible.find(:all,
43 issues = version.fixed_issues.visible.find(:all,
44 :include => [:project, :status, :tracker, :priority],
44 :include => [:project, :status, :tracker, :priority],
45 :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids},
45 :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids},
46 :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
46 :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
47 @issues_by_version[version] = issues
47 @issues_by_version[version] = issues
48 end
48 end
49 end
49 end
50 @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
50 @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
51 end
51 end
52
52
53 def show
53 def show
54 @issues = @version.fixed_issues.visible.find(:all,
54 @issues = @version.fixed_issues.visible.find(:all,
55 :include => [:status, :tracker, :priority],
55 :include => [:status, :tracker, :priority],
56 :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
56 :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
57 end
57 end
58
58
59 def new
59 def new
60 @version = @project.versions.build
60 @version = @project.versions.build
61 if params[:version]
61 if params[:version]
62 attributes = params[:version].dup
62 attributes = params[:version].dup
63 attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
63 attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
64 @version.attributes = attributes
64 @version.attributes = attributes
65 end
65 end
66 end
66 end
67
67
68 def create
68 def create
69 # TODO: refactor with code above in #new
69 # TODO: refactor with code above in #new
70 @version = @project.versions.build
70 @version = @project.versions.build
71 if params[:version]
71 if params[:version]
72 attributes = params[:version].dup
72 attributes = params[:version].dup
73 attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
73 attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
74 @version.attributes = attributes
74 @version.attributes = attributes
75 end
75 end
76
76
77 if request.post?
77 if request.post?
78 if @version.save
78 if @version.save
79 respond_to do |format|
79 respond_to do |format|
80 format.html do
80 format.html do
81 flash[:notice] = l(:notice_successful_create)
81 flash[:notice] = l(:notice_successful_create)
82 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
82 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
83 end
83 end
84 format.js do
84 format.js do
85 # IE doesn't support the replace_html rjs method for select box options
85 # IE doesn't support the replace_html rjs method for select box options
86 render(:update) {|page| page.replace "issue_fixed_version_id",
86 render(:update) {|page| page.replace "issue_fixed_version_id",
87 content_tag('select', '<option></option>' + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]')
87 content_tag('select', '<option></option>' + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]')
88 }
88 }
89 end
89 end
90 end
90 end
91 else
91 else
92 respond_to do |format|
92 respond_to do |format|
93 format.html { render :action => 'new' }
93 format.html { render :action => 'new' }
94 format.js do
94 format.js do
95 render(:update) {|page| page.alert(@version.errors.full_messages.join('\n')) }
95 render(:update) {|page| page.alert(@version.errors.full_messages.join('\n')) }
96 end
96 end
97 end
97 end
98 end
98 end
99 end
99 end
100 end
100 end
101
101
102 def edit
102 def edit
103 end
103 end
104
104
105 def update
105 def update
106 if request.post? && params[:version]
106 if request.post? && params[:version]
107 attributes = params[:version].dup
107 attributes = params[:version].dup
108 attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
108 attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
109 if @version.update_attributes(attributes)
109 if @version.update_attributes(attributes)
110 flash[:notice] = l(:notice_successful_update)
110 flash[:notice] = l(:notice_successful_update)
111 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
111 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
112 else
113 respond_to do |format|
114 format.html { render :action => 'edit' }
115 end
112 end
116 end
113 end
117 end
114 end
118 end
115
119
116 def close_completed
120 def close_completed
117 if request.post?
121 if request.post?
118 @project.close_completed_versions
122 @project.close_completed_versions
119 end
123 end
120 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
124 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
121 end
125 end
122
126
123 def destroy
127 def destroy
124 if @version.fixed_issues.empty?
128 if @version.fixed_issues.empty?
125 @version.destroy
129 @version.destroy
126 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
130 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
127 else
131 else
128 flash[:error] = l(:notice_unable_delete_version)
132 flash[:error] = l(:notice_unable_delete_version)
129 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
133 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
130 end
134 end
131 end
135 end
132
136
133 def status_by
137 def status_by
134 respond_to do |format|
138 respond_to do |format|
135 format.html { render :action => 'show' }
139 format.html { render :action => 'show' }
136 format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
140 format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
137 end
141 end
138 end
142 end
139
143
140 private
144 private
141 def find_project
145 def find_project
142 @project = Project.find(params[:project_id])
146 @project = Project.find(params[:project_id])
143 rescue ActiveRecord::RecordNotFound
147 rescue ActiveRecord::RecordNotFound
144 render_404
148 render_404
145 end
149 end
146
150
147 def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
151 def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
148 if ids = params[:tracker_ids]
152 if ids = params[:tracker_ids]
149 @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
153 @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
150 else
154 else
151 @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
155 @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
152 end
156 end
153 end
157 end
154
158
155 end
159 end
@@ -1,139 +1,148
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'versions_controller'
19 require 'versions_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class VersionsController; def rescue_action(e) raise e end; end
22 class VersionsController; def rescue_action(e) raise e end; end
23
23
24 class VersionsControllerTest < ActionController::TestCase
24 class VersionsControllerTest < ActionController::TestCase
25 fixtures :projects, :versions, :issues, :users, :roles, :members, :member_roles, :enabled_modules
25 fixtures :projects, :versions, :issues, :users, :roles, :members, :member_roles, :enabled_modules
26
26
27 def setup
27 def setup
28 @controller = VersionsController.new
28 @controller = VersionsController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
31 User.current = nil
32 end
32 end
33
33
34 def test_index
34 def test_index
35 get :index, :project_id => 1
35 get :index, :project_id => 1
36 assert_response :success
36 assert_response :success
37 assert_template 'index'
37 assert_template 'index'
38 assert_not_nil assigns(:versions)
38 assert_not_nil assigns(:versions)
39 # Version with no date set appears
39 # Version with no date set appears
40 assert assigns(:versions).include?(Version.find(3))
40 assert assigns(:versions).include?(Version.find(3))
41 # Completed version doesn't appear
41 # Completed version doesn't appear
42 assert !assigns(:versions).include?(Version.find(1))
42 assert !assigns(:versions).include?(Version.find(1))
43 # Context menu on issues
43 # Context menu on issues
44 assert_select "script", :text => Regexp.new(Regexp.escape("new ContextMenu('/issues/context_menu')"))
44 assert_select "script", :text => Regexp.new(Regexp.escape("new ContextMenu('/issues/context_menu')"))
45 end
45 end
46
46
47 def test_index_with_completed_versions
47 def test_index_with_completed_versions
48 get :index, :project_id => 1, :completed => 1
48 get :index, :project_id => 1, :completed => 1
49 assert_response :success
49 assert_response :success
50 assert_template 'index'
50 assert_template 'index'
51 assert_not_nil assigns(:versions)
51 assert_not_nil assigns(:versions)
52 # Version with no date set appears
52 # Version with no date set appears
53 assert assigns(:versions).include?(Version.find(3))
53 assert assigns(:versions).include?(Version.find(3))
54 # Completed version appears
54 # Completed version appears
55 assert assigns(:versions).include?(Version.find(1))
55 assert assigns(:versions).include?(Version.find(1))
56 end
56 end
57
57
58 def test_index_showing_subprojects_versions
58 def test_index_showing_subprojects_versions
59 @subproject_version = Version.generate!(:project => Project.find(3))
59 @subproject_version = Version.generate!(:project => Project.find(3))
60 get :index, :project_id => 1, :with_subprojects => 1
60 get :index, :project_id => 1, :with_subprojects => 1
61 assert_response :success
61 assert_response :success
62 assert_template 'index'
62 assert_template 'index'
63 assert_not_nil assigns(:versions)
63 assert_not_nil assigns(:versions)
64
64
65 assert assigns(:versions).include?(Version.find(4)), "Shared version not found"
65 assert assigns(:versions).include?(Version.find(4)), "Shared version not found"
66 assert assigns(:versions).include?(@subproject_version), "Subproject version not found"
66 assert assigns(:versions).include?(@subproject_version), "Subproject version not found"
67 end
67 end
68
68
69 def test_show
69 def test_show
70 get :show, :id => 2
70 get :show, :id => 2
71 assert_response :success
71 assert_response :success
72 assert_template 'show'
72 assert_template 'show'
73 assert_not_nil assigns(:version)
73 assert_not_nil assigns(:version)
74
74
75 assert_tag :tag => 'h2', :content => /1.0/
75 assert_tag :tag => 'h2', :content => /1.0/
76 end
76 end
77
77
78 def test_create
78 def test_create
79 @request.session[:user_id] = 2 # manager
79 @request.session[:user_id] = 2 # manager
80 assert_difference 'Version.count' do
80 assert_difference 'Version.count' do
81 post :create, :project_id => '1', :version => {:name => 'test_add_version'}
81 post :create, :project_id => '1', :version => {:name => 'test_add_version'}
82 end
82 end
83 assert_redirected_to '/projects/ecookbook/settings/versions'
83 assert_redirected_to '/projects/ecookbook/settings/versions'
84 version = Version.find_by_name('test_add_version')
84 version = Version.find_by_name('test_add_version')
85 assert_not_nil version
85 assert_not_nil version
86 assert_equal 1, version.project_id
86 assert_equal 1, version.project_id
87 end
87 end
88
88
89 def test_create_from_issue_form
89 def test_create_from_issue_form
90 @request.session[:user_id] = 2 # manager
90 @request.session[:user_id] = 2 # manager
91 assert_difference 'Version.count' do
91 assert_difference 'Version.count' do
92 xhr :post, :create, :project_id => '1', :version => {:name => 'test_add_version_from_issue_form'}
92 xhr :post, :create, :project_id => '1', :version => {:name => 'test_add_version_from_issue_form'}
93 end
93 end
94 assert_response :success
94 assert_response :success
95 assert_select_rjs :replace, 'issue_fixed_version_id'
95 assert_select_rjs :replace, 'issue_fixed_version_id'
96 version = Version.find_by_name('test_add_version_from_issue_form')
96 version = Version.find_by_name('test_add_version_from_issue_form')
97 assert_not_nil version
97 assert_not_nil version
98 assert_equal 1, version.project_id
98 assert_equal 1, version.project_id
99 end
99 end
100
100
101 def test_get_edit
101 def test_get_edit
102 @request.session[:user_id] = 2
102 @request.session[:user_id] = 2
103 get :edit, :id => 2
103 get :edit, :id => 2
104 assert_response :success
104 assert_response :success
105 assert_template 'edit'
105 assert_template 'edit'
106 end
106 end
107
107
108 def test_close_completed
108 def test_close_completed
109 Version.update_all("status = 'open'")
109 Version.update_all("status = 'open'")
110 @request.session[:user_id] = 2
110 @request.session[:user_id] = 2
111 post :close_completed, :project_id => 'ecookbook'
111 post :close_completed, :project_id => 'ecookbook'
112 assert_redirected_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => 'ecookbook'
112 assert_redirected_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => 'ecookbook'
113 assert_not_nil Version.find_by_status('closed')
113 assert_not_nil Version.find_by_status('closed')
114 end
114 end
115
115
116 def test_post_update
116 def test_post_update
117 @request.session[:user_id] = 2
117 @request.session[:user_id] = 2
118 post :update, :id => 2,
118 post :update, :id => 2,
119 :version => { :name => 'New version name',
119 :version => { :name => 'New version name',
120 :effective_date => Date.today.strftime("%Y-%m-%d")}
120 :effective_date => Date.today.strftime("%Y-%m-%d")}
121 assert_redirected_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => 'ecookbook'
121 assert_redirected_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => 'ecookbook'
122 version = Version.find(2)
122 version = Version.find(2)
123 assert_equal 'New version name', version.name
123 assert_equal 'New version name', version.name
124 assert_equal Date.today, version.effective_date
124 assert_equal Date.today, version.effective_date
125 end
125 end
126
127 def test_post_update_with_validation_failure
128 @request.session[:user_id] = 2
129 put :update, :id => 2,
130 :version => { :name => '',
131 :effective_date => Date.today.strftime("%Y-%m-%d")}
132 assert_response :success
133 assert_template 'edit'
134 end
126
135
127 def test_destroy
136 def test_destroy
128 @request.session[:user_id] = 2
137 @request.session[:user_id] = 2
129 post :destroy, :id => 3
138 post :destroy, :id => 3
130 assert_redirected_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => 'ecookbook'
139 assert_redirected_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => 'ecookbook'
131 assert_nil Version.find_by_id(3)
140 assert_nil Version.find_by_id(3)
132 end
141 end
133
142
134 def test_issue_status_by
143 def test_issue_status_by
135 xhr :get, :status_by, :id => 2
144 xhr :get, :status_by, :id => 2
136 assert_response :success
145 assert_response :success
137 assert_template '_issue_counts'
146 assert_template '_issue_counts'
138 end
147 end
139 end
148 end
General Comments 0
You need to be logged in to leave comments. Login now