Mercurial > hg > soundsoftware-site
view test/functional/issues_controller_test.rb @ 1082:997f6d7738f7 bug_531
In repo controller entry action, show the page for the file even if it's binary (so user still has access to history etc links). This makes it possible to use the entry action as the default when a file is clicked on
author | Chris Cannam <chris.cannam@soundsoftware.ac.uk> |
---|---|
date | Thu, 22 Nov 2012 18:04:17 +0000 |
parents | 5f33065ddc4b |
children | 433d4f72a19b |
line wrap: on
line source
# Redmine - project management software # Copyright (C) 2006-2011 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.expand_path('../../test_helper', __FILE__) require 'issues_controller' 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_projects, :custom_fields_trackers, :time_entries, :journals, :journal_details, :queries include Redmine::I18n def setup @controller = IssuesController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new User.current = nil end def test_index Setting.default_language = 'en' get :index assert_response :success assert_template 'index' 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' 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_should_list_visible_issues_only get :index, :per_page => 100 assert_response :success assert_not_nil assigns(:issues) assert_nil assigns(:issues).detect {|issue| !issue.visible?} end def test_index_with_project Setting.display_subprojects_issues = 0 get :index, :project_id => 1 assert_response :success assert_template 'index' 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' 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' 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_and_default_filter get :index, :project_id => 1, :set_filter => 1 assert_response :success assert_template 'index' assert_not_nil assigns(:issues) query = assigns(:query) assert_not_nil query # default filter assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters) end def test_index_with_project_and_filter get :index, :project_id => 1, :set_filter => 1, :f => ['tracker_id'], :op => {'tracker_id' => '='}, :v => {'tracker_id' => ['1']} assert_response :success assert_template 'index' assert_not_nil assigns(:issues) query = assigns(:query) assert_not_nil query assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters) end def test_index_with_short_filters to_test = { 'status_id' => { 'o' => { :op => 'o', :values => [''] }, 'c' => { :op => 'c', :values => [''] }, '7' => { :op => '=', :values => ['7'] }, '7|3|4' => { :op => '=', :values => ['7', '3', '4'] }, '=7' => { :op => '=', :values => ['7'] }, '!3' => { :op => '!', :values => ['3'] }, '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }}, 'subject' => { 'This is a subject' => { :op => '=', :values => ['This is a subject'] }, 'o' => { :op => '=', :values => ['o'] }, '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] }, '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }}, 'tracker_id' => { '3' => { :op => '=', :values => ['3'] }, '=3' => { :op => '=', :values => ['3'] }}, 'start_date' => { '2011-10-12' => { :op => '=', :values => ['2011-10-12'] }, '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] }, '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] }, '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] }, '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] }, '<t+2' => { :op => '<t+', :values => ['2'] }, '>t+2' => { :op => '>t+', :values => ['2'] }, 't+2' => { :op => 't+', :values => ['2'] }, 't' => { :op => 't', :values => [''] }, 'w' => { :op => 'w', :values => [''] }, '>t-2' => { :op => '>t-', :values => ['2'] }, '<t-2' => { :op => '<t-', :values => ['2'] }, 't-2' => { :op => 't-', :values => ['2'] }}, 'created_on' => { '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] }, '<t-2' => { :op => '<t-', :values => ['2'] }, '>t-2' => { :op => '>t-', :values => ['2'] }, 't-2' => { :op => 't-', :values => ['2'] }}, 'cf_1' => { 'c' => { :op => '=', :values => ['c'] }, '!c' => { :op => '!', :values => ['c'] }, '!*' => { :op => '!*', :values => [''] }, '*' => { :op => '*', :values => [''] }}, 'estimated_hours' => { '=13.4' => { :op => '=', :values => ['13.4'] }, '>=45' => { :op => '>=', :values => ['45'] }, '<=125' => { :op => '<=', :values => ['125'] }, '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] }, '!*' => { :op => '!*', :values => [''] }, '*' => { :op => '*', :values => [''] }} } default_filter = { 'status_id' => {:operator => 'o', :values => [''] }} to_test.each do |field, expression_and_expected| expression_and_expected.each do |filter_expression, expected| get :index, :set_filter => 1, field => filter_expression assert_response :success assert_template 'index' assert_not_nil assigns(:issues) query = assigns(:query) assert_not_nil query assert query.has_filter?(field) assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters) end end end def test_index_with_project_and_empty_filters get :index, :project_id => 1, :set_filter => 1, :fields => [''] assert_response :success assert_template 'index' assert_not_nil assigns(:issues) query = assigns(:query) assert_not_nil query # no filter assert_equal({}, query.filters) end def test_index_with_query get :index, :project_id => 1, :query_id => 5 assert_response :success assert_template 'index' assert_not_nil assigns(:issues) assert_nil assigns(:issue_count_by_group) end def test_index_with_query_grouped_by_tracker get :index, :project_id => 1, :query_id => 6 assert_response :success assert_template 'index' assert_not_nil assigns(:issues) assert_not_nil assigns(:issue_count_by_group) end def test_index_with_query_grouped_by_list_custom_field get :index, :project_id => 1, :query_id => 9 assert_response :success assert_template 'index' assert_not_nil assigns(:issues) assert_not_nil assigns(:issue_count_by_group) end def test_index_with_query_id_and_project_id_should_set_session_query get :index, :project_id => 1, :query_id => 4 assert_response :success assert_kind_of Hash, session[:query] assert_equal 4, session[:query][:id] assert_equal 1, session[:query][:project_id] end def test_index_with_cross_project_query_in_session_should_show_project_issues q = Query.create!(:name => "test", :user_id => 2, :is_public => false, :project => nil) @request.session[:query] = {:id => q.id, :project_id => 1} with_settings :display_subprojects_issues => '0' do get :index, :project_id => 1 end assert_response :success assert_not_nil assigns(:query) assert_equal q.id, assigns(:query).id assert_equal 1, assigns(:query).project_id assert_equal [1], assigns(:issues).map(&:project_id).uniq end def test_private_query_should_not_be_available_to_other_users q = Query.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil) @request.session[:user_id] = 3 get :index, :query_id => q.id assert_response 403 end def test_private_query_should_be_available_to_its_user q = Query.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil) @request.session[:user_id] = 2 get :index, :query_id => q.id assert_response :success end def test_public_query_should_be_available_to_other_users q = Query.create!(:name => "private", :user => User.find(2), :is_public => true, :project => nil) @request.session[:user_id] = 3 get :index, :query_id => q.id assert_response :success end def test_index_csv get :index, :format => 'csv' assert_response :success assert_not_nil assigns(:issues) assert_equal 'text/csv', @response.content_type assert @response.body.starts_with?("#,") lines = @response.body.chomp.split("\n") assert_equal assigns(:query).columns.size + 1, lines[0].split(',').size end def test_index_csv_with_project 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_csv_with_description get :index, :format => 'csv', :description => '1' assert_response :success assert_not_nil assigns(:issues) assert_equal 'text/csv', @response.content_type assert @response.body.starts_with?("#,") lines = @response.body.chomp.split("\n") assert_equal assigns(:query).columns.size + 2, lines[0].split(',').size end def test_index_csv_with_all_columns get :index, :format => 'csv', :columns => 'all' assert_response :success assert_not_nil assigns(:issues) assert_equal 'text/csv', @response.content_type assert @response.body.starts_with?("#,") lines = @response.body.chomp.split("\n") assert_equal assigns(:query).available_columns.size + 1, lines[0].split(',').size end def test_index_csv_big_5 with_settings :default_language => "zh-TW" do str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88" str_big5 = "\xa4@\xa4\xeb" if str_utf8.respond_to?(:force_encoding) str_utf8.force_encoding('UTF-8') str_big5.force_encoding('Big5') end issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => str_utf8) assert issue.save get :index, :project_id => 1, :f => ['subject'], :op => '=', :values => [str_utf8], :format => 'csv' assert_equal 'text/csv', @response.content_type lines = @response.body.chomp.split("\n") s1 = "\xaa\xac\xbaA" if str_utf8.respond_to?(:force_encoding) s1.force_encoding('Big5') end assert lines[0].include?(s1) assert lines[1].include?(str_big5) end end def test_index_csv_cannot_convert_should_be_replaced_big_5 with_settings :default_language => "zh-TW" do str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85" if str_utf8.respond_to?(:force_encoding) str_utf8.force_encoding('UTF-8') end issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => str_utf8) assert issue.save get :index, :project_id => 1, :f => ['subject'], :op => '=', :values => [str_utf8], :c => ['status', 'subject'], :format => 'csv', :set_filter => 1 assert_equal 'text/csv', @response.content_type lines = @response.body.chomp.split("\n") s1 = "\xaa\xac\xbaA" # status if str_utf8.respond_to?(:force_encoding) s1.force_encoding('Big5') end assert lines[0].include?(s1) s2 = lines[1].split(",")[2] if s1.respond_to?(:force_encoding) s3 = "\xa5H?" # subject s3.force_encoding('Big5') assert_equal s3, s2 elsif RUBY_PLATFORM == 'java' assert_equal "??", s2 else assert_equal "\xa5H???", s2 end end end def test_index_csv_tw with_settings :default_language => "zh-TW" do str1 = "test_index_csv_tw" issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => str1, :estimated_hours => '1234.5') assert issue.save assert_equal 1234.5, issue.estimated_hours get :index, :project_id => 1, :f => ['subject'], :op => '=', :values => [str1], :c => ['estimated_hours', 'subject'], :format => 'csv', :set_filter => 1 assert_equal 'text/csv', @response.content_type lines = @response.body.chomp.split("\n") assert_equal "#{issue.id},1234.5,#{str1}", lines[1] str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)" if str_tw.respond_to?(:force_encoding) str_tw.force_encoding('UTF-8') end assert_equal str_tw, l(:general_lang_name) assert_equal ',', l(:general_csv_separator) assert_equal '.', l(:general_csv_decimal_separator) end end def test_index_csv_fr with_settings :default_language => "fr" do str1 = "test_index_csv_fr" issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => str1, :estimated_hours => '1234.5') assert issue.save assert_equal 1234.5, issue.estimated_hours get :index, :project_id => 1, :f => ['subject'], :op => '=', :values => [str1], :c => ['estimated_hours', 'subject'], :format => 'csv', :set_filter => 1 assert_equal 'text/csv', @response.content_type lines = @response.body.chomp.split("\n") assert_equal "#{issue.id};1234,5;#{str1}", lines[1] str_fr = "Fran\xc3\xa7ais" if str_fr.respond_to?(:force_encoding) str_fr.force_encoding('UTF-8') end assert_equal str_fr, l(:general_lang_name) assert_equal ';', l(:general_csv_separator) assert_equal ',', l(:general_csv_decimal_separator) end end def test_index_pdf ["en", "zh", "zh-TW", "ja", "ko"].each do |lang| with_settings :default_language => lang do get :index assert_response :success assert_template 'index' if lang == "ja" if RUBY_PLATFORM != 'java' assert_equal "CP932", l(:general_pdf_encoding) end if RUBY_PLATFORM == 'java' && l(:general_pdf_encoding) == "CP932" next end end 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 end end def test_index_pdf_with_query_grouped_by_list_custom_field get :index, :project_id => 1, :query_id => 9, :format => 'pdf' assert_response :success assert_not_nil assigns(:issues) assert_not_nil assigns(:issue_count_by_group) 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_index_sort_by_field_not_included_in_columns Setting.issue_list_default_columns = %w(subject author) get :index, :sort => 'tracker' end def test_index_sort_by_assigned_to get :index, :sort => 'assigned_to' assert_response :success assignees = assigns(:issues).collect(&:assigned_to).compact assert_equal assignees.sort, assignees end def test_index_sort_by_assigned_to_desc get :index, :sort => 'assigned_to:desc' assert_response :success assignees = assigns(:issues).collect(&:assigned_to).compact assert_equal assignees.sort.reverse, assignees end def test_index_group_by_assigned_to get :index, :group_by => 'assigned_to', :sort => 'priority' assert_response :success end def test_index_sort_by_author get :index, :sort => 'author' assert_response :success authors = assigns(:issues).collect(&:author) assert_equal authors.sort, authors end def test_index_sort_by_author_desc get :index, :sort => 'author:desc' assert_response :success authors = assigns(:issues).collect(&:author) assert_equal authors.sort.reverse, authors end def test_index_group_by_author get :index, :group_by => 'author', :sort => 'priority' assert_response :success end def test_index_with_columns columns = ['tracker', 'subject', 'assigned_to'] get :index, :set_filter => 1, :c => columns assert_response :success # query should use specified columns query = assigns(:query) assert_kind_of Query, query assert_equal columns, query.column_names.map(&:to_s) # columns should be stored in session assert_kind_of Hash, session[:query] assert_kind_of Array, session[:query][:column_names] assert_equal columns, session[:query][:column_names].map(&:to_s) # ensure only these columns are kept in the selected columns list assert_tag :tag => 'select', :attributes => { :id => 'selected_columns' }, :children => { :count => 3 } assert_no_tag :tag => 'option', :attributes => { :value => 'project' }, :parent => { :tag => 'select', :attributes => { :id => "selected_columns" } } end def test_index_without_project_should_implicitly_add_project_column_to_default_columns Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to'] get :index, :set_filter => 1 # query should use specified columns query = assigns(:query) assert_kind_of Query, query assert_equal [:project, :tracker, :subject, :assigned_to], query.columns.map(&:name) end def test_index_without_project_and_explicit_default_columns_should_not_add_project_column Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to'] columns = ['tracker', 'subject', 'assigned_to'] get :index, :set_filter => 1, :c => columns # query should use specified columns query = assigns(:query) assert_kind_of Query, query assert_equal columns.map(&:to_sym), query.columns.map(&:name) end def test_index_with_custom_field_column columns = %w(tracker subject cf_2) get :index, :set_filter => 1, :c => columns assert_response :success # query should use specified columns query = assigns(:query) assert_kind_of Query, query assert_equal columns, query.column_names.map(&:to_s) assert_tag :td, :attributes => {:class => 'cf_2 string'}, :ancestor => {:tag => 'table', :attributes => {:class => /issues/}} end def test_index_with_date_column Issue.find(1).update_attribute :start_date, '1987-08-24' with_settings :date_format => '%d/%m/%Y' do get :index, :set_filter => 1, :c => %w(start_date) assert_tag 'td', :attributes => {:class => /start_date/}, :content => '24/08/1987' end end def test_index_with_done_ratio Issue.find(1).update_attribute :done_ratio, 40 get :index, :set_filter => 1, :c => %w(done_ratio) assert_tag 'td', :attributes => {:class => /done_ratio/}, :child => {:tag => 'table', :attributes => {:class => 'progress'}, :descendant => {:tag => 'td', :attributes => {:class => 'closed', :style => 'width: 40%;'}} } end def test_index_with_fixed_version get :index, :set_filter => 1, :c => %w(fixed_version) assert_tag 'td', :attributes => {:class => /fixed_version/}, :child => {:tag => 'a', :content => '1.0', :attributes => {:href => '/versions/2'}} end def test_index_send_html_if_query_is_invalid get :index, :f => ['start_date'], :op => {:start_date => '='} assert_equal 'text/html', @response.content_type assert_template 'index' end def test_index_send_nothing_if_query_is_invalid get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv' assert_equal 'text/csv', @response.content_type assert @response.body.blank? end def test_show_by_anonymous get :show, :id => 1 assert_response :success assert_template 'show' 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/ } } assert_tag :tag => 'title', :content => "Bug #1: Can't print recipes - eCookbook - Redmine" end def test_show_by_manager @request.session[:user_id] = 2 get :show, :id => 1 assert_response :success assert_tag :tag => 'a', :content => /Quote/ 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_update_form_should_not_display_inactive_enumerations @request.session[:user_id] = 2 get :show, :id => 1 assert_response :success assert ! IssuePriority.find(15).active? assert_no_tag :option, :attributes => {:value => '15'}, :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} } end def test_update_form_should_allow_attachment_upload @request.session[:user_id] = 2 get :show, :id => 1 assert_tag :tag => 'form', :attributes => {:id => 'issue-form', :method => 'post', :enctype => 'multipart/form-data'}, :descendant => { :tag => 'input', :attributes => {:type => 'file', :name => 'attachments[1][file]'} } end def test_show_should_deny_anonymous_access_without_permission Role.anonymous.remove_permission!(:view_issues) get :show, :id => 1 assert_response :redirect end def test_show_should_deny_anonymous_access_to_private_issue Issue.update_all(["is_private = ?", true], "id = 1") get :show, :id => 1 assert_response :redirect end def test_show_should_deny_non_member_access_without_permission Role.non_member.remove_permission!(:view_issues) @request.session[:user_id] = 9 get :show, :id => 1 assert_response 403 end def test_show_should_deny_non_member_access_to_private_issue Issue.update_all(["is_private = ?", true], "id = 1") @request.session[:user_id] = 9 get :show, :id => 1 assert_response 403 end def test_show_should_deny_member_access_without_permission Role.find(1).remove_permission!(:view_issues) @request.session[:user_id] = 2 get :show, :id => 1 assert_response 403 end def test_show_should_deny_member_access_to_private_issue_without_permission Issue.update_all(["is_private = ?", true], "id = 1") @request.session[:user_id] = 3 get :show, :id => 1 assert_response 403 end def test_show_should_allow_author_access_to_private_issue Issue.update_all(["is_private = ?, author_id = 3", true], "id = 1") @request.session[:user_id] = 3 get :show, :id => 1 assert_response :success end def test_show_should_allow_assignee_access_to_private_issue Issue.update_all(["is_private = ?, assigned_to_id = 3", true], "id = 1") @request.session[:user_id] = 3 get :show, :id => 1 assert_response :success end def test_show_should_allow_member_access_to_private_issue_with_permission Issue.update_all(["is_private = ?", true], "id = 1") User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all' @request.session[:user_id] = 3 get :show, :id => 1 assert_response :success 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 'journals/index' # Inline image assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10')) 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' } # Be sure we don't display inactive IssuePriorities assert ! IssuePriority.find(15).active? assert_no_tag :option, :attributes => {:value => '15'}, :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} } end def test_get_new_without_default_start_date_is_creation_date Setting.default_issue_start_date_to_creation_date = 0 @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[start_date]', :value => nil } end def test_get_new_with_default_start_date_is_creation_date Setting.default_issue_start_date_to_creation_date = 1 @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[start_date]', :value => Date.today.to_s } end def test_get_new_form_should_allow_attachment_upload @request.session[:user_id] = 2 get :new, :project_id => 1, :tracker_id => 1 assert_tag :tag => 'form', :attributes => {:id => 'issue-form', :method => 'post', :enctype => 'multipart/form-data'}, :descendant => { :tag => 'input', :attributes => {:type => 'file', :name => 'attachments[1][file]'} } 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_error_tag :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_error_tag :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 'attributes' issue = assigns(:issue) assert_kind_of Issue, issue assert_equal 1, issue.project_id assert_equal 2, issue.tracker_id assert_equal 'This is the test_new issue', issue.subject end def test_post_create @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 3, :status_id => 2, :subject => 'This is the test_new issue', :description => 'This is the description', :priority_id => 5, :start_date => '2010-11-07', :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_equal 2, issue.status_id assert_equal Date.parse('2010-11-07'), issue.start_date 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_with_group_assignment group = Group.find(11) project = Project.find(1) project.members << Member.new(:principal => group, :roles => [Role.givable.first]) with_settings :issue_group_assignment => '1' do @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => project.id, :issue => {:tracker_id => 3, :status_id => 1, :subject => 'This is the test_new_with_group_assignment issue', :assigned_to_id => group.id} end end assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue') assert_not_nil issue assert_equal group, issue.assigned_to end def test_post_create_without_start_date_and_default_start_date_is_not_creation_date Setting.default_issue_start_date_to_creation_date = 0 @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 3, :status_id => 2, :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_nil issue.start_date end def test_post_create_without_start_date_and_default_start_date_is_creation_date Setting.default_issue_start_date_to_creation_date = 1 @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 3, :status_id => 2, :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 Date.today, issue.start_date end def test_post_create_and_continue @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5}, :continue => '' end issue = Issue.first(:order => 'id DESC') assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3} assert_not_nil flash[:notice], "flash was not set" assert flash[:notice].include?("<a href='/issues/#{issue.id}'>##{issue.id}</a>"), "issue link not found in flash: #{flash[:notice]}" end def test_post_create_without_custom_fields_param @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :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_create_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 :create, :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_create_with_watchers @request.session[:user_id] = 2 ActionMailer::Base.deliveries.clear assert_difference 'Watcher.count', 2 do post :create, :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_create_subissue @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 1, :subject => 'This is a child issue', :parent_issue_id => 2} end issue = Issue.find_by_subject('This is a child issue') assert_not_nil issue assert_equal Issue.find(2), issue.parent end def test_post_create_subissue_with_non_numeric_parent_id @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 1, :subject => 'This is a child issue', :parent_issue_id => 'ABC'} end issue = Issue.find_by_subject('This is a child issue') assert_not_nil issue assert_nil issue.parent end def test_post_create_private @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 1, :subject => 'This is a private issue', :is_private => '1'} end issue = Issue.first(:order => 'id DESC') assert issue.is_private? end def test_post_create_private_with_set_own_issues_private_permission role = Role.find(1) role.remove_permission! :set_issues_private role.add_permission! :set_own_issues_private @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 1, :subject => 'This is a private issue', :is_private => '1'} end issue = Issue.first(:order => 'id DESC') assert issue.is_private? end def test_post_create_should_send_a_notification ActionMailer::Base.deliveries.clear @request.session[:user_id] = 2 assert_difference 'Issue.count' do post :create, :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_create_should_preserve_fields_values_on_validation_failure @request.session[:user_id] = 2 post :create, :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_post_create_should_ignore_non_safe_attributes @request.session[:user_id] = 2 assert_nothing_raised do post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" } end end def test_post_create_with_attachment set_tmp_attachments_directory @request.session[:user_id] = 2 assert_difference 'Issue.count' do assert_difference 'Attachment.count' do post :create, :project_id => 1, :issue => { :tracker_id => '1', :subject => 'With attachment' }, :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}} end end issue = Issue.first(:order => 'id DESC') attachment = Attachment.first(:order => 'id DESC') assert_equal issue, attachment.container assert_equal 2, attachment.author_id assert_equal 'testfile.txt', attachment.filename assert_equal 'text/plain', attachment.content_type assert_equal 'test file', attachment.description assert_equal 59, attachment.filesize assert File.exists?(attachment.diskfile) assert_equal 59, File.size(attachment.diskfile) end context "without workflow privilege" do setup do Workflow.delete_all(["role_id = ?", Role.anonymous.id]) Role.anonymous.add_permission! :add_issues, :add_issue_notes end context "#new" do should "propose default status only" do get :new, :project_id => 1 assert_response :success assert_template 'new' assert_tag :tag => 'select', :attributes => {:name => 'issue[status_id]'}, :children => {:count => 1}, :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}} end should "accept default status" do assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 1, :subject => 'This is an issue', :status_id => 1} end issue = Issue.last(:order => 'id') assert_equal IssueStatus.default, issue.status end should "ignore unauthorized status" do assert_difference 'Issue.count' do post :create, :project_id => 1, :issue => {:tracker_id => 1, :subject => 'This is an issue', :status_id => 3} end issue = Issue.last(:order => 'id') assert_equal IssueStatus.default, issue.status end end context "#update" do should "ignore status change" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3} end assert_equal 1, Issue.find(1).status_id end should "ignore attributes changes" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2} end issue = Issue.find(1) assert_equal "Can't print recipes", issue.subject assert_nil issue.assigned_to end end end context "with workflow privilege" do setup do Workflow.delete_all(["role_id = ?", Role.anonymous.id]) Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3) Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4) Role.anonymous.add_permission! :add_issues, :add_issue_notes end context "#update" do should "accept authorized status" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3} end assert_equal 3, Issue.find(1).status_id end should "ignore unauthorized status" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2} end assert_equal 1, Issue.find(1).status_id end should "accept authorized attributes changes" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:assigned_to_id => 2} end issue = Issue.find(1) assert_equal 2, issue.assigned_to_id end should "ignore unauthorized attributes changes" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed'} end issue = Issue.find(1) assert_equal "Can't print recipes", issue.subject end end context "and :edit_issues permission" do setup do Role.anonymous.add_permission! :add_issues, :edit_issues end should "accept authorized status" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3} end assert_equal 3, Issue.find(1).status_id end should "ignore unauthorized status" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2} end assert_equal 1, Issue.find(1).status_id end should "accept authorized attributes changes" do assert_difference 'Journal.count' do put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2} end issue = Issue.find(1) assert_equal "changed", issue.subject assert_equal 2, issue.assigned_to_id end end 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_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) # Be sure we don't display inactive IssuePriorities assert ! IssuePriority.find(15).active? assert_no_tag :option, :attributes => {:value => '15'}, :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} } end def test_get_edit_should_display_the_time_entry_form_with_log_time_permission @request.session[:user_id] = 2 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time] get :edit, :id => 1 assert_tag 'input', :attributes => {:name => 'time_entry[hours]'} end def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission @request.session[:user_id] = 2 Role.find_by_name('Manager').remove_permission! :log_time get :edit, :id => 1 assert_no_tag 'input', :attributes => {:name => 'time_entry[hours]'} end def test_get_edit_with_params @request.session[:user_id] = 2 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }, :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => TimeEntryActivity.first.id } 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' } } assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => '2.5' } assert_tag :select, :attributes => { :name => 'time_entry[activity_id]' }, :child => { :tag => 'option', :attributes => { :selected => 'selected', :value => TimeEntryActivity.first.id } } assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => 'test_get_edit_with_params' } end def test_update_edit_form @request.session[:user_id] = 2 xhr :post, :new, :project_id => 1, :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 'attributes' issue = assigns(:issue) assert_kind_of Issue, issue assert_equal 1, issue.id assert_equal 1, issue.project_id assert_equal 2, issue.tracker_id assert_equal 'This is the test_new issue', issue.subject end def test_update_using_invalid_http_verbs @request.session[:user_id] = 2 subject = 'Updated by an invalid http verb' get :update, :id => 1, :issue => {:subject => subject} assert_not_equal subject, Issue.find(1).subject post :update, :id => 1, :issue => {:subject => subject} assert_not_equal subject, Issue.find(1).subject delete :update, :id => 1, :issue => {:subject => subject} assert_not_equal subject, Issue.find(1).subject end def test_put_update_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 put :update, :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_put_update_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 put :update, :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_put_update_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 put :update, :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 = Journal.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_put_update_with_note_only notes = 'Note added by IssuesControllerTest#test_update_with_note_only' # anonymous user put :update, :id => 1, :notes => notes assert_redirected_to :action => 'show', :id => '1' j = Journal.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_put_update_with_note_and_spent_time @request.session[:user_id] = 2 spent_hours_before = Issue.find(1).spent_hours assert_difference('TimeEntry.count') do put :update, :id => 1, :notes => '2.5 hours added', :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id } end assert_redirected_to :action => 'show', :id => '1' issue = Issue.find(1) j = Journal.find(:first, :order => 'id DESC') assert_equal '2.5 hours added', j.notes assert_equal 0, j.details.size t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time') assert_not_nil t assert_equal 2.5, t.hours assert_equal spent_hours_before + 2.5, issue.spent_hours end def test_put_update_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 assert_difference 'Attachment.count' do put :update, :id => 1, :notes => '', :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}} end 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 attachment = Attachment.first(:order => 'id DESC') assert_equal Issue.find(1), attachment.container assert_equal User.anonymous, attachment.author assert_equal 'testfile.txt', attachment.filename assert_equal 'text/plain', attachment.content_type assert_equal 'test file', attachment.description assert_equal 59, attachment.filesize assert File.exists?(attachment.diskfile) assert_equal 59, File.size(attachment.diskfile) mail = ActionMailer::Base.deliveries.last assert mail.body.include?('testfile.txt') end def test_put_update_with_attachment_that_fails_to_save 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 # Mock out the unsaved attachment Attachment.any_instance.stubs(:create).returns(Attachment.new) # anonymous user put :update, :id => 1, :notes => '', :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} assert_redirected_to :action => 'show', :id => '1' assert_equal '1 file(s) could not be saved.', flash[:warning] end if Object.const_defined?(:Mocha) def test_put_update_with_no_change issue = Issue.find(1) issue.journals.clear ActionMailer::Base.deliveries.clear put :update, :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_put_update_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' put :update, :id => 1, :issue => {:subject => new_subject, :priority_id => '6', :category_id => '1' # no change } assert_equal 1, ActionMailer::Base.deliveries.size end def test_put_update_with_invalid_spent_time_hours_only @request.session[:user_id] = 2 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time' assert_no_difference('Journal.count') do put :update, :id => 1, :notes => notes, :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"} end assert_response :success assert_template 'edit' assert_error_tag :descendant => {:content => /Activity can't be blank/} assert_tag :textarea, :attributes => { :name => 'notes' }, :content => notes assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" } end def test_put_update_with_invalid_spent_time_comments_only @request.session[:user_id] = 2 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time' assert_no_difference('Journal.count') do put :update, :id => 1, :notes => notes, :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""} end assert_response :success assert_template 'edit' assert_error_tag :descendant => {:content => /Activity can't be blank/} assert_error_tag :descendant => {:content => /Hours can't be blank/} assert_tag :textarea, :attributes => { :name => 'notes' }, :content => notes assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => "this is my comment" } end def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject issue = Issue.find(2) @request.session[:user_id] = 2 put :update, :id => issue.id, :issue => { :fixed_version_id => 4 } assert_response :redirect issue.reload assert_equal 4, issue.fixed_version_id assert_not_equal issue.project_id, issue.fixed_version.project_id end def test_put_update_should_redirect_back_using_the_back_url_parameter issue = Issue.find(2) @request.session[:user_id] = 2 put :update, :id => issue.id, :issue => { :fixed_version_id => 4 }, :back_url => '/issues' assert_response :redirect assert_redirected_to '/issues' end def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host issue = Issue.find(2) @request.session[:user_id] = 2 put :update, :id => issue.id, :issue => { :fixed_version_id => 4 }, :back_url => 'http://google.com' assert_response :redirect assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id end def test_get_bulk_edit @request.session[:user_id] = 2 get :bulk_edit, :ids => [1, 2] assert_response :success assert_template 'bulk_edit' assert_tag :input, :attributes => {:name => 'issue[parent_issue_id]'} # Project specific custom field, date type field = CustomField.find(9) assert !field.is_for_all? assert_equal 'date', field.field_format assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'} # System wide custom field assert CustomField.find(1).is_for_all? assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'} # Be sure we don't display inactive IssuePriorities assert ! IssuePriority.find(15).active? assert_no_tag :option, :attributes => {:value => '15'}, :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} } end def test_get_bulk_edit_on_different_projects @request.session[:user_id] = 2 get :bulk_edit, :ids => [1, 2, 6] assert_response :success assert_template 'bulk_edit' # Can not set issues from different projects as children of an issue assert_no_tag :input, :attributes => {:name => 'issue[parent_issue_id]'} # Project specific custom field, date type field = CustomField.find(9) assert !field.is_for_all? assert !field.project_ids.include?(Issue.find(6).project_id) assert_no_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'} end def test_get_bulk_edit_with_user_custom_field field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true) @request.session[:user_id] = 2 get :bulk_edit, :ids => [1, 2] assert_response :success assert_template 'bulk_edit' assert_tag :select, :attributes => {:name => "issue[custom_field_values][#{field.id}]"}, :children => { :only => {:tag => 'option'}, :count => Project.find(1).users.count + 1 } end def test_get_bulk_edit_with_version_custom_field field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true) @request.session[:user_id] = 2 get :bulk_edit, :ids => [1, 2] assert_response :success assert_template 'bulk_edit' assert_tag :select, :attributes => {:name => "issue[custom_field_values][#{field.id}]"}, :children => { :only => {:tag => 'option'}, :count => Project.find(1).shared_versions.count + 1 } end def test_bulk_update @request.session[:user_id] = 2 # update issues priority post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing', :issue => {:priority_id => 7, :assigned_to_id => '', :custom_field_values => {'2' => ''}} 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_bulk_update_with_group_assignee group = Group.find(11) project = Project.find(1) project.members << Member.new(:principal => group, :roles => [Role.givable.first]) @request.session[:user_id] = 2 # update issues assignee post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing', :issue => {:priority_id => '', :assigned_to_id => group.id, :custom_field_values => {'2' => ''}} assert_response 302 assert_equal [group, group], Issue.find_all_by_id([1, 2]).collect {|i| i.assigned_to} end def test_bulk_update_on_different_projects @request.session[:user_id] = 2 # update issues priority post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing', :issue => {:priority_id => 7, :assigned_to_id => '', :custom_field_values => {'2' => ''}} assert_response 302 # check that the issues were updated assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&: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_bulk_update_on_different_projects_without_rights @request.session[:user_id] = 3 user = User.find(3) action = { :controller => "issues", :action => "bulk_update" } assert user.allowed_to?(action, Issue.find(1).project) assert ! user.allowed_to?(action, Issue.find(6).project) post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail', :issue => {:priority_id => 7, :assigned_to_id => '', :custom_field_values => {'2' => ''}} assert_response 403 assert_not_equal "Bulk should fail", Journal.last.notes end def test_bullk_update_should_send_a_notification @request.session[:user_id] = 2 ActionMailer::Base.deliveries.clear post(:bulk_update, { :ids => [1, 2], :notes => 'Bulk editing', :issue => { :priority_id => 7, :assigned_to_id => '', :custom_field_values => {'2' => ''} } }) assert_response 302 assert_equal 2, ActionMailer::Base.deliveries.size end def test_bulk_update_status @request.session[:user_id] = 2 # update issues priority post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status', :issue => {:priority_id => '', :assigned_to_id => '', :status_id => '5'} assert_response 302 issue = Issue.find(1) assert issue.closed? end def test_bulk_update_parent_id @request.session[:user_id] = 2 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing parent', :issue => {:priority_id => '', :assigned_to_id => '', :status_id => '', :parent_issue_id => '2'} assert_response 302 parent = Issue.find(2) assert_equal parent.id, Issue.find(1).parent_id assert_equal parent.id, Issue.find(3).parent_id assert_equal [1, 3], parent.children.collect(&:id).sort end def test_bulk_update_custom_field @request.session[:user_id] = 2 # update issues priority post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field', :issue => {:priority_id => '', :assigned_to_id => '', :custom_field_values => {'2' => '777'}} 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_update_unassign assert_not_nil Issue.find(2).assigned_to @request.session[:user_id] = 2 # unassign issues post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'} assert_response 302 # check that the issues were updated assert_nil Issue.find(2).assigned_to end def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject @request.session[:user_id] = 2 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4} assert_response :redirect issues = Issue.find([1,2]) issues.each do |issue| assert_equal 4, issue.fixed_version_id assert_not_equal issue.project_id, issue.fixed_version.project_id end end def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter @request.session[:user_id] = 2 post :bulk_update, :ids => [1,2], :back_url => '/issues' assert_response :redirect assert_redirected_to '/issues' end def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host @request.session[:user_id] = 2 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com' assert_response :redirect assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier 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 def test_destroy_issues_from_different_projects @request.session[:user_id] = 2 post :destroy, :ids => [1, 2, 6], :todo => 'destroy' assert_redirected_to :controller => 'issues', :action => 'index' assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6)) end def test_destroy_parent_and_child_issues parent = Issue.generate!(:project_id => 1, :tracker_id => 1) child = Issue.generate!(:project_id => 1, :tracker_id => 1, :parent_issue_id => parent.id) assert child.is_descendant_of?(parent.reload) @request.session[:user_id] = 2 assert_difference 'Issue.count', -2 do post :destroy, :ids => [parent.id, child.id], :todo => 'destroy' end assert_response 302 end def test_default_search_scope get :index assert_tag :div, :attributes => {:id => 'quick-search'}, :child => {:tag => 'form', :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}} end end