annotate test/functional/projects_controller_test.rb @ 8:0c83d98252d9 yuya

* Add custom repo prefix and proper auth realm, remove auth cache (seems like an unwise feature), pass DB handle around, various other bits of tidying
author Chris Cannam
date Thu, 12 Aug 2010 15:31:37 +0100
parents 513646585e45
children 40f7cfd4df19
rev   line source
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