Project

General

Profile

Feature #31322 » 20200131-series.diff

Toshi MARUYAMA, 2020-01-31 15:22

View differences:

config/locales/en.yml
1192 1192
  text_time_logged_by_changeset: "Applied in changeset %{value}."
1193 1193
  text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?'
1194 1194
  text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)."
1195
  text_close_parent_issue_with_open_subtasks_confirmation: Are you sure you want to close parent issue with open subtasks?
1195 1196
  text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?'
1196 1197
  text_select_project_modules: 'Select modules to enable for this project:'
1197 1198
  text_default_administrator_account_changed: Default administrator account changed
app/views/issues/_edit.html.erb
82 82
    <%= hidden_field_tag 'issue_position', @issue_position if @issue_position %>
83 83
    <%= hidden_field_tag 'issue_count', @issue_count if @issue_count %>
84 84
<% end %>
85
<%= javascript_tag do %>
86
  $('#issue-form').submit(function(){
87
    var closedIssueStatusIds =
88
          <%= @allowed_statuses.select{|i| i.is_closed?}.map{|i| i.id.to_s}.to_json.html_safe  %> ;
89
    var children = $("#issue_tree").find("tr.issue.child");
90
    if (($.inArray($("#issue_status_id").val(), closedIssueStatusIds) > -1) &&
91
        (children.length > 0) &&
92
        ((children.length - $("#issue_tree").find("tr.issue.child.closed").length) > 0)) {
93
      if (!confirm(
94
          "<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>"
95
      )){
96
        return false;
97
      }
98
    }
99
    $("#issue-form").off('submit');
100
    $("#issue-form").submit();
101
  });
102
<% end %>
test/system/issues_test.rb
234 234
    assert_equal 5, issue.reload.status.id
235 235
  end
236 236

  
237
  test "add confirm dialog to issue submit button" do
238
    parent = Issue.generate!(:project_id => 1)
239
    child = Issue.generate!(:project_id => 1, :parent_issue_id => parent.id)
240
    with_settings :closed_parent_issues_with_open_subtasks => 1 do
241
      log_user('dlopper', 'foo')
242
      visit "/issues/#{parent.id}"
243

  
244
      page.first(:link, 'Edit').click
245
      assert page.has_select?("issue_status_id", {:selected => "New"})
246
      page.find("#issue_status_id").select("Closed")
247
      assert_no_difference ['Issue.count', 'child.journals.count'] do
248
        assert_no_difference 'parent.journals.count' do
249
          page.dismiss_confirm /Are you sure/ do
250
            page.first(:button, 'Submit').click
251
          end
252
          assert_equal 1, parent.reload.status.id
253
        end
254
        assert_difference 'parent.journals.count' do
255
          page.accept_confirm /Are you sure/ do
256
            page.first(:button, 'Submit').click
257
          end
258
          assert page.has_css?('#flash_notice')
259
          assert_equal 5, parent.reload.status.id
260
        end
261
      end
262

  
263
      page.first(:link, 'Edit').click
264
      assert page.has_select?("issue_status_id", {:selected => "Closed"})
265
      fill_in 'Subject', :with => 'test of confirm dialog'
266
      assert_no_difference ['Issue.count', 'child.journals.count'] do
267
        assert_no_difference 'parent.journals.count' do
268
          page.dismiss_confirm /Are you sure/ do
269
            page.first(:button, 'Submit').click
270
          end
271
          assert_equal 5, parent.reload.status.id
272
        end
273
        assert_difference 'parent.journals.count' do
274
          page.accept_confirm /Are you sure/ do
275
            page.first(:button, 'Submit').click
276
          end
277
          assert page.has_css?('#flash_notice')
278
          assert_equal 5, parent.reload.status.id
279
          assert_equal 'test of confirm dialog', parent.reload.subject
280
        end
281
      end
282

  
283
      page.first(:link, 'Edit').click
284
      assert page.has_select?("issue_status_id", {:selected => "Closed"})
285
      page.find("#issue_status_id").select("New")
286
      assert_no_difference ['Issue.count', 'child.journals.count'] do
287
        assert_difference 'parent.journals.count' do
288
          page.first(:button, 'Submit').click
289
          assert page.has_css?('#flash_notice')
290
          assert_equal 1, parent.reload.status.id
291
        end
292
      end
293

  
294
      visit "/issues/#{child.id}"
295
      page.first(:link, 'Edit').click
296
      assert page.has_select?("issue_status_id", {:selected => "New"})
297
      page.find("#issue_status_id").select("Closed")
298
      assert_no_difference ['Issue.count', 'parent.journals.count'] do
299
        assert_difference 'child.journals.count' do
