Passed
Push — master ( cddcf6...1d3855 )
by Alexander
01:59
created

tcms/static/js/testrun_actions.js (2 issues)

1
Nitrate.TestRuns = {};
2
Nitrate.TestRuns.Details = {};
3
Nitrate.TestRuns.Execute = {}
4
Nitrate.TestRuns.AssignCase = {}
5
6
7
Nitrate.TestRuns.Details.on_load = function() {
8
  setAddTagAutocomplete();
9
10
  // Observe the interface buttons
11
  jQ('#id_check_all_button').bind('click', function(e) {
12
    toggleAllCheckBoxes(this, 'id_table_cases', 'case_run');
13
  });
14
15
  if (jQ('#id_check_box_highlight').attr('checked')) {
16
    jQ('.mine').addClass('highlight');
17
  }
18
19
  jQ('#id_check_box_highlight').bind('click', function(e) {
20
    e = jQ('.mine');
21
    this.checked && e.addClass('highlight') || e.removeClass('highlight');
22
  });
23
24
  jQ('#id_blind_all_link').bind('click', function(e) {
25
    if (!jQ('td[id^="id_loading_"]').length) {
26
      jQ(this).removeClass('locked');
27
    }
28
    if (jQ(this).is('.locked')) {
29
      //To disable the 'expand all' until all case runs are expanded.
30
      return false;
31
    } else {
32
      jQ(this).addClass('locked');
33
      var element = jQ(this).children();
34
      if (element.is('.collapse-all')) {
35
        this.title = "Collapse all cases";
36
        blinddownAllCases(element[0]);
37
      } else {
38
        this.title = "Expand all cases";
39
        blindupAllCases(element[0]);
40
      }
41
    }
42
  });
43
44
  // Observe the case run toggle and the comment form
45
  var toggle_case_run = function(e) {
46
    var c = jQ(this).parent(); // Container
47
    var c_container = c.next(); // Content Containers
48
    var case_id = c.find('input[name="case"]')[0].value;
49
    var case_run_id = c.find('input[name="case_run"]')[0].value;
50
    var case_text_version = c.find('input[name="case_text_version"]')[0].value;
51
    var type = 'case_run';
52
    var callback = function(t) {
53
      // Observe the update case run stauts/comment form
54
      c_container.parent().find('.update_form')
55
        .unbind('submit').bind('submit', updateCaseRunStatus);
56
57
      // Observe the delete comment form
58
      var refresh_case = function(t) {
59
        constructCaseRunZone(c_container[0], c[0], case_id);
60
      };
61
62
      var rc_callback = function(e) {
63
        e.stopPropagation();
64
        e.preventDefault();
65
        if (!window.confirm(default_messages.confirm.remove_comment)) {
66
          return false;
67
        }
68
        removeComment(this, refresh_case);
69
      };
70
      c_container.parent().find('.form_comment')
71
        .unbind('submit').bind('submit', rc_callback);
72
      c_container.find('.js-status-button').bind('click', function() {
73
        this.form.value.value = jQ(this).data('formvalue');
74
      });
75
      c_container.find('.js-show-comments').bind('click', function() {
76
        toggleDiv(this, jQ(this).data('param'));
77
      });
78
      c_container.find('.js-show-changelog').bind('click', function() {
79
        toggleDiv(this, jQ(this).data('param'));
80
      });
81
      c_container.find('.js-file-caserun-bug').bind('click', function(){
82
        var params = jQ(this).data('params');
83
        fileCaseRunBug(params[0], c[0], c_container[0], params[1], params[2]);
84
      });
85
      c_container.find('.js-add-caserun-bug').bind('click', function(){
86
        var params = jQ(this).data('params');
87
        addCaseRunBug(params[0], c[0], c_container[0], params[1], params[2]);
88
      });
89
      c_container.find('.js-remove-caserun-bug').bind('click', function(){
90
        var params = jQ(this).data('params');
91
        removeCaseBug(params[1], params[2], params[3]);
92
      });
93
      c_container.find('.js-add-testlog').bind('click', function(){
94
        var params = jQ(this).data('params');
95
        addLinkToCaseRun(this, params[0], params[1]);
96
      });
97
      c_container.find('.js-remove-testlog').bind('click', function(){
98
        removeLink(this, window.parseInt(jQ(this).data('param')));
99
      });
100
    };
101
102
    toggleTestCaseRunPane({
103
      'callback': callback,
104
      'caseId': case_id,
105
      'caserunId': case_run_id,
106
      'caseTextVersion': case_text_version,
107
      'caserunRowContainer': c,
108
      'expandPaneContainer': c_container
109
    });
110
  };
111
  jQ('.expandable').bind('click', toggle_case_run);
112
113
  // Auto show the case run contents.
114
  if (window.location.hash != '') {
115
    fireEvent(jQ('a[href=\"' + window.location.hash + '\"]')[0], 'click');
116
  };
117
118
  // Filter Case-Run
119
  if (jQ('#filter_case_run').length) {
120
    jQ('#filter_case_run').bind('click',function(e){
121
      if (jQ('#id_filter').is(':hidden')){
122
        jQ('#id_filter').show();
123
        jQ(this).html(default_messages.link.hide_filter);
124
      } else {
125
        jQ('#id_filter').hide();
126
        jQ(this).html(default_messages.link.show_filter);
127
      }
128
    });
129
  }
130
  //bind click to status btn
131
  jQ('.btn_status').live('click', function() {
132
    var from = jQ(this).siblings('.btn_status:disabled')[0].title;
133
    var to = this.title;
134
    if (jQ('span#' + to + ' a').text() === '0') {
135
      var htmlstr = "[<a href='javascript:void(0)' onclick=\"showCaseRunsWithSelectedStatus(jQ('#id_filter')[0], '"
136
        + jQ(this).attr('crs_id')+"')\">0</a>]";
137
      jQ('span#' + to).html(htmlstr);
138
    }
139
    if (jQ('span#' + from + ' a').text() === '1') {
140
      jQ('span#' + from).html("[<a>1</a>]");
141
    }
142
    jQ('span#' + to + ' a').text(window.parseInt(jQ('span#' + to + ' a').text()) + 1);
143
    jQ('span#' + from + ' a').text(window.parseInt(jQ('span#' + from + ' a').text()) - 1);
144
145
    var caseRunCount = window.parseInt(jQ('span#TOTAL').next().text()) || 0;
146
    var passedCaseRunCount = window.parseInt(jQ('span#PASSED a').text()) || 0;
147
    var errorCaseRunCount = window.parseInt(jQ('span#ERROR a').text()) || 0;
148
    var failedCaseRunCount = window.parseInt(jQ('span#FAILED a').text()) || 0;
149
    var waivedCaseRunCount = window.parseInt(jQ('span#WAIVED a').text()) || 0;
150
    var completePercent = 100 * ((passedCaseRunCount + errorCaseRunCount + failedCaseRunCount
151
      + waivedCaseRunCount) / caseRunCount).toFixed(2);
152
    var failedPercent = 100 * ((errorCaseRunCount + failedCaseRunCount) / (passedCaseRunCount
153
      + errorCaseRunCount + failedCaseRunCount + waivedCaseRunCount)).toFixed(2);
154
155
    jQ('span#complete_percent').text(completePercent);
156
    jQ('div.progress-inner').attr('style', 'width:' + completePercent + '%');
157
    jQ('div.progress-failed').attr('style', 'width:' + failedPercent + '%');
158
  });
159
160
  jQ('#btn_edit').bind('click', function() {
161
    var params = jQ(this).data('params');
162
    window.location.href = params[0] + '?from_plan=' + params[1];
163
  });
164
  jQ('#btn_clone').bind('click', function() {
165
    postToURL(jQ(this).data('param'), serializeCaseRunFromInputList('id_table_cases','case_run'));
166
  });
167
  jQ('#btn_delete').bind('click', function() {
168
    window.location.href = jQ(this).data('param');
169
  });
170
171
  bindJSRemoveTagButton();
172
  jQ('.js-add-tag').bind('click', function() {
173
    addRunTag(jQ('.js-tag-ul')[0], jQ(this).data('param'));
174
  });
175
  jQ('.js-set-running').bind('click', function() {
176
    window.location.href = jQ(this).data('param') + '?finished=0';
177
  });
178
  jQ('.js-set-finished').bind('click', function() {
179
    window.location.href = jQ(this).data('param') + '?finished=1';
180
  });
181
  jQ('.js-del-case').bind('click', function() {
182
    delCaseRun(jQ(this).data('param'));
183
  });
184
  jQ('.js-update-case').bind('click', function() {
185
    postToURL(jQ(this).data('param'), serializeCaseRunFromInputList('id_table_cases', 'case_run'));
186
  });
187
  jQ('.js-change-assignee').bind('click', function() {
188
    changeCaseRunAssignee();
189
  });
190
  jQ('.js-add-bugs').bind('click', function() {
191
    updateBugs('add');
192
  });
193
  jQ('.js-remove-bugs').bind('click', function() {
194
    updateBugs('remove');
195
  });
196
  jQ('.js-show-commentdialog').bind('click', function() {
197
    showCommentForm();
198
  });
199
  jQ('.js-add-cc').bind('click', function() {
200
    addRunCC(jQ(this).data('param'), jQ('.js-cc-ul')[0]);
201
  });
202
  jQ('.js-remove-cc').bind('click', function() {
203
    var params = jQ(this).data('params');
204
    removeRunCC(params[0], params[1], jQ('.js-cc-ul')[0]);
205
  });
206
  jQ('.js-caserun-total').bind('click', function() {
207
    showCaseRunsWithSelectedStatus(jQ('#id_filter')[0], '');
208
  });
209
  jQ('.js-status-subtotal').bind('click', function() {
210
    showCaseRunsWithSelectedStatus(jQ('#id_filter')[0], jQ(this).data('param'));
211
  });
212
};
213
214
Nitrate.TestRuns.AssignCase.on_load = function() {
215
  if (jQ('#id_check_all_button').length) {
216
    jQ('#id_check_all_button').bind('click', function(m) {
217
      toggleAllCheckBoxes(this, 'id_table_cases', 'case');
218
    });
219
  }
220
221
  jQ('input[name="case"]').bind('click', function(t) {
222
    if (this.checked) {
223
      jQ(this).closest('tr').addClass('selection_row');
224
      jQ(this).parent().siblings().eq(7).html('<div class="apply_icon"></div>');
225
    } else {
226
      jQ(this).closest('tr').removeClass('selection_row');
227
      jQ(this).parent().siblings().eq(7).html('');
228
    }
229
  });
230
231
  jQ('.js-how-assign-case').bind('click', function() {
232
    jQ('#help_assign').show();
233
  });
234
  jQ('.js-close-how-assign').bind('click', function() {
235
    jQ('#help_assign').hide();
236
  });
237
  jQ('.js-toggle-button, .js-case-summary').bind('click', function() {
238
    toggleTestCaseContents(jQ(this).data('param'));
239
  });
240
};
241
242
243
function updateRunStatus(object_pk, value, callback) {
244
  jQ.ajax({
245
    'url': '/runs/case-run-update-status/',
246
    'type': 'POST',
247
    'data': {'object_pk': object_pk, 'status_id': value },
248
    'success': function (data, textStatus, jqXHR) {
249
      callback();
250
    },
251
    'error': function (jqXHR, textStatus, errorThrown) {
252
      json_failure(jqXHR);
253
    }
254
  });
255
}
256
257
var updateCaseRunStatus = function(e) {
258
  e.stopPropagation();
259
  e.preventDefault();
260
  var container = jQ(this).parents().eq(3);
261
  var parent = container.parent();
262
  var title = parent.prev();
263
  var link = title.find('.expandable')[0];
264
  var parameters = Nitrate.Utils.formSerialize(this);
265
  var object_pk = parameters['object_pk'];
266
  var value = parameters['value'];
267
268
  // Callback when
269
  var callback = function(t) {
270
    // Update the contents
271
    if (parameters['value'] != '') {
272
      // Update the case run status icon
273
      var crs = Nitrate.TestRuns.CaseRunStatus;
274
      title.find('.icon_status').each(function(index) {
275
        for (i in crs) {
276
          if (typeof crs[i] === 'string' && jQ(this).is('.btn_' + crs[i])) {
277
            jQ(this).removeClass('btn_' + crs[i]);
278
          }
279
        }
280
        jQ(this).addClass('btn_' + Nitrate.TestRuns.CaseRunStatus[value - 1]);
281
      });
282
283
      // Update related people
284
      var usr = Nitrate.User;
285
      title.find('.link_tested_by').each(function(i) {
286
        jQ(this).html(usr.username);
287
      });
288
    }
289
290
    // Mark the case run to mine
291
    if (!title.is('.mine')) {
292
      title.addClass('mine');
293
    }
294
295
    // Blind down next case
296
    fireEvent(link, 'click');
297
    if (jQ('#id_check_box_auto_blinddown').attr('checked') && parameters['value'] != '') {
298
      var next_title = parent.next();
299
      if (!next_title.length) {
300
        return false;
301
      }
302
      if (next_title.next().is(':hidden')) {
303
        fireEvent(next_title.find('.expandable')[0], 'click');
304
      }
305
    } else {
306
      fireEvent(link, 'click');
307
    }
308
  };
309
310
  // Add comment
311
  if (parameters['comment'] != '') {
312
    // Reset the content to loading
313
    var ajax_loading = getAjaxLoading();
314
    ajax_loading.id = 'id_loading_' + parameters['case_id'];
315
    container.html(ajax_loading);
316
    var c = jQ('<div>');
317
    if (parameters['value'] != '') {
318
      submitComment(c[0], parameters);
319
    } else {
320
      submitComment(c[0], parameters, callback);
321
    }
322
  }
323
324
  // Update the object when changing the status
325
  if (parameters['value'] != '') {
326
    // Reset the content to loading
327
    var ajax_loading = getAjaxLoading();
328
    ajax_loading.id = 'id_loading_' + parameters['case_id'];
329
    container.html(ajax_loading);
330
    updateRunStatus([object_pk], value, callback);
331
  }
332
};
333
334
335
function constructCaseRunZone(container, title_container, case_id) {
336
  var link = jQ(title_container).find('.expandable')[0];
337
  if (container) {
338
    var td = jQ('<td>', {'id': 'id_loading_' + case_id, 'colspan': 12 });
339
    td.html(getAjaxLoading());
340
    jQ(container).html(td);
341
  }
342
343
  if (title_container) {
344
    fireEvent(link, 'click');
345
    fireEvent(link, 'click');
346
  }
347
}
348
349
350
//////////////////////////////////////////////////////////////////////////////////////////////
351
////////   AddIssueDialog Definition //////////////
352
353
354
/*
355
 * Dialog to allow user to add sort of issue keys to case run(s).
356
 *
357
 * Here, issue key is a general to whatever the issue tracker system is.
358
 *
359
 * options:
360
 * @param extraFormHiddenData: used for providing extra data for specific AJAX request.
361
 * @param onSubmit: callback function when user click Add button
362
 * @param action: string - Add or Remove. Default is Add
363
 */
