Chris@0
|
1 # Redmine - project management software
|
Chris@0
|
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
|
Chris@0
|
3 #
|
Chris@0
|
4 # This program is free software; you can redistribute it and/or
|
Chris@0
|
5 # modify it under the terms of the GNU General Public License
|
Chris@0
|
6 # as published by the Free Software Foundation; either version 2
|
Chris@0
|
7 # of the License, or (at your option) any later version.
|
Chris@0
|
8 #
|
Chris@0
|
9 # This program is distributed in the hope that it will be useful,
|
Chris@0
|
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Chris@0
|
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Chris@0
|
12 # GNU General Public License for more details.
|
Chris@0
|
13 #
|
Chris@0
|
14 # You should have received a copy of the GNU General Public License
|
Chris@0
|
15 # along with this program; if not, write to the Free Software
|
Chris@0
|
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
Chris@0
|
17
|
Chris@0
|
18 require File.dirname(__FILE__) + '/../test_helper'
|
Chris@0
|
19 require 'projects_controller'
|
Chris@0
|
20
|
Chris@0
|
21 # Re-raise errors caught by the controller.
|
Chris@0
|
22 class ProjectsController; def rescue_action(e) raise e end; end
|
Chris@0
|
23
|
Chris@0
|
24 class ProjectsControllerTest < ActionController::TestCase
|
Chris@0
|
25 fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
|
Chris@0
|
26 :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
|
Chris@0
|
27 :attachments, :custom_fields, :custom_values, :time_entries
|
Chris@0
|
28
|
Chris@0
|
29 def setup
|
Chris@0
|
30 @controller = ProjectsController.new
|
Chris@0
|
31 @request = ActionController::TestRequest.new
|
Chris@0
|
32 @response = ActionController::TestResponse.new
|
Chris@0
|
33 @request.session[:user_id] = nil
|
Chris@0
|
34 Setting.default_language = 'en'
|
Chris@0
|
35 end
|
Chris@0
|
36
|
Chris@0
|
37 def test_index
|
Chris@0
|
38 get :index
|
Chris@0
|
39 assert_response :success
|
Chris@0
|
40 assert_template 'index'
|
Chris@0
|
41 assert_not_nil assigns(:projects)
|
Chris@0
|
42
|
Chris@0
|
43 assert_tag :ul, :child => {:tag => 'li',
|
Chris@0
|
44 :descendant => {:tag => 'a', :content => 'eCookbook'},
|
Chris@0
|
45 :child => { :tag => 'ul',
|
Chris@0
|
46 :descendant => { :tag => 'a',
|
Chris@0
|
47 :content => 'Child of private child'
|
Chris@0
|
48 }
|
Chris@0
|
49 }
|
Chris@0
|
50 }
|
Chris@0
|
51
|
Chris@0
|
52 assert_no_tag :a, :content => /Private child of eCookbook/
|
Chris@0
|
53 end
|
Chris@0
|
54
|
Chris@0
|
55 def test_index_atom
|
Chris@0
|
56 get :index, :format => 'atom'
|
Chris@0
|
57 assert_response :success
|
Chris@0
|
58 assert_template 'common/feed.atom.rxml'
|
Chris@0
|
59 assert_select 'feed>title', :text => 'Redmine: Latest projects'
|
Chris@0
|
60 assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
|
Chris@0
|
61 end
|
Chris@0
|
62
|
Chris@0
|
63 context "#index" do
|
Chris@0
|
64 context "by non-admin user with view_time_entries permission" do
|
Chris@0
|
65 setup do
|
Chris@0
|
66 @request.session[:user_id] = 3
|
Chris@0
|
67 end
|
Chris@0
|
68 should "show overall spent time link" do
|
Chris@0
|
69 get :index
|
Chris@0
|
70 assert_template 'index'
|
Chris@0
|
71 assert_tag :a, :attributes => {:href => '/time_entries'}
|
Chris@0
|
72 end
|
Chris@0
|
73 end
|
Chris@0
|
74
|
Chris@0
|
75 context "by non-admin user without view_time_entries permission" do
|
Chris@0
|
76 setup do
|
Chris@0
|
77 Role.find(2).remove_permission! :view_time_entries
|
Chris@0
|
78 Role.non_member.remove_permission! :view_time_entries
|
Chris@0
|
79 Role.anonymous.remove_permission! :view_time_entries
|
Chris@0
|
80 @request.session[:user_id] = 3
|
Chris@0
|
81 end
|
Chris@0
|
82 should "not show overall spent time link" do
|
Chris@0
|
83 get :index
|
Chris@0
|
84 assert_template 'index'
|
Chris@0
|
85 assert_no_tag :a, :attributes => {:href => '/time_entries'}
|
Chris@0
|
86 end
|
Chris@0
|
87 end
|
Chris@0
|
88 end
|
Chris@0
|
89
|
Chris@0
|
90 context "#add" do
|
Chris@0
|
91 context "by admin user" do
|
Chris@0
|
92 setup do
|
Chris@0
|
93 @request.session[:user_id] = 1
|
Chris@0
|
94 end
|
Chris@0
|
95
|
Chris@0
|
96 should "accept get" do
|
Chris@0
|
97 get :add
|
Chris@0
|
98 assert_response :success
|
Chris@0
|
99 assert_template 'add'
|
Chris@0
|
100 end
|
Chris@0
|
101
|
Chris@0
|
102 should "accept post" do
|
Chris@0
|
103 post :add, :project => { :name => "blog",
|
Chris@0
|
104 :description => "weblog",
|
Chris@0
|
105 :identifier => "blog",
|
Chris@0
|
106 :is_public => 1,
|
Chris@0
|
107 :custom_field_values => { '3' => 'Beta' }
|
Chris@0
|
108 }
|
Chris@0
|
109 assert_redirected_to '/projects/blog/settings'
|
Chris@0
|
110
|
Chris@0
|
111 project = Project.find_by_name('blog')
|
Chris@0
|
112 assert_kind_of Project, project
|
Chris@0
|
113 assert_equal 'weblog', project.description
|
Chris@0
|
114 assert_equal true, project.is_public?
|
Chris@0
|
115 assert_nil project.parent
|
Chris@0
|
116 end
|
Chris@0
|
117
|
Chris@0
|
118 should "accept post with parent" do
|
Chris@0
|
119 post :add, :project => { :name => "blog",
|
Chris@0
|
120 :description => "weblog",
|
Chris@0
|
121 :identifier => "blog",
|
Chris@0
|
122 :is_public => 1,
|
Chris@0
|
123 :custom_field_values => { '3' => 'Beta' },
|
Chris@0
|
124 :parent_id => 1
|
Chris@0
|
125 }
|
Chris@0
|
126 assert_redirected_to '/projects/blog/settings'
|
Chris@0
|
127
|
Chris@0
|
128 project = Project.find_by_name('blog')
|
Chris@0
|
129 assert_kind_of Project, project
|
Chris@0
|
130 assert_equal Project.find(1), project.parent
|
Chris@0
|
131 end
|
Chris@0
|
132 end
|
Chris@0
|
133
|
Chris@0
|
134 context "by non-admin user with add_project permission" do
|
Chris@0
|
135 setup do
|
Chris@0
|
136 Role.non_member.add_permission! :add_project
|
Chris@0
|
137 @request.session[:user_id] = 9
|
Chris@0
|
138 end
|
Chris@0
|
139
|
Chris@0
|
140 should "accept get" do
|
Chris@0
|
141 get :add
|
Chris@0
|
142 assert_response :success
|
Chris@0
|
143 assert_template 'add'
|
Chris@0
|
144 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
|
Chris@0
|
145 end
|
Chris@0
|
146
|
Chris@0
|
147 should "accept post" do
|
Chris@0
|
148 post :add, :project => { :name => "blog",
|
Chris@0
|
149 :description => "weblog",
|
Chris@0
|
150 :identifier => "blog",
|
Chris@0
|
151 :is_public => 1,
|
Chris@0
|
152 :custom_field_values => { '3' => 'Beta' }
|
Chris@0
|
153 }
|
Chris@0
|
154
|
Chris@0
|
155 assert_redirected_to '/projects/blog/settings'
|
Chris@0
|
156
|
Chris@0
|
157 project = Project.find_by_name('blog')
|
Chris@0
|
158 assert_kind_of Project, project
|
Chris@0
|
159 assert_equal 'weblog', project.description
|
Chris@0
|
160 assert_equal true, project.is_public?
|
Chris@0
|
161
|
Chris@0
|
162 # User should be added as a project member
|
Chris@0
|
163 assert User.find(9).member_of?(project)
|
Chris@0
|
164 assert_equal 1, project.members.size
|
Chris@0
|
165 end
|
Chris@0
|
166
|
Chris@0
|
167 should "fail with parent_id" do
|
Chris@0
|
168 assert_no_difference 'Project.count' do
|
Chris@0
|
169 post :add, :project => { :name => "blog",
|
Chris@0
|
170 :description => "weblog",
|
Chris@0
|
171 :identifier => "blog",
|
Chris@0
|
172 :is_public => 1,
|
Chris@0
|
173 :custom_field_values => { '3' => 'Beta' },
|
Chris@0
|
174 :parent_id => 1
|
Chris@0
|
175 }
|
Chris@0
|
176 end
|
Chris@0
|
177 assert_response :success
|
Chris@0
|
178 project = assigns(:project)
|
Chris@0
|
179 assert_kind_of Project, project
|
Chris@0
|
180 assert_not_nil project.errors.on(:parent_id)
|
Chris@0
|
181 end
|
Chris@0
|
182 end
|
Chris@0
|
183
|
Chris@0
|
184 context "by non-admin user with add_subprojects permission" do
|
Chris@0
|
185 setup do
|
Chris@0
|
186 Role.find(1).remove_permission! :add_project
|
Chris@0
|
187 Role.find(1).add_permission! :add_subprojects
|
Chris@0
|
188 @request.session[:user_id] = 2
|
Chris@0
|
189 end
|
Chris@0
|
190
|
Chris@0
|
191 should "accept get" do
|
Chris@0
|
192 get :add, :parent_id => 'ecookbook'
|
Chris@0
|
193 assert_response :success
|
Chris@0
|
194 assert_template 'add'
|
Chris@0
|
195 # parent project selected
|
Chris@0
|
196 assert_tag :select, :attributes => {:name => 'project[parent_id]'},
|
Chris@0
|
197 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
|
Chris@0
|
198 # no empty value
|
Chris@0
|
199 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
|
Chris@0
|
200 :child => {:tag => 'option', :attributes => {:value => ''}}
|
Chris@0
|
201 end
|
Chris@0
|
202
|
Chris@0
|
203 should "accept post with parent_id" do
|
Chris@0
|
204 post :add, :project => { :name => "blog",
|
Chris@0
|
205 :description => "weblog",
|
Chris@0
|
206 :identifier => "blog",
|
Chris@0
|
207 :is_public => 1,
|
Chris@0
|
208 :custom_field_values => { '3' => 'Beta' },
|
Chris@0
|
209 :parent_id => 1
|
Chris@0
|
210 }
|
Chris@0
|
211 assert_redirected_to '/projects/blog/settings'
|
Chris@0
|
212 project = Project.find_by_name('blog')
|
Chris@0
|
213 end
|
Chris@0
|
214
|
Chris@0
|
215 should "fail without parent_id" do
|
Chris@0
|
216 assert_no_difference 'Project.count' do
|
Chris@0
|
217 post :add, :project => { :name => "blog",
|
Chris@0
|
218 :description => "weblog",
|
Chris@0
|
219 :identifier => "blog",
|
Chris@0
|
220 :is_public => 1,
|
Chris@0
|
221 :custom_field_values => { '3' => 'Beta' }
|
Chris@0
|
222 }
|
Chris@0
|
223 end
|
Chris@0
|
224 assert_response :success
|
Chris@0
|
225 project = assigns(:project)
|
Chris@0
|
226 assert_kind_of Project, project
|
Chris@0
|
227 assert_not_nil project.errors.on(:parent_id)
|
Chris@0
|
228 end
|
Chris@0
|
229
|
Chris@0
|
230 should "fail with unauthorized parent_id" do
|
Chris@0
|
231 assert !User.find(2).member_of?(Project.find(6))
|
Chris@0
|
232 assert_no_difference 'Project.count' do
|
Chris@0
|
233 post :add, :project => { :name => "blog",
|
Chris@0
|
234 :description => "weblog",
|
Chris@0
|
235 :identifier => "blog",
|
Chris@0
|
236 :is_public => 1,
|
Chris@0
|
237 :custom_field_values => { '3' => 'Beta' },
|
Chris@0
|
238 :parent_id => 6
|
Chris@0
|
239 }
|
Chris@0
|
240 end
|
Chris@0
|
241 assert_response :success
|
Chris@0
|
242 project = assigns(:project)
|
Chris@0
|
243 assert_kind_of Project, project
|
Chris@0
|
244 assert_not_nil project.errors.on(:parent_id)
|
Chris@0
|
245 end
|
Chris@0
|
246 end
|
Chris@0
|
247 end
|
Chris@0
|
248
|
Chris@0
|
249 def test_show_by_id
|
Chris@0
|
250 get :show, :id => 1
|
Chris@0
|
251 assert_response :success
|
Chris@0
|
252 assert_template 'show'
|
Chris@0
|
253 assert_not_nil assigns(:project)
|
Chris@0
|
254 end
|
Chris@0
|
255
|
Chris@0
|
256 def test_show_by_identifier
|
Chris@0
|
257 get :show, :id => 'ecookbook'
|
Chris@0
|
258 assert_response :success
|
Chris@0
|
259 assert_template 'show'
|
Chris@0
|
260 assert_not_nil assigns(:project)
|
Chris@0
|
261 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
|
Chris@0
|
262 end
|
Chris@0
|
263
|
Chris@0
|
264 def test_show_should_not_fail_when_custom_values_are_nil
|
Chris@0
|
265 project = Project.find_by_identifier('ecookbook')
|
Chris@0
|
266 project.custom_values.first.update_attribute(:value, nil)
|
Chris@0
|
267 get :show, :id => 'ecookbook'
|
Chris@0
|
268 assert_response :success
|
Chris@0
|
269 assert_template 'show'
|
Chris@0
|
270 assert_not_nil assigns(:project)
|
Chris@0
|
271 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
|
Chris@0
|
272 end
|
Chris@0
|
273
|
Chris@0
|
274 def test_private_subprojects_hidden
|
Chris@0
|
275 get :show, :id => 'ecookbook'
|
Chris@0
|
276 assert_response :success
|
Chris@0
|
277 assert_template 'show'
|
Chris@0
|
278 assert_no_tag :tag => 'a', :content => /Private child/
|
Chris@0
|
279 end
|
Chris@0
|
280
|
Chris@0
|
281 def test_private_subprojects_visible
|
Chris@0
|
282 @request.session[:user_id] = 2 # manager who is a member of the private subproject
|
Chris@0
|
283 get :show, :id => 'ecookbook'
|
Chris@0
|
284 assert_response :success
|
Chris@0
|
285 assert_template 'show'
|
Chris@0
|
286 assert_tag :tag => 'a', :content => /Private child/
|
Chris@0
|
287 end
|
Chris@0
|
288
|
Chris@0
|
289 def test_settings
|
Chris@0
|
290 @request.session[:user_id] = 2 # manager
|
Chris@0
|
291 get :settings, :id => 1
|
Chris@0
|
292 assert_response :success
|
Chris@0
|
293 assert_template 'settings'
|
Chris@0
|
294 end
|
Chris@0
|
295
|
Chris@0
|
296 def test_edit
|
Chris@0
|
297 @request.session[:user_id] = 2 # manager
|
Chris@0
|
298 post :edit, :id => 1, :project => {:name => 'Test changed name',
|
Chris@0
|
299 :issue_custom_field_ids => ['']}
|
Chris@0
|
300 assert_redirected_to 'projects/ecookbook/settings'
|
Chris@0
|
301 project = Project.find(1)
|
Chris@0
|
302 assert_equal 'Test changed name', project.name
|
Chris@0
|
303 end
|
Chris@0
|
304
|
Chris@0
|
305 def test_get_destroy
|
Chris@0
|
306 @request.session[:user_id] = 1 # admin
|
Chris@0
|
307 get :destroy, :id => 1
|
Chris@0
|
308 assert_response :success
|
Chris@0
|
309 assert_template 'destroy'
|
Chris@0
|
310 assert_not_nil Project.find_by_id(1)
|
Chris@0
|
311 end
|
Chris@0
|
312
|
Chris@0
|
313 def test_post_destroy
|
Chris@0
|
314 @request.session[:user_id] = 1 # admin
|
Chris@0
|
315 post :destroy, :id => 1, :confirm => 1
|
Chris@0
|
316 assert_redirected_to 'admin/projects'
|
Chris@0
|
317 assert_nil Project.find_by_id(1)
|
Chris@0
|
318 end
|
Chris@0
|
319
|
Chris@0
|
320 def test_add_file
|
Chris@0
|
321 set_tmp_attachments_directory
|
Chris@0
|
322 @request.session[:user_id] = 2
|
Chris@0
|
323 Setting.notified_events = ['file_added']
|
Chris@0
|
324 ActionMailer::Base.deliveries.clear
|
Chris@0
|
325
|
Chris@0
|
326 assert_difference 'Attachment.count' do
|
Chris@0
|
327 post :add_file, :id => 1, :version_id => '',
|
Chris@0
|
328 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
|
Chris@0
|
329 end
|
Chris@0
|
330 assert_redirected_to 'projects/ecookbook/files'
|
Chris@0
|
331 a = Attachment.find(:first, :order => 'created_on DESC')
|
Chris@0
|
332 assert_equal 'testfile.txt', a.filename
|
Chris@0
|
333 assert_equal Project.find(1), a.container
|
Chris@0
|
334
|
Chris@0
|
335 mail = ActionMailer::Base.deliveries.last
|
Chris@0
|
336 assert_kind_of TMail::Mail, mail
|
Chris@0
|
337 assert_equal "[eCookbook] New file", mail.subject
|
Chris@0
|
338 assert mail.body.include?('testfile.txt')
|
Chris@0
|
339 end
|
Chris@0
|
340
|
Chris@0
|
341 def test_add_version_file
|
Chris@0
|
342 set_tmp_attachments_directory
|
Chris@0
|
343 @request.session[:user_id] = 2
|
Chris@0
|
344 Setting.notified_events = ['file_added']
|
Chris@0
|
345
|
Chris@0
|
346 assert_difference 'Attachment.count' do
|
Chris@0
|
347 post :add_file, :id => 1, :version_id => '2',
|
Chris@0
|
348 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
|
Chris@0
|
349 end
|
Chris@0
|
350 assert_redirected_to 'projects/ecookbook/files'
|
Chris@0
|
351 a = Attachment.find(:first, :order => 'created_on DESC')
|
Chris@0
|
352 assert_equal 'testfile.txt', a.filename
|
Chris@0
|
353 assert_equal Version.find(2), a.container
|
Chris@0
|
354 end
|
Chris@0
|
355
|
Chris@0
|
356 def test_list_files
|
Chris@0
|
357 get :list_files, :id => 1
|
Chris@0
|
358 assert_response :success
|
Chris@0
|
359 assert_template 'list_files'
|
Chris@0
|
360 assert_not_nil assigns(:containers)
|
Chris@0
|
361
|
Chris@0
|
362 # file attached to the project
|
Chris@0
|
363 assert_tag :a, :content => 'project_file.zip',
|
Chris@0
|
364 :attributes => { :href => '/attachments/download/8/project_file.zip' }
|
Chris@0
|
365
|
Chris@0
|
366 # file attached to a project's version
|
Chris@0
|
367 assert_tag :a, :content => 'version_file.zip',
|
Chris@0
|
368 :attributes => { :href => '/attachments/download/9/version_file.zip' }
|
Chris@0
|
369 end
|
Chris@0
|
370
|
Chris@0
|
371 def test_roadmap
|
Chris@0
|
372 get :roadmap, :id => 1
|
Chris@0
|
373 assert_response :success
|
Chris@0
|
374 assert_template 'roadmap'
|
Chris@0
|
375 assert_not_nil assigns(:versions)
|
Chris@0
|
376 # Version with no date set appears
|
Chris@0
|
377 assert assigns(:versions).include?(Version.find(3))
|
Chris@0
|
378 # Completed version doesn't appear
|
Chris@0
|
379 assert !assigns(:versions).include?(Version.find(1))
|
Chris@0
|
380 end
|
Chris@0
|
381
|
Chris@0
|
382 def test_roadmap_with_completed_versions
|
Chris@0
|
383 get :roadmap, :id => 1, :completed => 1
|
Chris@0
|
384 assert_response :success
|
Chris@0
|
385 assert_template 'roadmap'
|
Chris@0
|
386 assert_not_nil assigns(:versions)
|
Chris@0
|
387 # Version with no date set appears
|
Chris@0
|
388 assert assigns(:versions).include?(Version.find(3))
|
Chris@0
|
389 # Completed version appears
|
Chris@0
|
390 assert assigns(:versions).include?(Version.find(1))
|
Chris@0
|
391 end
|
Chris@0
|
392
|
Chris@0
|
393 def test_roadmap_showing_subprojects_versions
|
Chris@0
|
394 @subproject_version = Version.generate!(:project => Project.find(3))
|
Chris@0
|
395 get :roadmap, :id => 1, :with_subprojects => 1
|
Chris@0
|
396 assert_response :success
|
Chris@0
|
397 assert_template 'roadmap'
|
Chris@0
|
398 assert_not_nil assigns(:versions)
|
Chris@0
|
399
|
Chris@0
|
400 assert assigns(:versions).include?(Version.find(4)), "Shared version not found"
|
Chris@0
|
401 assert assigns(:versions).include?(@subproject_version), "Subproject version not found"
|
Chris@0
|
402 end
|
Chris@0
|
403 def test_project_activity
|
Chris@0
|
404 get :activity, :id => 1, :with_subprojects => 0
|
Chris@0
|
405 assert_response :success
|
Chris@0
|
406 assert_template 'activity'
|
Chris@0
|
407 assert_not_nil assigns(:events_by_day)
|
Chris@0
|
408
|
Chris@0
|
409 assert_tag :tag => "h3",
|
Chris@0
|
410 :content => /#{2.days.ago.to_date.day}/,
|
Chris@0
|
411 :sibling => { :tag => "dl",
|
Chris@0
|
412 :child => { :tag => "dt",
|
Chris@0
|
413 :attributes => { :class => /issue-edit/ },
|
Chris@0
|
414 :child => { :tag => "a",
|
Chris@0
|
415 :content => /(#{IssueStatus.find(2).name})/,
|
Chris@0
|
416 }
|
Chris@0
|
417 }
|
Chris@0
|
418 }
|
Chris@0
|
419 end
|
Chris@0
|
420
|
Chris@0
|
421 def test_previous_project_activity
|
Chris@0
|
422 get :activity, :id => 1, :from => 3.days.ago.to_date
|
Chris@0
|
423 assert_response :success
|
Chris@0
|
424 assert_template 'activity'
|
Chris@0
|
425 assert_not_nil assigns(:events_by_day)
|
Chris@0
|
426
|
Chris@0
|
427 assert_tag :tag => "h3",
|
Chris@0
|
428 :content => /#{3.day.ago.to_date.day}/,
|
Chris@0
|
429 :sibling => { :tag => "dl",
|
Chris@0
|
430 :child => { :tag => "dt",
|
Chris@0
|
431 :attributes => { :class => /issue/ },
|
Chris@0
|
432 :child => { :tag => "a",
|
Chris@0
|
433 :content => /#{Issue.find(1).subject}/,
|
Chris@0
|
434 }
|
Chris@0
|
435 }
|
Chris@0
|
436 }
|
Chris@0
|
437 end
|
Chris@0
|
438
|
Chris@0
|
439 def test_global_activity
|
Chris@0
|
440 get :activity
|
Chris@0
|
441 assert_response :success
|
Chris@0
|
442 assert_template 'activity'
|
Chris@0
|
443 assert_not_nil assigns(:events_by_day)
|
Chris@0
|
444
|
Chris@0
|
445 assert_tag :tag => "h3",
|
Chris@0
|
446 :content => /#{5.day.ago.to_date.day}/,
|
Chris@0
|
447 :sibling => { :tag => "dl",
|
Chris@0
|
448 :child => { :tag => "dt",
|
Chris@0
|
449 :attributes => { :class => /issue/ },
|
Chris@0
|
450 :child => { :tag => "a",
|
Chris@0
|
451 :content => /#{Issue.find(5).subject}/,
|
Chris@0
|
452 }
|
Chris@0
|
453 }
|
Chris@0
|
454 }
|
Chris@0
|
455 end
|
Chris@0
|
456
|
Chris@0
|
457 def test_user_activity
|
Chris@0
|
458 get :activity, :user_id => 2
|
Chris@0
|
459 assert_response :success
|
Chris@0
|
460 assert_template 'activity'
|
Chris@0
|
461 assert_not_nil assigns(:events_by_day)
|
Chris@0
|
462
|
Chris@0
|
463 assert_tag :tag => "h3",
|
Chris@0
|
464 :content => /#{3.day.ago.to_date.day}/,
|
Chris@0
|
465 :sibling => { :tag => "dl",
|
Chris@0
|
466 :child => { :tag => "dt",
|
Chris@0
|
467 :attributes => { :class => /issue/ },
|
Chris@0
|
468 :child => { :tag => "a",
|
Chris@0
|
469 :content => /#{Issue.find(1).subject}/,
|
Chris@0
|
470 }
|
Chris@0
|
471 }
|
Chris@0
|
472 }
|
Chris@0
|
473 end
|
Chris@0
|
474
|
Chris@0
|
475 def test_activity_atom_feed
|
Chris@0
|
476 get :activity, :format => 'atom'
|
Chris@0
|
477 assert_response :success
|
Chris@0
|
478 assert_template 'common/feed.atom.rxml'
|
Chris@0
|
479 assert_tag :tag => 'entry', :child => {
|
Chris@0
|
480 :tag => 'link',
|
Chris@0
|
481 :attributes => {:href => 'http://test.host/issues/11'}}
|
Chris@0
|
482 end
|
Chris@0
|
483
|
Chris@0
|
484 def test_archive
|
Chris@0
|
485 @request.session[:user_id] = 1 # admin
|
Chris@0
|
486 post :archive, :id => 1
|
Chris@0
|
487 assert_redirected_to 'admin/projects'
|
Chris@0
|
488 assert !Project.find(1).active?
|
Chris@0
|
489 end
|
Chris@0
|
490
|
Chris@0
|
491 def test_unarchive
|
Chris@0
|
492 @request.session[:user_id] = 1 # admin
|
Chris@0
|
493 Project.find(1).archive
|
Chris@0
|
494 post :unarchive, :id => 1
|
Chris@0
|
495 assert_redirected_to 'admin/projects'
|
Chris@0
|
496 assert Project.find(1).active?
|
Chris@0
|
497 end
|
Chris@0
|
498
|
Chris@0
|
499 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
|
Chris@0
|
500 CustomField.delete_all
|
Chris@0
|
501 parent = nil
|
Chris@0
|
502 6.times do |i|
|
Chris@0
|
503 p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
|
Chris@0
|
504 p.set_parent!(parent)
|
Chris@0
|
505 get :show, :id => p
|
Chris@0
|
506 assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
|
Chris@0
|
507 :children => { :count => [i, 3].min,
|
Chris@0
|
508 :only => { :tag => 'a' } }
|
Chris@0
|
509
|
Chris@0
|
510 parent = p
|
Chris@0
|
511 end
|
Chris@0
|
512 end
|
Chris@0
|
513
|
Chris@0
|
514 def test_copy_with_project
|
Chris@0
|
515 @request.session[:user_id] = 1 # admin
|
Chris@0
|
516 get :copy, :id => 1
|
Chris@0
|
517 assert_response :success
|
Chris@0
|
518 assert_template 'copy'
|
Chris@0
|
519 assert assigns(:project)
|
Chris@0
|
520 assert_equal Project.find(1).description, assigns(:project).description
|
Chris@0
|
521 assert_nil assigns(:project).id
|
Chris@0
|
522 end
|
Chris@0
|
523
|
Chris@0
|
524 def test_copy_without_project
|
Chris@0
|
525 @request.session[:user_id] = 1 # admin
|
Chris@0
|
526 get :copy
|
Chris@0
|
527 assert_response :redirect
|
Chris@0
|
528 assert_redirected_to :controller => 'admin', :action => 'projects'
|
Chris@0
|
529 end
|
Chris@0
|
530
|
Chris@0
|
531 def test_jump_should_redirect_to_active_tab
|
Chris@0
|
532 get :show, :id => 1, :jump => 'issues'
|
Chris@0
|
533 assert_redirected_to 'projects/ecookbook/issues'
|
Chris@0
|
534 end
|
Chris@0
|
535
|
Chris@0
|
536 def test_jump_should_not_redirect_to_inactive_tab
|
Chris@0
|
537 get :show, :id => 3, :jump => 'documents'
|
Chris@0
|
538 assert_response :success
|
Chris@0
|
539 assert_template 'show'
|
Chris@0
|
540 end
|
Chris@0
|
541
|
Chris@0
|
542 def test_jump_should_not_redirect_to_unknown_tab
|
Chris@0
|
543 get :show, :id => 3, :jump => 'foobar'
|
Chris@0
|
544 assert_response :success
|
Chris@0
|
545 assert_template 'show'
|
Chris@0
|
546 end
|
Chris@0
|
547
|
Chris@0
|
548 def test_reset_activities
|
Chris@0
|
549 @request.session[:user_id] = 2 # manager
|
Chris@0
|
550 project_activity = TimeEntryActivity.new({
|
Chris@0
|
551 :name => 'Project Specific',
|
Chris@0
|
552 :parent => TimeEntryActivity.find(:first),
|
Chris@0
|
553 :project => Project.find(1),
|
Chris@0
|
554 :active => true
|
Chris@0
|
555 })
|
Chris@0
|
556 assert project_activity.save
|
Chris@0
|
557 project_activity_two = TimeEntryActivity.new({
|
Chris@0
|
558 :name => 'Project Specific Two',
|
Chris@0
|
559 :parent => TimeEntryActivity.find(:last),
|
Chris@0
|
560 :project => Project.find(1),
|
Chris@0
|
561 :active => true
|
Chris@0
|
562 })
|
Chris@0
|
563 assert project_activity_two.save
|
Chris@0
|
564
|
Chris@0
|
565 delete :reset_activities, :id => 1
|
Chris@0
|
566 assert_response :redirect
|
Chris@0
|
567 assert_redirected_to 'projects/ecookbook/settings/activities'
|
Chris@0
|
568
|
Chris@0
|
569 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
|
Chris@0
|
570 assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
|
Chris@0
|
571 end
|
Chris@0
|
572
|
Chris@0
|
573 def test_reset_activities_should_reassign_time_entries_back_to_the_system_activity
|
Chris@0
|
574 @request.session[:user_id] = 2 # manager
|
Chris@0
|
575 project_activity = TimeEntryActivity.new({
|
Chris@0
|
576 :name => 'Project Specific Design',
|
Chris@0
|
577 :parent => TimeEntryActivity.find(9),
|
Chris@0
|
578 :project => Project.find(1),
|
Chris@0
|
579 :active => true
|
Chris@0
|
580 })
|
Chris@0
|
581 assert project_activity.save
|
Chris@0
|
582 assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
|
Chris@0
|
583 assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
|
Chris@0
|
584
|
Chris@0
|
585 delete :reset_activities, :id => 1
|
Chris@0
|
586 assert_response :redirect
|
Chris@0
|
587 assert_redirected_to 'projects/ecookbook/settings/activities'
|
Chris@0
|
588
|
Chris@0
|
589 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
|
Chris@0
|
590 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity"
|
Chris@0
|
591 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
|
Chris@0
|
592 end
|
Chris@0
|
593
|
Chris@0
|
594 def test_save_activities_to_override_system_activities
|
Chris@0
|
595 @request.session[:user_id] = 2 # manager
|
Chris@0
|
596 billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
|
Chris@0
|
597
|
Chris@0
|
598 post :save_activities, :id => 1, :enumerations => {
|
Chris@0
|
599 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate
|
Chris@0
|
600 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
|
Chris@0
|
601 "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
|
Chris@0
|
602 "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
|
Chris@0
|
603 }
|
Chris@0
|
604
|
Chris@0
|
605 assert_response :redirect
|
Chris@0
|
606 assert_redirected_to 'projects/ecookbook/settings/activities'
|
Chris@0
|
607
|
Chris@0
|
608 # Created project specific activities...
|
Chris@0
|
609 project = Project.find('ecookbook')
|
Chris@0
|
610
|
Chris@0
|
611 # ... Design
|
Chris@0
|
612 design = project.time_entry_activities.find_by_name("Design")
|
Chris@0
|
613 assert design, "Project activity not found"
|
Chris@0
|
614
|
Chris@0
|
615 assert_equal 9, design.parent_id # Relate to the system activity
|
Chris@0
|
616 assert_not_equal design.parent.id, design.id # Different records
|
Chris@0
|
617 assert_equal design.parent.name, design.name # Same name
|
Chris@0
|
618 assert !design.active?
|
Chris@0
|
619
|
Chris@0
|
620 # ... Development
|
Chris@0
|
621 development = project.time_entry_activities.find_by_name("Development")
|
Chris@0
|
622 assert development, "Project activity not found"
|
Chris@0
|
623
|
Chris@0
|
624 assert_equal 10, development.parent_id # Relate to the system activity
|
Chris@0
|
625 assert_not_equal development.parent.id, development.id # Different records
|
Chris@0
|
626 assert_equal development.parent.name, development.name # Same name
|
Chris@0
|
627 assert development.active?
|
Chris@0
|
628 assert_equal "0", development.custom_value_for(billable_field).value
|
Chris@0
|
629
|
Chris@0
|
630 # ... Inactive Activity
|
Chris@0
|
631 previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
|
Chris@0
|
632 assert previously_inactive, "Project activity not found"
|
Chris@0
|
633
|
Chris@0
|
634 assert_equal 14, previously_inactive.parent_id # Relate to the system activity
|
Chris@0
|
635 assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
|
Chris@0
|
636 assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
|
Chris@0
|
637 assert previously_inactive.active?
|
Chris@0
|
638 assert_equal "1", previously_inactive.custom_value_for(billable_field).value
|
Chris@0
|
639
|
Chris@0
|
640 # ... QA
|
Chris@0
|
641 assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
|
Chris@0
|
642 end
|
Chris@0
|
643
|
Chris@0
|
644 def test_save_activities_will_update_project_specific_activities
|
Chris@0
|
645 @request.session[:user_id] = 2 # manager
|
Chris@0
|
646
|
Chris@0
|
647 project_activity = TimeEntryActivity.new({
|
Chris@0
|
648 :name => 'Project Specific',
|
Chris@0
|
649 :parent => TimeEntryActivity.find(:first),
|
Chris@0
|
650 :project => Project.find(1),
|
Chris@0
|
651 :active => true
|
Chris@0
|
652 })
|
Chris@0
|
653 assert project_activity.save
|
Chris@0
|
654 project_activity_two = TimeEntryActivity.new({
|
Chris@0
|
655 :name => 'Project Specific Two',
|
Chris@0
|
656 :parent => TimeEntryActivity.find(:last),
|
Chris@0
|
657 :project => Project.find(1),
|
Chris@0
|
658 :active => true
|
Chris@0
|
659 })
|
Chris@0
|
660 assert project_activity_two.save
|
Chris@0
|
661
|
Chris@0
|
662
|
Chris@0
|
663 post :save_activities, :id => 1, :enumerations => {
|
Chris@0
|
664 project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate
|
Chris@0
|
665 project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
|
Chris@0
|
666 }
|
Chris@0
|
667
|
Chris@0
|
668 assert_response :redirect
|
Chris@0
|
669 assert_redirected_to 'projects/ecookbook/settings/activities'
|
Chris@0
|
670
|
Chris@0
|
671 # Created project specific activities...
|
Chris@0
|
672 project = Project.find('ecookbook')
|
Chris@0
|
673 assert_equal 2, project.time_entry_activities.count
|
Chris@0
|
674
|
Chris@0
|
675 activity_one = project.time_entry_activities.find_by_name(project_activity.name)
|
Chris@0
|
676 assert activity_one, "Project activity not found"
|
Chris@0
|
677 assert_equal project_activity.id, activity_one.id
|
Chris@0
|
678 assert !activity_one.active?
|
Chris@0
|
679
|
Chris@0
|
680 activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
|
Chris@0
|
681 assert activity_two, "Project activity not found"
|
Chris@0
|
682 assert_equal project_activity_two.id, activity_two.id
|
Chris@0
|
683 assert !activity_two.active?
|
Chris@0
|
684 end
|
Chris@0
|
685
|
Chris@0
|
686 def test_save_activities_when_creating_new_activities_will_convert_existing_data
|
Chris@0
|
687 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
|
Chris@0
|
688
|
Chris@0
|
689 @request.session[:user_id] = 2 # manager
|
Chris@0
|
690 post :save_activities, :id => 1, :enumerations => {
|
Chris@0
|
691 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate
|
Chris@0
|
692 }
|
Chris@0
|
693 assert_response :redirect
|
Chris@0
|
694
|
Chris@0
|
695 # No more TimeEntries using the system activity
|
Chris@0
|
696 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities"
|
Chris@0
|
697 # All TimeEntries using project activity
|
Chris@0
|
698 project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
|
Chris@0
|
699 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity"
|
Chris@0
|
700 end
|
Chris@0
|
701
|
Chris@0
|
702 def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
|
Chris@0
|
703 # TODO: Need to cause an exception on create but these tests
|
Chris@0
|
704 # aren't setup for mocking. Just create a record now so the
|
Chris@0
|
705 # second one is a dupicate
|
Chris@0
|
706 parent = TimeEntryActivity.find(9)
|
Chris@0
|
707 TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true})
|
Chris@0
|
708 TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
|
Chris@0
|
709
|
Chris@0
|
710 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
|
Chris@0
|
711 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
|
Chris@0
|
712
|
Chris@0
|
713 @request.session[:user_id] = 2 # manager
|
Chris@0
|
714 post :save_activities, :id => 1, :enumerations => {
|
Chris@0
|
715 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
|
Chris@0
|
716 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
|
Chris@0
|
717 }
|
Chris@0
|
718 assert_response :redirect
|
Chris@0
|
719
|
Chris@0
|
720 # TimeEntries shouldn't have been reassigned on the failed record
|
Chris@0
|
721 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
|
Chris@0
|
722 # TimeEntries shouldn't have been reassigned on the saved record either
|
Chris@0
|
723 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities"
|
Chris@0
|
724 end
|
Chris@0
|
725
|
Chris@0
|
726 # A hook that is manually registered later
|
Chris@0
|
727 class ProjectBasedTemplate < Redmine::Hook::ViewListener
|
Chris@0
|
728 def view_layouts_base_html_head(context)
|
Chris@0
|
729 # Adds a project stylesheet
|
Chris@0
|
730 stylesheet_link_tag(context[:project].identifier) if context[:project]
|
Chris@0
|
731 end
|
Chris@0
|
732 end
|
Chris@0
|
733 # Don't use this hook now
|
Chris@0
|
734 Redmine::Hook.clear_listeners
|
Chris@0
|
735
|
Chris@0
|
736 def test_hook_response
|
Chris@0
|
737 Redmine::Hook.add_listener(ProjectBasedTemplate)
|
Chris@0
|
738 get :show, :id => 1
|
Chris@0
|
739 assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
|
Chris@0
|
740 :parent => {:tag => 'head'}
|
Chris@0
|
741
|
Chris@0
|
742 Redmine::Hook.clear_listeners
|
Chris@0
|
743 end
|
Chris@0
|
744 end
|