300
          page.first(:button, 'Submit').click
301
          assert page.has_css?('#flash_notice')
302
          assert_equal 5, child.reload.status.id
303
        end
304
      end
305

  
306
      visit "/issues/#{parent.id}"
307
      page.first(:link, 'Edit').click
308
      assert page.has_select?("issue_status_id", {:selected => "New"})
309
      page.find("#issue_status_id").select("Closed")
310
      assert_no_difference ['Issue.count', 'child.journals.count'] do
311
        assert_difference 'parent.journals.count' do
312
          page.first(:button, 'Submit').click
313
          assert page.has_css?('#flash_notice')
314
          assert_equal 5, parent.reload.status.id
315
        end
316
      end
317
    end
318
  end
319

  
237 320
  test "removing issue shows confirm dialog" do
238 321
    log_user('jsmith', 'jsmith')
239 322
    visit '/issues/1'
app/controllers/issues_controller.rb
181 181
  end
182 182

  
183 183
  def update
184
    if request.xhr?
185
      if params[:check_go_to_close_confirm]
186
        result = true
187
        status_id = params[:status_id].to_i
188
        if status_id <= 0
189
          result = false
190
        else
191
          status = IssueStatus.find(status_id)
192
          if !status.is_closed
193
            result = false
194
          else
195
            result = !@issue.descendants.open.empty?
196
          end
197
        end
198
        render :json => {:result => result}
199
        return
200
      end
201

  
202
      return
203
    end
204

  
184 205
    return unless update_issue_from_params