364
/*
365
 * FIXME: which namespace is proper to hold this dialog class?
366
 */
367
function AddIssueDialog(options) {
368
  this.onSubmit = options.onSubmit;
369
  if (this.onSubmit !== undefined && typeof this.onSubmit !== "function") {
370
    throw new Error("onSubmit should be a function object.");
371
  }
372
  this.extraFormHiddenData = options.extraFormHiddenData;
373
  if (this.extraFormHiddenData !== undefined && typeof this.extraFormHiddenData !== "object") {
374
    throw new Error("extraFormHiddenData sould be an object if present.");
375
  }
376
377
  this.action = options.action;
378
  if (this.action === undefined) {
379
    this.action = "Add";
380
  }
381
382
  this.a = options.a;
383
  if (this.a === undefined) {
384
    this.a = this.action.toLowerCase();
385
  }
386
387
  if (options.hasOwnProperty("show_bug_id_field")) {
388
    this.show_bug_id_field = options.show_bug_id_field;
389
  } else {
390
    this.show_bug_id_field = false;
391
  }
392
}
393
394
395
AddIssueDialog.prototype.show = function () {
396
  var dialog = jQ("#dialog")[0];
397
  if (dialog == null) {
398
    throw new Error("No HTML element with ID dialog. This should not happen in the runtime.");
399
  }
400
401
  var hiddenPart = [];
402
  if (this.extraFormHiddenData !== undefined) {
403
    for (var name_attr in this.extraFormHiddenData) {
404
      hiddenPart.push({'name': name_attr, 'value': this.extraFormHiddenData[name_attr]});
405
    }
406
  }
407
408
  var template = Handlebars.compile(jQ("#add_issue_form_template").html());
409
  var context = {
410
    'hiddenFields': hiddenPart,
411
    'action_button_text': this.action,
412
    'show_bug_id_field': this.show_bug_id_field || this.action === 'Add',
413
    'show_add_to_bugzilla_checkbox': this.action === 'Add',
414
    'a': this.a,
415
  };
416
417
  jQ('#dialog').html(template(context))
418
    .find('.js-cancel-button').bind('click', function() {
419
      jQ('#dialog').hide();
420
    })
421
    .end().show();
422
423
  this.form = jQ("#add_issue_form")[0];
424
425
  // Used for following event callbacks to ref this dialog's instance
426
  var that = this;
427
428
  // Set custom callback functions
429
  if (this.onSubmit !== undefined) {
430
    jQ(this.form).bind('submit', function (form_event) {
431
      that.onSubmit(form_event, that);
432
    });
433
  }
434
};
435
436
AddIssueDialog.prototype.get_data = function () {
437
  var form_data = Nitrate.Utils.formSerialize(this.form);
438
  form_data.bug_validation_regexp = $('#bug_system_id option:selected').data('validation-regexp');
439
  form_data.bz_external_track = $('input[name=bz_external_track]').is(':checked');
440
  return form_data;
441
};
442
443
//// end of AddIssueDialog definition /////////
444
/////////////////////////////////////////////////////////////////////////////////////////////
445
446
function fileCaseRunBug(run_id, title_container, container, case_id, case_run_id) {
447
  var dialog = new AddIssueDialog({
448
    'action': 'Report',
449
    'onSubmit': function (e, dialog) {
450
      e.stopPropagation();
451
      e.preventDefault();
452
453
        var tracker_id = dialog.get_data()['bug_system_id'];
454
        jsonRPC('Bug.report', [case_run_id, tracker_id], function(result) {
455
            $('#dialog').hide();
456
457
            if (result.rc === 0) {
458
                window.open(result.response, '_blank');
459
            } else {
460
                window.alert(result.response);
461
            }
462
      });
463
    }
464
  });
465
466
  dialog.show();
467
}
468
469
function addCaseRunBug(run_id, title_container, container, case_id, case_run_id) {
470
  var dialog = new AddIssueDialog({
471
    'onSubmit': function (e, dialog) {
472
      e.stopPropagation();
473
      e.preventDefault();
474
475
      form_data = dialog.get_data();
476
477
      form_data.bug_id = form_data.bug_id.trim();
478
      if (!form_data.bug_id.length) {
479
        return;
480
      }
481
482
        jsonRPC('Bug.create', [{
483
                case_id: case_id,
484
                case_run_id: case_run_id,
485
                bug_id: form_data.bug_id,
486
                bug_system_id: form_data.bug_system_id
487
            }, form_data.bz_external_track],
488
            function(result) {
489
                // todo: missing error handling when bz_external_track is true
490
                $('#dialog').hide();
491
492
                // Update bugs count associated with just updated case run
493
                var jqCaserunBugCount = $('span#' + case_run_id + '_case_bug_count');
494
                jqCaserunBugCount.addClass('have_bug');
495
496
                // refresh the links of bugs
497
                constructCaseRunZone(container, title_container, case_id);
498
        });
499
    }
500
  });
501
502
  dialog.show();
503
}
504
505
506
function delCaseRun(run_id) {
507
  var caseruns = serializeCaseRunFromInputList('id_table_cases', 'case_run');
508
  var numCaseRuns = caseruns.case_run.length;
509
  if (window.confirm('You are about to delete ' + numCaseRuns + ' case run(s). Are you sure?')) {
510
    postToURL('remove_execution/', caseruns);
511
  }
512
}
513
514
515
// binds the remove buttons for all tags
516
function bindJSRemoveTagButton() {
517
  $('.js-remove-tag').bind('click', function() {
518
    var params = $(this).data('params');
519
    removeRunTag($('.js-tag-ul')[0], params[0], params[1]);
520
  });
521
}
522
523
524
// data is an array of id/name for tags
525
function updateTagContainer(container, data, run_id) {
526
    var html = '';
527
528
    data.forEach(function(element) {
529
        var li = '<li>' + element['name'] +
530
                    '<a href="#" class="js-remove-tag" data-params=\'["'+ run_id + '", "' + element['name'] + '"]\'>' +
531
                        '&nbsp;<i class="fa fa-trash-o"></i>' +
532
                    '</a>' +
533
                 '</li>';
534
        html += li;
535
    });
536
537
    $(container).html(html);
538
    bindJSRemoveTagButton();
539
}
540
541
542
function addRunTag(container, run_id) {
543
    var tag_container = $('#id_tags');
544
    var tag = tag_container.val();
545
546
    if (!tag) {
547
        return false;
548
    }
549
550
    var inner_callback = function(data) {
551
        updateTagContainer(container, data, run_id);
552
        tag_container.val('');
553
    }
554
    jsonRPC('TestRun.add_tag', [run_id, tag], inner_callback);
555
}
556
557
function removeRunTag(container, run_id, tag) {
558
    var inner_callback = function(data) {
559
        updateTagContainer(container, data, run_id);
560
    }
561
    jsonRPC('TestRun.remove_tag', [run_id, tag], inner_callback);
562
}
563
564
function constructRunCC(container, run_id, parameters) {
565
  var complete = function(t) {
566
    jQ('.js-remove-cc').bind('click', function() {
567
      var params = jQ(this).data('params');
568
      removeRunCC(params[0], params[1], jQ('.js-cc-ul')[0]);
569
    });
570
    if (jQ('#message').length) {
571
      window.alert(jQ('#message').html());
572
      return false;
573
    }
574
  };
575
  var url = '/runs/' + run_id + '/cc/';
576
  jQ.ajax({
577
    'url': url,
578
    'type': 'GET',
579
    'data': parameters,
580
    'success': function (data, textStatus, jqXHR) {
581
      jQ(container).html(data);
582
    },
583
    'complete': function() {
584
      complete();
585
    }
586
  });
587
}
588
589
function addRunCC(run_id, container) {
590
  var user = window.prompt('Please type new email or username for CC.');
591
  if (!user) {
592
    return false;
593
  }
594
  var parameters = {'do': 'add', 'user': user};
595
  constructRunCC(container, run_id, parameters);
596
}
597
598
function removeRunCC(run_id, user, container) {
599
  var c = window.confirm('Are you sure to delete this user from CC?');
600
601
  if (!c) {
602
    return false;
603
  }
604
605
  var parameters = { 'do': 'remove', 'user': user };
606
  constructRunCC(container, run_id, parameters);
607
}
608
609
function changeCaseRunAssignee() {
610
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
611
  if (!runs.length) {
612
    window.alert(default_messages.alert.no_case_selected);
613
    return false;
614
  }
615
616
  var p = window.prompt('Please type new email or username for assignee');
617
  if (!p) {
618
    return false;
619
  }
620
621
  jQ.ajax({
622
    'url': '/runs/update-assignee/',
623
    'type': 'POST',
624
    'data': { ids: runs, assignee: p },
625
    'success': function (data, textStatus, jqXHR) {
626
      window.location.reload();
627
    },
628
    'error': function (jqXHR, textStatus, errorThrown) {
629
      json_failure(jqXHR);
630
    }
631
  });
632
}
633
634
function serializeCaseRunFromInputList(table, name) {
635
  var elements;
636
  if (typeof table === 'string') {
637
    elements = jQ('#' + table).parent().find('input[name="case_run"]:checked');
638
  } else {
639
    elements = jQ(table).parent().find('input[name="case_run"]:checked');
640
  }
641
642
  var returnobj_list = [];
643
  elements.each(function(i) {
644
    if (typeof this.value === 'string') {
645
      returnobj_list.push(this.value);
646
    }
647
  });
648
  if (name) {
649
    var returnobj = {};
650
    returnobj[name] = returnobj_list;
651
    return returnobj;
652
  }
653
654
  return returnobj_list;
655
}
656
657
function serialzeCaseForm(form, table, serialized) {
658
  if (typeof serialized !== 'boolean') {
659
    var serialized = true;
660
  }
661
  var data;
662
  if (serialized) {
663
    data = Nitrate.Utils.formSerialize(form);
664
  } else {
665
    data = jQ(form).serialize();
666
  }
667
668
  data['case_run'] = serializeCaseFromInputList(table);
669
  return data;
670
}
671
672
function showCaseRunsWithSelectedStatus(form, status_id) {
673
  form.status__pk.value = status_id;
674
  fireEvent(jQ(form).find('input[type="submit"]')[0], 'click');
675
}
676
677
function updateBugsActionAdd(case_runs) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
678
  var dialog = new AddIssueDialog({
679
    'extraFormHiddenData': { 'case_runs': case_runs.join() },
680
    'onSubmit': function(e, dialog) {
681
      e.stopPropagation();
682
      e.preventDefault();
683
      var form_data = dialog.get_data();
684
      form_data.bug_id = form_data.bug_id.trim();
685
686
      if (!form_data.bug_id.length) {
687
        return;
688
      }
689
690
      if (!validateIssueID(form_data.bug_validation_regexp, form_data.bug_id)) {
691
        return false;
692
      }
693
694
      jQ.ajax({
695
        url: '/caserun/update-bugs-for-many/',
696
        dataType: 'json',
697
        data: form_data,
698
        success: function(res){
699
          if (res.rc === 0) {
700
            reloadWindow();
701
          } else {
702
            window.alert(res.response);
703
            return false;
704
          }
705
        }
706
      });
707
    }
708
  });
