##// END OF EJS Templates
Menu should not include "New issue" for users with copy issues permission only....
Jean-Philippe Lang -
r13908:78384d147a48
parent child
Show More
@@ -1,278 +1,279
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'redmine/core_ext'
19 19
20 20 begin
21 21 require 'rmagick' unless Object.const_defined?(:Magick)
22 22 rescue LoadError
23 23 # RMagick is not available
24 24 end
25 25 begin
26 26 require 'redcarpet' unless Object.const_defined?(:Redcarpet)
27 27 rescue LoadError
28 28 # Redcarpet is not available
29 29 end
30 30
31 31 require 'redmine/scm/base'
32 32 require 'redmine/access_control'
33 33 require 'redmine/access_keys'
34 34 require 'redmine/activity'
35 35 require 'redmine/activity/fetcher'
36 36 require 'redmine/ciphering'
37 37 require 'redmine/codeset_util'
38 38 require 'redmine/field_format'
39 39 require 'redmine/i18n'
40 40 require 'redmine/menu_manager'
41 41 require 'redmine/notifiable'
42 42 require 'redmine/platform'
43 43 require 'redmine/mime_type'
44 44 require 'redmine/notifiable'
45 45 require 'redmine/search'
46 46 require 'redmine/syntax_highlighting'
47 47 require 'redmine/thumbnail'
48 48 require 'redmine/unified_diff'
49 49 require 'redmine/utils'
50 50 require 'redmine/version'
51 51 require 'redmine/wiki_formatting'
52 52
53 53 require 'redmine/default_data/loader'
54 54 require 'redmine/helpers/calendar'
55 55 require 'redmine/helpers/diff'
56 56 require 'redmine/helpers/gantt'
57 57 require 'redmine/helpers/time_report'
58 58 require 'redmine/views/other_formats_builder'
59 59 require 'redmine/views/labelled_form_builder'
60 60 require 'redmine/views/builders'
61 61
62 62 require 'redmine/themes'
63 63 require 'redmine/hook'
64 64 require 'redmine/plugin'
65 65
66 66 require 'csv'
67 67
68 68 Redmine::Scm::Base.add "Subversion"
69 69 Redmine::Scm::Base.add "Darcs"
70 70 Redmine::Scm::Base.add "Mercurial"
71 71 Redmine::Scm::Base.add "Cvs"
72 72 Redmine::Scm::Base.add "Bazaar"
73 73 Redmine::Scm::Base.add "Git"
74 74 Redmine::Scm::Base.add "Filesystem"
75 75
76 76 # Permissions
77 77 Redmine::AccessControl.map do |map|
78 78 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true, :read => true
79 79 map.permission :search_project, {:search => :index}, :public => true, :read => true
80 80 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
81 81 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
82 82 map.permission :close_project, {:projects => [:close, :reopen]}, :require => :member, :read => true
83 83 map.permission :select_project_modules, {:projects => :modules}, :require => :member
84 84 map.permission :view_members, {:members => [:index, :show]}, :public => true, :read => true
85 85 map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :new, :create, :update, :destroy, :autocomplete]}, :require => :member
86 86 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
87 87 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
88 88
89 89 map.project_module :issue_tracking do |map|
90 90 # Issue categories
91 91 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
92 92 # Issues
93 93 map.permission :view_issues, {:issues => [:index, :show],
94 94 :auto_complete => [:issues],
95 95 :context_menus => [:issues],
96 96 :versions => [:index, :show, :status_by],
97 97 :journals => [:index, :diff],
98 98 :queries => :index,
99 99 :reports => [:issue_report, :issue_report_details]},
100 100 :read => true
101 101 map.permission :add_issues, {:issues => [:new, :create], :attachments => :upload}
102 102 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update], :journals => [:new], :attachments => :upload}
103 103 map.permission :copy_issues, {:issues => [:new, :create, :bulk_edit, :bulk_update], :attachments => :upload}
104 104 map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
105 105 map.permission :manage_subtasks, {}
106 106 map.permission :set_issues_private, {}
107 107 map.permission :set_own_issues_private, {}, :require => :loggedin
108 108 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new], :attachments => :upload}
109 109 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
110 110 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
111 111 map.permission :view_private_notes, {}, :read => true, :require => :member
112 112 map.permission :set_notes_private, {}, :require => :member
113 113 map.permission :delete_issues, {:issues => :destroy}, :require => :member
114 114 # Queries
115 115 map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
116 116 map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
117 117 # Watchers
118 118 map.permission :view_issue_watchers, {}, :read => true
119 119 map.permission :add_issue_watchers, {:watchers => [:new, :create, :append, :autocomplete_for_user]}
120 120 map.permission :delete_issue_watchers, {:watchers => :destroy}
121 121 end
122 122
123 123 map.project_module :time_tracking do |map|
124 124 map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
125 125 map.permission :view_time_entries, {:timelog => [:index, :report, :show]}, :read => true
126 126 map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
127 127 map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
128 128 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
129 129 end
130 130
131 131 map.project_module :news do |map|
132 132 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy], :attachments => :upload}, :require => :member
133 133 map.permission :view_news, {:news => [:index, :show]}, :public => true, :read => true
134 134 map.permission :comment_news, {:comments => :create}
135 135 end
136 136
137 137 map.project_module :documents do |map|
138 138 map.permission :add_documents, {:documents => [:new, :create, :add_attachment], :attachments => :upload}, :require => :loggedin
139 139 map.permission :edit_documents, {:documents => [:edit, :update, :add_attachment], :attachments => :upload}, :require => :loggedin
140 140 map.permission :delete_documents, {:documents => [:destroy]}, :require => :loggedin
141 141 map.permission :view_documents, {:documents => [:index, :show, :download]}, :read => true
142 142 end
143 143
144 144 map.project_module :files do |map|
145 145 map.permission :manage_files, {:files => [:new, :create], :attachments => :upload}, :require => :loggedin
146 146 map.permission :view_files, {:files => :index, :versions => :download}, :read => true
147 147 end
148 148
149 149 map.project_module :wiki do |map|
150 150 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
151 151 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
152 152 map.permission :delete_wiki_pages, {:wiki => [:destroy, :destroy_version]}, :require => :member
153 153 map.permission :view_wiki_pages, {:wiki => [:index, :show, :special, :date_index]}, :read => true
154 154 map.permission :export_wiki_pages, {:wiki => [:export]}, :read => true
155 155 map.permission :view_wiki_edits, {:wiki => [:history, :diff, :annotate]}, :read => true
156 156 map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment], :attachments => :upload
157 157 map.permission :delete_wiki_pages_attachments, {}
158 158 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
159 159 end
160 160
161 161 map.project_module :repository do |map|
162 162 map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
163 163 map.permission :browse_repository, {:repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]}, :read => true
164 164 map.permission :view_changesets, {:repositories => [:show, :revisions, :revision]}, :read => true
165 165 map.permission :commit_access, {}
166 166 map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
167 167 end
168 168
169 169 map.project_module :boards do |map|
170 170 map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
171 171 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true, :read => true
172 172 map.permission :add_messages, {:messages => [:new, :reply, :quote], :attachments => :upload}
173 173 map.permission :edit_messages, {:messages => :edit, :attachments => :upload}, :require => :member
174 174 map.permission :edit_own_messages, {:messages => :edit, :attachments => :upload}, :require => :loggedin
175 175 map.permission :delete_messages, {:messages => :destroy}, :require => :member
176 176 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
177 177 end
178 178
179 179 map.project_module :calendar do |map|
180 180 map.permission :view_calendar, {:calendars => [:show, :update]}, :read => true
181 181 end
182 182
183 183 map.project_module :gantt do |map|
184 184 map.permission :view_gantt, {:gantts => [:show, :update]}, :read => true
185 185 end
186 186 end
187 187
188 188 Redmine::MenuManager.map :top_menu do |menu|
189 189 menu.push :home, :home_path
190 190 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
191 191 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
192 192 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
193 193 menu.push :help, Redmine::Info.help_url, :last => true
194 194 end
195 195
196 196 Redmine::MenuManager.map :account_menu do |menu|
197 197 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
198 198 menu.push :register, :register_path, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
199 199 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
200 200 menu.push :logout, :signout_path, :html => {:method => 'post'}, :if => Proc.new { User.current.logged? }
201 201 end
202 202
203 203 Redmine::MenuManager.map :application_menu do |menu|
204 204 # Empty
205 205 end
206 206
207 207 Redmine::MenuManager.map :admin_menu do |menu|
208 208 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
209 209 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
210 210 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
211 211 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
212 212 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
213 213 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
214 214 :html => {:class => 'issue_statuses'}
215 215 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
216 216 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
217 217 :html => {:class => 'custom_fields'}
218 218 menu.push :enumerations, {:controller => 'enumerations'}
219 219 menu.push :settings, {:controller => 'settings'}
220 220 menu.push :ldap_authentication, {:controller => 'auth_sources', :action => 'index'},
221 221 :html => {:class => 'server_authentication'}
222 222 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
223 223 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
224 224 end
225 225
226 226 Redmine::MenuManager.map :project_menu do |menu|
227 227 menu.push :overview, { :controller => 'projects', :action => 'show' }
228 228 menu.push :activity, { :controller => 'activities', :action => 'index' }
229 229 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
230 230 :if => Proc.new { |p| p.shared_versions.any? }
231 231 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
232 232 menu.push :new_issue, { :controller => 'issues', :action => 'new', :copy_from => nil }, :param => :project_id, :caption => :label_issue_new,
233 233 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) },
234 :if => Proc.new { |p| p.trackers.any? }
234 :if => Proc.new { |p| p.trackers.any? },
235 :permission => :add_issues
235 236 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
236 237 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
237 238 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
238 239 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
239 240 menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
240 241 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
241 242 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
242 243 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
243 244 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
244 245 menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
245 246 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
246 247 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
247 248 end
248 249
249 250 Redmine::Activity.map do |activity|
250 251 activity.register :issues, :class_name => %w(Issue Journal)
251 252 activity.register :changesets
252 253 activity.register :news
253 254 activity.register :documents, :class_name => %w(Document Attachment)
254 255 activity.register :files, :class_name => 'Attachment'
255 256 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
256 257 activity.register :messages, :default => false
257 258 activity.register :time_entries, :default => false
258 259 end
259 260
260 261 Redmine::Search.map do |search|
261 262 search.register :issues
262 263 search.register :news
263 264 search.register :documents
264 265 search.register :changesets
265 266 search.register :wiki_pages
266 267 search.register :messages
267 268 search.register :projects
268 269 end
269 270
270 271 Redmine::WikiFormatting.map do |format|
271 272 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
272 273 if Object.const_defined?(:Redcarpet)
273 274 format.register :markdown, Redmine::WikiFormatting::Markdown::Formatter, Redmine::WikiFormatting::Markdown::Helper,
274 275 :label => 'Markdown'
275 276 end
276 277 end
277 278
278 279 ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
@@ -1,674 +1,684
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class ProjectsControllerTest < ActionController::TestCase
21 21 fixtures :projects, :versions, :users, :email_addresses, :roles, :members,
22 22 :member_roles, :issues, :journals, :journal_details,
23 23 :trackers, :projects_trackers, :issue_statuses,
24 24 :enabled_modules, :enumerations, :boards, :messages,
25 25 :attachments, :custom_fields, :custom_values, :time_entries,
26 26 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
27 27
28 28 def setup
29 29 @request.session[:user_id] = nil
30 30 Setting.default_language = 'en'
31 31 end
32 32
33 33 def test_index_by_anonymous_should_not_show_private_projects
34 34 get :index
35 35 assert_response :success
36 36 assert_template 'index'
37 37 projects = assigns(:projects)
38 38 assert_not_nil projects
39 39 assert projects.all?(&:is_public?)
40 40
41 41 assert_select 'ul' do
42 42 assert_select 'li' do
43 43 assert_select 'a', :text => 'eCookbook'
44 44 assert_select 'ul' do
45 45 assert_select 'a', :text => 'Child of private child'
46 46 end
47 47 end
48 48 end
49 49 assert_select 'a', :text => /Private child of eCookbook/, :count => 0
50 50 end
51 51
52 52 def test_index_atom
53 53 get :index, :format => 'atom'
54 54 assert_response :success
55 55 assert_template 'common/feed'
56 56 assert_select 'feed>title', :text => 'Redmine: Latest projects'
57 57 assert_select 'feed>entry', :count => Project.visible(User.current).count
58 58 end
59 59
60 60 test "#index by non-admin user with view_time_entries permission should show overall spent time link" do
61 61 @request.session[:user_id] = 3
62 62 get :index
63 63 assert_template 'index'
64 64 assert_select 'a[href=?]', '/time_entries'
65 65 end
66 66
67 67 test "#index by non-admin user without view_time_entries permission should not show overall spent time link" do
68 68 Role.find(2).remove_permission! :view_time_entries
69 69 Role.non_member.remove_permission! :view_time_entries
70 70 Role.anonymous.remove_permission! :view_time_entries
71 71 @request.session[:user_id] = 3
72 72
73 73 get :index
74 74 assert_template 'index'
75 75 assert_select 'a[href=?]', '/time_entries', 0
76 76 end
77 77
78 78 test "#index by non-admin user with permission should show add project link" do
79 79 Role.find(1).add_permission! :add_project
80 80 @request.session[:user_id] = 2
81 81 get :index
82 82 assert_template 'index'
83 83 assert_select 'a[href=?]', '/projects/new'
84 84 end
85 85
86 86 test "#new by admin user should accept get" do
87 87 @request.session[:user_id] = 1
88 88
89 89 get :new
90 90 assert_response :success
91 91 assert_template 'new'
92 92 end
93 93
94 94 test "#new by non-admin user with add_project permission should accept get" do
95 95 Role.non_member.add_permission! :add_project
96 96 @request.session[:user_id] = 9
97 97
98 98 get :new
99 99 assert_response :success
100 100 assert_template 'new'
101 101 assert_select 'select[name=?]', 'project[parent_id]', 0
102 102 end
103 103
104 104 test "#new by non-admin user with add_subprojects permission should accept get" do
105 105 Role.find(1).remove_permission! :add_project
106 106 Role.find(1).add_permission! :add_subprojects
107 107 @request.session[:user_id] = 2
108 108
109 109 get :new, :parent_id => 'ecookbook'
110 110 assert_response :success
111 111 assert_template 'new'
112 112
113 113 assert_select 'select[name=?]', 'project[parent_id]' do
114 114 # parent project selected
115 115 assert_select 'option[value="1"][selected=selected]'
116 116 # no empty value
117 117 assert_select 'option[value=""]', 0
118 118 end
119 119 end
120 120
121 121 test "#create by admin user should create a new project" do
122 122 @request.session[:user_id] = 1
123 123
124 124 post :create,
125 125 :project => {
126 126 :name => "blog",
127 127 :description => "weblog",
128 128 :homepage => 'http://weblog',
129 129 :identifier => "blog",
130 130 :is_public => 1,
131 131 :custom_field_values => { '3' => 'Beta' },
132 132 :tracker_ids => ['1', '3'],
133 133 # an issue custom field that is not for all project
134 134 :issue_custom_field_ids => ['9'],
135 135 :enabled_module_names => ['issue_tracking', 'news', 'repository']
136 136 }
137 137 assert_redirected_to '/projects/blog/settings'
138 138
139 139 project = Project.find_by_name('blog')
140 140 assert_kind_of Project, project
141 141 assert project.active?
142 142 assert_equal 'weblog', project.description
143 143 assert_equal 'http://weblog', project.homepage
144 144 assert_equal true, project.is_public?
145 145 assert_nil project.parent
146 146 assert_equal 'Beta', project.custom_value_for(3).value
147 147 assert_equal [1, 3], project.trackers.map(&:id).sort
148 148 assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
149 149 assert project.issue_custom_fields.include?(IssueCustomField.find(9))
150 150 end
151 151
152 152 test "#create by admin user should create a new subproject" do
153 153 @request.session[:user_id] = 1
154 154
155 155 assert_difference 'Project.count' do
156 156 post :create, :project => { :name => "blog",
157 157 :description => "weblog",
158 158 :identifier => "blog",
159 159 :is_public => 1,
160 160 :custom_field_values => { '3' => 'Beta' },
161 161 :parent_id => 1
162 162 }
163 163 assert_redirected_to '/projects/blog/settings'
164 164 end
165 165
166 166 project = Project.find_by_name('blog')
167 167 assert_kind_of Project, project
168 168 assert_equal Project.find(1), project.parent
169 169 end
170 170
171 171 test "#create by admin user should continue" do
172 172 @request.session[:user_id] = 1
173 173
174 174 assert_difference 'Project.count' do
175 175 post :create, :project => {:name => "blog", :identifier => "blog"}, :continue => 'Create and continue'
176 176 end
177 177 assert_redirected_to '/projects/new'
178 178 end
179 179
180 180 test "#create by non-admin user with add_project permission should create a new project" do
181 181 Role.non_member.add_permission! :add_project
182 182 @request.session[:user_id] = 9
183 183
184 184 post :create, :project => { :name => "blog",
185 185 :description => "weblog",
186 186 :identifier => "blog",
187 187 :is_public => 1,
188 188 :custom_field_values => { '3' => 'Beta' },
189 189 :tracker_ids => ['1', '3'],
190 190 :enabled_module_names => ['issue_tracking', 'news', 'repository']
191 191 }
192 192
193 193 assert_redirected_to '/projects/blog/settings'
194 194
195 195 project = Project.find_by_name('blog')
196 196 assert_kind_of Project, project
197 197 assert_equal 'weblog', project.description
198 198 assert_equal true, project.is_public?
199 199 assert_equal [1, 3], project.trackers.map(&:id).sort
200 200 assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
201 201
202 202 # User should be added as a project member
203 203 assert User.find(9).member_of?(project)
204 204 assert_equal 1, project.members.size
205 205 end
206 206
207 207 test "#create by non-admin user with add_project permission should fail with parent_id" do
208 208 Role.non_member.add_permission! :add_project
209 209 @request.session[:user_id] = 9
210 210
211 211 assert_no_difference 'Project.count' do
212 212 post :create, :project => { :name => "blog",
213 213 :description => "weblog",
214 214 :identifier => "blog",
215 215 :is_public => 1,
216 216 :custom_field_values => { '3' => 'Beta' },
217 217 :parent_id => 1
218 218 }
219 219 end
220 220 assert_response :success
221 221 project = assigns(:project)
222 222 assert_kind_of Project, project
223 223 assert_not_equal [], project.errors[:parent_id]
224 224 end
225 225
226 226 test "#create by non-admin user with add_subprojects permission should create a project with a parent_id" do
227 227 Role.find(1).remove_permission! :add_project
228 228 Role.find(1).add_permission! :add_subprojects
229 229 @request.session[:user_id] = 2
230 230
231 231 post :create, :project => { :name => "blog",
232 232 :description => "weblog",
233 233 :identifier => "blog",
234 234 :is_public => 1,
235 235 :custom_field_values => { '3' => 'Beta' },
236 236 :parent_id => 1
237 237 }
238 238 assert_redirected_to '/projects/blog/settings'
239 239 project = Project.find_by_name('blog')
240 240 end
241 241
242 242 test "#create by non-admin user with add_subprojects permission should fail without parent_id" do
243 243 Role.find(1).remove_permission! :add_project
244 244 Role.find(1).add_permission! :add_subprojects
245 245 @request.session[:user_id] = 2
246 246
247 247 assert_no_difference 'Project.count' do
248 248 post :create, :project => { :name => "blog",
249 249 :description => "weblog",
250 250 :identifier => "blog",
251 251 :is_public => 1,
252 252 :custom_field_values => { '3' => 'Beta' }
253 253 }
254 254 end
255 255 assert_response :success
256 256 project = assigns(:project)
257 257 assert_kind_of Project, project
258 258 assert_not_equal [], project.errors[:parent_id]
259 259 end
260 260
261 261 test "#create by non-admin user with add_subprojects permission should fail with unauthorized parent_id" do
262 262 Role.find(1).remove_permission! :add_project
263 263 Role.find(1).add_permission! :add_subprojects
264 264 @request.session[:user_id] = 2
265 265
266 266 assert !User.find(2).member_of?(Project.find(6))
267 267 assert_no_difference 'Project.count' do
268 268 post :create, :project => { :name => "blog",
269 269 :description => "weblog",
270 270 :identifier => "blog",
271 271 :is_public => 1,
272 272 :custom_field_values => { '3' => 'Beta' },
273 273 :parent_id => 6
274 274 }
275 275 end
276 276 assert_response :success
277 277 project = assigns(:project)
278 278 assert_kind_of Project, project
279 279 assert_not_equal [], project.errors[:parent_id]
280 280 end
281 281
282 282 def test_create_subproject_with_inherit_members_should_inherit_members
283 283 Role.find_by_name('Manager').add_permission! :add_subprojects
284 284 parent = Project.find(1)
285 285 @request.session[:user_id] = 2
286 286
287 287 assert_difference 'Project.count' do
288 288 post :create, :project => {
289 289 :name => 'inherited', :identifier => 'inherited', :parent_id => parent.id, :inherit_members => '1'
290 290 }
291 291 assert_response 302
292 292 end
293 293
294 294 project = Project.order('id desc').first
295 295 assert_equal 'inherited', project.name
296 296 assert_equal parent, project.parent
297 297 assert project.memberships.count > 0
298 298 assert_equal parent.memberships.count, project.memberships.count
299 299 end
300 300
301 301 def test_create_should_preserve_modules_on_validation_failure
302 302 with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
303 303 @request.session[:user_id] = 1
304 304 assert_no_difference 'Project.count' do
305 305 post :create, :project => {
306 306 :name => "blog",
307 307 :identifier => "",
308 308 :enabled_module_names => %w(issue_tracking news)
309 309 }
310 310 end
311 311 assert_response :success
312 312 project = assigns(:project)
313 313 assert_equal %w(issue_tracking news), project.enabled_module_names.sort
314 314 end
315 315 end
316 316
317 317 def test_show_by_id
318 318 get :show, :id => 1
319 319 assert_response :success
320 320 assert_template 'show'
321 321 assert_not_nil assigns(:project)
322 322 end
323 323
324 324 def test_show_by_identifier
325 325 get :show, :id => 'ecookbook'
326 326 assert_response :success
327 327 assert_template 'show'
328 328 assert_not_nil assigns(:project)
329 329 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
330 330
331 331 assert_select 'li', :text => /Development status/
332 332 end
333 333
334 334 def test_show_should_not_display_empty_sidebar
335 335 p = Project.find(1)
336 336 p.enabled_module_names = []
337 337 p.save!
338 338
339 339 get :show, :id => 'ecookbook'
340 340 assert_response :success
341 341 assert_select '#main.nosidebar'
342 342 end
343 343
344 344 def test_show_should_not_display_hidden_custom_fields
345 345 ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
346 346 get :show, :id => 'ecookbook'
347 347 assert_response :success
348 348 assert_template 'show'
349 349 assert_not_nil assigns(:project)
350 350
351 351 assert_select 'li', :text => /Development status/, :count => 0
352 352 end
353 353
354 354 def test_show_should_not_display_blank_custom_fields_with_multiple_values
355 355 f1 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Foo Bar), :multiple => true
356 356 f2 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Baz Qux), :multiple => true
357 357 project = Project.generate!(:custom_field_values => {f2.id.to_s => %w(Qux)})
358 358
359 359 get :show, :id => project.id
360 360 assert_response :success
361 361
362 362 assert_select 'li', :text => /#{f1.name}/, :count => 0
363 363 assert_select 'li', :text => /#{f2.name}/
364 364 end
365 365
366 366 def test_show_should_not_display_blank_text_custom_fields
367 367 f1 = ProjectCustomField.generate! :field_format => 'text'
368 368
369 369 get :show, :id => 1
370 370 assert_response :success
371 371
372 372 assert_select 'li', :text => /#{f1.name}/, :count => 0
373 373 end
374 374
375 375 def test_show_should_not_fail_when_custom_values_are_nil
376 376 project = Project.find_by_identifier('ecookbook')
377 377 project.custom_values.first.update_attribute(:value, nil)
378 378 get :show, :id => 'ecookbook'
379 379 assert_response :success
380 380 assert_template 'show'
381 381 assert_not_nil assigns(:project)
382 382 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
383 383 end
384 384
385 385 def show_archived_project_should_be_denied
386 386 project = Project.find_by_identifier('ecookbook')
387 387 project.archive!
388 388
389 389 get :show, :id => 'ecookbook'
390 390 assert_response 403
391 391 assert_nil assigns(:project)
392 392 assert_select 'p', :text => /archived/
393 393 end
394 394
395 395 def test_show_should_not_show_private_subprojects_that_are_not_visible
396 396 get :show, :id => 'ecookbook'
397 397 assert_response :success
398 398 assert_template 'show'
399 399 assert_select 'a', :text => /Private child/, :count => 0
400 400 end
401 401
402 402 def test_show_should_show_private_subprojects_that_are_visible
403 403 @request.session[:user_id] = 2 # manager who is a member of the private subproject
404 404 get :show, :id => 'ecookbook'
405 405 assert_response :success
406 406 assert_template 'show'
407 407 assert_select 'a', :text => /Private child/
408 408 end
409 409
410 410 def test_settings
411 411 @request.session[:user_id] = 2 # manager
412 412 get :settings, :id => 1
413 413 assert_response :success
414 414 assert_template 'settings'
415 415 end
416 416
417 417 def test_settings_of_subproject
418 418 @request.session[:user_id] = 2
419 419 get :settings, :id => 'private-child'
420 420 assert_response :success
421 421 assert_template 'settings'
422 422
423 423 assert_select 'input[type=checkbox][name=?]', 'project[inherit_members]'
424 424 end
425 425
426 426 def test_settings_should_be_denied_for_member_on_closed_project
427 427 Project.find(1).close
428 428 @request.session[:user_id] = 2 # manager
429 429
430 430 get :settings, :id => 1
431 431 assert_response 403
432 432 end
433 433
434 434 def test_settings_should_be_denied_for_anonymous_on_closed_project
435 435 Project.find(1).close
436 436
437 437 get :settings, :id => 1
438 438 assert_response 302
439 439 end
440 440
441 441 def test_setting_with_wiki_module_and_no_wiki
442 442 Project.find(1).wiki.destroy
443 443 Role.find(1).add_permission! :manage_wiki
444 444 @request.session[:user_id] = 2
445 445
446 446 get :settings, :id => 1
447 447 assert_response :success
448 448 assert_template 'settings'
449 449
450 450 assert_select 'form[action=?]', '/projects/ecookbook/wiki' do
451 451 assert_select 'input[name=?]', 'wiki[start_page]'
452 452 end
453 453 end
454 454
455 455 def test_update
456 456 @request.session[:user_id] = 2 # manager
457 457 post :update, :id => 1, :project => {:name => 'Test changed name',
458 458 :issue_custom_field_ids => ['']}
459 459 assert_redirected_to '/projects/ecookbook/settings'
460 460 project = Project.find(1)
461 461 assert_equal 'Test changed name', project.name
462 462 end
463 463
464 464 def test_update_with_failure
465 465 @request.session[:user_id] = 2 # manager
466 466 post :update, :id => 1, :project => {:name => ''}
467 467 assert_response :success
468 468 assert_template 'settings'
469 469 assert_select_error /name cannot be blank/i
470 470 end
471 471
472 472 def test_update_should_be_denied_for_member_on_closed_project
473 473 Project.find(1).close
474 474 @request.session[:user_id] = 2 # manager
475 475
476 476 post :update, :id => 1, :project => {:name => 'Closed'}
477 477 assert_response 403
478 478 assert_equal 'eCookbook', Project.find(1).name
479 479 end
480 480
481 481 def test_update_should_be_denied_for_anonymous_on_closed_project
482 482 Project.find(1).close
483 483
484 484 post :update, :id => 1, :project => {:name => 'Closed'}
485 485 assert_response 302
486 486 assert_equal 'eCookbook', Project.find(1).name
487 487 end
488 488
489 489 def test_modules
490 490 @request.session[:user_id] = 2
491 491 Project.find(1).enabled_module_names = ['issue_tracking', 'news']
492 492
493 493 post :modules, :id => 1, :enabled_module_names => ['issue_tracking', 'repository', 'documents']
494 494 assert_redirected_to '/projects/ecookbook/settings/modules'
495 495 assert_equal ['documents', 'issue_tracking', 'repository'], Project.find(1).enabled_module_names.sort
496 496 end
497 497
498 498 def test_destroy_leaf_project_without_confirmation_should_show_confirmation
499 499 @request.session[:user_id] = 1 # admin
500 500
501 501 assert_no_difference 'Project.count' do
502 502 delete :destroy, :id => 2
503 503 assert_response :success
504 504 assert_template 'destroy'
505 505 end
506 506 end
507 507
508 508 def test_destroy_without_confirmation_should_show_confirmation_with_subprojects
509 509 @request.session[:user_id] = 1 # admin
510 510
511 511 assert_no_difference 'Project.count' do
512 512 delete :destroy, :id => 1
513 513 assert_response :success
514 514 assert_template 'destroy'
515 515 end
516 516 assert_select 'strong',
517 517 :text => ['Private child of eCookbook',
518 518 'Child of private child, eCookbook Subproject 1',
519 519 'eCookbook Subproject 2'].join(', ')
520 520 end
521 521
522 522 def test_destroy_with_confirmation_should_destroy_the_project_and_subprojects
523 523 @request.session[:user_id] = 1 # admin
524 524
525 525 assert_difference 'Project.count', -5 do
526 526 delete :destroy, :id => 1, :confirm => 1
527 527 assert_redirected_to '/admin/projects'
528 528 end
529 529 assert_nil Project.find_by_id(1)
530 530 end
531 531
532 532 def test_archive
533 533 @request.session[:user_id] = 1 # admin
534 534 post :archive, :id => 1
535 535 assert_redirected_to '/admin/projects'
536 536 assert !Project.find(1).active?
537 537 end
538 538
539 539 def test_archive_with_failure
540 540 @request.session[:user_id] = 1
541 541 Project.any_instance.stubs(:archive).returns(false)
542 542 post :archive, :id => 1
543 543 assert_redirected_to '/admin/projects'
544 544 assert_match /project cannot be archived/i, flash[:error]
545 545 end
546 546
547 547 def test_unarchive
548 548 @request.session[:user_id] = 1 # admin
549 549 Project.find(1).archive
550 550 post :unarchive, :id => 1
551 551 assert_redirected_to '/admin/projects'
552 552 assert Project.find(1).active?
553 553 end
554 554
555 555 def test_close
556 556 @request.session[:user_id] = 2
557 557 post :close, :id => 1
558 558 assert_redirected_to '/projects/ecookbook'
559 559 assert_equal Project::STATUS_CLOSED, Project.find(1).status
560 560 end
561 561
562 562 def test_reopen
563 563 Project.find(1).close
564 564 @request.session[:user_id] = 2
565 565 post :reopen, :id => 1
566 566 assert_redirected_to '/projects/ecookbook'
567 567 assert Project.find(1).active?
568 568 end
569 569
570 570 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
571 571 CustomField.delete_all
572 572 parent = nil
573 573 6.times do |i|
574 574 p = Project.generate_with_parent!(parent)
575 575 get :show, :id => p
576 576 assert_select '#header h1' do
577 577 assert_select 'a', :count => [i, 3].min
578 578 end
579 579
580 580 parent = p
581 581 end
582 582 end
583 583
584 584 def test_get_copy
585 585 @request.session[:user_id] = 1 # admin
586 586 get :copy, :id => 1
587 587 assert_response :success
588 588 assert_template 'copy'
589 589 assert assigns(:project)
590 590 assert_equal Project.find(1).description, assigns(:project).description
591 591 assert_nil assigns(:project).id
592 592
593 593 assert_select 'input[name=?][value=?]', 'project[enabled_module_names][]', 'issue_tracking', 1
594 594 end
595 595
596 596 def test_get_copy_with_invalid_source_should_respond_with_404
597 597 @request.session[:user_id] = 1
598 598 get :copy, :id => 99
599 599 assert_response 404
600 600 end
601 601
602 602 def test_post_copy_should_copy_requested_items
603 603 @request.session[:user_id] = 1 # admin
604 604 CustomField.delete_all
605 605
606 606 assert_difference 'Project.count' do
607 607 post :copy, :id => 1,
608 608 :project => {
609 609 :name => 'Copy',
610 610 :identifier => 'unique-copy',
611 611 :tracker_ids => ['1', '2', '3', ''],
612 612 :enabled_module_names => %w(issue_tracking time_tracking)
613 613 },
614 614 :only => %w(issues versions)
615 615 end
616 616 project = Project.find('unique-copy')
617 617 source = Project.find(1)
618 618 assert_equal %w(issue_tracking time_tracking), project.enabled_module_names.sort
619 619
620 620 assert_equal source.versions.count, project.versions.count, "All versions were not copied"
621 621 assert_equal source.issues.count, project.issues.count, "All issues were not copied"
622 622 assert_equal 0, project.members.count
623 623 end
624 624
625 625 def test_post_copy_should_redirect_to_settings_when_successful
626 626 @request.session[:user_id] = 1 # admin
627 627 post :copy, :id => 1, :project => {:name => 'Copy', :identifier => 'unique-copy'}
628 628 assert_response :redirect
629 629 assert_redirected_to :controller => 'projects', :action => 'settings', :id => 'unique-copy'
630 630 end
631 631
632 632 def test_post_copy_with_failure
633 633 @request.session[:user_id] = 1
634 634 post :copy, :id => 1, :project => {:name => 'Copy', :identifier => ''}
635 635 assert_response :success
636 636 assert_template 'copy'
637 637 end
638 638
639 639 def test_jump_should_redirect_to_active_tab
640 640 get :show, :id => 1, :jump => 'issues'
641 641 assert_redirected_to '/projects/ecookbook/issues'
642 642 end
643 643
644 644 def test_jump_should_not_redirect_to_inactive_tab
645 645 get :show, :id => 3, :jump => 'documents'
646 646 assert_response :success
647 647 assert_template 'show'
648 648 end
649 649
650 650 def test_jump_should_not_redirect_to_unknown_tab
651 651 get :show, :id => 3, :jump => 'foobar'
652 652 assert_response :success
653 653 assert_template 'show'
654 654 end
655 655
656 656 def test_body_should_have_project_css_class
657 657 get :show, :id => 1
658 658 assert_select 'body.project-ecookbook'
659 659 end
660 660
661 661 def test_project_menu_should_include_new_issue_link
662 662 @request.session[:user_id] = 2
663 663 get :show, :id => 1
664 664 assert_select '#main-menu a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
665 665 end
666 666
667 667 def test_project_menu_should_not_include_new_issue_link_for_project_without_trackers
668 668 Project.find(1).trackers.clear
669 669
670 670 @request.session[:user_id] = 2
671 671 get :show, :id => 1
672 672 assert_select '#main-menu a.new-issue', 0
673 673 end
674
675 def test_project_menu_should_not_include_new_issue_link_for_users_with_copy_issues_permission_only
676 role = Role.find(1)
677 role.remove_permission! :add_issues
678 role.add_permission! :copy_issues
679
680 @request.session[:user_id] = 2
681 get :show, :id => 1
682 assert_select '#main-menu a.new-issue', 0
683 end
674 684 end
General Comments 0
You need to be logged in to leave comments. Login now