"Fossies" - the Fresh Open Source Software Archive

Member "redmine-4.1.1/test/functional/issues_controller_test.rb" (6 Apr 2020, 224283 Bytes) of package /linux/www/redmine-4.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "issues_controller_test.rb": 4.1.0_vs_4.1.1.

    1 # frozen_string_literal: true
    2 
    3 # Redmine - project management software
    4 # Copyright (C) 2006-2019  Jean-Philippe Lang
    5 #
    6 # This program is free software; you can redistribute it and/or
    7 # modify it under the terms of the GNU General Public License
    8 # as published by the Free Software Foundation; either version 2
    9 # of the License, or (at your option) any later version.
   10 #
   11 # This program is distributed in the hope that it will be useful,
   12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 # GNU General Public License for more details.
   15 #
   16 # You should have received a copy of the GNU General Public License
   17 # along with this program; if not, write to the Free Software
   18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   19 
   20 require File.expand_path('../../test_helper', __FILE__)
   21 
   22 class IssuesControllerTest < Redmine::ControllerTest
   23   fixtures :projects,
   24            :users, :email_addresses, :user_preferences,
   25            :roles,
   26            :members,
   27            :member_roles,
   28            :issues,
   29            :issue_statuses,
   30            :issue_relations,
   31            :versions,
   32            :trackers,
   33            :projects_trackers,
   34            :issue_categories,
   35            :enabled_modules,
   36            :enumerations,
   37            :attachments,
   38            :workflows,
   39            :custom_fields,
   40            :custom_values,
   41            :custom_fields_projects,
   42            :custom_fields_trackers,
   43            :time_entries,
   44            :journals,
   45            :journal_details,
   46            :queries,
   47            :repositories,
   48            :changesets,
   49            :watchers
   50 
   51   include Redmine::I18n
   52 
   53   def setup
   54     User.current = nil
   55   end
   56 
   57   def test_index
   58     with_settings :default_language => "en" do
   59       get :index
   60       assert_response :success
   61 
   62       # links to visible issues
   63       assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
   64       assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
   65       # private projects hidden
   66       assert_select 'a[href="/issues/6"]', 0
   67       assert_select 'a[href="/issues/4"]', 0
   68       # project column
   69       assert_select 'th', :text => /Project/
   70     end
   71   end
   72 
   73   def test_index_should_not_list_issues_when_module_disabled
   74     EnabledModule.where("name = 'issue_tracking' AND project_id = 1").delete_all
   75     get :index
   76     assert_response :success
   77 
   78     assert_select 'a[href="/issues/1"]', 0
   79     assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
   80   end
   81 
   82   def test_index_should_list_visible_issues_only
   83     get :index, :params => {
   84         :per_page => 100
   85       }
   86     assert_response :success
   87 
   88     Issue.open.each do |issue|
   89       assert_select "tr#issue-#{issue.id}", issue.visible? ? 1 : 0
   90     end
   91   end
   92 
   93   def test_index_with_project
   94     Setting.display_subprojects_issues = 0
   95     get :index, :params => {
   96         :project_id => 1
   97       }
   98     assert_response :success
   99 
  100     # query form
  101     assert_select 'form#query_form' do
  102       assert_select 'div#query_form_with_buttons.hide-when-print' do
  103         assert_select 'div#query_form_content' do
  104           assert_select 'fieldset#filters.collapsible'
  105           assert_select 'fieldset#options'
  106         end
  107         assert_select 'p.buttons'
  108       end
  109     end
  110 
  111     assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  112     assert_select 'a[href="/issues/5"]', 0
  113   end
  114 
  115   def test_index_with_project_and_subprojects
  116     Setting.display_subprojects_issues = 1
  117     get :index, :params => {
  118         :project_id => 1
  119       }
  120     assert_response :success
  121 
  122     assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  123     assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
  124     assert_select 'a[href="/issues/6"]', 0
  125   end
  126 
  127   def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
  128     @request.session[:user_id] = 2
  129     Setting.display_subprojects_issues = 1
  130     get :index, :params => {
  131         :project_id => 1
  132       }
  133     assert_response :success
  134 
  135     assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  136     assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
  137     assert_select 'a[href="/issues/6"]', :text => /Issue of a private subproject/
  138   end
  139 
  140   def test_index_with_project_and_default_filter
  141     get :index, :params => {
  142         :project_id => 1,
  143         :set_filter => 1
  144       }
  145     assert_response :success
  146 
  147     # default filter
  148     assert_query_filters [['status_id', 'o', '']]
  149   end
  150 
  151   def test_index_with_project_and_filter
  152     get :index, :params => {
  153         :project_id => 1,
  154         :set_filter => 1,
  155         :f => ['tracker_id'],
  156         :op => {
  157           'tracker_id' => '='
  158         },
  159         :v => {
  160           'tracker_id' => ['1']
  161         }
  162       }
  163     assert_response :success
  164 
  165     assert_query_filters [['tracker_id', '=', '1']]
  166   end
  167 
  168   def test_index_with_short_filters
  169     to_test = {
  170       'status_id' => {
  171         'o' => { :op => 'o', :values => [''] },
  172         'c' => { :op => 'c', :values => [''] },
  173         '7' => { :op => '=', :values => ['7'] },
  174         '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
  175         '=7' => { :op => '=', :values => ['7'] },
  176         '!3' => { :op => '!', :values => ['3'] },
  177         '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
  178       'subject' => {
  179         'This is a subject' => { :op => '=', :values => ['This is a subject'] },
  180         'o' => { :op => '=', :values => ['o'] },
  181         '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
  182         '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
  183       'tracker_id' => {
  184         '3' => { :op => '=', :values => ['3'] },
  185         '=3' => { :op => '=', :values => ['3'] }},
  186       'start_date' => {
  187         '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
  188         '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
  189         '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
  190         '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
  191         '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
  192         '<t+2' => { :op => '<t+', :values => ['2'] },
  193         '>t+2' => { :op => '>t+', :values => ['2'] },
  194         't+2' => { :op => 't+', :values => ['2'] },
  195         't' => { :op => 't', :values => [''] },
  196         'w' => { :op => 'w', :values => [''] },
  197         '>t-2' => { :op => '>t-', :values => ['2'] },
  198         '<t-2' => { :op => '<t-', :values => ['2'] },
  199         't-2' => { :op => 't-', :values => ['2'] }},
  200       'created_on' => {
  201         '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
  202         '<t-2' => { :op => '<t-', :values => ['2'] },
  203         '>t-2' => { :op => '>t-', :values => ['2'] },
  204         't-2' => { :op => 't-', :values => ['2'] }},
  205       'cf_1' => {
  206         'c' => { :op => '=', :values => ['c'] },
  207         '!c' => { :op => '!', :values => ['c'] },
  208         '!*' => { :op => '!*', :values => [''] },
  209         '*' => { :op => '*', :values => [''] }},
  210       'estimated_hours' => {
  211         '=13.4' => { :op => '=', :values => ['13.4'] },
  212         '>=45' => { :op => '>=', :values => ['45'] },
  213         '<=125' => { :op => '<=', :values => ['125'] },
  214         '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
  215         '!*' => { :op => '!*', :values => [''] },
  216         '*' => { :op => '*', :values => [''] }}
  217     }
  218     default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
  219     to_test.each do |field, expression_and_expected|
  220       expression_and_expected.each do |filter_expression, expected|
  221         get :index, :params => {
  222             :set_filter => 1, field => filter_expression
  223           }
  224         assert_response :success
  225         expected_with_default = default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}})
  226         assert_query_filters expected_with_default.map {|f, v| [f, v[:operator], v[:values]]}
  227       end
  228     end
  229   end
  230 
  231   def test_index_with_project_and_empty_filters
  232     get :index, :params => {
  233         :project_id => 1,
  234         :set_filter => 1,
  235         :fields => ['']
  236       }
  237     assert_response :success
  238 
  239     # no filter
  240     assert_query_filters []
  241   end
  242 
  243   def test_index_with_project_custom_field_filter
  244     field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
  245     CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
  246     CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
  247     filter_name = "project.cf_#{field.id}"
  248     @request.session[:user_id] = 1
  249 
  250     get :index, :params => {
  251         :set_filter => 1,
  252         :f => [filter_name],
  253         :op => {
  254           filter_name => '='
  255         },
  256         :v => {
  257           filter_name => ['Foo']
  258         },
  259         :c => ['project']
  260       }
  261     assert_response :success
  262 
  263     assert_equal [3, 5], issues_in_list.map(&:project_id).uniq.sort
  264   end
  265 
  266   def test_index_with_project_status_filter
  267     project = Project.find(2)
  268     project.close
  269     project.save
  270 
  271     get :index, :params => {
  272         :set_filter => 1,
  273         :f => ['project.status'],
  274         :op => {'project.status' => '='},
  275         :v => {'project.status' => ['1']}
  276       }
  277 
  278     assert_response :success
  279 
  280     issues = issues_in_list.map(&:id).uniq.sort
  281     assert_include 1, issues
  282     assert_not_include 4, issues
  283   end
  284 
  285   def test_index_with_query
  286     get :index, :params => {
  287         :project_id => 1,
  288         :query_id => 5
  289       }
  290     assert_response :success
  291 
  292     assert_select '#sidebar .queries' do
  293       # assert only query is selected in sidebar
  294       assert_select 'a.query.selected', 1
  295       # assert link properties
  296       assert_select 'a.query.selected[href=?]', '/projects/ecookbook/issues?query_id=5', :text => "Open issues by priority and tracker"
  297       # assert only one clear link exists
  298       assert_select 'a.icon-clear-query', 1
  299       # assert clear link properties
  300       assert_select 'a.icon-clear-query[title=?][href=?]', 'Clear', '/projects/ecookbook/issues?set_filter=1&sort=', 1
  301     end
  302   end
  303 
  304   def test_index_with_query_grouped_by_tracker
  305     get :index, :params => {
  306         :project_id => 1,
  307         :query_id => 6
  308       }
  309     assert_response :success
  310     assert_select 'tr.group span.count'
  311   end
  312 
  313   def test_index_with_query_grouped_and_sorted_by_category
  314     get :index, :params => {
  315         :project_id => 1,
  316         :set_filter => 1,
  317         :group_by => "category",
  318         :sort => "category"
  319       }
  320     assert_response :success
  321     assert_select 'tr.group span.count'
  322   end
  323 
  324   def test_index_with_query_grouped_and_sorted_by_fixed_version
  325     get :index, :params => {
  326         :project_id => 1,
  327         :set_filter => 1,
  328         :group_by => "fixed_version",
  329         :sort => "fixed_version"
  330       }
  331     assert_response :success
  332     assert_select 'tr.group span.count'
  333   end
  334 
  335   def test_index_with_query_grouped_and_sorted_by_fixed_version_in_reverse_order
  336     get :index, :params => {
  337         :project_id => 1,
  338         :set_filter => 1,
  339         :group_by => "fixed_version",
  340         :sort => "fixed_version:desc"
  341       }
  342     assert_response :success
  343     assert_select 'tr.group span.count'
  344   end
  345 
  346   def test_index_grouped_by_due_date
  347     set_tmp_attachments_directory
  348     Issue.destroy_all
  349     Issue.generate!(:due_date => '2018-08-10')
  350     Issue.generate!(:due_date => '2018-08-10')
  351     Issue.generate!
  352 
  353     get :index, :params => {
  354         :set_filter => 1,
  355         :group_by => "due_date"
  356       }
  357     assert_response :success
  358     assert_select 'tr.group span.name', :value => '2018-08-10' do
  359       assert_select '~ span.count', :value => '2'
  360     end
  361     assert_select 'tr.group span.name', :value => '(blank)' do
  362       assert_select '~ span.count', :value => '1'
  363     end
  364   end
  365 
  366   def test_index_grouped_by_created_on_if_time_zone_is_utc
  367     # TODO: test fails with mysql
  368     skip if mysql?
  369     skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on}
  370 
  371     @request.session[:user_id] = 2
  372     User.find(2).pref.update(time_zone: 'UTC')
  373 
  374     get :index, :params => {
  375         :set_filter => 1,
  376         :group_by => 'created_on'
  377       }
  378     assert_response :success
  379 
  380     assert_select 'tr.group span.name', :text => '07/19/2006' do
  381       assert_select '+ span.count', :text => '2'
  382     end
  383   end
  384 
  385   def test_index_grouped_by_created_on_if_time_zone_is_nil
  386     skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on}
  387     current_user = User.find(2)
  388     @request.session[:user_id] = current_user.id
  389     current_user.pref.update(time_zone: nil)
  390 
  391     get :index, :params => {
  392         :set_filter => 1,
  393         :group_by => 'created_on'
  394       }
  395     assert_response :success
  396 
  397     # group_name depends on localtime
  398     group_name = format_date(Issue.second.created_on.localtime)
  399     assert_select 'tr.group span.name', :text => group_name do
  400       assert_select '+ span.count', :text => '2'
  401     end
  402   end
  403 
  404   def test_index_grouped_by_created_on_as_pdf
  405     skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on}
  406 
  407     get :index, :params => {
  408         :set_filter => 1,
  409         :group_by => 'created_on',
  410         :format => 'pdf'
  411       }
  412     assert_response :success
  413     assert_equal 'application/pdf', response.content_type
  414   end
  415 
  416   def test_index_with_query_grouped_by_list_custom_field
  417     get :index, :params => {
  418         :project_id => 1,
  419         :query_id => 9
  420       }
  421     assert_response :success
  422     assert_select 'tr.group span.count'
  423   end
  424 
  425   def test_index_with_query_grouped_by_key_value_custom_field
  426     cf = IssueCustomField.create!(:name => 'Key', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'enumeration')
  427     cf.enumerations << valueb = CustomFieldEnumeration.new(:name => 'Value B', :position => 1)
  428     cf.enumerations << valuea = CustomFieldEnumeration.new(:name => 'Value A', :position => 2)
  429     CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => valueb.id)
  430     CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => valueb.id)
  431     CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => valuea.id)
  432     CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  433 
  434     get :index, :params => {
  435         :project_id => 1,
  436         :set_filter => 1,
  437       :group_by => "cf_#{cf.id}"
  438       }
  439     assert_response :success
  440 
  441     assert_select 'tr.group', 3
  442     assert_select 'tr.group' do
  443       assert_select 'span.name', :text => 'Value B'
  444       assert_select 'span.count', :text => '2'
  445     end
  446     assert_select 'tr.group' do
  447       assert_select 'span.name', :text => 'Value A'
  448       assert_select 'span.count', :text => '1'
  449     end
  450   end
  451 
  452   def test_index_with_query_grouped_by_user_custom_field
  453     cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
  454     CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  455     CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  456     CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  457     CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  458 
  459     get :index, :params => {
  460         :project_id => 1,
  461         :set_filter => 1,
  462       :group_by => "cf_#{cf.id}"
  463       }
  464     assert_response :success
  465 
  466     assert_select 'tr.group', 3
  467     assert_select 'tr.group' do
  468       assert_select 'a', :text => 'John Smith'
  469       assert_select 'span.count', :text => '1'
  470     end
  471     assert_select 'tr.group' do
  472       assert_select 'a', :text => 'Dave Lopper'
  473       assert_select 'span.count', :text => '2'
  474     end
  475   end
  476 
  477   def test_index_grouped_by_boolean_custom_field_should_distinguish_blank_and_false_values
  478     cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool')
  479     CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '1')
  480     CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
  481     CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '')
  482 
  483     with_settings :default_language => 'en' do
  484       get :index, :params => {
  485           :project_id => 1,
  486           :set_filter => 1,
  487         :group_by => "cf_#{cf.id}"
  488         }
  489       assert_response :success
  490     end
  491 
  492     assert_select 'tr.group', 3
  493     assert_select 'tr.group', :text => /Yes/
  494     assert_select 'tr.group', :text => /No/
  495     assert_select 'tr.group', :text => /blank/
  496   end
  497 
  498   def test_index_grouped_by_boolean_custom_field_with_false_group_in_first_position_should_show_the_group
  499     cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool', :is_filter => true)
  500     CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '0')
  501     CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
  502 
  503     with_settings :default_language => 'en' do
  504       get :index, :params => {
  505           :project_id => 1,
  506         :set_filter => 1, "cf_#{cf.id}" => "*",
  507         :group_by => "cf_#{cf.id}"
  508         }
  509       assert_response :success
  510     end
  511 
  512     assert_equal [1, 2], issues_in_list.map(&:id).sort
  513     assert_select 'tr.group', 1
  514     assert_select 'tr.group', :text => /No/
  515   end
  516 
  517   def test_index_with_query_grouped_by_tracker_in_normal_order
  518     3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
  519     get :index, :params => {
  520         :set_filter => 1,
  521         :group_by => 'tracker',
  522         :sort => 'id:desc'
  523       }
  524     assert_response :success
  525     assert_equal ["Bug", "Feature request", "Support request"],
  526                  css_select("tr.issue td.tracker").map(&:text).uniq
  527   end
  528 
  529   def test_index_with_query_grouped_by_tracker_in_reverse_order
  530     3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
  531     get :index, :params => {
  532         :set_filter => 1,
  533         :group_by => 'tracker',
  534         :c => ['tracker', 'subject'],
  535         :sort => 'id:desc,tracker:desc'
  536       }
  537     assert_response :success
  538     assert_equal ["Bug", "Feature request", "Support request"].reverse,
  539                  css_select("tr.issue td.tracker").map(&:text).uniq
  540   end
  541 
  542   def test_index_with_query_id_and_project_id_should_set_session_query
  543     get :index, :params => {
  544         :project_id => 1,
  545         :query_id => 4
  546       }
  547     assert_response :success
  548     assert_kind_of Hash, session[:issue_query]
  549     assert_equal 4, session[:issue_query][:id]
  550     assert_equal 1, session[:issue_query][:project_id]
  551   end
  552 
  553   def test_index_with_invalid_query_id_should_respond_404
  554     get :index, :params => {
  555         :project_id => 1,
  556         :query_id => 999
  557       }
  558     assert_response 404
  559   end
  560 
  561   def test_index_with_cross_project_query_in_session_should_show_project_issues
  562     q = IssueQuery.create!(:name => "cross_project_query", :user_id => 2, :project => nil, :column_names => ['project'])
  563     @request.session[:issue_query] = {:id => q.id, :project_id => 1}
  564 
  565     with_settings :display_subprojects_issues => '0' do
  566       get :index, :params => {
  567           :project_id => 1
  568         }
  569     end
  570     assert_response :success
  571 
  572     assert_select 'h2', :text => q.name
  573     assert_equal ["eCookbook"], css_select("tr.issue td.project").map(&:text).uniq
  574   end
  575 
  576   def test_private_query_should_not_be_available_to_other_users
  577     q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
  578     @request.session[:user_id] = 3
  579 
  580     get :index, :params => {
  581         :query_id => q.id
  582       }
  583     assert_response 403
  584   end
  585 
  586   def test_private_query_should_be_available_to_its_user
  587     q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
  588     @request.session[:user_id] = 2
  589 
  590     get :index, :params => {
  591         :query_id => q.id
  592       }
  593     assert_response :success
  594   end
  595 
  596   def test_public_query_should_be_available_to_other_users
  597     q = IssueQuery.create!(:name => "public", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PUBLIC, :project => nil)
  598     @request.session[:user_id] = 3
  599 
  600     get :index, :params => {
  601         :query_id => q.id
  602       }
  603     assert_response :success
  604   end
  605 
  606   def test_index_should_omit_page_param_in_export_links
  607     get :index, :params => {
  608         :page => 2
  609       }
  610     assert_response :success
  611     assert_select 'a.atom[href="/issues.atom"]'
  612     assert_select 'a.csv[href="/issues.csv"]'
  613     assert_select 'a.pdf[href="/issues.pdf"]'
  614     assert_select 'form#csv-export-form[action="/issues.csv"]'
  615   end
  616 
  617   def test_index_should_not_warn_when_not_exceeding_export_limit
  618     with_settings :issues_export_limit => 200 do
  619       get :index
  620       assert_select '#csv-export-options p.icon-warning', 0
  621     end
  622   end
  623 
  624   def test_index_should_warn_when_exceeding_export_limit
  625     with_settings :issues_export_limit => 2 do
  626       get :index
  627       assert_select '#csv-export-options p.icon-warning', :text => %r{limit: 2}
  628     end
  629   end
  630 
  631   def test_index_should_include_query_params_as_hidden_fields_in_csv_export_form
  632     get :index, :params => {
  633         :project_id => 1,
  634         :set_filter => "1",
  635         :tracker_id => "2",
  636         :sort => 'status',
  637         :c => ["status", "priority"]
  638       }
  639 
  640     assert_select '#csv-export-form[action=?]', '/projects/ecookbook/issues.csv'
  641     assert_select '#csv-export-form[method=?]', 'get'
  642 
  643     assert_select '#csv-export-form' do
  644       assert_select 'input[name=?][value=?]', 'set_filter', '1'
  645 
  646       assert_select 'input[name=?][value=?]', 'f[]', 'tracker_id'
  647       assert_select 'input[name=?][value=?]', 'op[tracker_id]', '='
  648       assert_select 'input[name=?][value=?]', 'v[tracker_id][]', '2'
  649 
  650       assert_select 'input[name=?][value=?]', 'c[]', 'status'
  651       assert_select 'input[name=?][value=?]', 'c[]', 'priority'
  652 
  653       assert_select 'input[name=?][value=?]', 'sort', 'status'
  654     end
  655 
  656     get :index, :params => {
  657         :project_id => 1,
  658         :set_filter => "1",
  659         :f => ['']
  660       }
  661     assert_select '#csv-export-form input[name=?][value=?]', 'f[]', ''
  662   end
  663 
  664   def test_index_should_show_block_columns_in_csv_export_form
  665     field = IssueCustomField.
  666               create!(
  667                 :name => 'Long text', :field_format => 'text',
  668                 :full_width_layout => '1',
  669                 :tracker_ids => [1], :is_for_all => true
  670               )
  671     get :index
  672 
  673     assert_response :success
  674     assert_select '#csv-export-form' do
  675       assert_select 'input[value=?]', 'description'
  676       assert_select 'input[value=?]', 'last_notes'
  677       assert_select 'input[value=?]', "cf_#{field.id}"
  678     end
  679   end
  680 
  681   def test_index_csv
  682     get :index, :params => {
  683         :format => 'csv'
  684       }
  685     assert_response :success
  686 
  687     assert_equal 'text/csv', @response.media_type
  688     assert response.body.starts_with?("#,")
  689     lines = response.body.chomp.split("\n")
  690     # default columns + id and project
  691     assert_equal Setting.issue_list_default_columns.size + 2, lines[0].split(',').size
  692   end
  693 
  694   def test_index_csv_with_project
  695     get :index, :params => {
  696         :project_id => 1,
  697         :format => 'csv'
  698       }
  699     assert_response :success
  700     assert_equal 'text/csv', @response.media_type
  701   end
  702 
  703   def test_index_csv_without_any_filters
  704     @request.session[:user_id] = 1
  705     Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5, :subject => 'Closed issue', :author_id => 1)
  706     get :index, :params => {
  707         :set_filter => 1,
  708         :f => [''],
  709         :format => 'csv'
  710       }
  711     assert_response :success
  712     # -1 for headers
  713     assert_equal Issue.count, response.body.chomp.split("\n").size - 1
  714   end
  715 
  716   def test_index_csv_with_description
  717     Issue.generate!(:description => 'test_index_csv_with_description')
  718     with_settings :default_language => 'en' do
  719       get :index, :params => {
  720           :format => 'csv',
  721           :c => [:tracker, :description]
  722         }
  723       assert_response :success
  724     end
  725     assert_equal 'text/csv', response.media_type
  726     headers = response.body.chomp.split("\n").first.split(',')
  727     assert_include 'Description', headers
  728     assert_include 'test_index_csv_with_description', response.body
  729   end
  730 
  731   def test_index_csv_with_spent_time_column
  732     issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
  733     TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
  734 
  735     get :index, :params => {
  736         :format => 'csv',
  737         :set_filter => '1',
  738         :c => %w(subject spent_hours)
  739       }
  740     assert_response :success
  741     assert_equal 'text/csv', @response.media_type
  742     lines = @response.body.chomp.split("\n")
  743     assert_include "#{issue.id},#{issue.subject},7.33", lines
  744   end
  745 
  746   def test_index_csv_with_all_columns
  747     get :index, :params => {
  748         :format => 'csv',
  749         :c => ['all_inline']
  750       }
  751     assert_response :success
  752 
  753     assert_equal 'text/csv', @response.media_type
  754     assert_match /\A#,/, response.body
  755     lines = response.body.chomp.split("\n")
  756     assert_equal IssueQuery.new.available_inline_columns.size, lines[0].split(',').size
  757   end
  758 
  759   def test_index_csv_with_multi_column_field
  760     CustomField.find(1).update_attribute :multiple, true
  761     issue = Issue.find(1)
  762     issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  763     issue.save!
  764 
  765     get :index, :params => {
  766         :format => 'csv',
  767         :c => ['tracker', "cf_1"]
  768       }
  769     assert_response :success
  770     lines = @response.body.chomp.split("\n")
  771     assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
  772   end
  773 
  774   def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
  775     field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
  776     issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
  777 
  778     with_settings :default_language => 'fr' do
  779       get :index, :params => {
  780           :format => 'csv',
  781         :c => ['id', 'tracker', "cf_#{field.id}"]
  782         }
  783       assert_response :success
  784       issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
  785       assert_include '185,60', issue_line
  786     end
  787 
  788     with_settings :default_language => 'en' do
  789       get :index, :params => {
  790           :format => 'csv',
  791         :c => ['id', 'tracker', "cf_#{field.id}"]
  792         }
  793       assert_response :success
  794       issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
  795       assert_include '185.60', issue_line
  796     end
  797   end
  798 
  799   def test_index_csv_should_fill_parent_column_with_parent_id
  800     Issue.delete_all
  801     parent = Issue.generate!
  802     child = Issue.generate!(:parent_issue_id => parent.id)
  803 
  804     with_settings :default_language => 'en' do
  805       get :index, :params => {
  806           :format => 'csv',
  807           :c => %w(parent)
  808         }
  809     end
  810     lines = response.body.split("\n")
  811     assert_include "#{child.id},#{parent.id}", lines
  812   end
  813 
  814   def test_index_csv_big_5
  815     with_settings :default_language => "zh-TW" do
  816       str_utf8  = '一月'
  817       str_big5  = (+"\xa4@\xa4\xeb").force_encoding('Big5')
  818       issue = Issue.generate!(:subject => str_utf8)
  819 
  820       get :index, :params => {
  821           :project_id => 1,
  822           :subject => str_utf8,
  823           :format => 'csv'
  824         }
  825       assert_equal 'text/csv', @response.media_type
  826       lines = @response.body.chomp.split("\n")
  827       header = lines[0]
  828       status = (+"\xaa\xac\xbaA").force_encoding('Big5')
  829       assert_include status, header
  830       issue_line = lines.find {|l| l =~ /^#{issue.id},/}
  831       assert_include str_big5, issue_line
  832     end
  833   end
  834 
  835   def test_index_csv_cannot_convert_should_be_replaced_big_5
  836     with_settings :default_language => "zh-TW" do
  837       str_utf8  = '以内'
  838       issue = Issue.generate!(:subject => str_utf8)
  839 
  840       get :index, :params => {
  841           :project_id => 1,
  842           :subject => str_utf8,
  843           :c => ['status', 'subject'],
  844           :format => 'csv',
  845           :set_filter => 1
  846         }
  847       assert_equal 'text/csv', @response.media_type
  848       lines = @response.body.chomp.split("\n")
  849       header = lines[0]
  850       issue_line = lines.find {|l| l =~ /^#{issue.id},/}
  851       s1 = (+"\xaa\xac\xbaA").force_encoding('Big5') # status
  852       assert header.include?(s1)
  853       s2 = issue_line.split(",")[2]
  854       s3 = (+"\xa5H?").force_encoding('Big5') # subject
  855       assert_equal s3, s2
  856     end
  857   end
  858 
  859   def test_index_csv_tw
  860     with_settings :default_language => "zh-TW" do
  861       str1  = "test_index_csv_tw"
  862       issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
  863 
  864       get :index, :params => {
  865           :project_id => 1,
  866           :subject => str1,
  867           :c => ['estimated_hours', 'subject'],
  868           :format => 'csv',
  869           :set_filter => 1
  870         }
  871       assert_equal 'text/csv', @response.media_type
  872       lines = @response.body.chomp.split("\n")
  873       assert_include "#{issue.id},1234.50,#{str1}", lines
  874     end
  875   end
  876 
  877   def test_index_csv_fr
  878     with_settings :default_language => "fr" do
  879       str1  = "test_index_csv_fr"
  880       issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
  881 
  882       get :index, :params => {
  883           :project_id => 1,
  884           :subject => str1,
  885           :c => ['estimated_hours', 'subject'],
  886           :format => 'csv',
  887           :set_filter => 1
  888         }
  889       assert_equal 'text/csv', @response.media_type
  890       lines = @response.body.chomp.split("\n")
  891       assert_include "#{issue.id};1234,50;#{str1}", lines
  892     end
  893   end
  894 
  895   def test_index_csv_should_not_change_selected_columns
  896     get :index, :params => {
  897         :set_filter => 1,
  898         :c => ["subject", "due_date"],
  899         :project_id => "ecookbook"
  900       }
  901     assert_response :success
  902     assert_equal [:subject, :due_date], session[:issue_query][:column_names]
  903 
  904     get :index, :params => {
  905         :set_filter => 1,
  906         :c =>["all_inline"],
  907         :project_id => "ecookbook",
  908         :format => 'csv'
  909       }
  910     assert_response :success
  911     assert_equal [:subject, :due_date], session[:issue_query][:column_names]
  912   end
  913 
  914   def test_index_pdf
  915     ["en", "zh", "zh-TW", "ja", "ko", "ar"].each do |lang|
  916       with_settings :default_language => lang do
  917         get :index
  918         assert_response :success
  919 
  920         get :index, :params => {
  921             :format => 'pdf'
  922           }
  923         assert_response :success
  924         assert_equal 'application/pdf', @response.content_type
  925 
  926         get :index, :params => {
  927             :project_id => 1,
  928             :format => 'pdf'
  929           }
  930         assert_response :success
  931         assert_equal 'application/pdf', @response.content_type
  932 
  933         get :index, :params => {
  934             :project_id => 1,
  935             :query_id => 6,
  936             :format => 'pdf'
  937           }
  938         assert_response :success
  939         assert_equal 'application/pdf', @response.content_type
  940       end
  941     end
  942   end
  943 
  944   def test_index_pdf_with_query_grouped_by_list_custom_field
  945     get :index, :params => {
  946         :project_id => 1,
  947         :query_id => 9,
  948         :format => 'pdf'
  949       }
  950     assert_response :success
  951     assert_equal 'application/pdf', @response.content_type
  952   end
  953 
  954   def test_index_atom
  955     get :index, :params => {
  956         :project_id => 'ecookbook',
  957         :format => 'atom'
  958       }
  959     assert_response :success
  960     assert_equal 'application/atom+xml', response.content_type
  961 
  962     assert_select 'feed' do
  963       assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
  964       assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
  965       assert_select 'entry link[href=?]', 'http://test.host/issues/1'
  966     end
  967   end
  968 
  969   def test_index_should_include_back_url_input
  970     get :index, :params => {
  971         :project_id => 'ecookbook',
  972         :foo => 'bar'
  973       }
  974     assert_response :success
  975     assert_select 'input[name=back_url][value=?]', '/projects/ecookbook/issues?foo=bar'
  976   end
  977 
  978   def test_index_sort
  979     get :index, :params => {
  980         :sort => 'tracker,id:desc'
  981       }
  982     assert_response :success
  983 
  984     assert_equal issues_in_list.sort_by {|issue| [issue.tracker.position, -issue.id]}, issues_in_list
  985     assert_select 'table.issues.sort-by-tracker.sort-asc'
  986   end
  987 
  988   def test_index_sort_by_field_not_included_in_columns
  989     with_settings :issue_list_default_columns => %w(subject author) do
  990       get :index, :params => {
  991           :sort => 'tracker'
  992         }
  993       assert_response :success
  994     end
  995   end
  996 
  997   def test_index_sort_by_assigned_to
  998     get :index, :params => {
  999         :sort => 'assigned_to'
 1000       }
 1001     assert_response :success
 1002 
 1003     assignees = issues_in_list.map(&:assigned_to).compact
 1004     assert_equal assignees.sort, assignees
 1005     assert_select 'table.issues.sort-by-assigned-to.sort-asc'
 1006   end
 1007 
 1008   def test_index_sort_by_assigned_to_desc
 1009     get :index, :params => {
 1010         :sort => 'assigned_to:desc'
 1011       }
 1012     assert_response :success
 1013 
 1014     assignees = issues_in_list.map(&:assigned_to).compact
 1015     assert_equal assignees.sort.reverse, assignees
 1016     assert_select 'table.issues.sort-by-assigned-to.sort-desc'
 1017   end
 1018 
 1019   def test_index_group_by_assigned_to
 1020     get :index, :params => {
 1021         :group_by => 'assigned_to',
 1022         :sort => 'priority'
 1023       }
 1024     assert_response :success
 1025   end
 1026 
 1027   def test_index_sort_by_author
 1028     get :index, :params => {
 1029         :sort => 'author',
 1030         :c => ['author']
 1031       }
 1032     assert_response :success
 1033 
 1034     authors = issues_in_list.map(&:author)
 1035     assert_equal authors.sort, authors
 1036   end
 1037 
 1038   def test_index_sort_by_author_desc
 1039     get :index, :params => {
 1040         :sort => 'author:desc'
 1041       }
 1042     assert_response :success
 1043 
 1044     authors = issues_in_list.map(&:author)
 1045     assert_equal authors.sort.reverse, authors
 1046   end
 1047 
 1048   def test_index_group_by_author
 1049     get :index, :params => {
 1050         :group_by => 'author',
 1051         :sort => 'priority'
 1052       }
 1053     assert_response :success
 1054   end
 1055 
 1056   def test_index_sort_by_last_updated_by
 1057     get :index, :params => {
 1058         :sort => 'last_updated_by'
 1059       }
 1060     assert_response :success
 1061     assert_select 'table.issues.sort-by-last-updated-by.sort-asc'
 1062   end
 1063 
 1064   def test_index_sort_by_last_updated_by_desc
 1065     get :index, :params => {
 1066         :sort => 'last_updated_by:desc'
 1067       }
 1068     assert_response :success
 1069     assert_select 'table.issues.sort-by-last-updated-by.sort-desc'
 1070   end
 1071 
 1072   def test_index_sort_by_spent_hours
 1073     get :index, :params => {
 1074         :sort => 'spent_hours:desc'
 1075       }
 1076     assert_response :success
 1077     hours = issues_in_list.map(&:spent_hours)
 1078     assert_equal hours.sort.reverse, hours
 1079   end
 1080 
 1081   def test_index_sort_by_spent_hours_should_sort_by_visible_spent_hours
 1082     TimeEntry.delete_all
 1083     TimeEntry.generate!(:issue => Issue.generate!(:project_id => 1), :hours => 3)
 1084     TimeEntry.generate!(:issue => Issue.generate!(:project_id => 3), :hours => 4)
 1085 
 1086     get :index, :params => {:sort => "spent_hours:desc", :c => ['subject','spent_hours']}
 1087     assert_response :success
 1088     assert_equal ['4.00', '3.00', '0.00'], columns_values_in_list('spent_hours')[0..2]
 1089 
 1090     Project.find(3).disable_module!(:time_tracking)
 1091 
 1092     get :index, :params => {:sort => "spent_hours:desc", :c => ['subject','spent_hours']}
 1093     assert_response :success
 1094     assert_equal ['3.00', '0.00', '0.00'], columns_values_in_list('spent_hours')[0..2]
 1095   end
 1096 
 1097   def test_index_sort_by_total_spent_hours
 1098     get :index, :params => {
 1099         :sort => 'total_spent_hours:desc'
 1100       }
 1101     assert_response :success
 1102     hours = issues_in_list.map(&:total_spent_hours)
 1103     assert_equal hours.sort.reverse, hours
 1104   end
 1105 
 1106   def test_index_sort_by_total_estimated_hours
 1107     get :index, :params => {
 1108         :sort => 'total_estimated_hours:desc'
 1109       }
 1110     assert_response :success
 1111     hours = issues_in_list.map(&:total_estimated_hours)
 1112     # Removes nil because the position of NULL is database dependent
 1113     hours.compact!
 1114     assert_equal hours.sort.reverse, hours
 1115   end
 1116 
 1117   def test_index_sort_by_user_custom_field
 1118     cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
 1119     CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
 1120     CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
 1121     CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
 1122     CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
 1123 
 1124     get :index, :params => {
 1125         :project_id => 1,
 1126         :set_filter => 1,
 1127       :sort => "cf_#{cf.id},id"
 1128       }
 1129     assert_response :success
 1130 
 1131     assert_equal [2, 3, 1], issues_in_list.select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
 1132   end
 1133 
 1134   def test_index_with_columns
 1135     columns = ['tracker', 'subject', 'assigned_to', 'buttons']
 1136     get :index, :params => {
 1137         :set_filter => 1,
 1138         :c => columns
 1139       }
 1140     assert_response :success
 1141 
 1142     # query should use specified columns + id and checkbox
 1143     assert_select 'table.issues thead' do
 1144       assert_select 'th', columns.size + 2
 1145       assert_select 'th.tracker'
 1146       assert_select 'th.subject'
 1147       assert_select 'th.assigned_to'
 1148       assert_select 'th.buttons'
 1149     end
 1150 
 1151     # columns should be stored in session
 1152     assert_kind_of Hash, session[:issue_query]
 1153     assert_kind_of Array, session[:issue_query][:column_names]
 1154     assert_equal columns, session[:issue_query][:column_names].map(&:to_s)
 1155 
 1156     # ensure only these columns are kept in the selected columns list
 1157     assert_select 'select[name=?] option', 'c[]' do
 1158       assert_select 'option', 3
 1159       assert_select 'option[value=tracker]'
 1160       assert_select 'option[value=project]', 0
 1161     end
 1162   end
 1163 
 1164   def test_index_without_project_should_implicitly_add_project_column_to_default_columns
 1165     with_settings :issue_list_default_columns => ['tracker', 'subject', 'assigned_to'] do
 1166       get :index, :params => {
 1167           :set_filter => 1
 1168         }
 1169     end
 1170 
 1171     # query should use specified columns
 1172     assert_equal ["#", "Project", "Tracker", "Subject", "Assignee"], columns_in_issues_list
 1173   end
 1174 
 1175   def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
 1176     with_settings :issue_list_default_columns => ['tracker', 'subject', 'assigned_to'] do
 1177       columns = ['id', 'tracker', 'subject', 'assigned_to']
 1178       get :index, :params => {
 1179           :set_filter => 1,
 1180           :c => columns
 1181         }
 1182     end
 1183 
 1184     # query should use specified columns
 1185     assert_equal ["#", "Tracker", "Subject", "Assignee"], columns_in_issues_list
 1186   end
 1187 
 1188   def test_index_with_default_columns_should_respect_default_columns_order
 1189     columns = ['assigned_to', 'subject', 'status', 'tracker']
 1190     with_settings :issue_list_default_columns => columns do
 1191       get :index, :params => {
 1192           :project_id => 1,
 1193           :set_filter => 1
 1194         }
 1195 
 1196       assert_equal ["#", "Assignee", "Subject", "Status", "Tracker"], columns_in_issues_list
 1197     end
 1198   end
 1199 
 1200   def test_index_with_custom_field_column
 1201     columns = %w(tracker subject cf_2)
 1202     get :index, :params => {
 1203         :set_filter => 1,
 1204         :c => columns
 1205       }
 1206     assert_response :success
 1207 
 1208     # query should use specified columns
 1209     assert_equal ["#", "Tracker", "Subject", "Searchable field"], columns_in_issues_list
 1210     assert_select 'table.issues' do
 1211       assert_select 'th.cf_2.string'
 1212       assert_select 'td.cf_2.string'
 1213     end
 1214   end
 1215 
 1216   def test_index_with_multi_custom_field_column
 1217     field = CustomField.find(1)
 1218     field.update_attribute :multiple, true
 1219     issue = Issue.find(1)
 1220     issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
 1221     issue.save!
 1222 
 1223     get :index, :params => {
 1224         :set_filter => 1,
 1225         :c => %w(tracker subject cf_1)
 1226       }
 1227     assert_response :success
 1228 
 1229     assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
 1230   end
 1231 
 1232   def test_index_with_multi_user_custom_field_column
 1233     field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
 1234       :tracker_ids => [1], :is_for_all => true)
 1235     issue = Issue.find(1)
 1236     issue.custom_field_values = {field.id => ['2', '3']}
 1237     issue.save!
 1238 
 1239     get :index, :params => {
 1240         :set_filter => 1,
 1241       :c => ['tracker', 'subject', "cf_#{field.id}"]
 1242       }
 1243     assert_response :success
 1244 
 1245     assert_select "table.issues td.cf_#{field.id}" do
 1246       assert_select 'a', 2
 1247       assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
 1248       assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
 1249     end
 1250   end
 1251 
 1252   def test_index_with_date_column
 1253     with_settings :date_format => '%d/%m/%Y' do
 1254       Issue.find(1).update_attribute :start_date, '1987-08-24'
 1255       get :index, :params => {
 1256           :set_filter => 1,
 1257           :c => %w(start_date)
 1258         }
 1259       assert_select 'table.issues' do
 1260         assert_select 'th.start_date'
 1261         assert_select 'td.start_date', :text => '24/08/1987'
 1262       end
 1263     end
 1264   end
 1265 
 1266   def test_index_with_done_ratio_column
 1267     Issue.find(1).update_attribute :done_ratio, 40
 1268     get :index, :params => {
 1269         :set_filter => 1,
 1270         :c => %w(done_ratio)
 1271       }
 1272     assert_select 'table.issues td.done_ratio' do
 1273       assert_select 'table.progress' do
 1274         assert_select 'td.closed[style=?]', 'width: 40%;'
 1275       end
 1276     end
 1277   end
 1278 
 1279   def test_index_with_spent_hours_column
 1280     Issue.expects(:load_visible_spent_hours).once
 1281     get :index, :params => {
 1282         :set_filter => 1,
 1283         :c => %w(subject spent_hours)
 1284       }
 1285     assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
 1286   end
 1287 
 1288   def test_index_with_total_spent_hours_column
 1289     Issue.expects(:load_visible_total_spent_hours).once
 1290     get :index, :params => {
 1291         :set_filter => 1,
 1292         :c => %w(subject total_spent_hours)
 1293       }
 1294     assert_select 'table.issues tr#issue-3 td.total_spent_hours', :text => '1.00'
 1295   end
 1296 
 1297   def test_index_with_total_estimated_hours_column
 1298     get :index, :params => {
 1299         :set_filter => 1,
 1300         :c => %w(subject total_estimated_hours)
 1301       }
 1302     assert_select 'table.issues td.total_estimated_hours'
 1303   end
 1304 
 1305   def test_index_should_not_show_spent_hours_column_without_permission
 1306     Role.anonymous.remove_permission! :view_time_entries
 1307     get :index, :params => {
 1308         :set_filter => 1,
 1309         :c => %w(subject spent_hours)
 1310       }
 1311     assert_select 'td.spent_hours', 0
 1312   end
 1313 
 1314   def test_index_with_fixed_version_column
 1315     get :index, :params => {
 1316         :set_filter => 1,
 1317         :c => %w(fixed_version)
 1318       }
 1319     assert_select 'table.issues td.fixed_version' do
 1320       assert_select 'a[href=?]', '/versions/2', :text => 'eCookbook - 1.0'
 1321     end
 1322   end
 1323 
 1324   def test_index_with_relations_column
 1325     IssueRelation.delete_all
 1326     IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
 1327     IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
 1328     IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
 1329     IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
 1330 
 1331     get :index, :params => {
 1332         :set_filter => 1,
 1333         :c => %w(subject relations)
 1334       }
 1335     assert_response :success
 1336     assert_select "tr#issue-1 td.relations" do
 1337       assert_select "span", 3
 1338       assert_select "span", :text => "Related to #7"
 1339       assert_select "span", :text => "Related to #8"
 1340       assert_select "span", :text => "Blocks #11"
 1341     end
 1342     assert_select "tr#issue-2 td.relations" do
 1343       assert_select "span", 1
 1344       assert_select "span", :text => "Blocked by #12"
 1345     end
 1346     assert_select "tr#issue-3 td.relations" do
 1347       assert_select "span", 0
 1348     end
 1349 
 1350     get :index, :params => {
 1351         :set_filter => 1,
 1352         :c => %w(relations),
 1353         :format => 'csv'
 1354       }
 1355     assert_response :success
 1356     assert_equal 'text/csv', response.media_type
 1357     lines = response.body.chomp.split("\n")
 1358     assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
 1359     assert_include '2,Blocked by #12', lines
 1360     assert_include '3,""', lines
 1361 
 1362     get :index, :params => {
 1363         :set_filter => 1,
 1364         :c => %w(subject relations),
 1365         :format => 'pdf'
 1366       }
 1367     assert_response :success
 1368     assert_equal 'application/pdf', response.content_type
 1369   end
 1370 
 1371   def test_index_with_description_column
 1372     get :index, :params => {
 1373         :set_filter => 1,
 1374         :c => %w(subject description)
 1375       }
 1376 
 1377     assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
 1378     assert_select 'td.description[colspan="4"]', :text => 'Unable to print recipes'
 1379 
 1380     get :index, :params => {
 1381         :set_filter => 1,
 1382         :c => %w(subject description),
 1383         :format => 'pdf'
 1384       }
 1385     assert_response :success
 1386     assert_equal 'application/pdf', response.content_type
 1387   end
 1388 
 1389   def test_index_with_last_notes_column
 1390     get :index, :params => {
 1391         :set_filter => 1,
 1392         :c => %w(subject last_notes)
 1393       }
 1394 
 1395     assert_response :success
 1396     assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
 1397 
 1398     assert_select 'td.last_notes[colspan="4"]', :text => 'Some notes with Redmine links: #2, r2.'
 1399     assert_select 'td.last_notes[colspan="4"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
 1400 
 1401     get :index, :params => {
 1402         :set_filter => 1,
 1403         :c => %w(subject last_notes),
 1404         :format => 'pdf'
 1405       }
 1406     assert_response :success
 1407     assert_equal 'application/pdf', response.content_type
 1408   end
 1409 
 1410   def test_index_with_last_notes_column_should_display_private_notes_with_permission_only
 1411     journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Public notes', :user_id => 1)
 1412     journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
 1413     @request.session[:user_id] = 2
 1414 
 1415     get :index, :params => {
 1416         :set_filter => 1,
 1417         :c => %w(subject last_notes)
 1418       }
 1419     assert_response :success
 1420     assert_select 'td.last_notes[colspan="4"]', :text => 'Privates notes'
 1421 
 1422     Role.find(1).remove_permission! :view_private_notes
 1423 
 1424     get :index, :params => {
 1425         :set_filter => 1,
 1426         :c => %w(subject last_notes)
 1427       }
 1428     assert_response :success
 1429     assert_select 'td.last_notes[colspan="4"]', :text => 'Public notes'
 1430   end
 1431 
 1432   def test_index_with_description_and_last_notes_columns_should_display_column_name
 1433     get :index, :params => {
 1434         :set_filter => 1,
 1435         :c => %w(subject last_notes description)
 1436       }
 1437     assert_response :success
 1438 
 1439     assert_select 'td.last_notes[colspan="4"] span', :text => 'Last notes'
 1440     assert_select 'td.description[colspan="4"] span', :text => 'Description'
 1441   end
 1442 
 1443   def test_index_with_full_width_layout_custom_field_column_should_show_column_as_block_column
 1444     field = IssueCustomField.create!(:name => 'Long text', :field_format => 'text', :full_width_layout => '1',
 1445       :tracker_ids => [1], :is_for_all => true)
 1446     issue = Issue.find(1)
 1447     issue.custom_field_values = {field.id => 'This is a long text'}
 1448     issue.save!
 1449 
 1450     get :index, :params => {
 1451         :set_filter => 1,
 1452         :c => ['subject', 'description', "cf_#{field.id}"]
 1453       }
 1454     assert_response :success
 1455 
 1456     assert_select 'td.description[colspan="4"] span', :text => 'Description'
 1457     assert_select "td.cf_#{field.id} span", :text => 'Long text'
 1458   end
 1459 
 1460   def test_index_with_parent_column
 1461     Issue.delete_all
 1462     parent = Issue.generate!
 1463     child = Issue.generate!(:parent_issue_id => parent.id)
 1464 
 1465     get :index, :params => {
 1466         :c => %w(parent)
 1467       }
 1468 
 1469     assert_select 'td.parent', :text => "#{parent.tracker} ##{parent.id}"
 1470     assert_select 'td.parent a[title=?]', parent.subject
 1471   end
 1472 
 1473   def test_index_with_parent_subject_column
 1474     Issue.delete_all
 1475     parent = Issue.generate!
 1476     child = Issue.generate!(:parent_issue_id => parent.id)
 1477 
 1478     get :index, :params => {
 1479         :c => %w(parent.subject)
 1480       }
 1481 
 1482     assert_select 'table.issues' do
 1483       assert_select 'th.parent-subject', :text => l(:field_parent_issue_subject)
 1484       assert_select "tr#issue-#{child.id}" do
 1485         assert_select 'td.parent-subject', :text => parent.subject
 1486       end
 1487     end
 1488   end
 1489 
 1490   def test_index_with_last_updated_by_column
 1491     get :index, :params => {
 1492         :c => %w(subject last_updated_by),
 1493         :issue_id => '1,2,3',
 1494         :sort => 'id',
 1495         :set_filter => '1'
 1496       }
 1497 
 1498     assert_select 'td.last_updated_by'
 1499     assert_equal ["John Smith", "John Smith", ""], css_select('td.last_updated_by').map(&:text)
 1500   end
 1501 
 1502   def test_index_with_attachments_column
 1503     get :index, :params => {
 1504         :c => %w(subject attachments),
 1505         :set_filter => '1',
 1506         :sort => 'id'
 1507       }
 1508     assert_response :success
 1509 
 1510     assert_select 'td.attachments'
 1511     assert_select 'tr#issue-2' do
 1512       assert_select 'td.attachments' do
 1513         assert_select 'a', :text => 'source.rb'
 1514         assert_select 'a', :text => 'picture.jpg'
 1515       end
 1516     end
 1517   end
 1518 
 1519   def test_index_with_attachments_column_as_csv
 1520     get :index, :params => {
 1521         :c => %w(subject attachments),
 1522         :set_filter => '1',
 1523         :sort => 'id',
 1524         :format => 'csv'
 1525       }
 1526     assert_response :success
 1527 
 1528     assert_include "\"source.rb\npicture.jpg\"", response.body
 1529   end
 1530 
 1531   def test_index_with_estimated_hours_total
 1532     Issue.delete_all
 1533     Issue.generate!(:estimated_hours => 5.5)
 1534     Issue.generate!(:estimated_hours => 1.1)
 1535 
 1536     get :index, :params => {
 1537         :t => %w(estimated_hours)
 1538       }
 1539     assert_response :success
 1540     assert_select '.query-totals'
 1541     assert_select '.total-for-estimated-hours span.value', :text => '6.60'
 1542     assert_select 'input[type=checkbox][name=?][value=estimated_hours][checked=checked]', 't[]'
 1543   end
 1544 
 1545   def test_index_with_grouped_query_and_estimated_hours_total
 1546     Issue.delete_all
 1547     Issue.generate!(:estimated_hours => 5.5, :category_id => 1)
 1548     Issue.generate!(:estimated_hours => 2.3, :category_id => 1)
 1549     Issue.generate!(:estimated_hours => 1.1, :category_id => 2)
 1550     Issue.generate!(:estimated_hours => 4.6)
 1551 
 1552     get :index, :params => {
 1553         :t => %w(estimated_hours),
 1554         :group_by => 'category'
 1555       }
 1556     assert_response :success
 1557     assert_select '.query-totals'
 1558     assert_select '.query-totals .total-for-estimated-hours span.value', :text => '13.50'
 1559     assert_select 'tr.group', :text => /Printing/ do
 1560       assert_select '.total-for-estimated-hours span.value', :text => '7.80'
 1561     end
 1562     assert_select 'tr.group', :text => /Recipes/ do
 1563       assert_select '.total-for-estimated-hours span.value', :text => '1.10'
 1564     end
 1565     assert_select 'tr.group', :text => /blank/ do
 1566       assert_select '.total-for-estimated-hours span.value', :text => '4.60'
 1567     end
 1568   end
 1569 
 1570   def test_index_with_int_custom_field_total
 1571     field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
 1572     CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
 1573     CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
 1574 
 1575     get :index, :params => {
 1576       :t => ["cf_#{field.id}"]
 1577       }
 1578     assert_response :success
 1579     assert_select '.query-totals'
 1580     assert_select ".total-for-cf-#{field.id} span.value", :text => '9'
 1581   end
 1582 
 1583   def test_index_with_spent_time_total_should_sum_visible_spent_time_only
 1584     TimeEntry.delete_all
 1585     TimeEntry.generate!(:issue => Issue.generate!(:project_id => 1), :hours => 3)
 1586     TimeEntry.generate!(:issue => Issue.generate!(:project_id => 3), :hours => 4)
 1587 
 1588     get :index, :params => {:t => ["spent_hours"]}
 1589     assert_response :success
 1590     assert_select ".total-for-spent-hours span.value", :text => '7.00'
 1591 
 1592     Project.find(3).disable_module!(:time_tracking)
 1593 
 1594     get :index, :params => {:t => ["spent_hours"]}
 1595     assert_response :success
 1596     assert_select ".total-for-spent-hours span.value", :text => '3.00'
 1597   end
 1598 
 1599   def test_index_totals_should_default_to_settings
 1600     with_settings :issue_list_default_totals => ['estimated_hours'] do
 1601       get :index
 1602       assert_response :success
 1603       assert_select '.total-for-estimated-hours span.value'
 1604       assert_select '.query-totals>span', 1
 1605     end
 1606   end
 1607 
 1608   def test_index_send_html_if_query_is_invalid
 1609     get :index, :params => {
 1610         :f => ['start_date'],
 1611         :op => {
 1612           :start_date => '='
 1613         }
 1614       }
 1615     assert_equal 'text/html', @response.content_type
 1616     assert_select_error /Start date cannot be blank/i
 1617   end
 1618 
 1619   def test_index_send_nothing_if_query_is_invalid
 1620     get :index, :params => {
 1621         :f => ['start_date'],
 1622         :op => {
 1623           :start_date => '='
 1624         },
 1625         :format => 'csv'
 1626       }
 1627     assert_equal 'text/csv', @response.content_type
 1628     assert @response.body.blank?
 1629   end
 1630 
 1631   def test_index_should_include_new_issue_link
 1632     @request.session[:user_id] = 2
 1633     get :index, :params => {
 1634         :project_id => 1
 1635       }
 1636     assert_select '#content a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
 1637   end
 1638 
 1639   def test_index_should_not_include_new_issue_link_for_project_without_trackers
 1640     Project.find(1).trackers.clear
 1641 
 1642     @request.session[:user_id] = 2
 1643     get :index, :params => {
 1644         :project_id => 1
 1645       }
 1646     assert_select '#content a.new-issue', 0
 1647   end
 1648 
 1649   def test_index_should_not_include_new_issue_link_for_users_with_copy_issues_permission_only
 1650     role = Role.find(1)
 1651     role.remove_permission! :add_issues
 1652     role.add_permission! :copy_issues
 1653 
 1654     @request.session[:user_id] = 2
 1655     get :index, :params => {
 1656         :project_id => 1
 1657       }
 1658     assert_select '#content a.new-issue', 0
 1659   end
 1660 
 1661   def test_index_without_project_should_include_new_issue_link
 1662     @request.session[:user_id] = 2
 1663     get :index
 1664     assert_select '#content a.new-issue[href="/issues/new"]', :text => 'New issue'
 1665   end
 1666 
 1667   def test_index_should_not_include_new_issue_tab_when_disabled
 1668     with_settings :new_item_menu_tab => '0' do
 1669       @request.session[:user_id] = 2
 1670       get :index, :params => {
 1671           :project_id => 1
 1672         }
 1673       assert_select '#main-menu a.new-issue', 0
 1674     end
 1675   end
 1676 
 1677   def test_index_should_include_new_issue_tab_when_enabled
 1678     with_settings :new_item_menu_tab => '1' do
 1679       @request.session[:user_id] = 2
 1680       get :index, :params => {
 1681           :project_id => 1
 1682         }
 1683       assert_select '#main-menu a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
 1684     end
 1685   end
 1686 
 1687   def test_new_should_have_new_issue_tab_as_current_menu_item
 1688     with_settings :new_item_menu_tab => '1' do
 1689       @request.session[:user_id] = 2
 1690       get :new, :params => {
 1691           :project_id => 1
 1692         }
 1693       assert_select '#main-menu a.new-issue.selected'
 1694     end
 1695   end
 1696 
 1697   def test_index_should_not_include_new_issue_tab_for_project_without_trackers
 1698     with_settings :new_item_menu_tab => '1' do
 1699       Project.find(1).trackers.clear
 1700 
 1701       @request.session[:user_id] = 2
 1702       get :index, :params => {
 1703           :project_id => 1
 1704         }
 1705       assert_select '#main-menu a.new-issue', 0
 1706     end
 1707   end
 1708 
 1709   def test_index_should_not_include_new_issue_tab_for_users_with_copy_issues_permission_only
 1710     with_settings :new_item_menu_tab => '1' do
 1711       role = Role.find(1)
 1712       role.remove_permission! :add_issues
 1713       role.add_permission! :copy_issues
 1714 
 1715       @request.session[:user_id] = 2
 1716       get :index, :params => {
 1717           :project_id => 1
 1718         }
 1719       assert_select '#main-menu a.new-issue', 0
 1720     end
 1721   end
 1722 
 1723   def test_show_by_anonymous
 1724     get :show, :params => {
 1725         :id => 1
 1726       }
 1727     assert_response :success
 1728 
 1729     assert_select 'div.issue div.description', :text => /Unable to print recipes/
 1730     # anonymous role is allowed to add a note
 1731     assert_select 'form#issue-form' do
 1732       assert_select 'fieldset' do
 1733         assert_select 'legend', :text => 'Notes'
 1734         assert_select 'textarea[name=?]', 'issue[notes]'
 1735       end
 1736     end
 1737     assert_select 'title', :text => "Bug #1: Cannot print recipes - eCookbook - Redmine"
 1738   end
 1739 
 1740   def test_show_by_manager
 1741     @request.session[:user_id] = 2
 1742     get :show, :params => {
 1743         :id => 1
 1744       }
 1745 
 1746     assert_select 'a', :text => /Quote/
 1747     assert_select 'form#issue-form' do
 1748       assert_select 'fieldset' do
 1749         assert_select 'legend', :text => 'Change properties'
 1750         assert_select 'input[name=?]', 'issue[subject]'
 1751       end
 1752       assert_select 'fieldset' do
 1753         assert_select 'legend', :text => 'Log time'
 1754         assert_select 'input[name=?]', 'time_entry[hours]'
 1755       end
 1756       assert_select 'fieldset' do
 1757         assert_select 'legend', :text => 'Notes'
 1758         assert_select 'textarea[name=?]', 'issue[notes]'
 1759       end
 1760     end
 1761   end
 1762 
 1763   def test_show_should_display_update_form
 1764     @request.session[:user_id] = 2
 1765     get :show, :params => {
 1766         :id => 1
 1767       }
 1768     assert_response :success
 1769 
 1770     assert_select 'form#issue-form' do
 1771       assert_select 'input[name=?]', 'issue[is_private]'
 1772       assert_select 'select[name=?]', 'issue[project_id]'
 1773       assert_select 'select[name=?]', 'issue[tracker_id]'
 1774       assert_select 'input[name=?]', 'issue[subject]'
 1775       assert_select 'textarea[name=?]', 'issue[description]'
 1776       assert_select 'select[name=?]', 'issue[status_id]'
 1777       assert_select 'select[name=?]', 'issue[priority_id]'
 1778       assert_select 'select[name=?]', 'issue[assigned_to_id]'
 1779       assert_select 'select[name=?]', 'issue[category_id]'
 1780       assert_select 'select[name=?]', 'issue[fixed_version_id]'
 1781       assert_select 'input[name=?]', 'issue[parent_issue_id]'
 1782       assert_select 'input[name=?]', 'issue[start_date]'
 1783       assert_select 'input[name=?]', 'issue[due_date]'
 1784       assert_select 'select[name=?]', 'issue[done_ratio]'
 1785       assert_select 'input[name=?]', 'issue[custom_field_values][2]'
 1786       assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
 1787       assert_select 'textarea[name=?]', 'issue[notes]'
 1788     end
 1789   end
 1790 
 1791   def test_show_should_display_update_form_with_minimal_permissions
 1792     Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
 1793     WorkflowTransition.where(:role_id => 1).delete_all
 1794 
 1795     @request.session[:user_id] = 2
 1796     get :show, :params => {
 1797         :id => 1
 1798       }
 1799     assert_response :success
 1800 
 1801     assert_select 'form#issue-form' do
 1802       assert_select 'input[name=?]', 'issue[is_private]', 0
 1803       assert_select 'select[name=?]', 'issue[project_id]', 0
 1804       assert_select 'select[name=?]', 'issue[tracker_id]', 0
 1805       assert_select 'input[name=?]', 'issue[subject]', 0
 1806       assert_select 'textarea[name=?]', 'issue[description]', 0
 1807       assert_select 'select[name=?]', 'issue[status_id]', 0
 1808       assert_select 'select[name=?]', 'issue[priority_id]', 0
 1809       assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
 1810       assert_select 'select[name=?]', 'issue[category_id]', 0
 1811       assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
 1812       assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
 1813       assert_select 'input[name=?]', 'issue[start_date]', 0
 1814       assert_select 'input[name=?]', 'issue[due_date]', 0
 1815       assert_select 'select[name=?]', 'issue[done_ratio]', 0
 1816       assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
 1817       assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
 1818       assert_select 'textarea[name=?]', 'issue[notes]'
 1819     end
 1820   end
 1821 
 1822   def test_show_should_not_display_update_form_without_permissions
 1823     Role.find(1).update_attribute :permissions, [:view_issues]
 1824 
 1825     @request.session[:user_id] = 2
 1826     get :show, :params => {
 1827         :id => 1
 1828       }
 1829     assert_response :success
 1830 
 1831     assert_select 'form#issue-form', 0
 1832   end
 1833 
 1834   def test_update_form_should_not_display_inactive_enumerations
 1835     assert !IssuePriority.find(15).active?
 1836 
 1837     @request.session[:user_id] = 2
 1838     get :show, :params => {
 1839         :id => 1
 1840       }
 1841     assert_response :success
 1842 
 1843     assert_select 'form#issue-form' do
 1844       assert_select 'select[name=?]', 'issue[priority_id]' do
 1845         assert_select 'option[value="4"]'
 1846         assert_select 'option[value="15"]', 0
 1847       end
 1848     end
 1849   end
 1850 
 1851   def test_update_form_should_allow_attachment_upload
 1852     @request.session[:user_id] = 2
 1853     get :show, :params => {
 1854         :id => 1
 1855       }
 1856 
 1857     assert_select 'form#issue-form[method=post][enctype="multipart/form-data"]' do
 1858       assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
 1859     end
 1860   end
 1861 
 1862   def test_show_should_deny_anonymous_access_without_permission
 1863     Role.anonymous.remove_permission!(:view_issues)
 1864     get :show, :params => {
 1865         :id => 1
 1866       }
 1867     assert_response :redirect
 1868   end
 1869 
 1870   def test_show_should_deny_anonymous_access_to_private_issue
 1871     Issue.where(:id => 1).update_all(["is_private = ?", true])
 1872     get :show, :params => {
 1873         :id => 1
 1874       }
 1875     assert_response :redirect
 1876   end
 1877 
 1878   def test_show_should_deny_non_member_access_without_permission
 1879     Role.non_member.remove_permission!(:view_issues)
 1880     @request.session[:user_id] = 9
 1881     get :show, :params => {
 1882         :id => 1
 1883       }
 1884     assert_response 403
 1885   end
 1886 
 1887   def test_show_should_deny_non_member_access_to_private_issue
 1888     Issue.where(:id => 1).update_all(["is_private = ?", true])
 1889     @request.session[:user_id] = 9
 1890     get :show, :params => {
 1891         :id => 1
 1892       }
 1893     assert_response 403
 1894   end
 1895 
 1896   def test_show_should_deny_member_access_without_permission
 1897     Role.find(1).remove_permission!(:view_issues)
 1898     @request.session[:user_id] = 2
 1899     get :show, :params => {
 1900         :id => 1
 1901       }
 1902     assert_response 403
 1903   end
 1904 
 1905   def test_show_should_deny_member_access_to_private_issue_without_permission
 1906     Issue.where(:id => 1).update_all(["is_private = ?", true])
 1907     @request.session[:user_id] = 3
 1908     get :show, :params => {
 1909         :id => 1
 1910       }
 1911     assert_response 403
 1912   end
 1913 
 1914   def test_show_should_allow_author_access_to_private_issue
 1915     Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
 1916     @request.session[:user_id] = 3
 1917     get :show, :params => {
 1918         :id => 1
 1919       }
 1920     assert_response :success
 1921   end
 1922 
 1923   def test_show_should_allow_assignee_access_to_private_issue
 1924     Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
 1925     @request.session[:user_id] = 3
 1926     get :show, :params => {
 1927         :id => 1
 1928       }
 1929     assert_response :success
 1930   end
 1931 
 1932   def test_show_should_allow_member_access_to_private_issue_with_permission
 1933     Issue.where(:id => 1).update_all(["is_private = ?", true])
 1934     User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
 1935     @request.session[:user_id] = 3
 1936     get :show, :params => {
 1937         :id => 1
 1938       }
 1939     assert_response :success
 1940   end
 1941 
 1942   def test_show_should_format_related_issues_dates
 1943     with_settings :date_format => '%d/%m/%Y' do
 1944       issue = Issue.generate!(:start_date => '2018-11-29', :due_date => '2018-12-01')
 1945       IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => issue, :relation_type => 'relates')
 1946 
 1947       get :show, :params => {
 1948           :id => 1
 1949         }
 1950       assert_response :success
 1951 
 1952       assert_select '#relations td.start_date', :text => '29/11/2018'
 1953       assert_select '#relations td.due_date', :text => '01/12/2018'
 1954     end
 1955   end
 1956 
 1957   def test_show_should_not_disclose_relations_to_invisible_issues
 1958     Setting.cross_project_issue_relations = '1'
 1959     IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
 1960     # Relation to a private project issue
 1961     IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
 1962 
 1963     get :show, :params => {
 1964         :id => 1
 1965       }
 1966     assert_response :success
 1967 
 1968     assert_select 'div#relations' do
 1969       assert_select 'a', :text => /#2$/
 1970       assert_select 'a', :text => /#4$/, :count => 0
 1971     end
 1972   end
 1973 
 1974   def test_show_should_list_subtasks
 1975     Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
 1976 
 1977     get :show, :params => {
 1978         :id => 1
 1979       }
 1980     assert_response :success
 1981 
 1982     assert_select 'div#issue_tree' do
 1983       assert_select 'td.subject', :text => /Child Issue/
 1984     end
 1985   end
 1986 
 1987   def test_show_should_list_parents
 1988     issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
 1989 
 1990     get :show, :params => {
 1991         :id => issue.id
 1992       }
 1993     assert_response :success
 1994 
 1995     assert_select 'div.subject' do
 1996       assert_select 'h3', 'Child Issue'
 1997       assert_select 'a[href="/issues/1"]'
 1998     end
 1999   end
 2000 
 2001   def test_show_should_not_display_prev_next_links_without_query_in_session
 2002     get :show, :params => {
 2003         :id => 1
 2004       }
 2005     assert_response :success
 2006 
 2007     assert_select 'div.next-prev-links', 0
 2008   end
 2009 
 2010   def test_show_should_display_prev_next_links_with_query_in_session
 2011     @request.session[:issue_query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil, :sort => [['id', 'asc']]}
 2012 
 2013     with_settings :display_subprojects_issues => '0' do
 2014       get :show, :params => {
 2015           :id => 3
 2016         }
 2017     end
 2018     assert_response :success
 2019 
 2020     count = Issue.open.visible.count
 2021 
 2022     # Previous and next issues for all projects
 2023     assert_select 'div.next-prev-links' do
 2024       assert_select 'a[href="/issues/2"]', :text => /Previous/
 2025       assert_select 'a[href="/issues/5"]', :text => /Next/
 2026       assert_select 'span.position', :text => "3 of #{count}"
 2027     end
 2028   end
 2029 
 2030   def test_show_should_display_prev_next_links_with_saved_query_in_session
 2031     query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC,  :user_id => 1,
 2032       :filters => {'status_id' => {:values => ['5'], :operator => '='}},
 2033       :sort_criteria => [['id', 'asc']])
 2034     @request.session[:issue_query] = {:id => query.id, :project_id => nil}
 2035 
 2036     get :show, :params => {
 2037         :id => 11
 2038       }
 2039     assert_response :success
 2040 
 2041     # Previous and next issues for all projects
 2042     assert_select 'div.next-prev-links' do
 2043       assert_select 'a[href="/issues/8"]', :text => /Previous/
 2044       assert_select 'a[href="/issues/12"]', :text => /Next/
 2045     end
 2046   end
 2047 
 2048   def test_show_should_display_prev_next_links_with_query_and_sort_on_association
 2049     @request.session[:issue_query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
 2050 
 2051     %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
 2052       @request.session[:issue_query][:sort] = [[assoc_sort, 'asc']]
 2053 
 2054       get :show, :params => {
 2055           :id => 3
 2056         }
 2057       assert_response :success, "Wrong response status for #{assoc_sort} sort"
 2058 
 2059       assert_select 'div.next-prev-links' do
 2060         assert_select 'a', :text => /(Previous|Next)/
 2061       end
 2062     end
 2063   end
 2064 
 2065   def test_show_should_display_prev_next_links_with_project_query_in_session
 2066     @request.session[:issue_query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1, :sort => [['id','asc']]}
 2067 
 2068     with_settings :display_subprojects_issues => '0' do
 2069       get :show, :params => {
 2070           :id => 3
 2071         }
 2072     end
 2073     assert_response :success
 2074 
 2075     # Previous and next issues inside project
 2076     assert_select 'div.next-prev-links' do
 2077       assert_select 'a[href="/issues/2"]', :text => /Previous/
 2078       assert_select 'a[href="/issues/7"]', :text => /Next/
 2079     end
 2080   end
 2081 
 2082   def test_show_should_not_display_prev_link_for_first_issue
 2083     @request.session[:issue_query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1, :sort => [['id', 'asc']]}
 2084 
 2085     with_settings :display_subprojects_issues => '0' do
 2086       get :show, :params => {
 2087           :id => 1
 2088         }
 2089     end
 2090     assert_response :success
 2091 
 2092     assert_select 'div.next-prev-links' do
 2093       assert_select 'a', :text => /Previous/, :count => 0
 2094       assert_select 'a[href="/issues/2"]', :text => /Next/
 2095     end
 2096   end
 2097 
 2098   def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
 2099     @request.session[:issue_query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1, :sort => [['id', 'asc']]}
 2100 
 2101     get :show, :params => {
 2102         :id => 1
 2103       }
 2104     assert_response :success
 2105 
 2106     assert_select 'a', :text => /Previous/, :count => 0
 2107     assert_select 'a', :text => /Next/, :count => 0
 2108   end
 2109 
 2110   def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
 2111     cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
 2112     CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
 2113     CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
 2114     CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
 2115     CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
 2116 
 2117     query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC,  :user_id => 1, :filters => {},
 2118       :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
 2119     @request.session[:issue_query] = {:id => query.id, :project_id => nil}
 2120 
 2121     get :show, :params => {
 2122         :id => 3
 2123       }
 2124     assert_response :success
 2125 
 2126     assert_select 'div.next-prev-links' do
 2127       assert_select 'a[href="/issues/2"]', :text => /Previous/
 2128       assert_select 'a[href="/issues/1"]', :text => /Next/
 2129     end
 2130   end
 2131 
 2132   def test_show_should_display_prev_next_links_when_request_has_previous_and_next_issue_ids_params
 2133     get :show, :params => {
 2134         :id => 1,
 2135         :prev_issue_id => 1,
 2136         :next_issue_id => 3,
 2137         :issue_position => 2,
 2138         :issue_count => 4
 2139       }
 2140     assert_response :success
 2141 
 2142     assert_select 'div.next-prev-links' do
 2143       assert_select 'a[href="/issues/1"]', :text => /Previous/
 2144       assert_select 'a[href="/issues/3"]', :text => /Next/
 2145       assert_select 'span.position', :text => "2 of 4"
 2146     end
 2147   end
 2148 
 2149   def test_show_should_display_category_field_if_categories_are_defined
 2150     Issue.update_all :category_id => nil
 2151 
 2152     get :show, :params => {
 2153         :id => 1
 2154       }
 2155     assert_response :success
 2156     assert_select '.attributes .category'
 2157   end
 2158 
 2159   def test_show_should_not_display_category_field_if_no_categories_are_defined
 2160     Project.find(1).issue_categories.delete_all
 2161 
 2162     get :show, :params => {
 2163         :id => 1
 2164       }
 2165     assert_response :success
 2166     assert_select 'table.attributes .category', 0
 2167   end
 2168 
 2169   def test_show_should_display_link_to_the_assignee
 2170     get :show, :params => {
 2171         :id => 2
 2172       }
 2173     assert_response :success
 2174     assert_select '.assigned-to' do
 2175       assert_select 'a[href="/users/3"]'
 2176     end
 2177   end
 2178 
 2179   def test_show_should_display_visible_changesets_from_other_projects
 2180     project = Project.find(2)
 2181     issue = project.issues.first
 2182     issue.changeset_ids = [102]
 2183     issue.save!
 2184     # changesets from other projects should be displayed even if repository
 2185     # is disabled on issue's project
 2186     project.disable_module! :repository
 2187 
 2188     @request.session[:user_id] = 2
 2189     get :issue_tab, :params => {
 2190         :id => issue.id,
 2191         :name => 'changesets'
 2192       },
 2193       :xhr => true
 2194 
 2195     assert_select 'a[href=?]', '/projects/ecookbook/repository/10/revisions/3'
 2196   end
 2197 
 2198   def test_show_should_display_watchers
 2199     @request.session[:user_id] = 2
 2200     Issue.find(1).add_watcher User.find(2)
 2201 
 2202     get :show, :params => {
 2203         :id => 1
 2204       }
 2205     assert_select 'div#watchers ul' do
 2206       assert_select 'li' do
 2207         assert_select 'a[href="/users/2"]'
 2208         assert_select 'a[class*=delete]'
 2209       end
 2210     end
 2211   end
 2212 
 2213   def test_show_should_display_watchers_with_gravatars
 2214     @request.session[:user_id] = 2
 2215     Issue.find(1).add_watcher User.find(2)
 2216 
 2217     with_settings :gravatar_enabled => '1' do
 2218       get :show, :params => {
 2219           :id => 1
 2220         }
 2221     end
 2222 
 2223     assert_select 'div#watchers ul' do
 2224       assert_select 'li' do
 2225         assert_select 'img.gravatar'
 2226         assert_select 'a[href="/users/2"]'
 2227         assert_select 'a[class*=delete]'
 2228       end
 2229     end
 2230   end
 2231 
 2232   def test_show_with_thumbnails_enabled_should_display_thumbnails
 2233     @request.session[:user_id] = 2
 2234 
 2235     with_settings :thumbnails_enabled => '1' do
 2236       get :show, :params => {
 2237           :id => 14
 2238         }
 2239       assert_response :success
 2240     end
 2241 
 2242     assert_select 'div.thumbnails' do
 2243       assert_select 'a[href="/attachments/16"]' do
 2244         assert_select 'img[src="/attachments/thumbnail/16"]'
 2245       end
 2246     end
 2247   end
 2248 
 2249   def test_show_with_thumbnails_disabled_should_not_display_thumbnails
 2250     @request.session[:user_id] = 2
 2251 
 2252     with_settings :thumbnails_enabled => '0' do
 2253       get :show, :params => {
 2254           :id => 14
 2255         }
 2256       assert_response :success
 2257     end
 2258 
 2259     assert_select 'div.thumbnails', 0
 2260   end
 2261 
 2262   def test_show_with_multi_custom_field
 2263     field = CustomField.find(1)
 2264     field.update_attribute :multiple, true
 2265     issue = Issue.find(1)
 2266     issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
 2267     issue.save!
 2268 
 2269     get :show, :params => {
 2270         :id => 1
 2271       }
 2272     assert_response :success
 2273 
 2274     assert_select ".cf_1 .value", :text => 'MySQL, Oracle'
 2275   end
 2276 
 2277   def test_show_with_full_width_layout_custom_field_should_show_field_under_description
 2278     field = IssueCustomField.create!(:name => 'Long text', :field_format => 'text', :full_width_layout => '1',
 2279       :tracker_ids => [1], :is_for_all => true)
 2280     issue = Issue.find(1)
 2281     issue.custom_field_values = {field.id => 'This is a long text'}
 2282     issue.save!
 2283 
 2284     get :show, :params => {
 2285         :id => 1
 2286       }
 2287     assert_response :success
 2288 
 2289     # long text custom field should not be render in the attributes div
 2290     assert_select "div.attributes div.attribute.cf_#{field.id} p strong", 0, :text => 'Long text'
 2291     assert_select "div.attributes div.attribute.cf_#{field.id} div.value", 0, :text => 'This is a long text'
 2292 
 2293     # long text custom field should be render under description field
 2294     assert_select "div.description ~ div.attribute.cf_#{field.id} p strong", :text => 'Long text'
 2295     assert_select "div.description ~ div.attribute.cf_#{field.id} div.value", :text => 'This is a long text'
 2296   end
 2297 
 2298   def test_show_custom_fields_with_full_text_formatting_should_be_rendered_using_wiki_class
 2299     half_field = IssueCustomField.create!(:name => 'Half width field', :field_format => 'text', :tracker_ids => [1],
 2300       :is_for_all => true, :text_formatting => 'full')
 2301     full_field = IssueCustomField.create!(:name => 'Full width field', :field_format => 'text', :full_width_layout => '1',
 2302       :tracker_ids => [1], :is_for_all => true, :text_formatting => 'full')
 2303 
 2304     issue = Issue.find(1)
 2305     issue.custom_field_values = {full_field.id => 'This is a long text', half_field.id => 'This is a short text'}
 2306     issue.save!
 2307 
 2308     get :show, :params => {
 2309         :id => 1
 2310       }
 2311     assert_response :success
 2312 
 2313     assert_select "div.attribute.cf_#{half_field.id} div.value div.wiki", 1
 2314     assert_select "div.attribute.cf_#{full_field.id} div.value div.wiki", 1
 2315   end
 2316 
 2317   def test_show_with_multi_user_custom_field
 2318     field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
 2319       :tracker_ids => [1], :is_for_all => true)
 2320     issue = Issue.find(1)
 2321     issue.custom_field_values = {field.id => ['2', '3']}
 2322     issue.save!
 2323 
 2324     get :show, :params => {
 2325         :id => 1
 2326       }
 2327     assert_response :success
 2328 
 2329     assert_select ".cf_#{field.id} .value", :text => 'Dave Lopper, John Smith' do
 2330       assert_select 'a', :text => 'Dave Lopper'
 2331       assert_select 'a', :text => 'John Smith'
 2332     end
 2333   end
 2334 
 2335   def test_show_should_not_display_default_value_for_new_custom_field
 2336     prior = Issue.generate!
 2337     field = IssueCustomField.generate!(:name => 'WithDefault', :field_format => 'string', :default_value => 'DEFAULT')
 2338     after = Issue.generate!
 2339 
 2340     get :show, :params => {:id => prior.id}
 2341     assert_response :success
 2342     assert_select ".cf_#{field.id} .value", :text => ''
 2343 
 2344     get :show, :params => {:id => after.id}
 2345     assert_response :success
 2346     assert_select ".cf_#{field.id} .value", :text => 'DEFAULT'
 2347   end
 2348 
 2349   def test_show_should_display_private_notes_with_permission_only
 2350     journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
 2351     @request.session[:user_id] = 2
 2352 
 2353     get :show, :params => {
 2354         :id => 2
 2355       }
 2356     assert_response :success
 2357     assert_select "#change-#{journal.id}", 1
 2358 
 2359     Role.find(1).remove_permission! :view_private_notes
 2360     get :show, :params => {
 2361         :id => 2
 2362       }
 2363     assert_response :success
 2364     assert_select "#change-#{journal.id}", 0
 2365   end
 2366 
 2367   def test_show_should_display_private_notes_created_by_current_user
 2368     User.find(3).roles_for_project(Project.find(1)).each do |role|
 2369       role.remove_permission! :view_private_notes
 2370     end
 2371     visible = Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes', :private_notes => true, :user_id => 3)
 2372     not_visible = Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes', :private_notes => true, :user_id => 1)
 2373     @request.session[:user_id] = 3
 2374 
 2375     get :show, :params => {
 2376         :id => 2
 2377       }
 2378     assert_response :success
 2379     assert_select "#change-#{visible.id}", 1
 2380     assert_select "#change-#{not_visible.id}", 0
 2381   end
 2382 
 2383   def test_show_atom
 2384     get :show, :params => {
 2385         :id => 2,
 2386         :format => 'atom'
 2387       }
 2388     assert_response :success
 2389     assert_equal 'application/atom+xml', response.content_type
 2390     # Inline image
 2391     assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
 2392   end
 2393 
 2394   def test_show_export_to_pdf
 2395     issue = Issue.find(3)
 2396     assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
 2397     get :show, :params => {
 2398         :id => 3,
 2399         :format => 'pdf'
 2400       }
 2401     assert_response :success
 2402     assert_equal 'application/pdf', @response.content_type
 2403     assert @response.body.starts_with?('%PDF')
 2404   end
 2405 
 2406   def test_export_to_pdf_with_utf8_u_fffd
 2407     issue = Issue.generate!(:subject => "�")
 2408     ["en", "zh", "zh-TW", "ja", "ko", "ar"].each do |lang|
 2409       with_settings :default_language => lang do
 2410         get :show, :params => {
 2411             :id => issue.id,
 2412             :format => 'pdf'
 2413           }
 2414         assert_response :success
 2415         assert_equal 'application/pdf', @response.content_type
 2416         assert @response.body.starts_with?('%PDF')
 2417       end
 2418     end
 2419   end
 2420 
 2421   def test_show_export_to_pdf_with_ancestors
 2422     issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
 2423 
 2424     get :show, :params => {
 2425         :id => issue.id,
 2426         :format => 'pdf'
 2427       }
 2428     assert_response :success
 2429     assert_equal 'application/pdf', @response.content_type
 2430     assert @response.body.starts_with?('%PDF')
 2431   end
 2432 
 2433   def test_show_export_to_pdf_with_descendants
 2434     c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
 2435     c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
 2436     c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
 2437 
 2438     get :show, :params => {
 2439         :id => 1,
 2440         :format => 'pdf'
 2441       }
 2442     assert_response :success
 2443     assert_equal 'application/pdf', @response.content_type
 2444     assert @response.body.starts_with?('%PDF')
 2445   end
 2446 
 2447   def test_show_export_to_pdf_with_journals
 2448     get :show, :params => {
 2449         :id => 1,
 2450         :format => 'pdf'
 2451       }
 2452     assert_response :success
 2453     assert_equal 'application/pdf', @response.content_type
 2454     assert @response.body.starts_with?('%PDF')
 2455   end
 2456 
 2457   def test_show_export_to_pdf_with_private_journal
 2458     Journal.create!(
 2459       :journalized => Issue.find(1),
 2460       :notes => 'Private notes',
 2461       :private_notes => true,
 2462       :user_id => 3
 2463     )
 2464     @request.session[:user_id] = 3
 2465     get(
 2466       :show,
 2467       :params => {
 2468         :id => 1,
 2469         :format => 'pdf'
 2470       }
 2471     )
 2472     assert_response :success
 2473     assert_equal 'application/pdf', @response.content_type
 2474     assert @response.body.starts_with?('%PDF')
 2475   end
 2476 
 2477   def test_show_export_to_pdf_with_changesets
 2478     [[100], [100, 101], [100, 101, 102]].each do |cs|
 2479       issue1 = Issue.find(3)
 2480       issue1.changesets = Changeset.find(cs)
 2481       issue1.save!
 2482       issue = Issue.find(3)
 2483       assert_equal issue.changesets.count, cs.size
 2484       get :show, :params => {
 2485           :id => 3,
 2486           :format => 'pdf'
 2487         }
 2488       assert_response :success
 2489       assert_equal 'application/pdf', @response.content_type
 2490       assert @response.body.starts_with?('%PDF')
 2491     end
 2492   end
 2493 
 2494   def test_show_invalid_should_respond_with_404
 2495     get :show, :params => {
 2496         :id => 999
 2497       }
 2498     assert_response 404
 2499   end
 2500 
 2501   def test_show_on_active_project_should_display_edit_links
 2502     @request.session[:user_id] = 1
 2503 
 2504     get :show, :params => {
 2505         :id => 1
 2506       }
 2507     assert_response :success
 2508     assert_select 'a', :text => 'Edit'
 2509     assert_select 'a', :text => 'Delete'
 2510   end
 2511 
 2512   def test_show_on_closed_project_should_not_display_edit_links
 2513     Issue.find(1).project.close
 2514     @request.session[:user_id] = 1
 2515 
 2516     get :show, :params => {
 2517         :id => 1
 2518       }
 2519     assert_response :success
 2520     assert_select 'a', :text => 'Edit', :count => 0
 2521     assert_select 'a', :text => 'Delete', :count => 0
 2522   end
 2523 
 2524   def test_show_should_not_display_history_tabs_for_issue_without_journals
 2525     @request.session[:user_id] = 1
 2526 
 2527     get :show, :params => {:id => 5}
 2528     assert_response :success
 2529     assert_select '#history div.tabs', 0
 2530     assert_select '#history p.nodata', :text => 'No data to display'
 2531   end
 2532 
 2533   def test_show_display_only_all_and_notes_tabs_for_issue_with_notes_only
 2534     @request.session[:user_id] = 1
 2535 
 2536     get :show, :params => {:id => 6}
 2537     assert_response :success
 2538     assert_select '#history' do
 2539       assert_select 'div.tabs ul a', 2
 2540       assert_select 'div.tabs a[id=?]', 'tab-history', :text => 'History'
 2541       assert_select 'div.tabs a[id=?]', 'tab-notes', :text => 'Notes'
 2542     end
 2543   end
 2544 
 2545   def test_show_display_only_all_and_history_tabs_for_issue_with_history_changes_only
 2546     journal = Journal.create!(:journalized => Issue.find(5), :user_id => 1)
 2547     detail = JournalDetail.create!(:journal => journal, :property => 'attr', :prop_key => 'description',
 2548       :old_value => 'Foo', :value => 'Bar')
 2549 
 2550     @request.session[:user_id] = 1
 2551 
 2552     get :show, :params => {:id => 5}
 2553     assert_response :success
 2554     assert_select '#history' do
 2555       assert_select 'div.tabs ul a', 2
 2556       assert_select 'div.tabs a[id=?]', 'tab-history', :text => 'History'
 2557       assert_select 'div.tabs a[id=?]', 'tab-properties', :text => 'Property changes'
 2558     end
 2559   end
 2560 
 2561   def test_show_display_all_notes_and_history_tabs_for_issue_with_notes_and_history_changes
 2562     journal = Journal.create!(:journalized => Issue.find(6), :user_id => 1)
 2563     detail = JournalDetail.create!(:journal => journal, :property => 'attr', :prop_key => 'description',
 2564       :old_value => 'Foo', :value => 'Bar')
 2565 
 2566     @request.session[:user_id] = 1
 2567 
 2568     get :show, :params => {:id => 6}
 2569     assert_response :success
 2570     assert_select '#history' do
 2571       assert_select 'div.tabs ul a', 3
 2572       assert_select 'div.tabs a[id=?]', 'tab-history', :text => 'History'
 2573       assert_select 'div.tabs a[id=?]', 'tab-notes', :text => 'Notes'
 2574       assert_select 'div.tabs a[id=?]', 'tab-properties', :text => 'Property changes'
 2575     end
 2576   end
 2577 
 2578   def test_show_display_changesets_tab_for_issue_with_changesets
 2579     project = Project.find(2)
 2580     issue = Issue.find(9)
 2581     issue.changeset_ids = [102]
 2582     issue.save!
 2583 
 2584     @request.session[:user_id] = 2
 2585     get :show, :params => {:id => issue.id}
 2586 
 2587     assert_select '#history' do
 2588       assert_select 'div.tabs ul a', 1
 2589       assert_select 'div.tabs a[id=?]', 'tab-changesets', :text => 'Associated revisions'
 2590     end
 2591   end
 2592 
 2593   def test_show_should_display_spent_time_tab_for_issue_with_time_entries
 2594     @request.session[:user_id] = 1
 2595     get :show, :params => {:id => 3}
 2596     assert_response :success
 2597 
 2598     assert_select '#history' do
 2599       assert_select 'div.tabs ul a', 1
 2600       assert_select 'div.tabs a[id=?]', 'tab-time_entries', :text => 'Spent time'
 2601     end
 2602 
 2603     get :issue_tab, :params => {
 2604         :id => 3,
 2605         :name => 'time_entries'
 2606       },
 2607       :xhr => true
 2608     assert_response :success
 2609 
 2610     assert_select 'div[id=?]', 'time-entry-3' do
 2611       assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
 2612       assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
 2613 
 2614       assert_select 'ul[class=?]', 'details', :text => /1.00 h/
 2615     end
 2616   end
 2617 
 2618   def test_get_new
 2619     @request.session[:user_id] = 2
 2620     get :new, :params => {
 2621         :project_id => 1,
 2622         :tracker_id => 1
 2623       }
 2624     assert_response :success
 2625 
 2626     assert_select 'form#issue-form[action=?]', '/projects/ecookbook/issues'
 2627     assert_select 'form#issue-form' do
 2628       assert_select 'input[name=?]', 'issue[is_private]'
 2629       assert_select 'select[name=?]', 'issue[project_id]'
 2630       assert_select 'select[name=?]', 'issue[tracker_id]'
 2631       assert_select 'input[name=?]', 'issue[subject]'
 2632       assert_select 'textarea[name=?]', 'issue[description]'
 2633       assert_select 'select[name=?]', 'issue[status_id]'
 2634       assert_select 'select[name=?]', 'issue[priority_id]'
 2635       assert_select 'select[name=?]', 'issue[assigned_to_id]'
 2636       assert_select 'select[name=?]', 'issue[category_id]'
 2637       assert_select 'select[name=?]', 'issue[fixed_version_id]'
 2638       assert_select 'input[name=?]', 'issue[parent_issue_id]'
 2639       assert_select 'input[name=?]', 'issue[start_date]'
 2640       assert_select 'input[name=?]', 'issue[due_date]'
 2641       assert_select 'select[name=?]', 'issue[done_ratio]'
 2642       assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
 2643       assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
 2644     end
 2645 
 2646     # Be sure we don't display inactive IssuePriorities
 2647     assert ! IssuePriority.find(15).active?
 2648     assert_select 'select[name=?]', 'issue[priority_id]' do
 2649       assert_select 'option[value="15"]', 0
 2650     end
 2651   end
 2652 
 2653   def test_get_new_should_show_project_selector_for_project_with_subprojects
 2654     @request.session[:user_id] = 2
 2655     get :new, :params => {
 2656         :project_id => 1,
 2657         :tracker_id => 1
 2658       }
 2659     assert_response :success
 2660 
 2661     assert_select 'select[name="issue[project_id]"]' do
 2662       assert_select 'option', 3
 2663       assert_select 'option[selected=selected]', :text => 'eCookbook'
 2664       assert_select 'option[value=?]', '5', :text => '  » Private child of eCookbook'
 2665       assert_select 'option[value=?]', '3', :text => '  » eCookbook Subproject 1'
 2666 
 2667       # user_id 2 is not allowed to add issues on project_id 4 (it's not a member)
 2668       assert_select 'option[value=?]', '4', 0
 2669     end
 2670   end
 2671 
 2672   def test_get_new_should_not_show_project_selector_for_project_without_subprojects
 2673     @request.session[:user_id] = 2
 2674     get :new, :params => {
 2675         :project_id => 2,
 2676         :tracker_id => 1
 2677       }
 2678     assert_response :success
 2679 
 2680     assert_select 'select[name="issue[project_id]"]', 0
 2681   end
 2682 
 2683   def test_get_new_with_minimal_permissions
 2684     Role.find(1).update_attribute :permissions, [:add_issues]
 2685     WorkflowTransition.where(:role_id => 1).delete_all
 2686 
 2687     @request.session[:user_id] = 2
 2688     get :new, :params => {
 2689         :project_id => 1,
 2690         :tracker_id => 1
 2691       }
 2692     assert_response :success
 2693 
 2694     assert_select 'form#issue-form' do
 2695       assert_select 'input[name=?]', 'issue[is_private]', 0
 2696       assert_select 'select[name=?]', 'issue[project_id]'
 2697       assert_select 'select[name=?]', 'issue[tracker_id]'
 2698       assert_select 'input[name=?]', 'issue[subject]'
 2699       assert_select 'textarea[name=?]', 'issue[description]'
 2700       assert_select 'select[name=?]', 'issue[status_id]'
 2701       assert_select 'select[name=?]', 'issue[priority_id]'
 2702       assert_select 'select[name=?]', 'issue[assigned_to_id]'
 2703       assert_select 'select[name=?]', 'issue[category_id]'
 2704       assert_select 'select[name=?]', 'issue[fixed_version_id]'
 2705       assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
 2706       assert_select 'input[name=?]', 'issue[start_date]'
 2707       assert_select 'input[name=?]', 'issue[due_date]'
 2708       assert_select 'select[name=?]', 'issue[done_ratio]'
 2709       assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
 2710       assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
 2711     end
 2712   end
 2713 
 2714   def test_new_without_project_id
 2715     @request.session[:user_id] = 2
 2716     get :new
 2717     assert_response :success
 2718 
 2719     assert_select 'form#issue-form[action=?]', '/issues'
 2720     assert_select 'form#issue-form' do
 2721       assert_select 'select[name=?]', 'issue[project_id]'
 2722     end
 2723   end
 2724 
 2725   def test_new_with_me_assigned_to_id
 2726     @request.session[:user_id] = 2
 2727     get :new, :params => {
 2728       :issue => { :assigned_to_id => 'me' }
 2729     }
 2730     assert_response :success
 2731     assert_select 'select[name=?]', 'issue[assigned_to_id]' do
 2732       assert_select 'option[value="2"][selected=selected]'
 2733     end
 2734   end
 2735 
 2736   def test_new_should_select_default_status
 2737     @request.session[:user_id] = 2
 2738 
 2739     get :new, :params => {
 2740         :project_id => 1
 2741       }
 2742     assert_response :success
 2743     assert_select 'select[name=?]', 'issue[status_id]' do
 2744       assert_select 'option[value="1"][selected=selected]'
 2745     end
 2746     assert_select 'input[name=was_default_status][value="1"]'
 2747   end
 2748 
 2749   def test_new_should_propose_allowed_statuses
 2750     WorkflowTransition.delete_all
 2751     WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 1)
 2752     WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 3)
 2753     @request.session[:user_id] = 2
 2754 
 2755     get :new, :params => {
 2756         :project_id => 1
 2757       }
 2758     assert_response :success
 2759     assert_select 'select[name=?]', 'issue[status_id]' do
 2760       assert_select 'option[value="1"]'
 2761       assert_select 'option[value="3"]'
 2762       assert_select 'option', 2
 2763       assert_select 'option[value="1"][selected=selected]'
 2764     end
 2765   end
 2766 
 2767   def test_new_should_propose_allowed_statuses_without_default_status_allowed
 2768     WorkflowTransition.delete_all
 2769     WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 2)
 2770     assert_equal 1, Tracker.find(1).default_status_id
 2771     @request.session[:user_id] = 2
 2772 
 2773     get :new, :params => {
 2774         :project_id => 1
 2775       }
 2776     assert_response :success
 2777     assert_select 'select[name=?]', 'issue[status_id]' do
 2778       assert_select 'option[value="2"]'
 2779       assert_select 'option', 1
 2780       assert_select 'option[value="2"][selected=selected]'
 2781     end
 2782   end
 2783 
 2784   def test_new_should_propose_allowed_trackers
 2785     role = Role.find(1)
 2786     role.set_permission_trackers 'add_issues', [1, 3]
 2787     role.save!
 2788     @request.session[:user_id] = 2
 2789 
 2790     get :new, :params => {
 2791         :project_id => 1
 2792       }
 2793     assert_response :success
 2794     assert_select 'select[name=?]', 'issue[tracker_id]' do
 2795       assert_select 'option', 2
 2796       assert_select 'option[value="1"]'
 2797       assert_select 'option[value="3"]'
 2798     end
 2799   end
 2800 
 2801   def test_new_should_default_to_first_tracker
 2802     @request.session[:user_id] = 2
 2803 
 2804     get :new, :params => {
 2805         :project_id => 1
 2806       }
 2807     assert_response :success
 2808     assert_select 'select[name=?]', 'issue[tracker_id]' do
 2809       assert_select 'option', 3
 2810       assert_select 'option[value="1"][selected=selected]'
 2811     end
 2812   end
 2813 
 2814   def test_new_with_parent_issue_id_should_default_to_first_tracker_without_disabled_parent_field
 2815     tracker = Tracker.find(1)
 2816     tracker.core_fields -= ['parent_issue_id']
 2817     tracker.save!
 2818     @request.session[:user_id] = 2
 2819 
 2820     get :new, :params => {
 2821         :project_id => 1,
 2822         :issue => {
 2823           :parent_issue_id => 1
 2824         }
 2825       }
 2826     assert_response :success
 2827     assert_select 'select[name=?]', 'issue[tracker_id]' do
 2828       assert_select 'option', 2
 2829       assert_select 'option[value="2"][selected=selected]'
 2830       assert_select 'option[value="1"]', 0
 2831     end
 2832   end
 2833 
 2834   def test_new_without_allowed_trackers_should_respond_with_403
 2835     role = Role.find(1)
 2836     role.set_permission_trackers 'add_issues', []
 2837     role.save!
 2838     @request.session[:user_id] = 2
 2839 
 2840     get :new, :params => {
 2841         :project_id => 1
 2842       }
 2843     assert_response 403
 2844   end
 2845 
 2846   def test_new_without_projects_should_respond_with_403
 2847     Project.delete_all
 2848     @request.session[:user_id] = 2
 2849 
 2850     get :new
 2851     assert_response 403
 2852     assert_select_error /no projects/
 2853   end
 2854 
 2855   def test_new_without_enabled_trackers_on_projects_should_respond_with_403
 2856     Project.all.each {|p| p.trackers.clear }
 2857     @request.session[:user_id] = 2
 2858 
 2859     get :new
 2860     assert_response 403
 2861     assert_select_error /no projects/
 2862   end
 2863 
 2864   def test_new_should_preselect_default_version
 2865     version = Version.generate!(:project_id => 1)
 2866     Project.find(1).update_attribute :default_version_id, version.id
 2867     @request.session[:user_id] = 2
 2868 
 2869     get :new, :params => {
 2870         :project_id => 1
 2871       }
 2872     assert_response :success
 2873     assert_select 'select[name=?]', 'issue[fixed_version_id]' do
 2874       assert_select 'option[value=?][selected=selected]', version.id.to_s
 2875     end
 2876   end
 2877 
 2878   def test_get_new_with_list_custom_field
 2879     @request.session[:user_id] = 2
 2880     get :new, :params => {
 2881         :project_id => 1,
 2882         :tracker_id => 1
 2883       }
 2884     assert_response :success
 2885 
 2886     assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
 2887       assert_select 'option', 4
 2888       assert_select 'option[value=MySQL]', :text => 'MySQL'
 2889     end
 2890   end
 2891 
 2892   def test_get_new_with_multi_custom_field
 2893     field = IssueCustomField.find(1)
 2894     field.update_attribute :multiple, true
 2895 
 2896     @request.session[:user_id] = 2
 2897     get :new, :params => {
 2898         :project_id => 1,
 2899         :tracker_id => 1
 2900       }
 2901     assert_response :success
 2902 
 2903     assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
 2904       assert_select 'option', 3
 2905       assert_select 'option[value=MySQL]', :text => 'MySQL'
 2906     end
 2907     assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
 2908   end
 2909 
 2910   def test_get_new_with_multi_user_custom_field
 2911     field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
 2912       :tracker_ids => [1], :is_for_all => true)
 2913 
 2914     @request.session[:user_id] = 2
 2915     get :new, :params => {
 2916         :project_id => 1,
 2917         :tracker_id => 1
 2918       }
 2919     assert_response :success
 2920 
 2921     assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
 2922       assert_select 'option', Project.find(1).users.count + 1 # users + 'me'
 2923       assert_select 'option[value="2"]', :text => 'John Smith'
 2924     end
 2925     assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
 2926   end
 2927 
 2928   def test_get_new_with_date_custom_field
 2929     field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
 2930 
 2931     @request.session[:user_id] = 2
 2932     get :new, :params => {
 2933         :project_id => 1,
 2934         :tracker_id => 1
 2935       }
 2936     assert_response :success
 2937 
 2938     assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
 2939   end
 2940 
 2941   def test_get_new_with_text_custom_field
 2942     field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
 2943 
 2944     @request.session[:user_id] = 2
 2945     get :new, :params => {
 2946         :project_id => 1,
 2947         :tracker_id => 1
 2948       }
 2949     assert_response :success
 2950 
 2951     assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
 2952   end
 2953 
 2954   def test_get_new_without_default_start_date_is_creation_date
 2955     with_settings :default_issue_start_date_to_creation_date  => 0 do
 2956       @request.session[:user_id] = 2
 2957       get :new, :params => {
 2958           :project_id => 1,
 2959           :tracker_id => 1
 2960         }
 2961       assert_response :success
 2962       assert_select 'input[name=?]', 'issue[start_date]'
 2963       assert_select 'input[name=?][value]', 'issue[start_date]', 0
 2964     end
 2965   end
 2966 
 2967   def test_get_new_with_default_start_date_is_creation_date
 2968     with_settings :default_issue_start_date_to_creation_date  => 1 do
 2969       @request.session[:user_id] = 2
 2970       get :new, :params => {
 2971           :project_id => 1,
 2972           :tracker_id => 1
 2973         }
 2974       assert_response :success
 2975       assert_select 'input[name=?][value=?]', 'issue[start_date]',
 2976                     Date.today.to_s
 2977     end
 2978   end
 2979 
 2980   def test_get_new_form_should_allow_attachment_upload
 2981     @request.session[:user_id] = 2
 2982     get :new, :params => {
 2983         :project_id => 1,
 2984         :tracker_id => 1
 2985       }
 2986     assert_response :success
 2987 
 2988     assert_select 'form[id=issue-form][method=post][enctype="multipart/form-data"]' do
 2989       assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
 2990     end
 2991   end
 2992 
 2993   def test_get_new_should_prefill_the_form_from_params
 2994     @request.session[:user_id] = 2
 2995     get :new, :params => {
 2996         :project_id => 1,
 2997         :issue => {
 2998           :tracker_id => 3,
 2999           :description => 'Prefilled',
 3000           :custom_field_values => {
 3001           '2' => 'Custom field value'}
 3002         }
 3003       }
 3004 
 3005     assert_select 'select[name=?]', 'issue[tracker_id]' do
 3006       assert_select 'option[value="3"][selected=selected]'
 3007     end
 3008     assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
 3009     assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
 3010   end
 3011 
 3012   def test_get_new_should_mark_required_fields
 3013     cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3014     cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3015     WorkflowPermission.delete_all
 3016     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
 3017     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
 3018     @request.session[:user_id] = 2
 3019 
 3020     get :new, :params => {
 3021         :project_id => 1
 3022       }
 3023     assert_response :success
 3024 
 3025     assert_select 'label[for=issue_start_date]' do
 3026       assert_select 'span[class=required]', 0
 3027     end
 3028     assert_select 'label[for=issue_due_date]' do
 3029       assert_select 'span[class=required]'
 3030     end
 3031     assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
 3032       assert_select 'span[class=required]', 0
 3033     end
 3034     assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
 3035       assert_select 'span[class=required]'
 3036     end
 3037   end
 3038 
 3039   def test_get_new_should_not_display_readonly_fields
 3040     cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3041     cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3042     WorkflowPermission.delete_all
 3043     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
 3044     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
 3045     @request.session[:user_id] = 2
 3046 
 3047     get :new, :params => {
 3048         :project_id => 1
 3049       }
 3050     assert_response :success
 3051 
 3052     assert_select 'input[name=?]', 'issue[start_date]'
 3053     assert_select 'input[name=?]', 'issue[due_date]', 0
 3054     assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
 3055     assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
 3056   end
 3057 
 3058   def test_new_with_tracker_set_as_readonly_should_accept_status
 3059     WorkflowPermission.delete_all
 3060     [1, 2].each do |status_id|
 3061       WorkflowPermission.create!(:tracker_id => 1, :old_status_id => status_id, :role_id => 1, :field_name => 'tracker_id', :rule => 'readonly')
 3062     end
 3063     @request.session[:user_id] = 2
 3064 
 3065     get :new, :params => {
 3066         :project_id => 1,
 3067         :issue => {
 3068           :status_id => 2
 3069         }
 3070       }
 3071     assert_select 'select[name=?]', 'issue[tracker_id]', 0
 3072     assert_select 'select[name=?]', 'issue[status_id]' do
 3073       assert_select 'option[value=?][selected=selected]', '2'
 3074     end
 3075   end
 3076 
 3077   def test_get_new_without_tracker_id
 3078     @request.session[:user_id] = 2
 3079     get :new, :params => {
 3080         :project_id => 1
 3081       }
 3082     assert_response :success
 3083 
 3084     assert_select 'select[name=?]', 'issue[tracker_id]' do
 3085       assert_select 'option[value=?][selected=selected]', Project.find(1).trackers.first.id.to_s
 3086     end
 3087   end
 3088 
 3089   def test_get_new_with_no_default_status_should_display_an_error
 3090     @request.session[:user_id] = 2
 3091     IssueStatus.delete_all
 3092 
 3093     get :new, :params => {
 3094         :project_id => 1
 3095       }
 3096     assert_response 500
 3097     assert_select_error /No default issue/
 3098   end
 3099 
 3100   def test_get_new_with_no_tracker_should_display_an_error
 3101     @request.session[:user_id] = 2
 3102     Tracker.delete_all
 3103 
 3104     get :new, :params => {
 3105         :project_id => 1
 3106       }
 3107     assert_response 500
 3108     assert_select_error /No tracker/
 3109   end
 3110 
 3111   def test_new_with_invalid_project_id
 3112     @request.session[:user_id] = 1
 3113     get :new, :params => {
 3114         :project_id => 'invalid'
 3115       }
 3116     assert_response 404
 3117   end
 3118 
 3119   def test_new_with_parent_id_should_only_propose_valid_trackers
 3120     @request.session[:user_id] = 2
 3121     t = Tracker.find(3)
 3122     assert !t.disabled_core_fields.include?('parent_issue_id')
 3123     get :new, :params => {
 3124         :project_id => 1, :issue => { parent_issue_id: 1 }
 3125       }
 3126     assert_response :success
 3127     assert_select 'option', text: /#{t.name}/, count: 1
 3128 
 3129     t.core_fields = Tracker::CORE_FIELDS - ['parent_issue_id']
 3130     t.save!
 3131     assert t.disabled_core_fields.include?('parent_issue_id')
 3132     get :new, :params => {
 3133         :project_id => 1, :issue => { parent_issue_id: 1 }
 3134       }
 3135     assert_response :success
 3136     assert_select 'option', text: /#{t.name}/, count: 0
 3137   end
 3138 
 3139   def test_get_new_should_show_trackers_description
 3140     @request.session[:user_id] = 2
 3141     get :new, :params => {
 3142       :project_id => 1,
 3143       :issue => {
 3144         :tracker_id => 1
 3145       }
 3146     }
 3147     assert_response :success
 3148 
 3149     assert_select 'form#issue-form' do
 3150       assert_select 'a[title=?]', 'View all trackers description', :text => 'View all trackers description'
 3151       assert_select 'select[name=?][title=?]', 'issue[tracker_id]', 'Description for Bug tracker'
 3152     end
 3153 
 3154     assert_select 'div#trackers_description' do
 3155       assert_select 'h3', 1, :text => 'Trackers description'
 3156       # only Bug and Feature have descriptions
 3157       assert_select 'dt', 2, :text => 'Bug'
 3158       assert_select 'dd', 2, :text => 'Description for Bug tracker'
 3159     end
 3160   end
 3161 
 3162   def test_get_new_should_not_show_trackers_description_for_trackers_without_description
 3163     Tracker.update_all(:description => '')
 3164 
 3165     @request.session[:user_id] = 2
 3166     get :new, :params => {
 3167       :project_id => 1,
 3168       :issue => {
 3169         :tracker_id => 1
 3170       }
 3171     }
 3172     assert_response :success
 3173 
 3174     assert_select 'form#issue-form' do
 3175       assert_select 'a[title=?]', 'View all trackers description', 0
 3176       assert_select 'select[name=?][title=?]', 'issue[tracker_id]', ''
 3177     end
 3178 
 3179     assert_select 'div#trackers_description', 0
 3180   end
 3181 
 3182   def test_update_form_for_new_issue
 3183     @request.session[:user_id] = 2
 3184     post :new, :params => {
 3185         :project_id => 1,
 3186         :issue => {
 3187           :tracker_id => 2,
 3188           :subject => 'This is the test_new issue',
 3189           :description => 'This is the description',
 3190           :priority_id => 5
 3191         }
 3192       },
 3193       :xhr => true
 3194     assert_response :success
 3195     assert_equal 'text/javascript', response.content_type
 3196     assert_include 'This is the test_new issue', response.body
 3197   end
 3198 
 3199   def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
 3200     @request.session[:user_id] = 2
 3201     WorkflowTransition.delete_all
 3202     WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 2)
 3203     WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 5)
 3204     WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
 3205 
 3206     post :new, :params => {
 3207         :project_id => 1,
 3208         :issue => {
 3209           :tracker_id => 1,
 3210           :status_id => 5,
 3211           :subject => 'This is an issue'
 3212         }
 3213       }
 3214 
 3215     assert_select 'select[name=?]', 'issue[status_id]' do
 3216       assert_select 'option[value=?][selected=selected]', '5'
 3217       assert_select 'option[value=?]', '2'
 3218       assert_select 'option', :count => 2
 3219     end
 3220   end
 3221 
 3222   def test_update_form_with_default_status_should_ignore_submitted_status_id_if_equals
 3223     @request.session[:user_id] = 2
 3224     tracker = Tracker.find(2)
 3225     tracker.update! :default_status_id => 2
 3226     tracker.generate_transitions! 2 => 1, :clear => true
 3227 
 3228     post :new, :params => {
 3229         :project_id => 1,
 3230         :issue => {
 3231           :tracker_id => 2,
 3232           :status_id => 1
 3233         },
 3234         :was_default_status => 1
 3235       }
 3236     assert_response :success
 3237 
 3238     assert_select 'select[name=?]', 'issue[status_id]' do
 3239       assert_select 'option[value=?][selected=selected]', '2'
 3240     end
 3241   end
 3242 
 3243   def test_update_form_for_new_issue_should_ignore_version_when_changing_project
 3244     version = Version.generate!(:project_id => 1)
 3245     Project.find(1).update_attribute :default_version_id, version.id
 3246     @request.session[:user_id] = 2
 3247 
 3248     post :new, :params => {
 3249         :issue => {
 3250           :project_id => 1,
 3251           :fixed_version_id => ''
 3252         },
 3253         :form_update_triggered_by => 'issue_project_id'
 3254       }
 3255     assert_response :success
 3256 
 3257     assert_select 'select[name=?]', 'issue[project_id]' do
 3258       assert_select 'option[value=?][selected=selected]', '1'
 3259     end
 3260     assert_select 'select[name=?]', 'issue[fixed_version_id]' do
 3261       assert_select 'option[value=?][selected=selected]', version.id.to_s
 3262     end
 3263   end
 3264 
 3265   def test_post_create
 3266     @request.session[:user_id] = 2
 3267     assert_difference 'Issue.count' do
 3268       assert_no_difference 'Journal.count' do
 3269         post :create, :params => {
 3270             :project_id => 1,
 3271             :issue => {
 3272               :tracker_id => 3,
 3273               :status_id => 2,
 3274               :subject => 'This is the test_new issue',
 3275               :description => 'This is the description',
 3276               :priority_id => 5,
 3277               :start_date => '2010-11-07',
 3278               :estimated_hours => '',
 3279               :custom_field_values => {
 3280               '2' => 'Value for field 2'}
 3281             }
 3282           }
 3283       end
 3284     end
 3285     assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
 3286 
 3287     issue = Issue.find_by_subject('This is the test_new issue')
 3288     assert_not_nil issue
 3289     assert_equal 2, issue.author_id
 3290     assert_equal 3, issue.tracker_id
 3291     assert_equal 2, issue.status_id
 3292     assert_equal Date.parse('2010-11-07'), issue.start_date
 3293     assert_nil issue.estimated_hours
 3294     v = issue.custom_values.where(:custom_field_id => 2).first
 3295     assert_not_nil v
 3296     assert_equal 'Value for field 2', v.value
 3297   end
 3298 
 3299   def test_post_new_with_group_assignment
 3300     group = Group.find(11)
 3301     project = Project.find(1)
 3302     project.members << Member.new(:principal => group, :roles => [Role.givable.first])
 3303 
 3304     with_settings :issue_group_assignment => '1' do
 3305       @request.session[:user_id] = 2
 3306       assert_difference 'Issue.count' do
 3307         post :create, :params => {
 3308             :project_id => project.id,
 3309             :issue => {
 3310               :tracker_id => 3,
 3311               :status_id => 1,
 3312               :subject => 'This is the test_new_with_group_assignment issue',
 3313               :assigned_to_id => group.id
 3314             }
 3315           }
 3316       end
 3317     end
 3318     assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
 3319 
 3320     issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
 3321     assert_not_nil issue
 3322     assert_equal group, issue.assigned_to
 3323   end
 3324 
 3325   def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
 3326     with_settings :default_issue_start_date_to_creation_date  => 0 do
 3327       @request.session[:user_id] = 2
 3328       assert_difference 'Issue.count' do
 3329         post :create, :params => {
 3330             :project_id => 1,
 3331             :issue => {
 3332               :tracker_id => 3,
 3333               :status_id => 2,
 3334               :subject => 'This is the test_new issue',
 3335               :description => 'This is the description',
 3336               :priority_id => 5,
 3337               :estimated_hours => '',
 3338               :custom_field_values => {
 3339               '2' => 'Value for field 2'}
 3340             }
 3341           }
 3342       end
 3343       assert_redirected_to :controller => 'issues', :action => 'show',
 3344                            :id => Issue.last.id
 3345       issue = Issue.find_by_subject('This is the test_new issue')
 3346       assert_not_nil issue
 3347       assert_nil issue.start_date
 3348     end
 3349   end
 3350 
 3351   def test_post_create_without_start_date_and_default_start_date_is_creation_date
 3352     with_settings :default_issue_start_date_to_creation_date  => 1 do
 3353       @request.session[:user_id] = 2
 3354       assert_difference 'Issue.count' do
 3355         post :create, :params => {
 3356             :project_id => 1,
 3357             :issue => {
 3358               :tracker_id => 3,
 3359               :status_id => 2,
 3360               :subject => 'This is the test_new issue',
 3361               :description => 'This is the description',
 3362               :priority_id => 5,
 3363               :estimated_hours => '',
 3364               :custom_field_values => {
 3365               '2' => 'Value for field 2'}
 3366             }
 3367           }
 3368       end
 3369       assert_redirected_to :controller => 'issues', :action => 'show',
 3370                            :id => Issue.last.id
 3371       issue = Issue.find_by_subject('This is the test_new issue')
 3372       assert_not_nil issue
 3373       assert_equal Date.today, issue.start_date
 3374     end
 3375   end
 3376 
 3377   def test_post_create_and_continue
 3378     @request.session[:user_id] = 2
 3379     assert_difference 'Issue.count' do
 3380       post :create, :params => {
 3381           :project_id => 1,
 3382           :issue => {
 3383             :tracker_id => 3,
 3384             :subject => 'This is first issue',
 3385             :priority_id => 5
 3386           },
 3387           :continue => ''
 3388         }
 3389     end
 3390 
 3391     issue = Issue.order('id DESC').first
 3392     assert_redirected_to :controller => 'issues',
 3393                          :action => 'new', :project_id => 'ecookbook',
 3394                          :issue => {:tracker_id => 3}
 3395     assert_not_nil flash[:notice], "flash was not set"
 3396     assert_select_in flash[:notice],
 3397                      'a[href=?][title=?]', "/issues/#{issue.id}",
 3398                      "This is first issue", :text => "##{issue.id}"
 3399   end
 3400 
 3401   def test_post_create_without_custom_fields_param
 3402     @request.session[:user_id] = 2
 3403     assert_difference 'Issue.count' do
 3404       post :create, :params => {
 3405           :project_id => 1,
 3406           :issue => {
 3407             :tracker_id => 1,
 3408             :subject => 'This is the test_new issue',
 3409             :description => 'This is the description',
 3410             :priority_id => 5
 3411           }
 3412         }
 3413     end
 3414     assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
 3415   end
 3416 
 3417   def test_post_create_with_multi_custom_field
 3418     field = IssueCustomField.find_by_name('Database')
 3419     field.update_attribute(:multiple, true)
 3420 
 3421     @request.session[:user_id] = 2
 3422     assert_difference 'Issue.count' do
 3423       post :create, :params => {
 3424           :project_id => 1,
 3425           :issue => {
 3426             :tracker_id => 1,
 3427             :subject => 'This is the test_new issue',
 3428             :description => 'This is the description',
 3429             :priority_id => 5,
 3430             :custom_field_values => {
 3431             '1' => ['', 'MySQL', 'Oracle']}
 3432           }
 3433         }
 3434     end
 3435     assert_response 302
 3436     issue = Issue.order('id DESC').first
 3437     assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
 3438   end
 3439 
 3440   def test_post_create_with_empty_multi_custom_field
 3441     field = IssueCustomField.find_by_name('Database')
 3442     field.update_attribute(:multiple, true)
 3443 
 3444     @request.session[:user_id] = 2
 3445     assert_difference 'Issue.count' do
 3446       post :create, :params => {
 3447           :project_id => 1,
 3448           :issue => {
 3449             :tracker_id => 1,
 3450             :subject => 'This is the test_new issue',
 3451             :description => 'This is the description',
 3452             :priority_id => 5,
 3453             :custom_field_values => {
 3454             '1' => ['']}
 3455           }
 3456         }
 3457     end
 3458     assert_response 302
 3459     issue = Issue.order('id DESC').first
 3460     assert_equal [''], issue.custom_field_value(1).sort
 3461   end
 3462 
 3463   def test_post_create_with_multi_user_custom_field
 3464     field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
 3465       :tracker_ids => [1], :is_for_all => true)
 3466 
 3467     @request.session[:user_id] = 2
 3468     assert_difference 'Issue.count' do
 3469       post :create, :params => {
 3470           :project_id => 1,
 3471           :issue => {
 3472             :tracker_id => 1,
 3473             :subject => 'This is the test_new issue',
 3474             :description => 'This is the description',
 3475             :priority_id => 5,
 3476             :custom_field_values => {
 3477             field.id.to_s => ['', '2', '3']}
 3478           }
 3479         }
 3480     end
 3481     assert_response 302
 3482     issue = Issue.order('id DESC').first
 3483     assert_equal ['2', '3'], issue.custom_field_value(field).sort
 3484   end
 3485 
 3486   def test_post_create_with_required_custom_field_and_without_custom_fields_param
 3487     field = IssueCustomField.find_by_name('Database')
 3488     field.update_attribute(:is_required, true)
 3489 
 3490     @request.session[:user_id] = 2
 3491     assert_no_difference 'Issue.count' do
 3492       post :create, :params => {
 3493           :project_id => 1,
 3494           :issue => {
 3495             :tracker_id => 1,
 3496             :subject => 'This is the test_new issue',
 3497             :description => 'This is the description',
 3498             :priority_id => 5
 3499           }
 3500         }
 3501     end
 3502     assert_response :success
 3503     assert_select_error /Database cannot be blank/
 3504   end
 3505 
 3506   def test_create_should_validate_required_fields
 3507     cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3508     cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3509     WorkflowPermission.delete_all
 3510     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
 3511     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
 3512     @request.session[:user_id] = 2
 3513 
 3514     assert_no_difference 'Issue.count' do
 3515       post :create, :params => {
 3516           :project_id => 1,
 3517           :issue => {
 3518             :tracker_id => 2,
 3519             :status_id => 1,
 3520             :subject => 'Test',
 3521             :start_date => '',
 3522             :due_date => '',
 3523             :custom_field_values => {
 3524               cf1.id.to_s => '', cf2.id.to_s => ''
 3525             }
 3526 
 3527           }
 3528         }
 3529       assert_response :success
 3530     end
 3531 
 3532     assert_select_error /Due date cannot be blank/i
 3533     assert_select_error /Bar cannot be blank/i
 3534   end
 3535 
 3536   def test_create_should_validate_required_list_fields
 3537     cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => false, :possible_values => ['a', 'b'])
 3538     cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => true, :possible_values => ['a', 'b'])
 3539     WorkflowPermission.delete_all
 3540     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf1.id.to_s, :rule => 'required')
 3541     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
 3542     @request.session[:user_id] = 2
 3543 
 3544     assert_no_difference 'Issue.count' do
 3545       post :create, :params => {
 3546           :project_id => 1,
 3547           :issue => {
 3548             :tracker_id => 2,
 3549             :status_id => 1,
 3550             :subject => 'Test',
 3551             :start_date => '',
 3552             :due_date => '',
 3553             :custom_field_values => {
 3554               cf1.id.to_s => '', cf2.id.to_s => ['']
 3555             }
 3556 
 3557           }
 3558         }
 3559       assert_response :success
 3560     end
 3561 
 3562     assert_select_error /Foo cannot be blank/i
 3563     assert_select_error /Bar cannot be blank/i
 3564   end
 3565 
 3566   def test_create_should_ignore_readonly_fields
 3567     cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3568     cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
 3569     WorkflowPermission.delete_all
 3570     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
 3571     WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
 3572     @request.session[:user_id] = 2
 3573 
 3574     assert_difference 'Issue.count' do
 3575       post :create, :params => {
 3576           :project_id => 1,
 3577           :issue => {
 3578             :tracker_id => 2,
 3579             :status_id => 1,
 3580             :subject => 'Test',
 3581             :start_date => '2012-07-14',
 3582             :due_date => '2012-07-16',
 3583             :custom_field_values => {
 3584               cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
 3585             }
 3586 
 3587           }
 3588         }
 3589       assert_response 302
 3590     end
 3591 
 3592     issue = Issue.order('id DESC').first
 3593     assert_equal Date.parse('2012-07-14'), issue.start_date
 3594     assert_nil issue.due_date
 3595     assert_equal 'value1', issue.custom_field_value(cf1)
 3596     assert_nil issue.custom_field_value(cf2)
 3597   end
 3598 
 3599   def test_create_should_ignore_unallowed_trackers
 3600     role = Role.find(1)
 3601     role.set_permission_trackers :add_issues, [3]
 3602     role.save!
 3603     @request.session[:user_id] = 2
 3604 
 3605     issue = new_record(Issue) do
 3606       post :create, :params => {
 3607           :project_id => 1,
 3608           :issue => {
 3609             :tracker_id => 1,
 3610             :status_id => 1,
 3611             :subject => 'Test'
 3612 
 3613           }
 3614         }
 3615       assert_response 302
 3616     end
 3617     assert_equal 3, issue.tracker_id
 3618   end
 3619 
 3620   def test_post_create_with_watchers
 3621     @request.session[:user_id] = 2
 3622     ActionMailer::Base.deliveries.clear
 3623 
 3624     with_settings :notified_events => %w(issue_added) do
 3625       assert_difference 'Watcher.count', 2 do
 3626         post :create, :params => {
 3627             :project_id => 1,
 3628             :issue => {
 3629               :tracker_id => 1,
 3630               :subject => 'This is a new issue with watchers',
 3631               :description => 'This is the description',
 3632               :priority_id => 5,
 3633               :watcher_user_ids => ['2', '3']
 3634             }
 3635           }
 3636       end
 3637     end
 3638     issue = Issue.find_by_subject('This is a new issue with watchers')
 3639     assert_not_nil issue
 3640     assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
 3641 
 3642     # Watchers added
 3643     assert_equal [2, 3], issue.watcher_user_ids.sort
 3644     assert issue.watched_by?(User.find(3))
 3645     # Watchers notified
 3646     mail = ActionMailer::Base.deliveries.last
 3647     assert_not_nil mail
 3648     assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
 3649   end
 3650 
 3651   def test_post_create_subissue
 3652     @request.session[:user_id] = 2
 3653 
 3654     assert_difference 'Issue.count' do
 3655       post :create, :params => {
 3656           :project_id => 1,
 3657           :issue => {
 3658             :tracker_id => 1,
 3659             :subject => 'This is a child issue',
 3660             :parent_issue_id => '2'
 3661           }
 3662         }
 3663       assert_response 302
 3664     end
 3665     issue = Issue.order('id DESC').first
 3666     assert_equal Issue.find(2), issue.parent
 3667   end
 3668 
 3669   def test_post_create_subissue_with_sharp_parent_id
 3670     @request.session[:user_id] = 2
 3671 
 3672     assert_difference 'Issue.count' do
 3673       post :create, :params => {
 3674           :project_id => 1,
 3675           :issue => {
 3676             :tracker_id => 1,
 3677             :subject => 'This is a child issue',
 3678             :parent_issue_id => '#2'
 3679           }
 3680         }
 3681       assert_response 302
 3682     end
 3683     issue = Issue.order('id DESC').first
 3684     assert_equal Issue.find(2), issue.parent
 3685   end
 3686 
 3687   def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
 3688     @request.session[:user_id] = 2
 3689 
 3690     assert_no_difference 'Issue.count' do
 3691       post :create, :params => {
 3692           :project_id => 1,
 3693           :issue => {
 3694             :tracker_id => 1,
 3695             :subject => 'This is a child issue',
 3696             :parent_issue_id => '4'
 3697           }
 3698         }
 3699 
 3700       assert_response :success
 3701       assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
 3702       assert_select_error /Parent task is invalid/i
 3703     end
 3704   end
 3705 
 3706   def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
 3707     @request.session[:user_id] = 2
 3708 
 3709     assert_no_difference 'Issue.count' do
 3710       post :create, :params => {
 3711           :project_id => 1,
 3712           :issue => {
 3713             :tracker_id => 1,
 3714             :subject => 'This is a child issue',
 3715             :parent_issue_id => '01ABC'
 3716           }
 3717         }
 3718 
 3719       assert_response :success
 3720       assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
 3721       assert_select_error /Parent task is invalid/i
 3722     end
 3723   end
 3724 
 3725   def test_post_create_private
 3726     @request.session[:user_id] = 2
 3727 
 3728     assert_difference 'Issue.count' do
 3729       post :create, :params => {
 3730           :project_id => 1,
 3731           :issue => {
 3732             :tracker_id => 1,
 3733             :subject => 'This is a private issue',
 3734             :is_private => '1'
 3735           }
 3736         }
 3737     end
 3738     issue = Issue.order('id DESC').first
 3739     assert issue.is_private?
 3740   end
 3741 
 3742   def test_post_create_private_with_set_own_issues_private_permission
 3743     role = Role.find(1)
 3744     role.remove_permission! :set_issues_private
 3745     role.add_permission! :set_own_issues_private
 3746 
 3747     @request.session[:user_id] = 2
 3748 
 3749     assert_difference 'Issue.count' do
 3750       post :create, :params => {
 3751           :project_id => 1,
 3752           :issue => {
 3753             :tracker_id => 1,
 3754             :subject => 'This is a private issue',
 3755             :is_private => '1'
 3756           }
 3757         }
 3758     end
 3759     issue = Issue.order('id DESC').first
 3760     assert issue.is_private?
 3761   end
 3762 
 3763   def test_create_without_project_id
 3764     @request.session[:user_id] = 2
 3765 
 3766     assert_difference 'Issue.count' do
 3767       post :create, :params => {
 3768           :issue => {
 3769             :project_id => 3,
 3770             :tracker_id => 2,
 3771             :subject => 'Foo'
 3772           }
 3773         }
 3774       assert_response 302
 3775     end
 3776     issue = Issue.order('id DESC').first
 3777     assert_equal 3, issue.project_id
 3778     assert_equal 2, issue.tracker_id
 3779   end
 3780 
 3781   def test_create_without_project_id_and_continue_should_redirect_without_project_id
 3782     @request.session[:user_id] = 2
 3783 
 3784     assert_difference 'Issue.count' do
 3785       post :create, :params => {
 3786           :issue => {
 3787             :project_id => 3,
 3788             :tracker_id => 2,
 3789             :subject => 'Foo'
 3790           },
 3791           :continue => '1'
 3792         }
 3793       assert_redirected_to '/issues/new?issue%5Bproject_id%5D=3&issue%5Btracker_id%5D=2'
 3794     end
 3795   end
 3796 
 3797   def test_create_without_project_id_should_be_denied_without_permission
 3798     Role.non_member.remove_permission! :add_issues
 3799     Role.anonymous.remove_permission! :add_issues
 3800     @request.session[:user_id] = 2
 3801 
 3802     assert_no_difference 'Issue.count' do
 3803       post :create, :params => {
 3804           :issue => {
 3805             :project_id => 3,
 3806             :tracker_id => 2,
 3807             :subject => 'Foo'
 3808           }
 3809         }
 3810       assert_response 422
 3811     end
 3812   end
 3813 
 3814   def test_create_without_project_id_with_failure_should_not_set_project
 3815     @request.session[:user_id] = 2
 3816 
 3817     post :create, :params => {
 3818         :issue => {
 3819           :project_id => 3,
 3820           :tracker_id => 2,
 3821           :subject => ''
 3822         }
 3823       }
 3824     assert_response :success
 3825     # no project menu
 3826     assert_select '#main-menu a.overview', 0
 3827   end
 3828 
 3829   def test_post_create_should_send_a_notification
 3830     ActionMailer::Base.deliveries.clear
 3831     @request.session[:user_id] = 2
 3832     with_settings :notified_events => %w(issue_added) do
 3833       assert_difference 'Issue.count' do
 3834         post :create, :params => {
 3835             :project_id => 1,
 3836             :issue => {
 3837               :tracker_id => 3,
 3838               :subject => 'This is the test_new issue',
 3839               :description => 'This is the description',
 3840               :priority_id => 5,
 3841               :estimated_hours => '',
 3842               :custom_field_values => {
 3843               '2' => 'Value for field 2'}
 3844             }
 3845           }
 3846       end
 3847       assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
 3848 
 3849       assert_equal 2, ActionMailer::Base.deliveries.size
 3850     end
 3851   end
 3852 
 3853   def test_post_create_should_preserve_fields_values_on_validation_failure
 3854     @request.session[:user_id] = 2
 3855     post :create, :params => {
 3856         :project_id => 1,
 3857         :issue => {
 3858           :tracker_id => 1,
 3859           :subject => '', # empty subject
 3860           :description => 'This is a description',
 3861           :priority_id => 6,
 3862           :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}
 3863         }
 3864       }
 3865     assert_response :success
 3866 
 3867     assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
 3868     assert_select 'select[name=?]', 'issue[priority_id]' do
 3869       assert_select 'option[value="6"][selected=selected]', :text => 'High'
 3870     end
 3871     # Custom fields
 3872     assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
 3873       assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
 3874     end
 3875     assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
 3876   end
 3877 
 3878   def test_post_create_with_failure_should_preserve_watchers
 3879     assert !User.find(8).member_of?(Project.find(1))
 3880 
 3881     @request.session[:user_id] = 2
 3882     post :create, :params => {
 3883         :project_id => 1,
 3884         :issue => {
 3885           :tracker_id => 1,
 3886           :watcher_user_ids => ['3', '8']
 3887         }
 3888       }
 3889     assert_response :success
 3890 
 3891     assert_select 'input[name=?][value="2"]:not(checked)', 'issue[watcher_user_ids][]'
 3892     assert_select 'input[name=?][value="3"][checked=checked]', 'issue[watcher_user_ids][]'
 3893     assert_select 'input[name=?][value="8"][checked=checked]', 'issue[watcher_user_ids][]'
 3894   end
 3895 
 3896   def test_post_create_should_ignore_non_safe_attributes
 3897     @request.session[:user_id] = 2
 3898     assert_nothing_raised do
 3899       post :create, :params => {
 3900           :project_id => 1,
 3901           :issue => {
 3902             :tracker => "A param can not be a Tracker"
 3903           }
 3904         }
 3905     end
 3906   end
 3907 
 3908   def test_post_create_with_attachment
 3909     set_tmp_attachments_directory
 3910     @request.session[:user_id] = 2
 3911 
 3912     assert_difference 'Issue.count' do
 3913       assert_difference 'Attachment.count' do
 3914         assert_no_difference 'Journal.count' do
 3915           post :create, :params => {
 3916               :project_id => 1,
 3917               :issue => {
 3918                 :tracker_id => '1',
 3919                 :subject => 'With attachment'
 3920               },
 3921               :attachments => {
 3922                 '1' => {
 3923                 'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}
 3924               }
 3925             }
 3926         end
 3927       end
 3928     end
 3929 
 3930     issue = Issue.order('id DESC').first
 3931     attachment = Attachment.order('id DESC').first
 3932 
 3933     assert_equal issue, attachment.container
 3934     assert_equal 2, attachment.author_id
 3935     assert_equal 'testfile.txt', attachment.filename
 3936     assert_equal 'text/plain', attachment.content_type
 3937     assert_equal 'test file', attachment.description
 3938     assert_equal 59, attachment.filesize
 3939     assert File.exists?(attachment.diskfile)
 3940     assert_equal 59, File.size(attachment.diskfile)
 3941   end
 3942 
 3943   def test_post_create_with_attachment_should_notify_with_attachments
 3944     ActionMailer::Base.deliveries.clear
 3945     set_tmp_attachments_directory
 3946     @request.session[:user_id] = 2
 3947 
 3948     with_settings :notified_events => %w(issue_added) do
 3949       assert_difference 'Issue.count' do
 3950         post :create, :params => {
 3951             :project_id => 1,
 3952             :issue => {
 3953               :tracker_id => '1',
 3954               :subject => 'With attachment'
 3955             },
 3956             :attachments => {
 3957               '1' => {
 3958               'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}
 3959             }
 3960           }
 3961       end
 3962     end
 3963 
 3964     assert_not_nil ActionMailer::Base.deliveries.last
 3965     assert_select_email do
 3966       assert_select 'a[href^=?]', 'http://localhost:3000/attachments/download', 'testfile.txt'
 3967     end
 3968   end
 3969 
 3970   def test_post_create_with_failure_should_save_attachments
 3971     set_tmp_attachments_directory
 3972     @request.session[:user_id] = 2
 3973 
 3974     assert_no_difference 'Issue.count' do
 3975       assert_difference 'Attachment.count' do
 3976         post :create, :params => {
 3977             :project_id => 1,
 3978             :issue => {
 3979               :tracker_id => '1',
 3980               :subject => ''
 3981             },
 3982             :attachments => {
 3983               '1' => {
 3984               'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}
 3985             }
 3986           }
 3987         assert_response :success
 3988       end
 3989     end
 3990 
 3991     attachment = Attachment.order('id DESC').first
 3992     assert_equal 'testfile.txt', attachment.filename
 3993     assert File.exists?(attachment.diskfile)
 3994     assert_nil attachment.container
 3995 
 3996     assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
 3997     assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
 3998   end
 3999 
 4000   def test_post_create_with_failure_should_keep_saved_attachments
 4001     set_tmp_attachments_directory
 4002     attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
 4003     @request.session[:user_id] = 2
 4004 
 4005     assert_no_difference 'Issue.count' do
 4006       assert_no_difference 'Attachment.count' do
 4007         post :create, :params => {
 4008             :project_id => 1,
 4009             :issue => {
 4010               :tracker_id => '1',
 4011               :subject => ''
 4012             },
 4013             :attachments => {
 4014               'p0' => {
 4015               'token' => attachment.token}
 4016             }
 4017           }
 4018         assert_response :success
 4019       end
 4020     end
 4021 
 4022     assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
 4023     assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
 4024   end
 4025 
 4026   def test_post_create_should_attach_saved_attachments
 4027     set_tmp_attachments_directory
 4028     attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
 4029     @request.session[:user_id] = 2
 4030 
 4031     assert_difference 'Issue.count' do
 4032       assert_no_difference 'Attachment.count' do
 4033         post :create, :params => {
 4034             :project_id => 1,
 4035             :issue => {
 4036               :tracker_id => '1',
 4037               :subject => 'Saved attachments'
 4038             },
 4039             :attachments => {
 4040               'p0' => {
 4041               'token' => attachment.token}
 4042             }
 4043           }
 4044         assert_response 302
 4045       end
 4046     end
 4047 
 4048     issue = Issue.order('id DESC').first
 4049     assert_equal 1, issue.attachments.count
 4050 
 4051     attachment.reload
 4052     assert_equal issue, attachment.container
 4053   end
 4054 
 4055   def setup_without_workflow_privilege
 4056     WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
 4057     Role.anonymous.add_permission! :add_issues, :add_issue_notes
 4058   end
 4059   private :setup_without_workflow_privilege
 4060 
 4061   test "without workflow privilege #new should propose default status only" do
 4062     setup_without_workflow_privilege
 4063     get :new, :params => {
 4064         :project_id => 1
 4065       }
 4066     assert_response :success
 4067 
 4068     assert_select 'select[name=?]', 'issue[status_id]' do
 4069       assert_select 'option', 1
 4070       assert_select 'option[value=?][selected=selected]', '1'
 4071     end
 4072   end
 4073 
 4074   test "without workflow privilege #create should accept default status" do
 4075     setup_without_workflow_privilege
 4076     assert_difference 'Issue.count' do
 4077       post :create, :params => {
 4078           :project_id => 1,
 4079           :issue => {
 4080             :tracker_id => 1,
 4081             :subject => 'This is an issue',
 4082             :status_id => 1
 4083           }
 4084         }
 4085     end
 4086     issue = Issue.order('id').last
 4087     assert_not_nil issue.default_status
 4088     assert_equal issue.default_status, issue.status
 4089   end
 4090 
 4091   test "without workflow privilege #create should ignore unauthorized status" do
 4092     setup_without_workflow_privilege
 4093     assert_difference 'Issue.count' do
 4094       post :create, :params => {
 4095           :project_id => 1,
 4096           :issue => {
 4097             :tracker_id => 1,
 4098             :subject => 'This is an issue',
 4099             :status_id => 3
 4100           }
 4101         }
 4102     end
 4103     issue = Issue.order('id').last
 4104     assert_not_nil issue.default_status
 4105     assert_equal issue.default_status, issue.status
 4106   end
 4107 
 4108   test "without workflow privilege #update should ignore status change" do
 4109     setup_without_workflow_privilege
 4110     assert_difference 'Journal.count' do
 4111       put :update, :params => {
 4112           :id => 1,
 4113           :issue => {
 4114             :status_id => 3,
 4115             :notes => 'just trying'
 4116           }
 4117         }
 4118     end
 4119     assert_equal 1, Issue.find(1).status_id
 4120   end
 4121 
 4122   test "without workflow privilege #update ignore attributes changes" do
 4123     setup_without_workflow_privilege
 4124     assert_difference 'Journal.count' do
 4125       put :update, :params => {
 4126           :id => 1,
 4127           :issue => {
 4128             :subject => 'changed',
 4129             :assigned_to_id => 2,
 4130             :notes => 'just trying'
 4131           }
 4132         }
 4133     end
 4134     issue = Issue.find(1)
 4135     assert_equal "Cannot print recipes", issue.subject
 4136     assert_nil issue.assigned_to
 4137   end
 4138 
 4139   def setup_with_workflow_privilege
 4140     WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
 4141     WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
 4142                                :old_status_id => 1, :new_status_id => 3)
 4143     WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
 4144                                :old_status_id => 1, :new_status_id => 4)
 4145     Role.anonymous.add_permission! :add_issues, :add_issue_notes
 4146   end
 4147   private :setup_with_workflow_privilege
 4148 
 4149   def setup_with_workflow_privilege_and_edit_issues_permission
 4150     setup_with_workflow_privilege
 4151     Role.anonymous.add_permission! :add_issues, :edit_issues
 4152   end
 4153   private :setup_with_workflow_privilege_and_edit_issues_permission
 4154 
 4155   test "with workflow privilege and :edit_issues permission should accept authorized status" do
 4156     setup_with_workflow_privilege_and_edit_issues_permission
 4157     assert_difference 'Journal.count' do
 4158       put :update, :params => {
 4159           :id => 1,
 4160           :issue => {
 4161             :status_id => 3,
 4162             :notes => 'just trying'
 4163           }
 4164         }
 4165     end
 4166     assert_equal 3, Issue.find(1).status_id
 4167   end
 4168 
 4169   test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
 4170     setup_with_workflow_privilege_and_edit_issues_permission
 4171     assert_difference 'Journal.count' do
 4172       put :update, :params => {
 4173           :id => 1,
 4174           :issue => {
 4175             :status_id => 2,
 4176             :notes => 'just trying'
 4177           }
 4178         }
 4179     end
 4180     assert_equal 1, Issue.find(1).status_id
 4181   end
 4182 
 4183   test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
 4184     setup_with_workflow_privilege_and_edit_issues_permission
 4185     assert_difference 'Journal.count' do
 4186       put :update, :params => {
 4187           :id => 1,
 4188           :issue => {
 4189             :subject => 'changed',
 4190             :assigned_to_id => 2,
 4191             :notes => 'just trying'
 4192           }
 4193         }
 4194     end
 4195     issue = Issue.find(1)
 4196     assert_equal "changed", issue.subject
 4197     assert_equal 2, issue.assigned_to_id
 4198   end
 4199 
 4200   def test_new_as_copy
 4201     orig = Issue.find(1)
 4202     @request.session[:user_id] = 2
 4203 
 4204     get :new, :params => {
 4205         :project_id => 1,
 4206         :copy_from => orig.id
 4207       }
 4208     assert_response :success
 4209 
 4210     assert_select 'form[id=issue-form][action="/projects/ecookbook/issues"]' do
 4211       assert_select 'select[name=?]', 'issue[project_id]' do
 4212         assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
 4213         assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
 4214       end
 4215       assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
 4216       assert_select 'input[name=copy_from][value="1"]'
 4217     end
 4218   end
 4219 
 4220   def test_new_as_copy_without_add_issues_permission_should_not_propose_current_project_as_target
 4221     user = setup_user_with_copy_but_not_add_permission
 4222 
 4223     @request.session[:user_id] = user.id
 4224     get :new, :params => {
 4225         :project_id => 1,
 4226         :copy_from => 1
 4227       }
 4228     assert_response :success
 4229 
 4230     assert_select 'select[name=?]', 'issue[project_id]' do
 4231       assert_select 'option[value="1"]', 0
 4232       assert_select 'option[value="2"]', :text => 'OnlineStore'
 4233     end
 4234   end
 4235 
 4236   def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
 4237     @request.session[:user_id] = 2
 4238     issue = Issue.find(3)
 4239     assert issue.attachments.count > 0
 4240     get :new, :params => {
 4241         :project_id => 1,
 4242         :copy_from => 3
 4243       }
 4244 
 4245     assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value="1"]'
 4246   end
 4247 
 4248   def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
 4249     @request.session[:user_id] = 2
 4250     issue = Issue.find(3)
 4251     issue.attachments.delete_all
 4252     get :new, :params => {
 4253         :project_id => 1,
 4254         :copy_from => 3
 4255       }
 4256 
 4257     assert_select 'input[name=copy_attachments]', 0
 4258   end
 4259 
 4260   def test_new_as_copy_should_preserve_parent_id
 4261     @request.session[:user_id] = 2
 4262     issue = Issue.generate!(:parent_issue_id => 2)
 4263     get :new, :params => {
 4264         :project_id => 1,
 4265         :copy_from => issue.id
 4266       }
 4267 
 4268     assert_select 'input[name=?][value="2"]', 'issue[parent_issue_id]'
 4269   end
 4270 
 4271   def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
 4272     @request.session[:user_id] = 2
 4273     issue = Issue.generate_with_descendants!
 4274     get :new, :params => {
 4275         :project_id => 1,
 4276         :copy_from => issue.id
 4277       }
 4278 
 4279     assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value="1"]'
 4280   end
 4281 
 4282   def test_new_as_copy_should_preserve_watchers
 4283     @request.session[:user_id] = 2
 4284     user = User.generate!
 4285     Watcher.create!(:watchable => Issue.find(1), :user => user)
 4286     get :new, :params => {
 4287         :project_id => 1,
 4288         :copy_from => 1
 4289       }
 4290 
 4291     assert_select 'input[type=checkbox][name=?][checked=checked]', 'issue[watcher_user_ids][]', 1
 4292     assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', user.id.to_s
 4293     assert_select 'input[type=hidden][name=?][value=?]', 'issue[watcher_user_ids][]', '', 1
 4294   end
 4295 
 4296   def test_new_as_copy_should_not_propose_locked_watchers
 4297     @request.session[:user_id] = 2
 4298 
 4299     issue = Issue.find(1)
 4300     user = User.generate!
 4301     user2 = User.generate!
 4302 
 4303     Watcher.create!(:watchable => issue, :user => user)
 4304     Watcher.create!(:watchable => issue, :user => user2)
 4305 
 4306     user2.status = User::STATUS_LOCKED
 4307     user2.save!
 4308     get :new, :params => {
 4309         :project_id => 1,
 4310         :copy_from => 1
 4311       }
 4312 
 4313     assert_select 'input[type=checkbox][name=?][checked=checked]', 'issue[watcher_user_ids][]', 1
 4314     assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', user.id.to_s
 4315     assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', user2.id.to_s, 0
 4316     assert_select 'input[type=hidden][name=?][value=?]', 'issue[watcher_user_ids][]', '', 1
 4317   end
 4318 
 4319   def test_new_as_copy_with_invalid_issue_should_respond_with_404
 4320     @request.session[:user_id] = 2
 4321     get :new, :params => {
 4322         :project_id => 1,
 4323         :copy_from => 99999
 4324       }
 4325     assert_response 404
 4326   end
 4327 
 4328   def test_create_as_copy_on_different_project
 4329     @request.session[:user_id] = 2
 4330     assert_difference 'Issue.count' do
 4331       post :create, :params => {
 4332           :project_id => 1,
 4333           :copy_from => 1,
 4334           :issue => {
 4335             :project_id => '2',
 4336             :tracker_id => '3',
 4337             :status_id => '1',
 4338             :subject => 'Copy'
 4339           }
 4340         }
 4341     end
 4342     issue = Issue.order('id DESC').first
 4343     assert_redirected_to "/issues/#{issue.id}"
 4344 
 4345     assert_equal 2, issue.project_id
 4346     assert_equal 3, issue.tracker_id
 4347     assert_equal 'Copy', issue.subject
 4348   end
 4349 
 4350   def test_create_as_copy_should_allow_status_to_be_set_to_default
 4351     copied = Issue.generate! :status_id => 2
 4352     assert_equal 2, copied.reload.status_id
 4353 
 4354     @request.session[:user_id] = 2
 4355     assert_difference 'Issue.count' do
 4356       post :create, :params => {
 4357           :project_id => 1,
 4358           :copy_from => copied.id,
 4359           :issue => {
 4360             :project_id => '1',
 4361             :tracker_id => '1',
 4362             :status_id => '1'
 4363           },
 4364           :was_default_status => '1'
 4365         }
 4366     end
 4367     issue = Issue.order('id DESC').first
 4368     assert_equal 1, issue.status_id
 4369   end
 4370 
 4371   def test_create_as_copy_should_fail_without_add_issue_permission_on_original_tracker
 4372     role = Role.find(2)
 4373     role.set_permission_trackers :add_issues, [1, 3]
 4374     role.save!
 4375     Role.non_member.remove_permission! :add_issues
 4376 
 4377     issue = Issue.generate!(:project_id => 1, :tracker_id => 2)
 4378     @request.session[:user_id] = 3
 4379 
 4380     assert_no_difference 'Issue.count' do
 4381       post :create, :params => {
 4382           :project_id => 1,
 4383           :copy_from => issue.id,
 4384           :issue => {
 4385             :project_id => '1'
 4386           }
 4387         }
 4388     end
 4389     assert_select_error 'Tracker is invalid'
 4390   end
 4391 
 4392   def test_create_as_copy_should_copy_attachments
 4393     @request.session[:user_id] = 2
 4394     issue = Issue.find(3)
 4395     count = issue.attachments.count
 4396     assert count > 0
 4397     assert_difference 'Issue.count' do
 4398       assert_difference 'Attachment.count', count do
 4399         post :create, :params => {
 4400             :project_id => 1,
 4401             :copy_from => 3,
 4402             :issue => {
 4403               :project_id => '1',
 4404               :tracker_id => '3',
 4405               :status_id => '1',
 4406               :subject => 'Copy with attachments'
 4407             },
 4408             :copy_attachments => '1'
 4409           }
 4410       end
 4411     end
 4412     copy = Issue.order('id DESC').first
 4413     assert_equal count, copy.attachments.count
 4414     assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
 4415   end
 4416 
 4417   def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
 4418     @request.session[:user_id] = 2
 4419     issue = Issue.find(3)
 4420     count = issue.attachments.count
 4421     assert count > 0
 4422     assert_difference 'Issue.count' do
 4423       assert_no_difference 'Attachment.count' do
 4424         post :create, :params => {
 4425             :project_id => 1,
 4426             :copy_from => 3,
 4427             :issue => {
 4428               :project_id => '1',
 4429               :tracker_id => '3',
 4430               :status_id => '1',
 4431               :subject => 'Copy with attachments'
 4432             }
 4433           }
 4434       end
 4435     end
 4436     copy = Issue.order('id DESC').first
 4437     assert_equal 0, copy.attachments.count
 4438   end
 4439 
 4440   def test_create_as_copy_with_attachments_should_also_add_new_files
 4441     set_tmp_attachments_directory
 4442     @request.session[:user_id] = 2
 4443     issue = Issue.find(3)
 4444     count = issue.attachments.count
 4445     assert count > 0
 4446     assert_difference 'Issue.count' do
 4447       assert_difference 'Attachment.count', count + 1 do
 4448         post :create, :params => {
 4449             :project_id => 1,
 4450             :copy_from => 3,
 4451             :issue => {
 4452               :project_id => '1',
 4453               :tracker_id => '3',
 4454               :status_id => '1',
 4455               :subject => 'Copy with attachments'
 4456             },
 4457             :copy_attachments => '1',
 4458             :attachments => {
 4459               '1' => {
 4460                 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
 4461                 'description' => 'test file'
 4462               }
 4463           }
 4464         }
 4465       end
 4466     end
 4467     copy = Issue.order('id DESC').first
 4468     assert_equal count + 1, copy.attachments.count
 4469   end
 4470 
 4471   def test_create_as_copy_should_add_relation_with_copied_issue
 4472     @request.session[:user_id] = 2
 4473     assert_difference 'Issue.count' do
 4474       assert_difference 'IssueRelation.count' do
 4475         post :create, :params => {
 4476             :project_id => 1,
 4477             :copy_from => 1,
 4478             :link_copy => '1',
 4479             :issue => {
 4480               :project_id => '1',
 4481               :tracker_id => '3',
 4482               :status_id => '1',
 4483               :subject => 'Copy'
 4484             }
 4485           }
 4486       end
 4487     end
 4488     copy = Issue.order('id DESC').first
 4489     assert_equal 1, copy.relations.size
 4490   end
 4491 
 4492   def test_create_as_copy_should_allow_not_to_add_relation_with_copied_issue
 4493     @request.session[:user_id] = 2
 4494     assert_difference 'Issue.count' do
 4495       assert_no_difference 'IssueRelation.count' do
 4496         post :create, :params => {
 4497             :project_id => 1,
 4498             :copy_from => 1,
 4499             :issue => {
 4500               :subject => 'Copy'
 4501             }
 4502           }
 4503       end
 4504     end
 4505   end
 4506 
 4507   def test_create_as_copy_should_always_add_relation_with_copied_issue_by_setting
 4508     with_settings :link_copied_issue => 'yes' do
 4509       @request.session[:user_id] = 2
 4510       assert_difference 'Issue.count' do
 4511         assert_difference 'IssueRelation.count' do
 4512           post :create, :params => {
 4513               :project_id => 1,
 4514               :copy_from => 1,
 4515               :issue => {
 4516                 :subject => 'Copy'
 4517               }
 4518             }
 4519         end
 4520       end
 4521     end
 4522   end
 4523 
 4524   def test_create_as_copy_should_never_add_relation_with_copied_issue_by_setting
 4525     with_settings :link_copied_issue => 'no' do
 4526       @request.session[:user_id] = 2
 4527       assert_difference 'Issue.count' do
 4528         assert_no_difference 'IssueRelation.count' do
 4529           post :create, :params => {
 4530               :project_id => 1,
 4531               :copy_from => 1,
 4532               :link_copy => '1',
 4533               :issue => {
 4534                 :subject => 'Copy'
 4535               }
 4536             }
 4537         end
 4538       end
 4539     end
 4540   end
 4541 
 4542   def test_create_as_copy_should_copy_subtasks
 4543     @request.session[:user_id] = 2
 4544     issue = Issue.generate_with_descendants!
 4545     count = issue.descendants.count
 4546     assert_difference 'Issue.count', count + 1 do
 4547       post :create, :params => {
 4548           :project_id => 1,
 4549           :copy_from => issue.id,
 4550           :issue => {
 4551             :project_id => '1',
 4552             :tracker_id => '3',
 4553             :status_id => '1',
 4554             :subject => 'Copy with subtasks'
 4555           },
 4556           :copy_subtasks => '1'
 4557         }
 4558     end
 4559     copy = Issue.where(:parent_id => nil).order('id DESC').first
 4560     assert_equal count, copy.descendants.count
 4561     assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
 4562   end
 4563 
 4564   def test_create_as_copy_to_a_different_project_should_copy_subtask_custom_fields
 4565     issue = Issue.generate! {|i| i.custom_field_values = {'2' => 'Foo'}}
 4566     child = Issue.generate!(:parent_issue_id => issue.id) {|i| i.custom_field_values = {'2' => 'Bar'}}
 4567     @request.session[:user_id] = 1
 4568 
 4569     assert_difference 'Issue.count', 2 do
 4570       post :create, :params => {
 4571           :project_id => 'ecookbook',
 4572           :copy_from => issue.id,
 4573           :issue => {
 4574             :project_id => '2',
 4575             :tracker_id => 1,
 4576             :status_id => '1',
 4577             :subject => 'Copy with subtasks',
 4578             :custom_field_values => {
 4579             '2' => 'Foo'}
 4580           },
 4581           :copy_subtasks => '1'
 4582         }
 4583     end
 4584 
 4585     child_copy, issue_copy = Issue.order(:id => :desc).limit(2).to_a
 4586     assert_equal 2, issue_copy.project_id
 4587     assert_equal 'Foo', issue_copy.custom_field_value(2)
 4588     assert_equal 'Bar', child_copy.custom_field_value(2)
 4589   end
 4590 
 4591   def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
 4592     @request.session[:user_id] = 2
 4593     issue = Issue.generate_with_descendants!
 4594     assert_difference 'Issue.count', 1 do
 4595       post :create, :params => {
 4596           :project_id => 1,
 4597           :copy_from => 3,
 4598           :issue => {
 4599             :project_id => '1',
 4600             :tracker_id => '3',
 4601             :status_id => '1',
 4602             :subject => 'Copy with subtasks'
 4603           }
 4604         }
 4605     end
 4606     copy = Issue.where(:parent_id => nil).order('id DESC').first
 4607     assert_equal 0, copy.descendants.count
 4608   end
 4609 
 4610   def test_create_as_copy_with_failure
 4611     @request.session[:user_id] = 2
 4612     post :create, :params => {
 4613         :project_id => 1,
 4614         :copy_from => 1,
 4615         :issue => {
 4616           :project_id => '2',
 4617           :tracker_id => '3',
 4618           :status_id => '1',
 4619           :subject => ''
 4620         }
 4621       }
 4622 
 4623     assert_response :success
 4624 
 4625     assert_select 'form#issue-form[action="/projects/ecookbook/issues"]' do
 4626       assert_select 'select[name=?]', 'issue[project_id]' do
 4627         assert_select 'option[value="1"]:not([selected])', :text => 'eCookbook'
 4628         assert_select 'option[value="2"][selected=selected]', :text => 'OnlineStore'
 4629       end
 4630       assert_select 'input[name=copy_from][value="1"]'
 4631     end
 4632   end
 4633 
 4634   def test_create_as_copy_on_project_without_permission_should_ignore_target_project
 4635     @request.session[:user_id] = 2
 4636     assert !User.find(2).member_of?(Project.find(4))
 4637 
 4638     assert_difference 'Issue.count' do
 4639       post :create, :params => {
 4640           :project_id => 1,
 4641           :copy_from => 1,
 4642           :issue => {
 4643             :project_id => '4',
 4644             :tracker_id => '3',
 4645             :status_id => '1',
 4646             :subject => 'Copy'
 4647           }
 4648         }
 4649     end
 4650     issue = Issue.order('id DESC').first
 4651     assert_equal 1, issue.project_id
 4652   end
 4653 
 4654   def test_create_as_copy_with_watcher_user_ids_should_copy_watchers
 4655     @request.session[:user_id] = 2
 4656     copied = Issue.generate!
 4657     copied.add_watcher User.find(2)
 4658     copied.add_watcher User.find(3)
 4659 
 4660     assert_difference 'Issue.count' do
 4661       post :create, :params => {
 4662           :project_id => 1,
 4663           :copy_from => copied.id,
 4664           :issue => {
 4665             :subject => 'Copy cleared watchers',
 4666             :watcher_user_ids => ['', '3']
 4667           }
 4668         }
 4669     end
 4670     issue = Issue.order('id DESC').first
 4671     assert_equal [3], issue.watcher_user_ids
 4672   end
 4673 
 4674   def test_create_as_copy_without_watcher_user_ids_should_not_copy_watchers
 4675     @request.session[:user_id] = 2
 4676     copied = Issue.generate!
 4677     copied.add_watcher User.find(2)
 4678     copied.add_watcher User.find(3)
 4679 
 4680     assert_difference 'Issue.count' do
 4681       post :create, :params => {
 4682           :project_id => 1,
 4683           :copy_from => copied.id,
 4684           :issue => {
 4685             :subject => 'Copy cleared watchers',
 4686             :watcher_user_ids => ['']
 4687           }
 4688         }
 4689     end
 4690     issue = Issue.order('id DESC').first
 4691     assert_equal [], issue.watcher_user_ids
 4692   end
 4693 
 4694   def test_get_edit
 4695     @request.session[:user_id] = 2
 4696     get :edit, :params => {
 4697         :id => 1
 4698       }
 4699     assert_response :success
 4700 
 4701     assert_select 'select[name=?]', 'issue[project_id]'
 4702     # Be sure we don't display inactive IssuePriorities
 4703     assert ! IssuePriority.find(15).active?
 4704     assert_select 'select[name=?]', 'issue[priority_id]' do
 4705       assert_select 'option[value="15"]', 0
 4706     end
 4707   end
 4708 
 4709   def test_edit_should_hide_project_if_user_is_not_allowed_to_change_project
 4710     WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :field_name => 'project_id', :rule => 'readonly')
 4711 
 4712     @request.session[:user_id] = 2
 4713     get :edit, :params => {
 4714         :id => 1
 4715       }
 4716     assert_response :success
 4717     assert_select 'select[name=?]', 'issue[project_id]', 0
 4718   end
 4719 
 4720   def test_edit_should_not_hide_project_when_user_changes_the_project_even_if_project_is_readonly_on_target_project
 4721     WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :field_name => 'project_id', :rule => 'readonly')
 4722     issue = Issue.generate!(:project_id => 2)
 4723 
 4724     @request.session[:user_id] = 2
 4725     get :edit, :params => {
 4726         :id => issue.id,
 4727         :issue => {
 4728           :project_id => 1
 4729         }
 4730       }
 4731     assert_response :success
 4732     assert_select 'select[name=?]', 'issue[project_id]'
 4733   end
 4734 
 4735   def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
 4736     @request.session[:user_id] = 2
 4737     Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
 4738 
 4739     get :edit, :params => {
 4740         :id => 1
 4741       }
 4742     assert_select 'input[name=?]', 'time_entry[hours]'
 4743   end
 4744 
 4745   def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
 4746     @request.session[:user_id] = 2
 4747     Role.find_by_name('Manager').remove_permission! :log_time
 4748 
 4749     get :edit, :params => {
 4750         :id => 1
 4751       }
 4752     assert_select 'input[name=?]', 'time_entry[hours]', 0
 4753   end
 4754 
 4755   def test_get_edit_with_params
 4756     @request.session[:user_id] = 2
 4757     get :edit, :params => {
 4758         :id => 1,
 4759         :issue => {
 4760           :status_id => 5,
 4761           :priority_id => 7
 4762         },
 4763         :time_entry => {
 4764           :hours => '2.5',
 4765           :comments => 'test_get_edit_with_params',
 4766           :activity_id => 10
 4767         }
 4768       }
 4769     assert_response :success
 4770 
 4771     assert_select 'select[name=?]', 'issue[status_id]' do
 4772       assert_select 'option[value="5"][selected=selected]', :text => 'Closed'
 4773     end
 4774 
 4775     assert_select 'select[name=?]', 'issue[priority_id]' do
 4776       assert_select 'option[value="7"][selected=selected]', :text => 'Urgent'
 4777     end
 4778 
 4779     assert_select 'input[name=?][value="2.50"]', 'time_entry[hours]'
 4780     assert_select 'select[name=?]', 'time_entry[activity_id]' do
 4781       assert_select 'option[value="10"][selected=selected]', :text => 'Development'
 4782     end
 4783     assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
 4784   end
 4785 
 4786   def test_get_edit_with_multi_custom_field
 4787     field = CustomField.find(1)
 4788     field.update_attribute :multiple, true
 4789     issue = Issue.find(1)
 4790     issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
 4791     issue.save!
 4792 
 4793     @request.session[:user_id] = 2
 4794     get :edit, :params => {
 4795         :id => 1
 4796       }
 4797     assert_response :success
 4798 
 4799     assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
 4800       assert_select 'option', 3
 4801       assert_select 'option[value=MySQL][selected=selected]'
 4802       assert_select 'option[value=Oracle][selected=selected]'
 4803       assert_select 'option[value=PostgreSQL]:not([selected])'
 4804     end
 4805   end
 4806 
 4807   def test_get_edit_with_me_assigned_to_id
 4808     @request.session[:user_id] = 2
 4809     get :edit, :params => {
 4810       :id => 1,
 4811       :issue => { :assigned_to_id => 'me' }
 4812     }
 4813     assert_response :success
 4814     assert_select 'select[name=?]', 'issue[assigned_to_id]' do
 4815       assert_select 'option[value="2"][selected=selected]'
 4816     end
 4817   end
 4818 
 4819   def test_update_form_for_existing_issue
 4820     @request.session[:user_id] = 2
 4821     patch :edit, :params => {
 4822         :id => 1,
 4823         :issue => {
 4824           :tracker_id => 2,
 4825           :subject => 'This is the test_new issue',
 4826           :description => 'This is the description',
 4827           :priority_id => 5
 4828         }
 4829       },
 4830       :xhr => true
 4831     assert_response :success
 4832     assert_equal 'text/javascript', response.content_type
 4833 
 4834     assert_include 'This is the test_new issue', response.body
 4835   end
 4836 
 4837   def test_update_form_for_existing_issue_should_keep_issue_author
 4838     @request.session[:user_id] = 3
 4839     patch :edit, :params => {
 4840         :id => 1,
 4841         :issue => {
 4842           :subject => 'Changed'
 4843         }
 4844       }
 4845     assert_response :success
 4846 
 4847     assert_equal User.find(2), Issue.find(1).author
 4848   end
 4849 
 4850   def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
 4851     @request.session[:user_id] = 2
 4852     WorkflowTransition.delete_all
 4853     WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
 4854     WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
 4855     WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
 4856 
 4857     patch :edit, :params => {
 4858         :id => 2,
 4859         :issue => {
 4860           :tracker_id => 2,
 4861           :status_id => 5,
 4862           :subject => 'This is an issue'
 4863         }
 4864       }
 4865 
 4866     assert_select 'select[name=?]', 'issue[status_id]' do
 4867       assert_select 'option[value="1"]'
 4868       assert_select 'option[value="2"]'
 4869       assert_select 'option[value="5"][selected=selected]'
 4870       assert_select 'option', 3
 4871     end
 4872   end
 4873 
 4874   def test_update_form_for_existing_issue_with_project_change
 4875     @request.session[:user_id] = 2
 4876     patch :edit, :params => {
 4877         :id => 1,
 4878         :issue => {
 4879           :project_id => 2,
 4880           :tracker_id => 2,
 4881           :subject => 'This is the test_new issue',
 4882           :description => 'This is the description',
 4883           :priority_id => 5
 4884         }
 4885       }
 4886     assert_response :success
 4887     assert_select 'select[name=?]', 'issue[project_id]' do
 4888       assert_select 'option[value="2"][selected=selected]'
 4889     end
 4890     assert_select 'select[name=?]', 'issue[tracker_id]' do
 4891       assert_select 'option[value="2"][selected=selected]'
 4892     end
 4893     assert_select 'input[name=?][value=?]', 'issue[subject]', 'This is the test_new issue'
 4894   end
 4895 
 4896   def test_update_form_should_keep_category_with_same_when_changing_project
 4897     source = Project.generate!
 4898     target = Project.generate!
 4899     source_category = IssueCategory.create!(:name => 'Foo', :project => source)
 4900     target_category = IssueCategory.create!(:name => 'Foo', :project => target)
 4901     issue = Issue.generate!(:project => source, :category => source_category)
 4902 
 4903     @request.session[:user_id] = 1
 4904     patch :edit, :params => {
 4905         :id => issue.id,
 4906         :issue => {
 4907           :project_id => target.id,
 4908           :category_id => source_category.id
 4909         }
 4910       }
 4911     assert_response :success
 4912 
 4913     assert_select 'select[name=?]', 'issue[category_id]' do
 4914       assert_select 'option[value=?][selected=selected]', target_category.id.to_s
 4915     end
 4916   end
 4917 
 4918   def test_update_form_should_propose_default_status_for_existing_issue
 4919     @request.session[:user_id] = 2
 4920     WorkflowTransition.delete_all
 4921     WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
 4922 
 4923     patch :edit, :params => {
 4924         :id => 2
 4925       }
 4926     assert_response :success
 4927     assert_select 'select[name=?]', 'issue[status_id]' do
 4928       assert_select 'option[value="2"]'
 4929       assert_select 'option[value="3"]'
 4930       assert_select 'option', 2
 4931     end
 4932   end
 4933 
 4934   def test_put_update_without_custom_fields_param
 4935     @request.session[:user_id] = 2
 4936 
 4937     issue = Issue.find(1)
 4938     assert_equal '125', issue.custom_value_for(2).value
 4939 
 4940     assert_difference('Journal.count') do
 4941       assert_difference('JournalDetail.count') do
 4942         put :update, :params => {
 4943             :id => 1,
 4944             :issue => {
 4945               :subject => 'New subject'
 4946             }
 4947           }
 4948       end
 4949     end
 4950     assert_redirected_to :action => 'show', :id => '1'
 4951     issue.reload
 4952     assert_equal 'New subject', issue.subject
 4953     # Make sure custom fields were not cleared
 4954     assert_equal '125', issue.custom_value_for(2).value
 4955   end
 4956 
 4957   def test_put_update_with_project_change
 4958     @request.session[:user_id] = 2
 4959     ActionMailer::Base.deliveries.clear
 4960 
 4961     with_settings :notified_events => %w(issue_updated) do
 4962       assert_difference('Journal.count') do
 4963         assert_difference('JournalDetail.count', 3) do
 4964           put :update, :params => {
 4965               :id => 1,
 4966               :issue => {
 4967                 :project_id => '2',
 4968                 :tracker_id => '1', # no change
 4969                 :priority_id => '6',
 4970                 :category_id => '3'
 4971               }
 4972             }
 4973         end
 4974       end
 4975     end
 4976     assert_redirected_to :action => 'show', :id => '1'
 4977     issue = Issue.find(1)
 4978     assert_equal 2, issue.project_id
 4979     assert_equal 1, issue.tracker_id
 4980     assert_equal 6, issue.priority_id
 4981     assert_equal 3, issue.category_id
 4982 
 4983     mail = ActionMailer::Base.deliveries.last
 4984     assert_not_nil mail
 4985     assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
 4986     assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
 4987   end
 4988 
 4989   def test_put_update_trying_to_move_issue_to_project_without_tracker_should_not_error
 4990     target = Project.generate!(:tracker_ids => [])
 4991     assert target.trackers.empty?
 4992     issue = Issue.generate!
 4993     @request.session[:user_id] = 1
 4994 
 4995     put :update, :params => {
 4996         :id => issue.id,
 4997         :issue => {
 4998           :project_id => target.id
 4999         }
 5000       }
 5001     assert_response 302
 5002   end
 5003 
 5004   def test_put_update_with_tracker_change
 5005     @request.session[:user_id] = 2
 5006     ActionMailer::Base.deliveries.clear
 5007 
 5008     with_settings :notified_events => %w(issue_updated) do
 5009       assert_difference('Journal.count') do
 5010         assert_difference('JournalDetail.count', 3) do
 5011           put :update, :params => {
 5012               :id => 1,
 5013               :issue => {
 5014                 :project_id => '1',
 5015                 :tracker_id => '2',
 5016                 :priority_id => '6'
 5017 
 5018               }
 5019             }
 5020         end
 5021       end
 5022     end
 5023     assert_redirected_to :action => 'show', :id => '1'
 5024     issue = Issue.find(1)
 5025     assert_equal 1, issue.project_id
 5026     assert_equal 2, issue.tracker_id
 5027     assert_equal 6, issue.priority_id
 5028     assert_equal 1, issue.category_id
 5029 
 5030     mail = ActionMailer::Base.deliveries.last
 5031     assert_not_nil mail
 5032     assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
 5033     assert_mail_body_match "Tracker changed from Bug to Feature request", mail
 5034   end
 5035 
 5036   def test_put_update_with_custom_field_change
 5037     @request.session[:user_id] = 2
 5038     issue = Issue.find(1)
 5039     assert_equal '125', issue.custom_value_for(2).value
 5040 
 5041     with_settings :notified_events => %w(issue_updated) do
 5042       assert_difference('Journal.count') do
 5043         assert_difference('JournalDetail.count', 3) do
 5044           put :update, :params => {
 5045               :id => 1,
 5046               :issue => {
 5047                 :subject => 'Custom field change',
 5048                 :priority_id => '6',
 5049                 :category_id => '1', # no change
 5050                 :custom_field_values => { '2' => 'New custom value' }
 5051               }
 5052             }
 5053         end
 5054       end
 5055     end
 5056     assert_redirected_to :action => 'show', :id => '1'
 5057     issue.reload
 5058     assert_equal 'New custom value', issue.custom_value_for(2).value
 5059 
 5060     mail = ActionMailer::Base.deliveries.last
 5061     assert_not_nil mail
 5062     assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
 5063   end
 5064 
 5065   def test_put_update_with_multi_custom_field_change
 5066     field = CustomField.find(1)
 5067     field.update_attribute :multiple, true
 5068     issue = Issue.find(1)
 5069     issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
 5070     issue.save!
 5071 
 5072     @request.session[:user_id] = 2
 5073     assert_difference('Journal.count') do
 5074       assert_difference('JournalDetail.count', 3) do
 5075         put :update, :params => {
 5076             :id => 1,
 5077             :issue => {
 5078               :subject => 'Custom field change',
 5079               :custom_field_values => {
 5080                 '1' => ['', 'Oracle', 'PostgreSQL']
 5081               }
 5082 
 5083             }
 5084           }
 5085       end
 5086     end
 5087     assert_redirected_to :action => 'show', :id => '1'
 5088     assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
 5089   end
 5090 
 5091   def test_put_update_with_status_and_assignee_change
 5092     issue = Issue.find(1)
 5093     assert_equal 1, issue.status_id
 5094     @request.session[:user_id] = 2
 5095 
 5096     with_settings :notified_events => %w(issue_updated) do
 5097       assert_difference('TimeEntry.count', 0) do
 5098         put :update, :params => {
 5099             :id => 1,
 5100             :issue => {
 5101               :status_id => 2,
 5102               :assigned_to_id => 3,
 5103               :notes => 'Assigned to dlopper'
 5104             },
 5105             :time_entry => {
 5106               :hours => '',
 5107               :comments => '',
 5108               :activity_id => TimeEntryActivity.first
 5109             }
 5110           }
 5111       end
 5112     end
 5113     assert_redirected_to :action => 'show', :id => '1'
 5114     issue.reload
 5115     assert_equal 2, issue.status_id
 5116     j = Journal.order('id DESC').first
 5117     assert_equal 'Assigned to dlopper', j.notes
 5118     assert_equal 2, j.details.size
 5119 
 5120     mail = ActionMailer::Base.deliveries.last
 5121     assert_mail_body_match "Status changed from New to Assigned", mail
 5122     # subject should contain the new status
 5123     assert mail.subject.include?("(#{IssueStatus.find(2).name})")
 5124   end
 5125 
 5126   def test_put_update_with_note_only
 5127     notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
 5128 
 5129     with_settings :notified_events => %w(issue_updated) do
 5130       # anonymous user
 5131       put :update, :params => {
 5132           :id => 1,
 5133           :issue => {
 5134             :notes => notes
 5135           }
 5136         }
 5137     end
 5138     assert_redirected_to :action => 'show', :id => '1'
 5139     j = Journal.order('id DESC').first
 5140     assert_equal notes, j.notes
 5141     assert_equal 0, j.details.size
 5142     assert_equal User.anonymous, j.user
 5143 
 5144     mail = ActionMailer::Base.deliveries.last
 5145     assert_mail_body_match notes, mail
 5146   end
 5147 
 5148   def test_put_update_with_private_note_only
 5149     notes = 'Private note'
 5150     @request.session[:user_id] = 2
 5151 
 5152     assert_difference 'Journal.count'