709
  dialog.show();
710
}
711
712
function updateBugsActionRemove(case_runs) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
713
  var dialog = new AddIssueDialog({
714
    'action': 'Remove',
715
    'show_bug_id_field': true,
716
    'extraFormHiddenData': { 'case_runs': case_runs.join() },
717
    'onSubmit': function(e, dialog) {
718
      e.stopPropagation();
719
      e.preventDefault();
720
      var form_data = dialog.get_data();
721
      form_data.bug_id = form_data.bug_id.trim();
722
723
      if (!form_data.bug_id.length) {
724
        return;
725
      }
726
727
      if (!validateIssueID(form_data.bug_validation_regexp, form_data.bug_id)) {
728
        return false;
729
      }
730
731
      jQ.ajax({
732
        url: '/caserun/update-bugs-for-many/',
733
        dataType: 'json',
734
        success: function(res) {
735
          if (res.rc == 0) {
736
            reloadWindow();
737
          } else {
738
            window.alert(res.response);
739
            return false;
740
          }
741
        },
742
        data: form_data,
743
      });
744
    }
745
  });
746
  dialog.show();
747
}
748
749
function updateBugs(action) {
750
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
751
  if (!runs.length) {
752
    window.alert(default_messages.alert.no_case_selected);
753
    return false;
754
  }
755
756
  if (action === "add") {
757
    updateBugsActionAdd(runs);
758
  } else if (action === "remove") {
759
    updateBugsActionRemove(runs);
760
  } else {
761
    throw new Error("Unknown operation when update case runs' bugs. This should not happen.");
762
  }
763
}
764
765
function showCommentForm() {
766
  var dialog = getDialog();
767
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
768
  if (!runs.length) {
769
    return window.alert(default_messages.alert.no_case_selected);
770
  }
771
  var template = Handlebars.compile(jQ("#batch_add_comment_to_caseruns_template").html());
772
  jQ(dialog).html(template());
773
774
  var commentText = jQ('#commentText');
775
  var commentsErr = jQ('#commentsErr');
776
  jQ('#btnComment').live('click', function() {
777
    var error;
778
    var comments = jQ.trim(commentText.val());
779
    if (!comments) {
780
      error = 'No comments given.';
781
    }
782
    if (error) {
783
      commentsErr.html(error);
784
      return false;
785
    }
786
    jQ.ajax({
787
      url: '/caserun/comment-many/',
788
      data: {'comment': comments, 'run': runs.join()},
789
      dataType: 'json',
790
      type: 'post',
791
      success: function(res) {
792
        if (res.rc == 0) {
793
          reloadWindow();
794
        } else {
795
          commentsErr.html(res.response);
796
          return false;
797
        }
798
      }
799
    });
800
  });
801
  jQ('#btnCancelComment').live('click', function(){
802
    jQ(dialog).hide();
803
    commentText.val('');
804
  });
805
  jQ(dialog).show();
806
}
807
808
jQ(document).ready(function(){
809
  jQ('.btnBlueCaserun').mouseover(function() {
810
    jQ(this).find('ul').show();
811
  }).mouseout(function() {
812
    jQ(this).find('ul').hide();
813
  });
814
  jQ('ul.statusOptions a').click(function() {
815
    var option = jQ(this).attr('value');
816
    var object_pks = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
817
    if (option == '') {
818
      return false;
819
    }
820
    if (!object_pks.length) {
821
      window.alert(default_messages.alert.no_case_selected);
822
      return false;
823
    }
824
    if (!window.confirm(default_messages.confirm.change_case_status)) {
825
      return false;
826
    }
827
    updateRunStatus(object_pks, option, reloadWindow);
828
  });
829
});
830
831
function get_addlink_dialog() {
832
  return jQ('#addlink_dialog');
833
}
834
835
/*
836
 * Do AJAX request to backend to remove a link
837
 *
838
 * - sender:
839
 * - link_id: the ID of an arbitrary link.
840
 */
