mirror of
https://github.com/redmine/redmine.git
synced 2025-11-04 20:35:57 +01:00
* Ran the Rails upgrade
* Upgraded to Rails Engines 2.3.2
* Added a plugin to let Engines override application views.
* Converted tests to use the new classes:
** ActionController::TestCase for functional
** ActiveSupport::TestCase for units
* Converted ActiveRecord::Error message to a string.
* ActiveRecord grouping returns an ordered hash which doesn't have #sort!
* Updated the I18n storage_units format.
* Added some default initializers from a fresh rails app
* Changed the order of check_box_tags and hidden_field_tags. The hidden tag
needs to appear first in Rails 2.3, otherwise it will override any value in
the check_box_tag.
* Removed the custom handler for when the cookie store is tampered with.
Rails 2.3 removed the TamperedWithCookie exception and instead Rails will not
load the data from it when it's been tampered with (e.g. no user login).
* Fixed mail layouts, 2.3 has problems with implicit multipart emails that
use layouts. Also removed some custom Redmine mailer code.
* Fixed a bug that occurred in tests where the "required" span tag would be
added to the :field_status translation. This resulted in an email string of:
<li>Status<span class="required"> *</span><span class="required"> *</span>
Instead of:
<li>Status: New</li>
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2887 e93f8b46-1217-0410-a6f0-8f06a7374b81
1097 lines
39 KiB
Ruby
1097 lines
39 KiB
Ruby
# Redmine - project management software
|
|
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
require File.dirname(__FILE__) + '/../test_helper'
|
|
require 'issues_controller'
|
|
|
|
# Re-raise errors caught by the controller.
|
|
class IssuesController; def rescue_action(e) raise e end; end
|
|
|
|
class IssuesControllerTest < ActionController::TestCase
|
|
fixtures :projects,
|
|
:users,
|
|
:roles,
|
|
:members,
|
|
:member_roles,
|
|
:issues,
|
|
:issue_statuses,
|
|
:versions,
|
|
:trackers,
|
|
:projects_trackers,
|
|
:issue_categories,
|
|
:enabled_modules,
|
|
:enumerations,
|
|
:attachments,
|
|
:workflows,
|
|
:custom_fields,
|
|
:custom_values,
|
|
:custom_fields_trackers,
|
|
:time_entries,
|
|
:journals,
|
|
:journal_details,
|
|
:queries
|
|
|
|
def setup
|
|
@controller = IssuesController.new
|
|
@request = ActionController::TestRequest.new
|
|
@response = ActionController::TestResponse.new
|
|
User.current = nil
|
|
end
|
|
|
|
def test_index_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/issues'},
|
|
:controller => 'issues', :action => 'index'
|
|
)
|
|
end
|
|
|
|
def test_index
|
|
Setting.default_language = 'en'
|
|
|
|
get :index
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_nil assigns(:project)
|
|
assert_tag :tag => 'a', :content => /Can't print recipes/
|
|
assert_tag :tag => 'a', :content => /Subproject issue/
|
|
# private projects hidden
|
|
assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
|
|
assert_no_tag :tag => 'a', :content => /Issue on project 2/
|
|
# project column
|
|
assert_tag :tag => 'th', :content => /Project/
|
|
end
|
|
|
|
def test_index_should_not_list_issues_when_module_disabled
|
|
EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
|
|
get :index
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_nil assigns(:project)
|
|
assert_no_tag :tag => 'a', :content => /Can't print recipes/
|
|
assert_tag :tag => 'a', :content => /Subproject issue/
|
|
end
|
|
|
|
def test_index_with_project_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/projects/23/issues'},
|
|
:controller => 'issues', :action => 'index', :project_id => '23'
|
|
)
|
|
end
|
|
|
|
def test_index_should_not_list_issues_when_module_disabled
|
|
EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
|
|
get :index
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_nil assigns(:project)
|
|
assert_no_tag :tag => 'a', :content => /Can't print recipes/
|
|
assert_tag :tag => 'a', :content => /Subproject issue/
|
|
end
|
|
|
|
def test_index_with_project_routing
|
|
assert_routing(
|
|
{:method => :get, :path => 'projects/23/issues'},
|
|
:controller => 'issues', :action => 'index', :project_id => '23'
|
|
)
|
|
end
|
|
|
|
def test_index_with_project
|
|
Setting.display_subprojects_issues = 0
|
|
get :index, :project_id => 1
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_tag :tag => 'a', :content => /Can't print recipes/
|
|
assert_no_tag :tag => 'a', :content => /Subproject issue/
|
|
end
|
|
|
|
def test_index_with_project_and_subprojects
|
|
Setting.display_subprojects_issues = 1
|
|
get :index, :project_id => 1
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_tag :tag => 'a', :content => /Can't print recipes/
|
|
assert_tag :tag => 'a', :content => /Subproject issue/
|
|
assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
|
|
end
|
|
|
|
def test_index_with_project_and_subprojects_should_show_private_subprojects
|
|
@request.session[:user_id] = 2
|
|
Setting.display_subprojects_issues = 1
|
|
get :index, :project_id => 1
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_tag :tag => 'a', :content => /Can't print recipes/
|
|
assert_tag :tag => 'a', :content => /Subproject issue/
|
|
assert_tag :tag => 'a', :content => /Issue of a private subproject/
|
|
end
|
|
|
|
def test_index_with_project_routing_formatted
|
|
assert_routing(
|
|
{:method => :get, :path => 'projects/23/issues.pdf'},
|
|
:controller => 'issues', :action => 'index', :project_id => '23', :format => 'pdf'
|
|
)
|
|
assert_routing(
|
|
{:method => :get, :path => 'projects/23/issues.atom'},
|
|
:controller => 'issues', :action => 'index', :project_id => '23', :format => 'atom'
|
|
)
|
|
end
|
|
|
|
def test_index_with_project_and_filter
|
|
get :index, :project_id => 1, :set_filter => 1
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
end
|
|
|
|
def test_index_with_query
|
|
get :index, :project_id => 1, :query_id => 5
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_nil assigns(:issue_count_by_group)
|
|
end
|
|
|
|
def test_index_with_grouped_query
|
|
get :index, :project_id => 1, :query_id => 6
|
|
assert_response :success
|
|
assert_template 'index.rhtml'
|
|
assert_not_nil assigns(:issues)
|
|
assert_not_nil assigns(:issue_count_by_group)
|
|
end
|
|
|
|
def test_index_csv_with_project
|
|
get :index, :format => 'csv'
|
|
assert_response :success
|
|
assert_not_nil assigns(:issues)
|
|
assert_equal 'text/csv', @response.content_type
|
|
|
|
get :index, :project_id => 1, :format => 'csv'
|
|
assert_response :success
|
|
assert_not_nil assigns(:issues)
|
|
assert_equal 'text/csv', @response.content_type
|
|
end
|
|
|
|
def test_index_formatted
|
|
assert_routing(
|
|
{:method => :get, :path => 'issues.pdf'},
|
|
:controller => 'issues', :action => 'index', :format => 'pdf'
|
|
)
|
|
assert_routing(
|
|
{:method => :get, :path => 'issues.atom'},
|
|
:controller => 'issues', :action => 'index', :format => 'atom'
|
|
)
|
|
end
|
|
|
|
def test_index_pdf
|
|
get :index, :format => 'pdf'
|
|
assert_response :success
|
|
assert_not_nil assigns(:issues)
|
|
assert_equal 'application/pdf', @response.content_type
|
|
|
|
get :index, :project_id => 1, :format => 'pdf'
|
|
assert_response :success
|
|
assert_not_nil assigns(:issues)
|
|
assert_equal 'application/pdf', @response.content_type
|
|
|
|
get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
|
|
assert_response :success
|
|
assert_not_nil assigns(:issues)
|
|
assert_equal 'application/pdf', @response.content_type
|
|
end
|
|
|
|
def test_index_sort
|
|
get :index, :sort => 'tracker,id:desc'
|
|
assert_response :success
|
|
|
|
sort_params = @request.session['issues_index_sort']
|
|
assert sort_params.is_a?(String)
|
|
assert_equal 'tracker,id:desc', sort_params
|
|
|
|
issues = assigns(:issues)
|
|
assert_not_nil issues
|
|
assert !issues.empty?
|
|
assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
|
|
end
|
|
|
|
def test_gantt
|
|
get :gantt, :project_id => 1
|
|
assert_response :success
|
|
assert_template 'gantt.rhtml'
|
|
assert_not_nil assigns(:gantt)
|
|
events = assigns(:gantt).events
|
|
assert_not_nil events
|
|
# Issue with start and due dates
|
|
i = Issue.find(1)
|
|
assert_not_nil i.due_date
|
|
assert events.include?(Issue.find(1))
|
|
# Issue with without due date but targeted to a version with date
|
|
i = Issue.find(2)
|
|
assert_nil i.due_date
|
|
assert events.include?(i)
|
|
end
|
|
|
|
def test_cross_project_gantt
|
|
get :gantt
|
|
assert_response :success
|
|
assert_template 'gantt.rhtml'
|
|
assert_not_nil assigns(:gantt)
|
|
events = assigns(:gantt).events
|
|
assert_not_nil events
|
|
end
|
|
|
|
def test_gantt_export_to_pdf
|
|
get :gantt, :project_id => 1, :format => 'pdf'
|
|
assert_response :success
|
|
assert_equal 'application/pdf', @response.content_type
|
|
assert @response.body.starts_with?('%PDF')
|
|
assert_not_nil assigns(:gantt)
|
|
end
|
|
|
|
def test_cross_project_gantt_export_to_pdf
|
|
get :gantt, :format => 'pdf'
|
|
assert_response :success
|
|
assert_equal 'application/pdf', @response.content_type
|
|
assert @response.body.starts_with?('%PDF')
|
|
assert_not_nil assigns(:gantt)
|
|
end
|
|
|
|
if Object.const_defined?(:Magick)
|
|
def test_gantt_image
|
|
get :gantt, :project_id => 1, :format => 'png'
|
|
assert_response :success
|
|
assert_equal 'image/png', @response.content_type
|
|
end
|
|
else
|
|
puts "RMagick not installed. Skipping tests !!!"
|
|
end
|
|
|
|
def test_calendar
|
|
get :calendar, :project_id => 1
|
|
assert_response :success
|
|
assert_template 'calendar'
|
|
assert_not_nil assigns(:calendar)
|
|
end
|
|
|
|
def test_cross_project_calendar
|
|
get :calendar
|
|
assert_response :success
|
|
assert_template 'calendar'
|
|
assert_not_nil assigns(:calendar)
|
|
end
|
|
|
|
def test_changes
|
|
get :changes, :project_id => 1
|
|
assert_response :success
|
|
assert_not_nil assigns(:journals)
|
|
assert_equal 'application/atom+xml', @response.content_type
|
|
end
|
|
|
|
def test_show_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/issues/64'},
|
|
:controller => 'issues', :action => 'show', :id => '64'
|
|
)
|
|
end
|
|
|
|
def test_show_routing_formatted
|
|
assert_routing(
|
|
{:method => :get, :path => '/issues/2332.pdf'},
|
|
:controller => 'issues', :action => 'show', :id => '2332', :format => 'pdf'
|
|
)
|
|
assert_routing(
|
|
{:method => :get, :path => '/issues/23123.atom'},
|
|
:controller => 'issues', :action => 'show', :id => '23123', :format => 'atom'
|
|
)
|
|
end
|
|
|
|
def test_show_by_anonymous
|
|
get :show, :id => 1
|
|
assert_response :success
|
|
assert_template 'show.rhtml'
|
|
assert_not_nil assigns(:issue)
|
|
assert_equal Issue.find(1), assigns(:issue)
|
|
|
|
# anonymous role is allowed to add a note
|
|
assert_tag :tag => 'form',
|
|
:descendant => { :tag => 'fieldset',
|
|
:child => { :tag => 'legend',
|
|
:content => /Notes/ } }
|
|
end
|
|
|
|
def test_show_by_manager
|
|
@request.session[:user_id] = 2
|
|
get :show, :id => 1
|
|
assert_response :success
|
|
|
|
assert_tag :tag => 'form',
|
|
:descendant => { :tag => 'fieldset',
|
|
:child => { :tag => 'legend',
|
|
:content => /Change properties/ } },
|
|
:descendant => { :tag => 'fieldset',
|
|
:child => { :tag => 'legend',
|
|
:content => /Log time/ } },
|
|
:descendant => { :tag => 'fieldset',
|
|
:child => { :tag => 'legend',
|
|
:content => /Notes/ } }
|
|
end
|
|
|
|
def test_show_should_not_disclose_relations_to_invisible_issues
|
|
Setting.cross_project_issue_relations = '1'
|
|
IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
|
|
# Relation to a private project issue
|
|
IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
|
|
|
|
get :show, :id => 1
|
|
assert_response :success
|
|
|
|
assert_tag :div, :attributes => { :id => 'relations' },
|
|
:descendant => { :tag => 'a', :content => /#2$/ }
|
|
assert_no_tag :div, :attributes => { :id => 'relations' },
|
|
:descendant => { :tag => 'a', :content => /#4$/ }
|
|
end
|
|
|
|
def test_show_atom
|
|
get :show, :id => 2, :format => 'atom'
|
|
assert_response :success
|
|
assert_template 'changes.rxml'
|
|
# Inline image
|
|
assert @response.body.include?("<img src="http://test.host/attachments/download/10" alt="" />")
|
|
end
|
|
|
|
def test_new_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/projects/1/issues/new'},
|
|
:controller => 'issues', :action => 'new', :project_id => '1'
|
|
)
|
|
assert_recognizes(
|
|
{:controller => 'issues', :action => 'new', :project_id => '1'},
|
|
{:method => :post, :path => '/projects/1/issues'}
|
|
)
|
|
end
|
|
|
|
def test_show_export_to_pdf
|
|
get :show, :id => 3, :format => 'pdf'
|
|
assert_response :success
|
|
assert_equal 'application/pdf', @response.content_type
|
|
assert @response.body.starts_with?('%PDF')
|
|
assert_not_nil assigns(:issue)
|
|
end
|
|
|
|
def test_get_new
|
|
@request.session[:user_id] = 2
|
|
get :new, :project_id => 1, :tracker_id => 1
|
|
assert_response :success
|
|
assert_template 'new'
|
|
|
|
assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
|
|
:value => 'Default string' }
|
|
end
|
|
|
|
def test_get_new_without_tracker_id
|
|
@request.session[:user_id] = 2
|
|
get :new, :project_id => 1
|
|
assert_response :success
|
|
assert_template 'new'
|
|
|
|
issue = assigns(:issue)
|
|
assert_not_nil issue
|
|
assert_equal Project.find(1).trackers.first, issue.tracker
|
|
end
|
|
|
|
def test_get_new_with_no_default_status_should_display_an_error
|
|
@request.session[:user_id] = 2
|
|
IssueStatus.delete_all
|
|
|
|
get :new, :project_id => 1
|
|
assert_response 500
|
|
assert_not_nil flash[:error]
|
|
assert_tag :tag => 'div', :attributes => { :class => /error/ },
|
|
:content => /No default issue/
|
|
end
|
|
|
|
def test_get_new_with_no_tracker_should_display_an_error
|
|
@request.session[:user_id] = 2
|
|
Tracker.delete_all
|
|
|
|
get :new, :project_id => 1
|
|
assert_response 500
|
|
assert_not_nil flash[:error]
|
|
assert_tag :tag => 'div', :attributes => { :class => /error/ },
|
|
:content => /No tracker/
|
|
end
|
|
|
|
def test_update_new_form
|
|
@request.session[:user_id] = 2
|
|
xhr :post, :new, :project_id => 1,
|
|
:issue => {:tracker_id => 2,
|
|
:subject => 'This is the test_new issue',
|
|
:description => 'This is the description',
|
|
:priority_id => 5}
|
|
assert_response :success
|
|
assert_template 'new'
|
|
end
|
|
|
|
def test_post_new
|
|
@request.session[:user_id] = 2
|
|
assert_difference 'Issue.count' do
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 3,
|
|
:subject => 'This is the test_new issue',
|
|
:description => 'This is the description',
|
|
:priority_id => 5,
|
|
:estimated_hours => '',
|
|
:custom_field_values => {'2' => 'Value for field 2'}}
|
|
end
|
|
assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
|
|
|
|
issue = Issue.find_by_subject('This is the test_new issue')
|
|
assert_not_nil issue
|
|
assert_equal 2, issue.author_id
|
|
assert_equal 3, issue.tracker_id
|
|
assert_nil issue.estimated_hours
|
|
v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
|
|
assert_not_nil v
|
|
assert_equal 'Value for field 2', v.value
|
|
end
|
|
|
|
def test_post_new_and_continue
|
|
@request.session[:user_id] = 2
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 3,
|
|
:subject => 'This is first issue',
|
|
:priority_id => 5},
|
|
:continue => ''
|
|
assert_redirected_to :controller => 'issues', :action => 'new', :tracker_id => 3
|
|
end
|
|
|
|
def test_post_new_without_custom_fields_param
|
|
@request.session[:user_id] = 2
|
|
assert_difference 'Issue.count' do
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 1,
|
|
:subject => 'This is the test_new issue',
|
|
:description => 'This is the description',
|
|
:priority_id => 5}
|
|
end
|
|
assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
|
|
end
|
|
|
|
def test_post_new_with_required_custom_field_and_without_custom_fields_param
|
|
field = IssueCustomField.find_by_name('Database')
|
|
field.update_attribute(:is_required, true)
|
|
|
|
@request.session[:user_id] = 2
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 1,
|
|
:subject => 'This is the test_new issue',
|
|
:description => 'This is the description',
|
|
:priority_id => 5}
|
|
assert_response :success
|
|
assert_template 'new'
|
|
issue = assigns(:issue)
|
|
assert_not_nil issue
|
|
assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
|
|
end
|
|
|
|
def test_post_new_with_watchers
|
|
@request.session[:user_id] = 2
|
|
ActionMailer::Base.deliveries.clear
|
|
|
|
assert_difference 'Watcher.count', 2 do
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 1,
|
|
:subject => 'This is a new issue with watchers',
|
|
:description => 'This is the description',
|
|
:priority_id => 5,
|
|
:watcher_user_ids => ['2', '3']}
|
|
end
|
|
issue = Issue.find_by_subject('This is a new issue with watchers')
|
|
assert_not_nil issue
|
|
assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
|
|
|
|
# Watchers added
|
|
assert_equal [2, 3], issue.watcher_user_ids.sort
|
|
assert issue.watched_by?(User.find(3))
|
|
# Watchers notified
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert_kind_of TMail::Mail, mail
|
|
assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
|
|
end
|
|
|
|
def test_post_new_should_send_a_notification
|
|
ActionMailer::Base.deliveries.clear
|
|
@request.session[:user_id] = 2
|
|
assert_difference 'Issue.count' do
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 3,
|
|
:subject => 'This is the test_new issue',
|
|
:description => 'This is the description',
|
|
:priority_id => 5,
|
|
:estimated_hours => '',
|
|
:custom_field_values => {'2' => 'Value for field 2'}}
|
|
end
|
|
assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
|
|
|
|
assert_equal 1, ActionMailer::Base.deliveries.size
|
|
end
|
|
|
|
def test_post_should_preserve_fields_values_on_validation_failure
|
|
@request.session[:user_id] = 2
|
|
post :new, :project_id => 1,
|
|
:issue => {:tracker_id => 1,
|
|
# empty subject
|
|
:subject => '',
|
|
:description => 'This is a description',
|
|
:priority_id => 6,
|
|
:custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
|
|
assert_response :success
|
|
assert_template 'new'
|
|
|
|
assert_tag :textarea, :attributes => { :name => 'issue[description]' },
|
|
:content => 'This is a description'
|
|
assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
|
|
:child => { :tag => 'option', :attributes => { :selected => 'selected',
|
|
:value => '6' },
|
|
:content => 'High' }
|
|
# Custom fields
|
|
assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
|
|
:child => { :tag => 'option', :attributes => { :selected => 'selected',
|
|
:value => 'Oracle' },
|
|
:content => 'Oracle' }
|
|
assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
|
|
:value => 'Value for field 2'}
|
|
end
|
|
|
|
def test_copy_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/projects/world_domination/issues/567/copy'},
|
|
:controller => 'issues', :action => 'new', :project_id => 'world_domination', :copy_from => '567'
|
|
)
|
|
end
|
|
|
|
def test_copy_issue
|
|
@request.session[:user_id] = 2
|
|
get :new, :project_id => 1, :copy_from => 1
|
|
assert_template 'new'
|
|
assert_not_nil assigns(:issue)
|
|
orig = Issue.find(1)
|
|
assert_equal orig.subject, assigns(:issue).subject
|
|
end
|
|
|
|
def test_edit_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/issues/1/edit'},
|
|
:controller => 'issues', :action => 'edit', :id => '1'
|
|
)
|
|
assert_recognizes( #TODO: use a PUT on the issue URI isntead, need to adjust form
|
|
{:controller => 'issues', :action => 'edit', :id => '1'},
|
|
{:method => :post, :path => '/issues/1/edit'}
|
|
)
|
|
end
|
|
|
|
def test_get_edit
|
|
@request.session[:user_id] = 2
|
|
get :edit, :id => 1
|
|
assert_response :success
|
|
assert_template 'edit'
|
|
assert_not_nil assigns(:issue)
|
|
assert_equal Issue.find(1), assigns(:issue)
|
|
end
|
|
|
|
def test_get_edit_with_params
|
|
@request.session[:user_id] = 2
|
|
get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
|
|
assert_response :success
|
|
assert_template 'edit'
|
|
|
|
issue = assigns(:issue)
|
|
assert_not_nil issue
|
|
|
|
assert_equal 5, issue.status_id
|
|
assert_tag :select, :attributes => { :name => 'issue[status_id]' },
|
|
:child => { :tag => 'option',
|
|
:content => 'Closed',
|
|
:attributes => { :selected => 'selected' } }
|
|
|
|
assert_equal 7, issue.priority_id
|
|
assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
|
|
:child => { :tag => 'option',
|
|
:content => 'Urgent',
|
|
:attributes => { :selected => 'selected' } }
|
|
end
|
|
|
|
def test_reply_routing
|
|
assert_routing(
|
|
{:method => :post, :path => '/issues/1/quoted'},
|
|
:controller => 'issues', :action => 'reply', :id => '1'
|
|
)
|
|
end
|
|
|
|
def test_reply_to_issue
|
|
@request.session[:user_id] = 2
|
|
get :reply, :id => 1
|
|
assert_response :success
|
|
assert_select_rjs :show, "update"
|
|
end
|
|
|
|
def test_reply_to_note
|
|
@request.session[:user_id] = 2
|
|
get :reply, :id => 1, :journal_id => 2
|
|
assert_response :success
|
|
assert_select_rjs :show, "update"
|
|
end
|
|
|
|
def test_post_edit_without_custom_fields_param
|
|
@request.session[:user_id] = 2
|
|
ActionMailer::Base.deliveries.clear
|
|
|
|
issue = Issue.find(1)
|
|
assert_equal '125', issue.custom_value_for(2).value
|
|
old_subject = issue.subject
|
|
new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
|
|
|
|
assert_difference('Journal.count') do
|
|
assert_difference('JournalDetail.count', 2) do
|
|
post :edit, :id => 1, :issue => {:subject => new_subject,
|
|
:priority_id => '6',
|
|
:category_id => '1' # no change
|
|
}
|
|
end
|
|
end
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
issue.reload
|
|
assert_equal new_subject, issue.subject
|
|
# Make sure custom fields were not cleared
|
|
assert_equal '125', issue.custom_value_for(2).value
|
|
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert_kind_of TMail::Mail, mail
|
|
assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
|
|
assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
|
|
end
|
|
|
|
def test_post_edit_with_custom_field_change
|
|
@request.session[:user_id] = 2
|
|
issue = Issue.find(1)
|
|
assert_equal '125', issue.custom_value_for(2).value
|
|
|
|
assert_difference('Journal.count') do
|
|
assert_difference('JournalDetail.count', 3) do
|
|
post :edit, :id => 1, :issue => {:subject => 'Custom field change',
|
|
:priority_id => '6',
|
|
:category_id => '1', # no change
|
|
:custom_field_values => { '2' => 'New custom value' }
|
|
}
|
|
end
|
|
end
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
issue.reload
|
|
assert_equal 'New custom value', issue.custom_value_for(2).value
|
|
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert_kind_of TMail::Mail, mail
|
|
assert mail.body.include?("Searchable field changed from 125 to New custom value")
|
|
end
|
|
|
|
def test_post_edit_with_status_and_assignee_change
|
|
issue = Issue.find(1)
|
|
assert_equal 1, issue.status_id
|
|
@request.session[:user_id] = 2
|
|
assert_difference('TimeEntry.count', 0) do
|
|
post :edit,
|
|
:id => 1,
|
|
:issue => { :status_id => 2, :assigned_to_id => 3 },
|
|
:notes => 'Assigned to dlopper',
|
|
:time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
|
|
end
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
issue.reload
|
|
assert_equal 2, issue.status_id
|
|
j = issue.journals.find(:first, :order => 'id DESC')
|
|
assert_equal 'Assigned to dlopper', j.notes
|
|
assert_equal 2, j.details.size
|
|
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert mail.body.include?("Status changed from New to Assigned")
|
|
# subject should contain the new status
|
|
assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
|
|
end
|
|
|
|
def test_post_edit_with_note_only
|
|
notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
|
|
# anonymous user
|
|
post :edit,
|
|
:id => 1,
|
|
:notes => notes
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
j = Issue.find(1).journals.find(:first, :order => 'id DESC')
|
|
assert_equal notes, j.notes
|
|
assert_equal 0, j.details.size
|
|
assert_equal User.anonymous, j.user
|
|
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert mail.body.include?(notes)
|
|
end
|
|
|
|
def test_post_edit_with_note_and_spent_time
|
|
@request.session[:user_id] = 2
|
|
spent_hours_before = Issue.find(1).spent_hours
|
|
assert_difference('TimeEntry.count') do
|
|
post :edit,
|
|
:id => 1,
|
|
:notes => '2.5 hours added',
|
|
:time_entry => { :hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first }
|
|
end
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
|
|
issue = Issue.find(1)
|
|
|
|
j = issue.journals.find(:first, :order => 'id DESC')
|
|
assert_equal '2.5 hours added', j.notes
|
|
assert_equal 0, j.details.size
|
|
|
|
t = issue.time_entries.find(:first, :order => 'id DESC')
|
|
assert_not_nil t
|
|
assert_equal 2.5, t.hours
|
|
assert_equal spent_hours_before + 2.5, issue.spent_hours
|
|
end
|
|
|
|
def test_post_edit_with_attachment_only
|
|
set_tmp_attachments_directory
|
|
|
|
# Delete all fixtured journals, a race condition can occur causing the wrong
|
|
# journal to get fetched in the next find.
|
|
Journal.delete_all
|
|
|
|
# anonymous user
|
|
post :edit,
|
|
:id => 1,
|
|
:notes => '',
|
|
:attachments => {'1' => {'file' => test_uploaded_file('testfile.txt', 'text/plain')}}
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
j = Issue.find(1).journals.find(:first, :order => 'id DESC')
|
|
assert j.notes.blank?
|
|
assert_equal 1, j.details.size
|
|
assert_equal 'testfile.txt', j.details.first.value
|
|
assert_equal User.anonymous, j.user
|
|
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert mail.body.include?('testfile.txt')
|
|
end
|
|
|
|
def test_post_edit_with_no_change
|
|
issue = Issue.find(1)
|
|
issue.journals.clear
|
|
ActionMailer::Base.deliveries.clear
|
|
|
|
post :edit,
|
|
:id => 1,
|
|
:notes => ''
|
|
assert_redirected_to :action => 'show', :id => '1'
|
|
|
|
issue.reload
|
|
assert issue.journals.empty?
|
|
# No email should be sent
|
|
assert ActionMailer::Base.deliveries.empty?
|
|
end
|
|
|
|
def test_post_edit_should_send_a_notification
|
|
@request.session[:user_id] = 2
|
|
ActionMailer::Base.deliveries.clear
|
|
issue = Issue.find(1)
|
|
old_subject = issue.subject
|
|
new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
|
|
|
|
post :edit, :id => 1, :issue => {:subject => new_subject,
|
|
:priority_id => '6',
|
|
:category_id => '1' # no change
|
|
}
|
|
assert_equal 1, ActionMailer::Base.deliveries.size
|
|
end
|
|
|
|
def test_post_edit_with_invalid_spent_time
|
|
@request.session[:user_id] = 2
|
|
notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
|
|
|
|
assert_no_difference('Journal.count') do
|
|
post :edit,
|
|
:id => 1,
|
|
:notes => notes,
|
|
:time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
|
|
end
|
|
assert_response :success
|
|
assert_template 'edit'
|
|
|
|
assert_tag :textarea, :attributes => { :name => 'notes' },
|
|
:content => notes
|
|
assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
|
|
end
|
|
|
|
def test_get_bulk_edit
|
|
@request.session[:user_id] = 2
|
|
get :bulk_edit, :ids => [1, 2]
|
|
assert_response :success
|
|
assert_template 'bulk_edit'
|
|
end
|
|
|
|
def test_bulk_edit
|
|
@request.session[:user_id] = 2
|
|
# update issues priority
|
|
post :bulk_edit, :ids => [1, 2], :priority_id => 7,
|
|
:assigned_to_id => '',
|
|
:custom_field_values => {'2' => ''},
|
|
:notes => 'Bulk editing'
|
|
assert_response 302
|
|
# check that the issues were updated
|
|
assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
|
|
|
|
issue = Issue.find(1)
|
|
journal = issue.journals.find(:first, :order => 'created_on DESC')
|
|
assert_equal '125', issue.custom_value_for(2).value
|
|
assert_equal 'Bulk editing', journal.notes
|
|
assert_equal 1, journal.details.size
|
|
end
|
|
|
|
def test_bullk_edit_should_send_a_notification
|
|
@request.session[:user_id] = 2
|
|
ActionMailer::Base.deliveries.clear
|
|
post(:bulk_edit,
|
|
{
|
|
:ids => [1, 2],
|
|
:priority_id => 7,
|
|
:assigned_to_id => '',
|
|
:custom_field_values => {'2' => ''},
|
|
:notes => 'Bulk editing'
|
|
})
|
|
|
|
assert_response 302
|
|
assert_equal 2, ActionMailer::Base.deliveries.size
|
|
end
|
|
|
|
def test_bulk_edit_status
|
|
@request.session[:user_id] = 2
|
|
# update issues priority
|
|
post :bulk_edit, :ids => [1, 2], :priority_id => '',
|
|
:assigned_to_id => '',
|
|
:status_id => '5',
|
|
:notes => 'Bulk editing status'
|
|
assert_response 302
|
|
issue = Issue.find(1)
|
|
assert issue.closed?
|
|
end
|
|
|
|
def test_bulk_edit_custom_field
|
|
@request.session[:user_id] = 2
|
|
# update issues priority
|
|
post :bulk_edit, :ids => [1, 2], :priority_id => '',
|
|
:assigned_to_id => '',
|
|
:custom_field_values => {'2' => '777'},
|
|
:notes => 'Bulk editing custom field'
|
|
assert_response 302
|
|
|
|
issue = Issue.find(1)
|
|
journal = issue.journals.find(:first, :order => 'created_on DESC')
|
|
assert_equal '777', issue.custom_value_for(2).value
|
|
assert_equal 1, journal.details.size
|
|
assert_equal '125', journal.details.first.old_value
|
|
assert_equal '777', journal.details.first.value
|
|
end
|
|
|
|
def test_bulk_unassign
|
|
assert_not_nil Issue.find(2).assigned_to
|
|
@request.session[:user_id] = 2
|
|
# unassign issues
|
|
post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :assigned_to_id => 'none'
|
|
assert_response 302
|
|
# check that the issues were updated
|
|
assert_nil Issue.find(2).assigned_to
|
|
end
|
|
|
|
def test_move_routing
|
|
assert_routing(
|
|
{:method => :get, :path => '/issues/1/move'},
|
|
:controller => 'issues', :action => 'move', :id => '1'
|
|
)
|
|
assert_recognizes(
|
|
{:controller => 'issues', :action => 'move', :id => '1'},
|
|
{:method => :post, :path => '/issues/1/move'}
|
|
)
|
|
end
|
|
|
|
def test_move_one_issue_to_another_project
|
|
@request.session[:user_id] = 2
|
|
post :move, :id => 1, :new_project_id => 2
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
assert_equal 2, Issue.find(1).project_id
|
|
end
|
|
|
|
def test_bulk_move_to_another_project
|
|
@request.session[:user_id] = 2
|
|
post :move, :ids => [1, 2], :new_project_id => 2
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
# Issues moved to project 2
|
|
assert_equal 2, Issue.find(1).project_id
|
|
assert_equal 2, Issue.find(2).project_id
|
|
# No tracker change
|
|
assert_equal 1, Issue.find(1).tracker_id
|
|
assert_equal 2, Issue.find(2).tracker_id
|
|
end
|
|
|
|
def test_bulk_move_to_another_tracker
|
|
@request.session[:user_id] = 2
|
|
post :move, :ids => [1, 2], :new_tracker_id => 2
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
assert_equal 2, Issue.find(1).tracker_id
|
|
assert_equal 2, Issue.find(2).tracker_id
|
|
end
|
|
|
|
def test_bulk_copy_to_another_project
|
|
@request.session[:user_id] = 2
|
|
assert_difference 'Issue.count', 2 do
|
|
assert_no_difference 'Project.find(1).issues.count' do
|
|
post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}
|
|
end
|
|
end
|
|
assert_redirected_to 'projects/ecookbook/issues'
|
|
end
|
|
|
|
def test_context_menu_one_issue
|
|
@request.session[:user_id] = 2
|
|
get :context_menu, :ids => [1]
|
|
assert_response :success
|
|
assert_template 'context_menu'
|
|
assert_tag :tag => 'a', :content => 'Edit',
|
|
:attributes => { :href => '/issues/1/edit',
|
|
:class => 'icon-edit' }
|
|
assert_tag :tag => 'a', :content => 'Closed',
|
|
:attributes => { :href => '/issues/1/edit?issue%5Bstatus_id%5D=5',
|
|
:class => '' }
|
|
assert_tag :tag => 'a', :content => 'Immediate',
|
|
:attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&priority_id=8',
|
|
:class => '' }
|
|
assert_tag :tag => 'a', :content => 'Dave Lopper',
|
|
:attributes => { :href => '/issues/bulk_edit?assigned_to_id=3&ids%5B%5D=1',
|
|
:class => '' }
|
|
assert_tag :tag => 'a', :content => 'Copy',
|
|
:attributes => { :href => '/projects/ecookbook/issues/1/copy',
|
|
:class => 'icon-copy' }
|
|
assert_tag :tag => 'a', :content => 'Move',
|
|
:attributes => { :href => '/issues/move?ids%5B%5D=1',
|
|
:class => 'icon-move' }
|
|
assert_tag :tag => 'a', :content => 'Delete',
|
|
:attributes => { :href => '/issues/destroy?ids%5B%5D=1',
|
|
:class => 'icon-del' }
|
|
end
|
|
|
|
def test_context_menu_one_issue_by_anonymous
|
|
get :context_menu, :ids => [1]
|
|
assert_response :success
|
|
assert_template 'context_menu'
|
|
assert_tag :tag => 'a', :content => 'Delete',
|
|
:attributes => { :href => '#',
|
|
:class => 'icon-del disabled' }
|
|
end
|
|
|
|
def test_context_menu_multiple_issues_of_same_project
|
|
@request.session[:user_id] = 2
|
|
get :context_menu, :ids => [1, 2]
|
|
assert_response :success
|
|
assert_template 'context_menu'
|
|
assert_tag :tag => 'a', :content => 'Edit',
|
|
:attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2',
|
|
:class => 'icon-edit' }
|
|
assert_tag :tag => 'a', :content => 'Immediate',
|
|
:attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2&priority_id=8',
|
|
:class => '' }
|
|
assert_tag :tag => 'a', :content => 'Dave Lopper',
|
|
:attributes => { :href => '/issues/bulk_edit?assigned_to_id=3&ids%5B%5D=1&ids%5B%5D=2',
|
|
:class => '' }
|
|
assert_tag :tag => 'a', :content => 'Move',
|
|
:attributes => { :href => '/issues/move?ids%5B%5D=1&ids%5B%5D=2',
|
|
:class => 'icon-move' }
|
|
assert_tag :tag => 'a', :content => 'Delete',
|
|
:attributes => { :href => '/issues/destroy?ids%5B%5D=1&ids%5B%5D=2',
|
|
:class => 'icon-del' }
|
|
end
|
|
|
|
def test_context_menu_multiple_issues_of_different_project
|
|
@request.session[:user_id] = 2
|
|
get :context_menu, :ids => [1, 2, 4]
|
|
assert_response :success
|
|
assert_template 'context_menu'
|
|
assert_tag :tag => 'a', :content => 'Delete',
|
|
:attributes => { :href => '#',
|
|
:class => 'icon-del disabled' }
|
|
end
|
|
|
|
def test_destroy_routing
|
|
assert_recognizes( #TODO: use DELETE on issue URI (need to change forms)
|
|
{:controller => 'issues', :action => 'destroy', :id => '1'},
|
|
{:method => :post, :path => '/issues/1/destroy'}
|
|
)
|
|
end
|
|
|
|
def test_destroy_issue_with_no_time_entries
|
|
assert_nil TimeEntry.find_by_issue_id(2)
|
|
@request.session[:user_id] = 2
|
|
post :destroy, :id => 2
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
assert_nil Issue.find_by_id(2)
|
|
end
|
|
|
|
def test_destroy_issues_with_time_entries
|
|
@request.session[:user_id] = 2
|
|
post :destroy, :ids => [1, 3]
|
|
assert_response :success
|
|
assert_template 'destroy'
|
|
assert_not_nil assigns(:hours)
|
|
assert Issue.find_by_id(1) && Issue.find_by_id(3)
|
|
end
|
|
|
|
def test_destroy_issues_and_destroy_time_entries
|
|
@request.session[:user_id] = 2
|
|
post :destroy, :ids => [1, 3], :todo => 'destroy'
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
|
|
assert_nil TimeEntry.find_by_id([1, 2])
|
|
end
|
|
|
|
def test_destroy_issues_and_assign_time_entries_to_project
|
|
@request.session[:user_id] = 2
|
|
post :destroy, :ids => [1, 3], :todo => 'nullify'
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
|
|
assert_nil TimeEntry.find(1).issue_id
|
|
assert_nil TimeEntry.find(2).issue_id
|
|
end
|
|
|
|
def test_destroy_issues_and_reassign_time_entries_to_another_issue
|
|
@request.session[:user_id] = 2
|
|
post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
|
|
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
|
assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
|
|
assert_equal 2, TimeEntry.find(1).issue_id
|
|
assert_equal 2, TimeEntry.find(2).issue_id
|
|
end
|
|
end
|