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