841
function removeLink(sender, link_id) {
842
  jQ.ajax({
843
    url: '/linkref/remove/' + link_id + '/',
844
    type: 'GET',
845
    dataType: 'json',
846
    success: function(data, textStatus, jqXHR) {
847
      if (data.rc !== 0) {
848
        window.alert(data.response);
849
        return false;
850
      }
851
      var li_node = sender.parentNode;
852
      li_node.parentNode.removeChild(li_node);
853
    },
854
    error: function(jqXHR, textStatus, errorThrown) {
855
      var data = JSON.parse(jqXHR.responseText);
856
      window.alert(data.message);
857
    }
858
  });
859
}
860
861
/*
862
 * Add link to case run
863
 *
864
 * - sender: the Add link button, which is pressed to fire this event.
865
 * - target_id: to which TestCaseRun the new link will be linked.
866
 */
867
function addLinkToCaseRun(sender, case_id, case_run_id) {
868
  var dialog_p = get_addlink_dialog();
869
870
  dialog_p.dialog('option', 'target_id', case_run_id);
871
  // These two options are used for reloading TestCaseRun when successfully.
872
  var container = jQ(sender).parents('.case_content.hide')[0];
873
  dialog_p.dialog('option', 'container', container);
874
  var title_container = jQ(container).prev()[0];
875
  dialog_p.dialog('option', 'title_container', title_container);
876
  dialog_p.dialog('option', 'case_id', case_id);
877
  dialog_p.dialog('open');
878
}
879
880
/*
881
 * Initialize dialog for getting information about new link, which is attached
882
 * to an arbitrary instance of TestCaseRun
883
 */
