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