185 206

  
186 207
    @issue.save_attachments(params[:attachments] ||
app/views/issues/_edit.html.erb
84 84
<% end %>
85 85
<%= javascript_tag do %>
86 86
  $('#issue-form').submit(function(){
87
    var closedIssueStatusIds =
88
          <%= @allowed_statuses.select{|i| i.is_closed?}.map{|i| i.id.to_s}.to_json.html_safe  %> ;
89
    var children = $("#issue_tree").find("tr.issue.child");
90
    if (($.inArray($("#issue_status_id").val(), closedIssueStatusIds) > -1) &&
91
        (children.length > 0) &&
92
        ((children.length - $("#issue_tree").find("tr.issue.child.closed").length) > 0)) {
87
    var status_id = 0;
88
    var result = false;
89
    if ($("#issue_status_id").length > 0) {
90
      status_id = $("#issue_status_id").val();
91
    }
92
    $.ajax({
93
      url: $("#issue-form").attr('action'),
94
      type: 'patch',
95
      async: false,
96
      data: { 
97
        "check_go_to_close_confirm": "",
98
        "status_id": status_id
99
       },
100
    })
101
      .then(
102
        function(data){
103
          result = data["result"];
104
        }
105
      );
106
    if (result) {
93 107
      if (!confirm(
94 108
          "<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>"
95 109
      )){
test/functional/issues_controller_test.rb
6242 6242
    assert_equal 2, issue.reload.assigned_to_id
6243 6243
  end
6244 6244

  
6245
  test "check_go_to_close_confirm returns false if status_id is not close" do
6246
    issue = Issue.find(1)
6247
    user = User.find(2)
6248
    assert issue.visible?(user)
6249
    assert_not issue.closed?
6250
    @request.session[:user_id] = user.id
6251
    put(
6252
      :update,
6253
      :params => {
6254
        :id => issue.id,
6255
        :check_go_to_close_confirm => "",
6256
        :status_id => 1
6257
      },
6258
      :xhr => true
6259
    )
6260
    assert_response :success
6261
    assert_equal 'application/json', response.content_type
6262
    json = ActiveSupport::JSON.decode(response.body)
6263
    assert_equal({"result" => false}, json)
6264
  end
6265

  
6266
  test "check_go_to_close_confirm returns false if status_id is 0" do
6267
    issue = Issue.find(1)
6268
    user = User.find(2)
6269
    assert issue.visible?(user)
6270
    assert_not issue.closed?
6271
    @request.session[:user_id] = user.id
6272
    put(
6273
      :update,
6274
      :params => {
6275
        :id => issue.id,
6276
        :check_go_to_close_confirm => "",
6277
        :status_id => 0
6278
      },
6279
      :xhr => true
6280
    )
6281
    assert_response :success
6282
    assert_equal 'application/json', response.content_type
6283
    json = ActiveSupport::JSON.decode(response.body)
6284
    assert_equal({"result" => false}, json)
6285
  end
6286

  
6287
  test "check_go_to_close_confirm returns false if issue does not have child" do
6288
    issue = Issue.generate!
6289
    user = User.find(2)
6290
    assert issue.visible?(user)
6291
    assert_not issue.closed?
6292
    @request.session[:user_id] = user.id
6293
    put(
6294
      :update,
6295
      :params => {
6296
        :id => issue.id,
6297
        :check_go_to_close_confirm => "",
6298
        :status_id => 5
6299
      },
6300
      :xhr => true
6301
    )
6302
    assert_response :success
6303
    assert_equal 'application/json', response.content_type
6304
    json = ActiveSupport::JSON.decode(response.body)
6305

  
6306
    assert_equal 1, issue.reload.status.id
6307
    assert_equal({"result" => false}, json)
6308
  end
6309

  
6310
  test "check_go_to_close_confirm returns true if issue have open child" do
6311
    parent = Issue.generate!
6312
    child = Issue.generate!(:parent_issue_id => parent.id)
6313
    user = User.find(2)
6314
    assert parent.reload.visible?(user)
6315
    assert_not parent.closed?
6316
    assert child.reload.visible?(user)
6317
    assert_not child.closed?
6318

  
6319
    @request.session[:user_id] = user.id
6320
    put(
6321
      :update,
6322
      :params => {
6323
        :id => parent.id,
6324
        :check_go_to_close_confirm => "",
6325
        :status_id => 5
6326
      },
6327
      :xhr => true
6328
    )
6329
    assert_response :success
6330
    assert_equal 'application/json', response.content_type
6331
    json = ActiveSupport::JSON.decode(response.body)
6332

  
6333
    assert_equal 1, parent.reload.status.id
6334
    assert_equal({"result" => true}, json)
6335
  end
6336

  
6337
  test "check_go_to_close_confirm returns false if child is closed" do
6338
    parent = Issue.generate!
6339
    child = Issue.
6340
              generate!(
6341
                :parent_issue_id => parent.id,
6342
                :status_id => 5
6343
              )
6344
    user = User.find(2)
6345
    assert parent.reload.visible?(user)
6346
    assert_not parent.closed?
6347
    assert child.reload.visible?(user)
6348
    assert child.closed?
6349

  
6350
    @request.session[:user_id] = user.id
6351
    put(
6352
      :update,
6353
      :params => {
6354
        :id => parent.id,
6355
        :check_go_to_close_confirm => "",
6356
        :status_id => 5
6357
      },
6358
      :xhr => true
6359
    )
6360
    assert_response :success
6361
    assert_equal 'application/json', response.content_type
6362
    json = ActiveSupport::JSON.decode(response.body)
6363

  
6364
    assert_equal 1, parent.reload.status.id
6365
    assert_equal({"result" => false}, json)
6366
  end
6367

  
6368
  test "check_go_to_close_confirm returns true if child is open and not visible" do
6369
    user = User.generate!
6370
    project = Project.generate!
6371
    role = Role.generate!
6372
    role.add_permission! :view_issues, :edit_issues
6373
    role.set_permission_trackers :view_issues, [2]
6374
    role.set_permission_trackers :edit_issues, [2]
6375
    role.save!
6376
    User.add_to_project(user, project, role)
6377
    parent = Issue.
6378
              generate!(
6379
                :project => project,
6380
                :tracker_id => 2,
6381
                :status_id => 1
6382
              )
6383
    child = Issue.
6384
              generate!(
6385
                :project => project,
6386
                :tracker_id => 1,
6387
                :parent_issue_id => parent.id,
6388
                :status_id => 1
6389
              )
6390
    assert parent.reload.visible?(user)
6391
    assert_not parent.closed?
6392
    assert_not child.reload.visible?(user)
6393
    assert_not child.closed?
6394

  
6395
    @request.session[:user_id] = user.id
6396
    put(
6397
      :update,
6398
      :params => {
6399
        :id => parent.id,
6400
        :check_go_to_close_confirm => "",
6401
        :status_id => 5
6402
      },
6403
      :xhr => true
6404
    )
6405
    assert_response :success
6406
    assert_equal 'application/json', response.content_type
6407
    json = ActiveSupport::JSON.decode(response.body)
6408

  
6409
    assert_equal 1, parent.reload.status.id
6410
    assert_equal({"result" => true}, json)
6411
  end
6412

  
6245 6413
  def test_get_bulk_edit
6246 6414
    @request.session[:user_id] = 2
6247 6415
    get(:bulk_edit, :params => {:ids => [1, 3]})
app/controllers/issues_controller.rb
199 199
        return
200 200
      end
201 201

  
202
      render(
203
        :partial => 'close_confirm',
204
        :layout => false,
205
        :locals => {}
206
      )
202 207
      return
203 208
    end
204 209

  
app/views/issues/_close_confirm.js.erb
1
$('#ajax-modal').html(
2
  '<%= escape_javascript(
3
         render(
4
           :partial => 'close_confirm_dialog',
5
           :locals  => {}
6
         )
7
       )
8
   %>'
9
);
10
showModal('ajax-modal', '400px');
app/views/issues/_close_confirm_dialog.html.erb
1
<h3 class="title">&nbsp;</h3>
2
<p>
3
  <%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>
4
</p>
5
<p class="buttons">
6
  <%= button_tag l(:button_apply), :type => "button", :onclick => "run_submit();" %>
7
  <%= link_to_function l(:button_cancel), "hideModal(this);" %>
8
</p>
9

  
10
<%= javascript_tag do %>
11
  function run_submit() {
12
    $("#issue-form").off('submit');
13
    $("#issue-form").submit();
14
  }
15
<% end %>
app/views/issues/_edit.html.erb
85 85
<%= javascript_tag do %>
86 86
  $('#issue-form').submit(function(){
87 87
    var status_id = 0;
88
    var result = false;
89 88
    if ($("#issue_status_id").length > 0) {
90 89
      status_id = $("#issue_status_id").val();
91 90
    }
92 91
    $.ajax({
93 92
      url: $("#issue-form").attr('action'),
94 93
      type: 'patch',
95
      async: false,
96 94
      data: { 
97 95
        "check_go_to_close_confirm": "",
98 96
        "status_id": status_id
......
100 98
    })
101 99
      .then(
102 100
        function(data){
103
          result = data["result"];
101
          if (data["result"]) {
102
            $.ajax({
103
              url:   $("#issue-form").attr('action'),
104
              type: 'patch',
105
              data: {}
106
              });
107
          } else {
108
            $("#issue-form").off('submit');
109
            $("#issue-form").submit();
110
          }
104 111
        }
105 112
      );
106
    if (result) {
107
      if (!confirm(
108
          "<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>"
109
      )){
110
        return false;
111
      }
112
    }
113
    $("#issue-form").off('submit');
114
    $("#issue-form").submit();
113
    return false;
115 114
  });
116 115
<% end %>
test/system/issues_test.rb
246 246
      page.find("#issue_status_id").select("Closed")
247 247
      assert_no_difference ['Issue.count', 'child.journals.count'] do
248 248
        assert_no_difference 'parent.journals.count' do
249
          page.dismiss_confirm /Are you sure/ do
250
            page.first(:button, 'Submit').click
249
          page.first(:button, 'Submit').click
250
          within('#ajax-modal') do
251
            assert page.has_text?(/Are you sure/)
252
            page.first(:link, 'Cancel').click
251 253
          end
252 254
          assert_equal 1, parent.reload.status.id
253 255
        end
254 256
        assert_difference 'parent.journals.count' do
255
          page.accept_confirm /Are you sure/ do
256
            page.first(:button, 'Submit').click
257
          page.first(:button, 'Submit').click
258
          within('#ajax-modal') do
259
            assert page.has_text?(/Are you sure/)
260
            page.first(:button, 'Apply').click
257 261
          end
258 262
          assert page.has_css?('#flash_notice')
259 263
          assert_equal 5, parent.reload.status.id
......
265 269
      fill_in 'Subject', :with => 'test of confirm dialog'
266 270
      assert_no_difference ['Issue.count', 'child.journals.count'] do
267 271
        assert_no_difference 'parent.journals.count' do
268
          page.dismiss_confirm /Are you sure/ do
269
            page.first(:button, 'Submit').click
272
          page.first(:button, 'Submit').click
273
          within('#ajax-modal') do
274
            assert page.has_text?(/Are you sure/)
275
            page.first(:link, 'Cancel').click
270 276
          end
271 277
          assert_equal 5, parent.reload.status.id
272 278
        end
273 279
        assert_difference 'parent.journals.count' do
274
          page.accept_confirm /Are you sure/ do
275
            page.first(:button, 'Submit').click
280
        page.first(:button, 'Submit').click
281
          within('#ajax-modal') do
282
            assert page.has_text?(/Are you sure/)
283
            page.first(:button, 'Apply').click
276 284
          end
277 285
          assert page.has_css?('#flash_notice')
278 286
          assert_equal 5, parent.reload.status.id
app/controllers/issues_controller.rb
184 184
    if request.xhr?
185 185
      if params[:check_go_to_close_confirm]
186 186
        result = true
187
        status = nil
187 188
        status_id = params[:status_id].to_i
189
        can_close_all_descendants = true
188 190
        if status_id <= 0
189 191
          result = false
190 192
        else
......
192 194
          if !status.is_closed
193 195
            result = false
194 196
          else
195
            result = !@issue.descendants.open.empty?
197
            opened_descendants = []
198
            @issue.descendants.open.sort_by(&:lft).each do |issue|
199
              unless issue.visible?
200
                can_close_all_descendants = false
201
                break
202
              end
203

  
204
              unless issue.new_statuses_allowed_to.map{|i| i.id}.include?(status.id)
205
                can_close_all_descendants = false
206
                break
207
              end
208

  
209
              opened_descendants << issue
210
            end
211
            if can_close_all_descendants && opened_descendants.empty?
212
              result = false
213
              can_close_all_descendants = false
214
            end
215
          end
216
          if result
217
            session[:can_close_descendant] = {}
218
            session[:can_close_descendant][:can_close_all] = can_close_all_descendants
219
            if can_close_all_descendants
220
              session[:can_close_descendant][:status_id] = status.id
221
              session[:can_close_descendant][:status_name] = status.name
222
              session[:can_close_descendant][:ids] = opened_descendants.map{|i| i.id}
223
            end
196 224
          end
197 225
        end
198 226
        render :json => {:result => result}
199 227
        return
200 228
      end
201 229

  
230
      if !session.has_key?(:can_close_descendant)
231
        return
232
      end
233

  
234
      render_data = {
235
        :status_name => session[:can_close_descendant][:status_name],
236
        :can_close_all => session[:can_close_descendant][:can_close_all]
237
      }
202 238
      render(
203 239
        :partial => 'close_confirm',
204 240
        :layout => false,
205
        :locals => {}
241
        :locals => render_data
206 242
      )
207 243
      return
208 244
    end
......
226 262

  
227 263
    if saved
228 264
      render_attachment_warning_if_needed(@issue)
265
      if params[:close_descendants] && session.has_key?(:can_close_descendant)
266
        close_descendant_ids = session[:can_close_descendant][:ids]
267
        session.delete(:can_close_descendant)
268
        close_descendant_ids.each do |id|
269
          issue = Issue.find(id)
270
          issue.init_journal(User.current, params[:issue][:notes])
271
          issue.safe_attributes = {'status_id' => params[:issue][:status_id].to_i}
272
          issue.save
273
        end
274
      end
275

  
229 276
      unless @issue.current_journal.new_record? || params[:no_flash]
230 277
        flash[:notice] = l(:notice_successful_update)
231 278
      end
app/views/issues/_close_confirm.js.erb
2 2
  '<%= escape_javascript(
3 3
         render(
4 4
           :partial => 'close_confirm_dialog',
5
           :locals  => {}
5
           :locals  => {
6
             :status_name => status_name,
7
             :can_close_all => can_close_all
8
           }
6 9
         )
7 10
       )
8 11
   %>'
app/views/issues/_close_confirm_dialog.html.erb
1 1
<h3 class="title">&nbsp;</h3>
2
<p>
3
  <%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>
4
</p>
2
<% if can_close_all %>
3
  <p>
4
    <%= l(:text_close_parent_issue_and_open_subtasks,
5
          :issue_id => params[:id]) %>
6
  </p>
7
  <p>
8
    <label class="block">
9
      <%= radio_button_tag 'choice', '1' %>
10
      <%= l(:text_close_parent_issue_and_open_subtasks_choice_close_also_all_subtasks,
11
            :status => status_name) %>
12
    </label>
13
    <label class="block">
14
      <%= radio_button_tag 'choice', '2', true %>
15
      <%= l(:text_close_parent_issue_and_open_subtasks_choice_close_only_parent,
16
            :issue_id => params[:id]) %>
17
    </label>
18
  </p>
19
<% else %>
20
  <p>
21
    <%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>
22
  </p>
23
<% end %>
5 24
<p class="buttons">
6 25
  <%= button_tag l(:button_apply), :type => "button", :onclick => "run_submit();" %>
7 26
  <%= link_to_function l(:button_cancel), "hideModal(this);" %>
......
9 28

  
10 29
<%= javascript_tag do %>
11 30
  function run_submit() {
31
    var canCloseAll = <%= can_close_all %>;
32
    if (canCloseAll) {
33
      var radioVal = $("input[name='choice']:checked").val();
34
      if (radioVal == '1') {
35
        $('<input />').attr('type', 'hidden')
36
            .attr('name', "close_descendants")
37
            .appendTo('#issue-form');
38
      }
39
    }
12 40
    $("#issue-form").off('submit');
13 41
    $("#issue-form").submit();
14 42
  }
config/locales/en.yml
1193 1193
  text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?'
1194 1194
  text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)."
1195 1195
  text_close_parent_issue_with_open_subtasks_confirmation: Are you sure you want to close parent issue with open subtasks?
1196
  text_close_parent_issue_and_open_subtasks: Issue %{issue_id} has open subtasks.
1197
  text_close_parent_issue_and_open_subtasks_choice_close_also_all_subtasks: Close all open subtasks by "%{status}" status too
1198
  text_close_parent_issue_and_open_subtasks_choice_close_only_parent: Close only issue %{issue_id}
1196 1199
  text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?'
1197 1200
  text_select_project_modules: 'Select modules to enable for this project:'
1198 1201
  text_default_administrator_account_changed: Default administrator account changed
test/system/issues_test.rb
237 237
  test "add confirm dialog to issue submit button" do
238 238
    parent = Issue.generate!(:project_id => 1)
239 239
    child = Issue.generate!(:project_id => 1, :parent_issue_id => parent.id)
240
    hidden_child =
241
      Issue.
242
        generate!(
243
          :project_id => 1,
244
          :parent_issue_id => parent.id,
245
          :author_id => 2,
246
          :is_private => true
247
        )
248
    assert_not hidden_child.visible?(User.find(3))
240 249
    with_settings :closed_parent_issues_with_open_subtasks => 1 do
241 250
      log_user('dlopper', 'foo')
242 251
      visit "/issues/#{parent.id}"
......
311 320
        end
312 321
      end
313 322

  
323
      hidden_child.status_id = 5
324
      hidden_child.save!
325

  
314 326
      visit "/issues/#{parent.id}"
315 327
      page.first(:link, 'Edit').click
316 328
      assert page.has_select?("issue_status_id", {:selected => "New"})
test/functional/issues_controller_test.rb
6261 6261
    assert_equal 'application/json', response.content_type
6262 6262
    json = ActiveSupport::JSON.decode(response.body)
6263 6263
    assert_equal({"result" => false}, json)
6264
    assert_not session.has_key?(:can_close_descendant)
6264 6265
  end
6265 6266

  
6266 6267
  test "check_go_to_close_confirm returns false if status_id is 0" do
......
6282 6283
    assert_equal 'application/json', response.content_type
6283 6284
    json = ActiveSupport::JSON.decode(response.body)
6284 6285
    assert_equal({"result" => false}, json)
6286
    assert_not session.has_key?(:can_close_descendant)
6285 6287
  end
6286 6288

  
6287 6289
  test "check_go_to_close_confirm returns false if issue does not have child" do
......
6305 6307

  
6306 6308
    assert_equal 1, issue.reload.status.id
6307 6309
    assert_equal({"result" => false}, json)
6310
    assert_not session.has_key?(:can_close_descendant)
6308 6311
  end
6309 6312

  
6310 6313
  test "check_go_to_close_confirm returns true if issue have open child" do
......
6332 6335

  
6333 6336
    assert_equal 1, parent.reload.status.id
6334 6337
    assert_equal({"result" => true}, json)
6338
    assert session.has_key?(:can_close_descendant)
6335 6339
  end
6336 6340

  
6337 6341
  test "check_go_to_close_confirm returns false if child is closed" do
......
6363 6367

  
6364 6368
    assert_equal 1, parent.reload.status.id
6365 6369
    assert_equal({"result" => false}, json)
6370
    assert_not session.has_key?(:can_close_descendant)
6366 6371
  end
6367 6372

  
6368 6373
  test "check_go_to_close_confirm returns true if child is open and not visible" do
......
6408 6413

  
6409 6414
    assert_equal 1, parent.reload.status.id
6410 6415
    assert_equal({"result" => true}, json)
6416
    assert session.has_key?(:can_close_descendant)
6417
    assert_not session[:can_close_descendant][:can_close_all]
6411 6418
  end
6412 6419

  
6413 6420
  def test_get_bulk_edit
test/functional/issues_controller_test.rb
6417 6417
    assert_not session[:can_close_descendant][:can_close_all]
6418 6418
  end
6419 6419

  
6420
  test "close all descendants which are open" do
6421
    with_settings :closed_parent_issues_with_open_subtasks => 1 do
6422
      parent = Issue.generate!
6423
      child =
6424
        Issue.
6425
         generate!(
6426
           :parent_issue_id => parent.id
6427
         )
6428
      grandchild1 =
6429
        Issue.
6430
          generate!(
6431
            :parent_issue_id => child.id
6432
          )
6433
      grandchild2 =
6434
        Issue.
6435
         generate!(
6436
           :parent_issue_id => child.id,
6437
           :status_id => 6
6438
         )
6439
      user = User.find(2)
6440
      assert parent.reload.visible?(user)
6441
      assert_not parent.closed?
6442
      assert child.reload.visible?(user)
6443
      assert_not child.closed?
6444
      assert grandchild1.reload.visible?(user)
6445
      assert_not grandchild1.closed?
6446
      assert grandchild2.reload.visible?(user)
6447
      assert grandchild2.closed?
6448

  
6449
      assert [parent, child, grandchild1, grandchild2].
6450
               map{|i| i.new_statuses_allowed_to(user)}.
6451
                 reduce(:&).map{|i| i.id}.include?(5)
6452
      @request.session[:user_id] = user.id
6453
      put(
6454
        :update,
6455
        :params => {
6456
          :id => parent.id,
6457
          :check_go_to_close_confirm => "",
6458
          :status_id => 5
6459
        },
6460
        :xhr => true
6461
      )
6462
      assert_response :success
6463
      assert_equal 'application/json', response.content_type
6464
      json = ActiveSupport::JSON.decode(response.body)
6465

  
6466
      assert_equal 1, parent.reload.status.id
6467
      assert_equal({"result" => true}, json)
6468
      assert session.has_key?(:can_close_descendant)
6469
      assert session[:can_close_descendant][:can_close_all]
6470
      assert_equal [child.id, grandchild1.id], session[:can_close_descendant][:ids] 
6471

  
6472
      notes = 'close all'
6473

  
6474
      assert_difference(
6475
        -> {parent.journals.count} => 1,
6476
        -> {child.journals.count} => 1,
6477
        -> {grandchild1.journals.count} => 1,
6478
        -> {grandchild2.journals.count} => 0
6479
      ) do
6480
        put(
6481
          :update,
6482
          :params => {
6483
            :id => parent.id,
6484
            :close_descendants => "",
6485
            :issue => {
6486
              :status_id => 5,
6487
              :notes => notes
6488
            }
6489
          }
6490
        )
6491
        assert_response 302
6492
      end
6493
      assert 5, parent.reload.status.id
6494
      assert_equal notes, parent.journals.last.notes
6495
      assert 5, child.reload.status.id
6496
      assert_equal notes, child.journals.last.notes
6497
      assert 5, grandchild1.reload.status.id
6498
      assert_equal notes, grandchild1.journals.last.notes
6499
      assert 6, grandchild2.reload.status.id
6500
    end
6501
  end
6502

  
6420 6503
  def test_get_bulk_edit
6421 6504
    @request.session[:user_id] = 2
6422 6505
    get(:bulk_edit, :params => {:ids => [1, 3]})
test/functional/issues_controller_test.rb
6500 6500
    end
6501 6501
  end
6502 6502

  
6503
  test "session generated by check_go_to_close_confirm should respect subtask statuses" do
6504
    with_settings :closed_parent_issues_with_open_subtasks => 1 do
6505
      WorkflowTransition.delete_all
6506
      WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
6507
                                 :old_status_id => 1, :new_status_id => 5)
6508
      WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
6509
                                 :old_status_id => 1, :new_status_id => 6)
6510
      WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
6511
                                 :old_status_id => 1, :new_status_id => 6)
6512
      user = User.find(2)
6513
      parent =
6514
        Issue.
6515
          generate!(
6516
            :author_id => 2,
6517
            :tracker_id => 1,
6518
            :status_id => 1
6519
          )
6520
     child1 =
6521
       Issue.
6522
         generate!(
6523
           :author_id => 2,
6524
           :parent_issue_id => parent.id,
6525
           :tracker_id => 1,
6526
           :status_id => 1
6527
         )
6528
     child2 =
6529
       Issue.
6530
         generate!(
6531
           :author_id => 2,
6532
           :parent_issue_id => parent.id,
6533
           :tracker_id => 2,
6534
           :status_id => 1
6535
         )
6536
      assert parent.reload.visible?(user)
6537
      assert child1.reload.visible?(user)
6538
      assert child2.reload.visible?(user)
6539

  
6540
      assert [5, 6].all? do |id|
6541
        parent.new_statuses_allowed_to(user).map{|s| s.id}.include?(id)
6542
      end
6543
      assert [5, 6].all? do |id|
6544
        child1.new_statuses_allowed_to(user).map{|s| s.id}.include?(id)
6545
      end
6546
      assert_not child2.new_statuses_allowed_to(user).map{|s| s.id}.include?(5)
6547
      assert child2.new_statuses_allowed_to(user).map{|s| s.id}.include?(6)
6548

  
6549
      @request.session[:user_id] = user.id
6550
      put(
6551
        :update,
6552
        :params => {
6553
          :id => parent.id,
6554
          :check_go_to_close_confirm => "",
6555
          :status_id => 6
6556
        },
6557
        :xhr => true
6558
      )
6559
      assert_response :success
6560
      assert_equal 'application/json', response.content_type
6561
      json = ActiveSupport::JSON.decode(response.body)
6562

  
6563
      assert_equal 1, parent.reload.status.id
6564
      assert_equal({"result" => true}, json)
6565
      assert session.has_key?(:can_close_descendant)
6566
      assert session[:can_close_descendant][:can_close_all]
6567
      assert_equal [child1.id, child2.id], session[:can_close_descendant][:ids] 
6568

  
6569
      @request.session.delete(:can_close_descendant)
6570

  
6571
      @request.session[:user_id] = user.id
6572
      put(
6573
        :update,
6574
        :params => {
6575
          :id => parent.id,
6576
          :check_go_to_close_confirm => "",
6577
          :status_id => 5
6578
        },
6579
        :xhr => true
6580
      )
6581
      assert_response :success
6582
      assert_equal 'application/json', response.content_type
6583
      json = ActiveSupport::JSON.decode(response.body)
6584

  
6585
      assert_equal 1, parent.reload.status.id
6586
      assert_equal({"result" => true}, json)
6587
      assert session.has_key?(:can_close_descendant)
6588
      assert_not session[:can_close_descendant][:can_close_all]
6589
      assert_not session[:can_close_descendant].has_key?(:ids)
6590
    end
6591
  end
6592

  
6503 6593
  def test_get_bulk_edit
6504 6594
    @request.session[:user_id] = 2
6505 6595
    get(:bulk_edit, :params => {:ids => [1, 3]})
test/system/issues_test.rb
337 337
    end
338 338
  end
339 339

  
340
  test "close all open subtasks" do
341
    parent = Issue.generate!(:project_id => 1)
342
    child = Issue.generate!(:project_id => 1, :parent_issue_id => parent.id)
343
    close_only_text = "Close only issue #{parent.id}"
344

  
345
    with_settings :closed_parent_issues_with_open_subtasks => 1 do
346
      log_user('dlopper', 'foo')
347
      visit "/issues/#{parent.id}"
348
      page.first(:link, 'Edit').click
349
      assert page.has_select?("issue_status_id", {:selected => "New"})
350
      page.find("#issue_status_id").select("Closed")
351
      assert_no_difference ['Issue.count', 'child.journals.count'] do
352
        assert_no_difference 'parent.journals.count' do
353
          page.first(:button, 'Submit').click
354
          within('#ajax-modal') do
355
            assert page.has_text?(/has open subtasks/)
356
            assert page.has_checked_field?(close_only_text)
357
            page.first(:link, 'Cancel').click
358
          end
359
          assert_equal 1, parent.reload.status.id
360
        end
361
        assert_difference 'parent.journals.count' do
362
          page.first(:button, 'Submit').click
363
          within('#ajax-modal') do
364
            assert page.has_text?(/has open subtasks/)
365
            assert page.has_checked_field?(close_only_text)
366
            page.first(:button, 'Apply').click
367
          end
368
          assert page.has_css?('#flash_notice')
369
          assert_equal 5, parent.reload.status.id
370
        end
371
      end
372
      page.first(:link, 'Edit').click
373
      assert page.has_select?("issue_status_id", {:selected => "Closed"})
374
      page.find("#issue_status_id").select("New")
375
      assert_no_difference ['Issue.count', 'child.journals.count'] do
376
        assert_difference 'parent.journals.count' do
377
          page.first(:button, 'Submit').click
378
          assert page.has_css?('#flash_notice')
379
          assert_equal 1, parent.reload.status.id
380
        end
381
      end
382
      page.first(:link, 'Edit').click
383
      assert page.has_select?("issue_status_id", {:selected => "New"})
384
      page.find("#issue_status_id").select("Closed")
385
      assert_no_difference 'Issue.count' do
386
        assert_difference ['parent.journals.count', 'child.journals.count'] do
387
          page.first(:button, 'Submit').click
388
          within('#ajax-modal') do
389
            all_text = 'Close all open subtasks by "Closed" status'
390
            assert page.has_text?(/has open subtasks/)
391
            assert page.has_checked_field?(close_only_text)
392
            page.choose(all_text)
393
            assert page.has_checked_field?(all_text)
394
            page.first(:button, 'Apply').click
395
          end
396
          assert page.has_css?('#flash_notice')
397
          assert_equal 5, parent.reload.status.id
398
          assert_equal 5, child.reload.status.id
399
        end
400
      end
401
    end
402
  end
403

  
340 404
  test "removing issue shows confirm dialog" do
341 405
    log_user('jsmith', 'jsmith')
342 406
    visit '/issues/1'
(13-13/15)