884
function initialize_addlink_dialog() {
885
  var dialog_p = get_addlink_dialog();
886
887
  dialog_p.dialog({
888
    autoOpen: false,
889
    modal: true,
890
    resizable: false,
891
    height: 300,
892
    width: 400,
893
    open: function() {
894
      jQ(this).unbind('submit').bind('submit', function (e) {
895
        e.stopPropagation();
896
        e.preventDefault();
897
        jQ(this).dialog('widget').find('span:contains("OK")').click();
898
      });
899
    },
900
    buttons: {
901
      "OK": function() {
902
        // TODO: validate name and url
903
        var name = jQ('#testlog_name').attr('value');
904
        var url = jQ('#testlog_url').attr('value');
905
        var target_id = jQ(this).dialog('option', 'target_id');
906
907
        jQ.ajax({
908
          url: '/linkref/add/',
909
          type: 'POST',
910
          data: { name: name, url: url, target_id: target_id },
911
          dataType: 'json',
912
          success: function(data, textStatus, jqXHR) {
913
            if (data.rc !== 0) {
914
              window.alert(data.response);
915
              return false;
916
            }
917
            dialog_p.dialog('close');
918
919
            // Begin to construct case run area
920
            var container = dialog_p.dialog('option', 'container');
921
            var title_container = dialog_p.dialog('option', 'title_container');
922
            var case_id = dialog_p.dialog('option', 'case_id');
923
            constructCaseRunZone(container, title_container, case_id);
924
          },
925
          error: function (jqXHR, textStatus, errorThrown) {
926
            var data = JSON.parse(jqXHR.responseText);
927
            window.alert(data.response);
928
          }
929
        });
930
      },
931
      "Cancel": function() {
932
        jQ(this).dialog('close');
933
      }
934
    },
935
    beforeClose: function() {
936
      // clean name and url for next input
937
      jQ('#testlog_name').val('');
938
      jQ('#testlog_url').val('');
939
940
      return true;
941
    },
942
    /* ATTENTION: target_id can be determined when open this dialog, and
943
     * this must be set
944
     */
945
    target_id: null
946
  });
947
}
948
949
950
/*
951
 * Toggle TestCaseRun panel to edit a case run in run page.
952
 *
953
 * Arguments:
954
 * options.casrunContainer:
955
 * options.expandPaneContainer:
956
 * options.caseId:
957
 * options.caserunId:
958
 * options.caseTextVersion:
959
 * options.callback:
960
 */
961
function toggleTestCaseRunPane(options) {
962
  var container = options.caserunRowContainer;
963
  var content_container = options.expandPaneContainer;
964
  var callback = options.callback;
965
966
  content_container.toggle();
967
968
  if (content_container.find('.ajax_loading').length) {
969
    var url = '/case/' + options.caseId + '/execution-detail-pane/';
970
    var data = { case_run_id: options.caserunId, case_text_version: options.caseTextVersion };
971
972
    jQ.get(url, data, function(data, textStatus) {
973
      content_container.html(data);
974
      callback();
975
    }, 'html');
976
  }
977
978
  toggleExpandArrow({ caseRowContainer: container, expandPaneContainer: content_container });
979
}
980