##// END OF EJS Templates
Merged r14160 (#19580)....
Jean-Philippe Lang -
r13831:490052575639
parent child
Show More
@@ -1,123 +1,123
1 1 <%= render :partial => 'action_menu' %>
2 2
3 3 <%= title l(:label_workflow) %>
4 4
5 5 <div class="tabs">
6 6 <ul>
7 7 <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers) %></li>
8 8 <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
9 9 </ul>
10 10 </div>
11 11
12 12 <p><%=l(:text_workflow_edit)%>:</p>
13 13
14 14 <%= form_tag({}, :method => 'get') do %>
15 15 <p>
16 16 <label><%=l(:label_role)%>:
17 17 <%= options_for_workflow_select 'role_id[]', Role.sorted.select(&:consider_workflow?), @roles, :id => 'role_id', :class => 'expandable' %>
18 18 </label>
19 19 <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
20 20
21 21 <label><%=l(:label_tracker)%>:
22 22 <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
23 23 </label>
24 24 <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
25 25
26 26 <%= submit_tag l(:button_edit), :name => nil %>
27 27
28 28 <%= hidden_field_tag 'used_statuses_only', '0', :id => nil %>
29 29 <label><%= check_box_tag 'used_statuses_only', '1', @used_statuses_only %> <%= l(:label_display_used_statuses_only) %></label>
30 30 </p>
31 31 <% end %>
32 32
33 33 <% if @trackers && @roles && @statuses.any? %>
34 34 <%= form_tag({}, :id => 'workflow_form' ) do %>
35 35 <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id, :id => nil}.join.html_safe %>
36 36 <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id, :id => nil}.join.html_safe %>
37 37 <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only], :id => nil %>
38 38 <div class="autoscroll">
39 39 <table class="list workflows fields_permissions">
40 40 <thead>
41 41 <tr>
42 42 <th>
43 43 </th>
44 44 <th colspan="<%= @statuses.length %>"><%=l(:label_issue_status)%></th>
45 45 </tr>
46 46 <tr>
47 47 <td></td>
48 48 <% for status in @statuses %>
49 49 <td style="width:<%= 75 / @statuses.size %>%;">
50 50 <%=h status.name %>
51 51 </td>
52 52 <% end %>
53 53 </tr>
54 54 </thead>
55 55 <tbody>
56 56 <tr class="group open">
57 57 <td colspan="<%= @statuses.size + 1 %>">
58 58 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
59 59 <%= l(:field_core_fields) %>
60 60 </td>
61 61 </tr>
62 62 <% @fields.each do |field, name| %>
63 63 <tr class="<%= cycle("odd", "even") %>">
64 64 <td class="name">
65 65 <%=h name %> <%= content_tag('span', '*', :class => 'required') if field_required?(field) %>
66 66 </td>
67 67 <% for status in @statuses -%>
68 <td class="<%= @permissions[status.id][field] %>">
68 <td class="<%= @permissions[status.id][field].try(:join, ' ') %>">
69 69 <%= field_permission_tag(@permissions, status, field, @roles) %>
70 70 <% unless status == @statuses.last %><a href="#" class="repeat-value">&#187;</a><% end %>
71 71 </td>
72 72 <% end -%>
73 73 </tr>
74 74 <% end %>
75 75 <% if @custom_fields.any? %>
76 76 <tr class="group open">
77 77 <td colspan="<%= @statuses.size + 1 %>">
78 78 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
79 79 <%= l(:label_custom_field_plural) %>
80 80 </td>
81 81 </tr>
82 82 <% @custom_fields.each do |field| %>
83 83 <tr class="<%= cycle("odd", "even") %>">
84 84 <td class="name">
85 85 <%=h field.name %> <%= content_tag('span', '*', :class => 'required') if field_required?(field) %>
86 86 </td>
87 87 <% for status in @statuses -%>
88 88 <td class="<%= @permissions[status.id][field.id.to_s] %>">
89 89 <%= field_permission_tag(@permissions, status, field, @roles) %>
90 90 <% unless status == @statuses.last %><a href="#" class="repeat-value">&#187;</a><% end %>
91 91 </td>
92 92 <% end -%>
93 93 </tr>
94 94 <% end %>
95 95 <% end %>
96 96 </tbody>
97 97 </table>
98 98 </div>
99 99 <%= submit_tag l(:button_save) %>
100 100 <% end %>
101 101 <% end %>
102 102
103 103 <%= javascript_tag do %>
104 104 $("a.repeat-value").click(function(e){
105 105 e.preventDefault();
106 106 var td = $(this).closest('td');
107 107 var selected = td.find("select").find(":selected").val();
108 108 td.nextAll('td').find("select").val(selected);
109 109 });
110 110
111 111 $("a[data-expands]").click(function(e){
112 112 e.preventDefault();
113 113 var target = $($(this).attr("data-expands"));
114 114 if (target.attr("multiple")) {
115 115 target.attr("multiple", false);
116 116 target.find("option[value=all]").show();
117 117 } else {
118 118 target.attr("multiple", true);
119 119 target.find("option[value=all]").attr("selected", false).hide();
120 120 }
121 121 });
122 122
123 123 <% end %>
@@ -1,360 +1,369
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class WorkflowsControllerTest < ActionController::TestCase
21 21 fixtures :roles, :trackers, :workflows, :users, :issue_statuses
22 22
23 23 def setup
24 24 User.current = nil
25 25 @request.session[:user_id] = 1 # admin
26 26 end
27 27
28 28 def test_index
29 29 get :index
30 30 assert_response :success
31 31 assert_template 'index'
32 32
33 33 count = WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count
34 34 assert_select 'a[href=?]', '/workflows/edit?role_id=1&tracker_id=2', :content => count.to_s
35 35 end
36 36
37 37 def test_get_edit
38 38 get :edit
39 39 assert_response :success
40 40 assert_template 'edit'
41 41 end
42 42
43 43 def test_get_edit_with_role_and_tracker
44 44 WorkflowTransition.delete_all
45 45 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 2, :new_status_id => 3)
46 46 WorkflowTransition.create!(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 5)
47 47
48 48 get :edit, :role_id => 2, :tracker_id => 1
49 49 assert_response :success
50 50 assert_template 'edit'
51 51
52 52 # used status only
53 53 assert_not_nil assigns(:statuses)
54 54 assert_equal [2, 3, 5], assigns(:statuses).collect(&:id)
55 55
56 56 # allowed transitions
57 57 assert_select 'input[type=checkbox][name=?][value="1"][checked=checked]', 'transitions[3][5][always]'
58 58 # not allowed
59 59 assert_select 'input[type=checkbox][name=?][value="1"]:not([checked=checked])', 'transitions[3][2][always]'
60 60 # unused
61 61 assert_select 'input[type=checkbox][name=?]', 'transitions[1][1][always]', 0
62 62 end
63 63
64 64 def test_get_edit_with_all_roles_and_all_trackers
65 65 get :edit, :role_id => 'all', :tracker_id => 'all'
66 66 assert_response :success
67 67 assert_equal Role.sorted.to_a, assigns(:roles)
68 68 assert_equal Tracker.sorted.to_a, assigns(:trackers)
69 69 end
70 70
71 71 def test_get_edit_with_role_and_tracker_and_all_statuses
72 72 WorkflowTransition.delete_all
73 73
74 74 get :edit, :role_id => 2, :tracker_id => 1, :used_statuses_only => '0'
75 75 assert_response :success
76 76 assert_template 'edit'
77 77
78 78 assert_not_nil assigns(:statuses)
79 79 assert_equal IssueStatus.count, assigns(:statuses).size
80 80
81 81 assert_select 'input[type=checkbox][name=?]', 'transitions[1][1][always]'
82 82 end
83 83
84 84 def test_post_edit
85 85 WorkflowTransition.delete_all
86 86
87 87 post :edit, :role_id => 2, :tracker_id => 1,
88 88 :transitions => {
89 89 '4' => {'5' => {'always' => '1'}},
90 90 '3' => {'1' => {'always' => '1'}, '2' => {'always' => '1'}}
91 91 }
92 92 assert_response 302
93 93
94 94 assert_equal 3, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
95 95 assert_not_nil WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
96 96 assert_nil WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4).first
97 97 end
98 98
99 99 def test_post_edit_with_additional_transitions
100 100 WorkflowTransition.delete_all
101 101
102 102 post :edit, :role_id => 2, :tracker_id => 1,
103 103 :transitions => {
104 104 '4' => {'5' => {'always' => '1', 'author' => '0', 'assignee' => '0'}},
105 105 '3' => {'1' => {'always' => '0', 'author' => '1', 'assignee' => '0'},
106 106 '2' => {'always' => '0', 'author' => '0', 'assignee' => '1'},
107 107 '4' => {'always' => '0', 'author' => '1', 'assignee' => '1'}}
108 108 }
109 109 assert_response 302
110 110
111 111 assert_equal 4, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
112 112
113 113 w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 4, :new_status_id => 5).first
114 114 assert ! w.author
115 115 assert ! w.assignee
116 116 w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 1).first
117 117 assert w.author
118 118 assert ! w.assignee
119 119 w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
120 120 assert ! w.author
121 121 assert w.assignee
122 122 w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 4).first
123 123 assert w.author
124 124 assert w.assignee
125 125 end
126 126
127 127 def test_get_permissions
128 128 get :permissions
129 129
130 130 assert_response :success
131 131 assert_template 'permissions'
132 132 end
133 133
134 134 def test_get_permissions_with_role_and_tracker
135 135 WorkflowPermission.delete_all
136 136 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'assigned_to_id', :rule => 'required')
137 137 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
138 138 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 3, :field_name => 'fixed_version_id', :rule => 'readonly')
139 139
140 140 get :permissions, :role_id => 1, :tracker_id => 2
141 141 assert_response :success
142 142 assert_template 'permissions'
143 143
144 144 assert_select 'input[name=?][value="1"]', 'role_id[]'
145 145 assert_select 'input[name=?][value="2"]', 'tracker_id[]'
146 146
147 147 # Required field
148 148 assert_select 'select[name=?]', 'permissions[2][assigned_to_id]' do
149 149 assert_select 'option[value=""]'
150 150 assert_select 'option[value=""][selected=selected]', 0
151 151 assert_select 'option[value=readonly]', :text => 'Read-only'
152 152 assert_select 'option[value=readonly][selected=selected]', 0
153 153 assert_select 'option[value=required]', :text => 'Required'
154 154 assert_select 'option[value=required][selected=selected]'
155 155 end
156 156
157 157 # Read-only field
158 158 assert_select 'select[name=?]', 'permissions[3][fixed_version_id]' do
159 159 assert_select 'option[value=""]'
160 160 assert_select 'option[value=""][selected=selected]', 0
161 161 assert_select 'option[value=readonly]', :text => 'Read-only'
162 162 assert_select 'option[value=readonly][selected=selected]'
163 163 assert_select 'option[value=required]', :text => 'Required'
164 164 assert_select 'option[value=required][selected=selected]', 0
165 165 end
166 166
167 167 # Other field
168 168 assert_select 'select[name=?]', 'permissions[3][due_date]' do
169 169 assert_select 'option[value=""]'
170 170 assert_select 'option[value=""][selected=selected]', 0
171 171 assert_select 'option[value=readonly]', :text => 'Read-only'
172 172 assert_select 'option[value=readonly][selected=selected]', 0
173 173 assert_select 'option[value=required]', :text => 'Required'
174 174 assert_select 'option[value=required][selected=selected]', 0
175 175 end
176 176 end
177 177
178 178 def test_get_permissions_with_required_custom_field_should_not_show_required_option
179 179 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :tracker_ids => [1], :is_required => true)
180 180
181 181 get :permissions, :role_id => 1, :tracker_id => 1
182 182 assert_response :success
183 183 assert_template 'permissions'
184 184
185 185 # Custom field that is always required
186 186 # The default option is "(Required)"
187 187 assert_select 'select[name=?]', "permissions[3][#{cf.id}]" do
188 188 assert_select 'option[value=""]'
189 189 assert_select 'option[value=readonly]', :text => 'Read-only'
190 190 assert_select 'option[value=required]', 0
191 191 end
192 192 end
193 193
194 194 def test_get_permissions_should_disable_hidden_custom_fields
195 195 cf1 = IssueCustomField.generate!(:tracker_ids => [1], :visible => true)
196 196 cf2 = IssueCustomField.generate!(:tracker_ids => [1], :visible => false, :role_ids => [1])
197 197 cf3 = IssueCustomField.generate!(:tracker_ids => [1], :visible => false, :role_ids => [1, 2])
198 198
199 199 get :permissions, :role_id => 2, :tracker_id => 1
200 200 assert_response :success
201 201 assert_template 'permissions'
202 202
203 203 assert_select 'select[name=?]:not(.disabled)', "permissions[1][#{cf1.id}]"
204 204 assert_select 'select[name=?]:not(.disabled)', "permissions[1][#{cf3.id}]"
205 205
206 206 assert_select 'select[name=?][disabled=disabled]', "permissions[1][#{cf2.id}]" do
207 207 assert_select 'option[value=""][selected=selected]', :text => 'Hidden'
208 208 end
209 209 end
210 210
211 211 def test_get_permissions_with_missing_permissions_for_roles_should_default_to_no_change
212 212 WorkflowPermission.delete_all
213 213 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
214 214
215 215 get :permissions, :role_id => [1, 2], :tracker_id => 2
216 216 assert_response :success
217 217
218 218 assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
219 219 assert_select 'option[selected]', 1
220 220 assert_select 'option[selected][value=no_change]'
221 221 end
222 222 end
223 223
224 224 def test_get_permissions_with_different_permissions_for_roles_should_default_to_no_change
225 225 WorkflowPermission.delete_all
226 226 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
227 227 WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'readonly')
228 228
229 229 get :permissions, :role_id => [1, 2], :tracker_id => 2
230 230 assert_response :success
231 231
232 232 assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
233 233 assert_select 'option[selected]', 1
234 234 assert_select 'option[selected][value=no_change]'
235 235 end
236 236 end
237 237
238 238 def test_get_permissions_with_same_permissions_for_roles_should_default_to_permission
239 239 WorkflowPermission.delete_all
240 240 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
241 241 WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
242 242
243 243 get :permissions, :role_id => [1, 2], :tracker_id => 2
244 244 assert_response :success
245 245
246 246 assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
247 247 assert_select 'option[selected]', 1
248 248 assert_select 'option[selected][value=required]'
249 249 end
250 250 end
251 251
252 252 def test_get_permissions_with_role_and_tracker_and_all_statuses_should_show_all_statuses
253 253 WorkflowTransition.delete_all
254 254
255 255 get :permissions, :role_id => 1, :tracker_id => 2, :used_statuses_only => '0'
256 256 assert_response :success
257 257 assert_equal IssueStatus.sorted.to_a, assigns(:statuses)
258 258 end
259 259
260 def test_get_permissions_should_set_css_class
261 WorkflowPermission.delete_all
262 WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
263
264 get :permissions, :role_id => 1, :tracker_id => 2
265 assert_response :success
266 assert_select 'td.required > select[name=?]', 'permissions[1][assigned_to_id]'
267 end
268
260 269 def test_post_permissions
261 270 WorkflowPermission.delete_all
262 271
263 272 post :permissions, :role_id => 1, :tracker_id => 2, :permissions => {
264 273 '1' => {'assigned_to_id' => '', 'fixed_version_id' => 'required', 'due_date' => ''},
265 274 '2' => {'assigned_to_id' => 'readonly', 'fixed_version_id' => 'readonly', 'due_date' => ''},
266 275 '3' => {'assigned_to_id' => '', 'fixed_version_id' => '', 'due_date' => ''}
267 276 }
268 277 assert_response 302
269 278
270 279 workflows = WorkflowPermission.all
271 280 assert_equal 3, workflows.size
272 281 workflows.each do |workflow|
273 282 assert_equal 1, workflow.role_id
274 283 assert_equal 2, workflow.tracker_id
275 284 end
276 285 assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'assigned_to_id' && wf.rule == 'readonly'}
277 286 assert workflows.detect {|wf| wf.old_status_id == 1 && wf.field_name == 'fixed_version_id' && wf.rule == 'required'}
278 287 assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'fixed_version_id' && wf.rule == 'readonly'}
279 288 end
280 289
281 290 def test_get_copy
282 291 get :copy
283 292 assert_response :success
284 293 assert_template 'copy'
285 294 assert_select 'select[name=source_tracker_id]' do
286 295 assert_select 'option[value="1"]', :text => 'Bug'
287 296 end
288 297 assert_select 'select[name=source_role_id]' do
289 298 assert_select 'option[value="2"]', :text => 'Developer'
290 299 end
291 300 assert_select 'select[name=?]', 'target_tracker_ids[]' do
292 301 assert_select 'option[value="3"]', :text => 'Support request'
293 302 end
294 303 assert_select 'select[name=?]', 'target_role_ids[]' do
295 304 assert_select 'option[value="1"]', :text => 'Manager'
296 305 end
297 306 end
298 307
299 308 def test_post_copy_one_to_one
300 309 source_transitions = status_transitions(:tracker_id => 1, :role_id => 2)
301 310
302 311 post :copy, :source_tracker_id => '1', :source_role_id => '2',
303 312 :target_tracker_ids => ['3'], :target_role_ids => ['1']
304 313 assert_response 302
305 314 assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1)
306 315 end
307 316
308 317 def test_post_copy_one_to_many
309 318 source_transitions = status_transitions(:tracker_id => 1, :role_id => 2)
310 319
311 320 post :copy, :source_tracker_id => '1', :source_role_id => '2',
312 321 :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
313 322 assert_response 302
314 323 assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 1)
315 324 assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1)
316 325 assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 3)
317 326 assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 3)
318 327 end
319 328
320 329 def test_post_copy_many_to_many
321 330 source_t2 = status_transitions(:tracker_id => 2, :role_id => 2)
322 331 source_t3 = status_transitions(:tracker_id => 3, :role_id => 2)
323 332
324 333 post :copy, :source_tracker_id => 'any', :source_role_id => '2',
325 334 :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
326 335 assert_response 302
327 336 assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 1)
328 337 assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 1)
329 338 assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 3)
330 339 assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 3)
331 340 end
332 341
333 342 def test_post_copy_with_incomplete_source_specification_should_fail
334 343 assert_no_difference 'WorkflowRule.count' do
335 344 post :copy,
336 345 :source_tracker_id => '', :source_role_id => '2',
337 346 :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
338 347 assert_response 200
339 348 assert_select 'div.flash.error', :text => 'Please select a source tracker or role'
340 349 end
341 350 end
342 351
343 352 def test_post_copy_with_incomplete_target_specification_should_fail
344 353 assert_no_difference 'WorkflowRule.count' do
345 354 post :copy,
346 355 :source_tracker_id => '1', :source_role_id => '2',
347 356 :target_tracker_ids => ['2', '3']
348 357 assert_response 200
349 358 assert_select 'div.flash.error', :text => 'Please select target tracker(s) and role(s)'
350 359 end
351 360 end
352 361
353 362 # Returns an array of status transitions that can be compared
354 363 def status_transitions(conditions)
355 364 WorkflowTransition.
356 365 where(conditions).
357 366 order('tracker_id, role_id, old_status_id, new_status_id').
358 367 collect {|w| [w.old_status, w.new_status_id]}
359 368 end
360 369 end
General Comments 0
You need to be logged in to leave comments. Login now