Passed
Push — master ( f58c94...986f62 )
by Alexander
03:34
created

tcms/static/js/testrun_actions.js (1 issue)

1
Nitrate.TestRuns = {};
2
Nitrate.TestRuns.Details = {};
3
Nitrate.TestRuns.Execute = {}
4
Nitrate.TestRuns.AssignCase = {}
5
6
7
function toggleDiv(link, divId) {
8
  var link = jQ(link);
9
  var div = jQ('#' + divId);
10
  var show = 'Show All';
11
  var hide = 'Hide All';
12
  div.toggle();
13
  var text = link.html();
14
  if (text !== show) {
15
    link.html(show);
16
  } else {
17
    link.html(hide);
18
  }
19
}
20
21
22
Nitrate.TestRuns.Details.on_load = function() {
23
  setAddTagAutocomplete();
24
25
  // Observe the interface buttons
26
  jQ('#id_check_all_button').bind('click', function(e) {
27
    toggleAllCheckBoxes(this, 'id_table_cases', 'case_run');
28
  });
29
30
  if (jQ('#id_check_box_highlight').attr('checked')) {
31
    jQ('.mine').addClass('highlight');
32
  }
33
34
  jQ('#id_check_box_highlight').bind('click', function(e) {
35
    e = jQ('.mine');
36
    this.checked && e.addClass('highlight') || e.removeClass('highlight');
37
  });
38
39
  jQ('#id_blind_all_link').bind('click', function(e) {
40
    if (!jQ('td[id^="id_loading_"]').length) {
41
      jQ(this).removeClass('locked');
42
    }
43
    if (jQ(this).is('.locked')) {
44
      //To disable the 'expand all' until all case runs are expanded.
45
      return false;
46
    } else {
47
      jQ(this).addClass('locked');
48
      var element = jQ(this).children();
49
      if (element.is('.collapse-all')) {
50
        this.title = "Collapse all cases";
51
        blinddownAllCases(element[0]);
52
      } else {
53
        this.title = "Expand all cases";
54
        blindupAllCases(element[0]);
55
      }
56
    }
57
  });
58
59
  // Observe the case run toggle and the comment form
60
  var toggle_case_run = function(e) {
61
    var c = jQ(this).parent(); // Container
62
    var c_container = c.next(); // Content Containers
63
    var case_id = c.find('input[name="case"]')[0].value;
64
    var case_run_id = c.find('input[name="case_run"]')[0].value;
65
    var case_text_version = c.find('input[name="case_text_version"]')[0].value;
66
    var type = 'case_run';
67
    var callback = function(t) {
68
      // Observe the update case run stauts/comment form
69
      c_container.parent().find('.update_form')
70
        .unbind('submit').bind('submit', updateCaseRunStatus);
71
72
      // Observe the delete comment form
73
      var refresh_case = function(t) {
74
        constructCaseRunZone(c_container[0], c[0], case_id);
75
      };
76
77
      var rc_callback = function(e) {
78
        e.stopPropagation();
79
        e.preventDefault();
80
        if (!window.confirm(default_messages.confirm.remove_comment)) {
81
          return false;
82
        }
83
        removeComment(this, refresh_case);
84
      };
85
      c_container.parent().find('.form_comment')
86
        .unbind('submit').bind('submit', rc_callback);
87
      c_container.find('.js-status-button').bind('click', function() {
88
        this.form.value.value = jQ(this).data('formvalue');
89
      });
90
      c_container.find('.js-show-comments').bind('click', function() {
91
        toggleDiv(this, jQ(this).data('param'));
92
      });
93
      c_container.find('.js-show-changelog').bind('click', function() {
94
        toggleDiv(this, jQ(this).data('param'));
95
      });
96
      c_container.find('.js-file-caserun-bug').bind('click', function(){
97
        var params = jQ(this).data('params');
98
        fileCaseRunBug(params[0], c[0], c_container[0], params[1], params[2]);
99
      });
100
      c_container.find('.js-add-caserun-bug').bind('click', function(){
101
        var params = jQ(this).data('params');
102
        addCaseRunBug(params[0], c[0], c_container[0], params[1], params[2]);
103
      });
104
      c_container.find('.js-remove-caserun-bug').bind('click', function(){
105
        var params = jQ(this).data('params');
106
        removeCaseBug(params[1], params[2], params[3]);
107
      });
108
      c_container.find('.js-add-testlog').bind('click', function(){
109
        var params = jQ(this).data('params');
110
        addLinkToTestExecution(this, params[0], [params[1]]);
111
      });
112
      c_container.find('.js-remove-testlog').bind('click', function(){
113
        var button = this;
114
        jsonRPC('TestExecution.remove_link', [{pk: $(button).data('param')}], function(result) {
115
            button.parentNode.remove();
116
        });
117
      });
118
    };
119
120
    toggleTestExecutionPane({
121
      'callback': callback,
122
      'caseId': case_id,
123
      'caserunId': case_run_id,
124
      'caseTextVersion': case_text_version,
125
      'caserunRowContainer': c,
126
      'expandPaneContainer': c_container
127
    });
128
  };
129
  jQ('.expandable').bind('click', toggle_case_run);
130
131
  // Auto show the case run contents.
132
  if (window.location.hash != '') {
133
    fireEvent(jQ('a[href=\"' + window.location.hash + '\"]')[0], 'click');
134
  };
135
136
  // Filter Case-Run
137
  if (jQ('#filter_case_run').length) {
138
    jQ('#filter_case_run').bind('click',function(e){
139
      if (jQ('#id_filter').is(':hidden')){
140
        jQ('#id_filter').show();
141
        jQ(this).html(default_messages.link.hide_filter);
142
      } else {
143
        jQ('#id_filter').hide();
144
        jQ(this).html(default_messages.link.show_filter);
145
      }
146
    });
147
  }
148
  //bind click to status btn
149
  jQ('.btn_status').live('click', function() {
150
    var from = jQ(this).siblings('.btn_status:disabled')[0].title;
151
    var to = this.title;
152
    if (jQ('span#' + to + ' a').text() === '0') {
153
      var htmlstr = "[<a href='javascript:void(0)' onclick=\"showCaseRunsWithSelectedStatus(jQ('#id_filter')[0], '"
154
        + jQ(this).attr('crs_id')+"')\">0</a>]";
155
      jQ('span#' + to).html(htmlstr);
156
    }
157
    if (jQ('span#' + from + ' a').text() === '1') {
158
      jQ('span#' + from).html("[<a>1</a>]");
159
    }
160
    jQ('span#' + to + ' a').text(window.parseInt(jQ('span#' + to + ' a').text()) + 1);
161
    jQ('span#' + from + ' a').text(window.parseInt(jQ('span#' + from + ' a').text()) - 1);
162
163
    var caseRunCount = window.parseInt(jQ('span#TOTAL').next().text()) || 0;
164
    var passedCaseRunCount = window.parseInt(jQ('span#PASSED a').text()) || 0;
165
    var errorCaseRunCount = window.parseInt(jQ('span#ERROR a').text()) || 0;
166
    var failedCaseRunCount = window.parseInt(jQ('span#FAILED a').text()) || 0;
167
    var waivedCaseRunCount = window.parseInt(jQ('span#WAIVED a').text()) || 0;
168
    var completePercent = 100 * ((passedCaseRunCount + errorCaseRunCount + failedCaseRunCount
169
      + waivedCaseRunCount) / caseRunCount).toFixed(2);
170
    var failedPercent = 100 * ((errorCaseRunCount + failedCaseRunCount) / (passedCaseRunCount
171
      + errorCaseRunCount + failedCaseRunCount + waivedCaseRunCount)).toFixed(2);
172
173
    jQ('span#complete_percent').text(completePercent);
174
    jQ('div.progress-inner').attr('style', 'width:' + completePercent + '%');
175
    jQ('div.progress-failed').attr('style', 'width:' + failedPercent + '%');
176
  });
177
178
  jQ('#btn_clone').bind('click', function() {
179
    postToURL(jQ(this).data('param'), serializeCaseRunFromInputList('id_table_cases','case_run'));
180
  });
181
  jQ('#btn_delete').bind('click', function() {
182
    window.location.href = jQ(this).data('param');
183
  });
184
185
  bindJSRemoveTagButton();
186
  jQ('.js-add-tag').bind('click', function() {
187
    addRunTag(jQ('.js-tag-ul')[0], jQ(this).data('param'));
188
  });
189
  jQ('.js-set-running').bind('click', function() {
190
    window.location.href = jQ(this).data('param') + '?finished=0';
191
  });
192
  jQ('.js-set-finished').bind('click', function() {
193
    window.location.href = jQ(this).data('param') + '?finished=1';
194
  });
195
  jQ('.js-del-case').bind('click', function() {
196
    delCaseRun(jQ(this).data('param'));
197
  });
198
  jQ('.js-update-case').bind('click', function() {
199
    postToURL(jQ(this).data('param'), serializeCaseRunFromInputList('id_table_cases', 'case_run'));
200
  });
201
  jQ('.js-change-assignee').bind('click', function() {
202
    changeCaseRunAssignee();
203
  });
204
  jQ('.js-add-bugs').bind('click', function() {
205
    updateBugs('add');
206
  });
207
  jQ('.js-remove-bugs').bind('click', function() {
208
    updateBugs('remove');
209
  });
210
  jQ('.js-show-commentdialog').bind('click', function() {
211
    showCommentForm();
212
  });
213
214
    $('.js-add-links').bind('click', function() {
215
        bulkAddLinkToTestExecution();
216
    });
217
218
  jQ('.js-add-cc').bind('click', function() {
219
    addRunCC(jQ(this).data('param'), jQ('.js-cc-ul')[0]);
220
  });
221
  jQ('.js-remove-cc').bind('click', function() {
222
    var params = jQ(this).data('params');
223
    removeRunCC(params[0], params[1], jQ('.js-cc-ul')[0]);
224
  });
225
  jQ('.js-caserun-total').bind('click', function() {
226
    showCaseRunsWithSelectedStatus(jQ('#id_filter')[0], '');
227
  });
228
  jQ('.js-status-subtotal').bind('click', function() {
229
    showCaseRunsWithSelectedStatus(jQ('#id_filter')[0], jQ(this).data('param'));
230
  });
231
};
232
233
Nitrate.TestRuns.AssignCase.on_load = function() {
234
  if (jQ('#id_check_all_button').length) {
235
    jQ('#id_check_all_button').bind('click', function(m) {
236
      toggleAllCheckBoxes(this, 'id_table_cases', 'case');
237
    });
238
  }
239
240
  jQ('input[name="case"]').bind('click', function(t) {
241
    if (this.checked) {
242
      jQ(this).closest('tr').addClass('selection_row');
243
      jQ(this).parent().siblings().eq(7).html('<div class="apply_icon"></div>');
244
    } else {
245
      jQ(this).closest('tr').removeClass('selection_row');
246
      jQ(this).parent().siblings().eq(7).html('');
247
    }
248
  });
249
250
  jQ('.js-how-assign-case').bind('click', function() {
251
    jQ('#help_assign').show();
252
  });
253
  jQ('.js-close-how-assign').bind('click', function() {
254
    jQ('#help_assign').hide();
255
  });
256
  jQ('.js-toggle-button, .js-case-summary').bind('click', function() {
257
    toggleTestCaseContents(jQ(this).data('param'));
258
  });
259
};
260
261
262
function updateRunStatus(object_pk, value, callback) {
263
  jQ.ajax({
264
    'url': '/runs/case-run-update-status/',
265
    'type': 'POST',
266
    'data': {'object_pk': object_pk, 'status_id': value },
267
    'success': function (data, textStatus, jqXHR) {
268
      callback();
269
    },
270
    'error': function (jqXHR, textStatus, errorThrown) {
271
      json_failure(jqXHR);
272
    }
273
  });
274
}
275
276
var updateCaseRunStatus = function(e) {
277
  e.stopPropagation();
278
  e.preventDefault();
279
  var container = jQ(this).parents().eq(3);
280
  var parent = container.parent();
281
  var title = parent.prev();
282
  var link = title.find('.expandable')[0];
283
  var parameters = Nitrate.Utils.formSerialize(this);
284
  var object_pk = parameters['object_pk'];
285
  var value = parameters['value'];
286
287
  // Callback when
288
  var callback = function(t) {
289
    // Update the contents
290
    if (parameters['value'] != '') {
291
      // Update the case run status icon
292
      var crs = Nitrate.TestRuns.CaseRunStatus;
293
      title.find('.icon_status').each(function(index) {
294
        for (i in crs) {
295
          if (typeof crs[i] === 'string' && jQ(this).is('.btn_' + crs[i])) {
296
            jQ(this).removeClass('btn_' + crs[i]);
297
          }
298
        }
299
        jQ(this).addClass('btn_' + Nitrate.TestRuns.CaseRunStatus[value - 1]);
300
      });
301
302
      // Update related people
303
      var usr = Nitrate.User;
304
      title.find('.link_tested_by').each(function(i) {
305
        jQ(this).html(usr.username);
306
      });
307
    }
308
309
    // Mark the case run to mine
310
    if (!title.is('.mine')) {
311
      title.addClass('mine');
312
    }
313
314
    // Blind down next case
315
    fireEvent(link, 'click');
316
    if (jQ('#id_check_box_auto_blinddown').attr('checked') && parameters['value'] != '') {
317
      var next_title = parent.next();
318
      if (!next_title.length) {
319
        return false;
320
      }
321
      if (next_title.next().is(':hidden')) {
322
        fireEvent(next_title.find('.expandable')[0], 'click');
323
      }
324
    } else {
325
      fireEvent(link, 'click');
326
    }
327
  };
328
329
  // Add comment
330
  if (parameters['comment'] != '') {
331
    // Reset the content to loading
332
    var ajax_loading = getAjaxLoading();
333
    ajax_loading.id = 'id_loading_' + parameters['case_id'];
334
    container.html(ajax_loading);
335
    var c = jQ('<div>');
336
    if (parameters['value'] != '') {
337
      submitComment(c[0], parameters);
338
    } else {
339
      submitComment(c[0], parameters, callback);
340
    }
341
  }
342
343
  // Update the object when changing the status
344
  if (parameters['value'] != '') {
345
    // Reset the content to loading
346
    var ajax_loading = getAjaxLoading();
347
    ajax_loading.id = 'id_loading_' + parameters['case_id'];
348
    container.html(ajax_loading);
349
    updateRunStatus([object_pk], value, callback);
350
  }
351
};
352
353
354
function constructCaseRunZone(container, title_container, case_id) {
355
  var link = jQ(title_container).find('.expandable')[0];
356
  if (container) {
357
    var td = jQ('<td>', {'id': 'id_loading_' + case_id, 'colspan': 12 });
358
    td.html(getAjaxLoading());
359
    jQ(container).html(td);
360
  }
361
362
  if (title_container) {
363
    fireEvent(link, 'click');
364
    fireEvent(link, 'click');
365
  }
366
}
367
368
369
//////////////////////////////////////////////////////////////////////////////////////////////
370
////////   AddIssueDialog Definition //////////////
371
372
373
/*
374
 * Dialog to allow user to add sort of issue keys to case run(s).
375
 *
376
 * Here, issue key is a general to whatever the issue tracker system is.
377
 *
378
 * options:
379
 * @param extraFormHiddenData: used for providing extra data for specific AJAX request.
380
 * @param onSubmit: callback function when user click Add button
381
 * @param action: string - Add or Remove. Default is Add
382
 */
383
/*
384
 * FIXME: which namespace is proper to hold this dialog class?
385
 */
386
function AddIssueDialog(options) {
387
  this.onSubmit = options.onSubmit;
388
  if (this.onSubmit !== undefined && typeof this.onSubmit !== "function") {
389
    throw new Error("onSubmit should be a function object.");
390
  }
391
  this.extraFormHiddenData = options.extraFormHiddenData;
392
  if (this.extraFormHiddenData !== undefined && typeof this.extraFormHiddenData !== "object") {
393
    throw new Error("extraFormHiddenData sould be an object if present.");
394
  }
395
396
  this.action = options.action;
397
  if (this.action === undefined) {
398
    this.action = "Add";
399
  }
400
401
  this.a = options.a;
402
  if (this.a === undefined) {
403
    this.a = this.action.toLowerCase();
404
  }
405
406
  if (options.hasOwnProperty("show_bug_id_field")) {
407
    this.show_bug_id_field = options.show_bug_id_field;
408
  } else {
409
    this.show_bug_id_field = false;
410
  }
411
}
412
413
414
AddIssueDialog.prototype.show = function () {
415
  var dialog = jQ("#dialog")[0];
416
  if (dialog == null) {
417
    throw new Error("No HTML element with ID dialog. This should not happen in the runtime.");
418
  }
419
420
  var hiddenPart = [];
421
  if (this.extraFormHiddenData !== undefined) {
422
    for (var name_attr in this.extraFormHiddenData) {
423
      hiddenPart.push({'name': name_attr, 'value': this.extraFormHiddenData[name_attr]});
424
    }
425
  }
426
427
  var template = Handlebars.compile(jQ("#add_issue_form_template").html());
428
  var context = {
429
    'hiddenFields': hiddenPart,
430
    'action_button_text': this.action,
431
    'show_bug_id_field': this.show_bug_id_field || this.action === 'Add',
432
    'show_add_to_bugzilla_checkbox': this.action === 'Add',
433
    'a': this.a,
434
  };
435
436
  jQ('#dialog').html(template(context))
437
    .find('.js-cancel-button').bind('click', function() {
438
      jQ('#dialog').hide();
439
    })
440
    .end().show();
441
442
  this.form = jQ("#add_issue_form")[0];
443
444
  // Used for following event callbacks to ref this dialog's instance
445
  var that = this;
446
447
  // Set custom callback functions
448
  if (this.onSubmit !== undefined) {
449
    jQ(this.form).bind('submit', function (form_event) {
450
      that.onSubmit(form_event, that);
451
    });
452
  }
453
};
454
455
AddIssueDialog.prototype.get_data = function () {
456
  var form_data = Nitrate.Utils.formSerialize(this.form);
457
  form_data.bug_validation_regexp = $('#bug_system_id option:selected').data('validation-regexp');
458
  form_data.bz_external_track = $('input[name=bz_external_track]').is(':checked');
459
  return form_data;
460
};
461
462
//// end of AddIssueDialog definition /////////
463
/////////////////////////////////////////////////////////////////////////////////////////////
464
465
function fileCaseRunBug(run_id, title_container, container, case_id, case_run_id) {
466
  var dialog = new AddIssueDialog({
467
    'action': 'Report',
468
    'onSubmit': function (e, dialog) {
469
      e.stopPropagation();
470
      e.preventDefault();
471
472
        var tracker_id = dialog.get_data()['bug_system_id'];
473
        jsonRPC('Bug.report', [case_run_id, tracker_id], function(result) {
474
            $('#dialog').hide();
475
476
            if (result.rc === 0) {
477
                window.open(result.response, '_blank');
478
            } else {
479
                window.alert(result.response);
480
            }
481
      });
482
    }
483
  });
484
485
  dialog.show();
486
}
487
488
function addCaseRunBug(run_id, title_container, container, case_id, case_run_id) {
489
  var dialog = new AddIssueDialog({
490
    'onSubmit': function (e, dialog) {
491
      e.stopPropagation();
492
      e.preventDefault();
493
494
      form_data = dialog.get_data();
495
496
      form_data.bug_id = form_data.bug_id.trim();
497
      if (!form_data.bug_id.length) {
498
        return;
499
      }
500
501
        jsonRPC('Bug.create', [{
502
                case_id: case_id,
503
                case_run_id: case_run_id,
504
                bug_id: form_data.bug_id,
505
                bug_system_id: form_data.bug_system_id
506
            }, form_data.bz_external_track],
507
            function(result) {
508
                // todo: missing error handling when bz_external_track is true
509
                $('#dialog').hide();
510
511
                // Update bugs count associated with just updated case run
512
                var jqCaserunBugCount = $('span#' + case_run_id + '_case_bug_count');
513
                jqCaserunBugCount.addClass('have_bug');
514
515
                // refresh the links of bugs
516
                constructCaseRunZone(container, title_container, case_id);
517
        });
518
    }
519
  });
520
521
  dialog.show();
522
}
523
524
525
function delCaseRun(run_id) {
0 ignored issues
show
The parameter run_id is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
526
  var caseruns = serializeCaseRunFromInputList('id_table_cases', 'case_run');
527
  var numCaseRuns = caseruns.case_run.length;
528
  if (window.confirm('You are about to delete ' + numCaseRuns + ' case run(s). Are you sure?')) {
529
    postToURL('remove_execution/', caseruns);
530
  }
531
}
532
533
534
// binds the remove buttons for all tags
535
function bindJSRemoveTagButton() {
536
  $('.js-remove-tag').bind('click', function() {
537
    var params = $(this).data('params');
538
    removeRunTag($('.js-tag-ul')[0], params[0], params[1]);
539
  });
540
}
541
542
543
// data is an array of id/name for tags
544
function updateTagContainer(container, data, run_id) {
545
    var html = '';
546
547
    data.forEach(function(element) {
548
        var li = '<li>' + element['name'] +
549
                    '<a href="#" class="js-remove-tag" data-params=\'["'+ run_id + '", "' + element['name'] + '"]\'>' +
550
                        '&nbsp;<i class="fa fa-trash-o"></i>' +
551
                    '</a>' +
552
                 '</li>';
553
        html += li;
554
    });
555
556
    $(container).html(html);
557
    bindJSRemoveTagButton();
558
}
559
560
561
function addRunTag(container, run_id) {
562
    var tag_container = $('#id_tags');
563
    var tag = tag_container.val();
564
565
    if (!tag) {
566
        return false;
567
    }
568
569
    var inner_callback = function(data) {
570
        updateTagContainer(container, data, run_id);
571
        tag_container.val('');
572
    }
573
    jsonRPC('TestRun.add_tag', [run_id, tag], inner_callback);
574
}
575
576
function removeRunTag(container, run_id, tag) {
577
    var inner_callback = function(data) {
578
        updateTagContainer(container, data, run_id);
579
    }
580
    jsonRPC('TestRun.remove_tag', [run_id, tag], inner_callback);
581
}
582
583
function constructRunCC(container, run_id, parameters) {
584
  var complete = function(t) {
585
    jQ('.js-remove-cc').bind('click', function() {
586
      var params = jQ(this).data('params');
587
      removeRunCC(params[0], params[1], jQ('.js-cc-ul')[0]);
588
    });
589
    if (jQ('#message').length) {
590
      window.alert(jQ('#message').html());
591
      return false;
592
    }
593
  };
594
  var url = '/runs/' + run_id + '/cc/';
595
  jQ.ajax({
596
    'url': url,
597
    'type': 'GET',
598
    'data': parameters,
599
    'success': function (data, textStatus, jqXHR) {
600
      jQ(container).html(data);
601
    },
602
    'complete': function() {
603
      complete();
604
    }
605
  });
606
}
607
608
function addRunCC(run_id, container) {
609
  var user = window.prompt('Please type new email or username for CC.');
610
  if (!user) {
611
    return false;
612
  }
613
  var parameters = {'do': 'add', 'user': user};
614
  constructRunCC(container, run_id, parameters);
615
}
616
617
function removeRunCC(run_id, user, container) {
618
  var c = window.confirm('Are you sure to delete this user from CC?');
619
620
  if (!c) {
621
    return false;
622
  }
623
624
  var parameters = { 'do': 'remove', 'user': user };
625
  constructRunCC(container, run_id, parameters);
626
}
627
628
function changeCaseRunAssignee() {
629
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
630
  if (!runs.length) {
631
    window.alert(default_messages.alert.no_case_selected);
632
    return false;
633
  }
634
635
  var p = window.prompt('Please type new email or username for assignee');
636
  if (!p) {
637
    return false;
638
  }
639
640
  jQ.ajax({
641
    'url': '/runs/update-assignee/',
642
    'type': 'POST',
643
    'data': { ids: runs, assignee: p },
644
    'success': function (data, textStatus, jqXHR) {
645
      window.location.reload();
646
    },
647
    'error': function (jqXHR, textStatus, errorThrown) {
648
      json_failure(jqXHR);
649
    }
650
  });
651
}
652
653
function serializeCaseRunFromInputList(table, name) {
654
  var elements;
655
  if (typeof table === 'string') {
656
    elements = jQ('#' + table).parent().find('input[name="case_run"]:checked');
657
  } else {
658
    elements = jQ(table).parent().find('input[name="case_run"]:checked');
659
  }
660
661
  var returnobj_list = [];
662
  elements.each(function(i) {
663
    if (typeof this.value === 'string') {
664
      returnobj_list.push(this.value);
665
    }
666
  });
667
  if (name) {
668
    var returnobj = {};
669
    returnobj[name] = returnobj_list;
670
    return returnobj;
671
  }
672
673
  return returnobj_list;
674
}
675
676
function serialzeCaseForm(form, table, serialized) {
677
  if (typeof serialized !== 'boolean') {
678
    var serialized = true;
679
  }
680
  var data;
681
  if (serialized) {
682
    data = Nitrate.Utils.formSerialize(form);
683
  } else {
684
    data = jQ(form).serialize();
685
  }
686
687
  data['case_run'] = serializeCaseFromInputList(table);
688
  return data;
689
}
690
691
function showCaseRunsWithSelectedStatus(form, status_id) {
692
  form.status__pk.value = status_id;
693
  fireEvent(jQ(form).find('input[type="submit"]')[0], 'click');
694
}
695
696
function updateBugsActionAdd(case_runs) {
697
  var dialog = new AddIssueDialog({
698
    'extraFormHiddenData': { 'case_runs': case_runs.join() },
699
    'onSubmit': function(e, dialog) {
700
      e.stopPropagation();
701
      e.preventDefault();
702
      var form_data = dialog.get_data();
703
      form_data.bug_id = form_data.bug_id.trim();
704
705
      if (!form_data.bug_id.length) {
706
        return;
707
      }
708
709
      if (!validateIssueID(form_data.bug_validation_regexp, form_data.bug_id)) {
710
        return false;
711
      }
712
713
      jQ.ajax({
714
        url: '/caserun/update-bugs-for-many/',
715
        dataType: 'json',
716
        data: form_data,
717
        success: function(res){
718
          if (res.rc === 0) {
719
            reloadWindow();
720
          } else {
721
            window.alert(res.response);
722
            return false;
723
          }
724
        }
725
      });
726
    }
727
  });
728
  dialog.show();
729
}
730
731
function updateBugsActionRemove(case_runs) {
732
  var dialog = new AddIssueDialog({
733
    'action': 'Remove',
734
    'show_bug_id_field': true,
735
    'extraFormHiddenData': { 'case_runs': case_runs.join() },
736
    'onSubmit': function(e, dialog) {
737
      e.stopPropagation();
738
      e.preventDefault();
739
      var form_data = dialog.get_data();
740
      form_data.bug_id = form_data.bug_id.trim();
741
742
      if (!form_data.bug_id.length) {
743
        return;
744
      }
745
746
      if (!validateIssueID(form_data.bug_validation_regexp, form_data.bug_id)) {
747
        return false;
748
      }
749
750
      jQ.ajax({
751
        url: '/caserun/update-bugs-for-many/',
752
        dataType: 'json',
753
        success: function(res) {
754
          if (res.rc == 0) {
755
            reloadWindow();
756
          } else {
757
            window.alert(res.response);
758
            return false;
759
          }
760
        },
761
        data: form_data,
762
      });
763
    }
764
  });
765
  dialog.show();
766
}
767
768
function updateBugs(action) {
769
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
770
  if (!runs.length) {
771
    window.alert(default_messages.alert.no_case_selected);
772
    return false;
773
  }
774
775
  if (action === "add") {
776
    updateBugsActionAdd(runs);
777
  } else if (action === "remove") {
778
    updateBugsActionRemove(runs);
779
  } else {
780
    throw new Error("Unknown operation when update case runs' bugs. This should not happen.");
781
  }
782
}
783
784
function showCommentForm() {
785
  var dialog = getDialog();
786
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
787
  if (!runs.length) {
788
    return window.alert(default_messages.alert.no_case_selected);
789
  }
790
  var template = Handlebars.compile(jQ("#batch_add_comment_to_caseruns_template").html());
791
  jQ(dialog).html(template());
792
793
  var commentText = jQ('#commentText');
794
  var commentsErr = jQ('#commentsErr');
795
  jQ('#btnComment').live('click', function() {
796
    var error;
797
    var comments = jQ.trim(commentText.val());
798
    if (!comments) {
799
      error = 'No comments given.';
800
    }
801
    if (error) {
802
      commentsErr.html(error);
803
      return false;
804
    }
805
    jQ.ajax({
806
      url: '/caserun/comment-many/',
807
      data: {'comment': comments, 'run': runs.join()},
808
      dataType: 'json',
809
      type: 'post',
810
      success: function(res) {
811
        if (res.rc == 0) {
812
          reloadWindow();
813
        } else {
814
          commentsErr.html(res.response);
815
          return false;
816
        }
817
      }
818
    });
819
  });
820
  jQ('#btnCancelComment').live('click', function(){
821
    jQ(dialog).hide();
822
    commentText.val('');
823
  });
824
  jQ(dialog).show();
825
}
826
827
jQ(document).ready(function(){
828
  jQ('.btnBlueCaserun').mouseover(function() {
829
    jQ(this).find('ul').show();
830
  }).mouseout(function() {
831
    jQ(this).find('ul').hide();
832
  });
833
  jQ('ul.statusOptions a').click(function() {
834
    var option = jQ(this).attr('value');
835
    var object_pks = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
836
    if (option == '') {
837
      return false;
838
    }
839
    if (!object_pks.length) {
840
      window.alert(default_messages.alert.no_case_selected);
841
      return false;
842
    }
843
    if (!window.confirm(default_messages.confirm.change_case_status)) {
844
      return false;
845
    }
846
    updateRunStatus(object_pks, option, reloadWindow);
847
  });
848
});
849
850
851
function bulkAddLinkToTestExecution() {
852
    var execution_ids = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
853
    if (!execution_ids.length) {
854
        return window.alert(default_messages.alert.no_case_selected);
855
    }
856
857
    addLinkToTestExecution(null, null, execution_ids);
858
}
859
860
/*
861
 * - sender: the Add link button, which is pressed to fire this event.
862
 * - case_id: used for reloading TE details. In case of bulk actions this
863
 *            is null/undefined and the entire page is reloaded!
864
 * - execution_ids: Array of TestExecution IDs to which the new link will be added
865
 */
866
function addLinkToTestExecution(sender, case_id, execution_ids) {
867
  var dialog_p = jQ('#addlink_dialog');
868
869
  dialog_p.dialog('option', 'target_id', execution_ids);
870
  dialog_p.dialog('option', 'case_id', case_id);
871
  if (case_id) {
872
      // These two options are used for reloading TestExecution when successfully.
873
      var container = jQ(sender).parents('.case_content.hide')[0];
874
      dialog_p.dialog('option', 'container', container);
875
      var title_container = jQ(container).prev()[0];
876
      dialog_p.dialog('option', 'title_container', title_container);
877
  }
878
  dialog_p.dialog('open');
879
}
880
881
/*
882
 * Initialize dialog for getting information about new link, which is attached
883
 * to an arbitrary instance of TestExecution
884
 */
885
function initialize_addlink_dialog() {
886
  var dialog_p = jQ('#addlink_dialog');
887
888
  dialog_p.dialog({
889
    autoOpen: false,
890
    modal: true,
891
    resizable: false,
892
    height: 300,
893
    width: 400,
894
    open: function() {
895
      jQ(this).unbind('submit').bind('submit', function (e) {
896
        e.stopPropagation();
897
        e.preventDefault();
898
        jQ(this).dialog('widget').find('span:contains("OK")').click();
899
      });
900
    },
901
    buttons: {
902
      "OK": function() {
903
        var name = jQ('#testlog_name').attr('value');
904
        var url = jQ('#testlog_url').attr('value');
905
        var case_id = dialog_p.dialog('option', 'case_id');
906
907
        dialog_p.dialog('close');
908
909
        jQ(this).dialog('option', 'target_id').forEach(function(target_id) {
910
            jsonRPC('TestExecution.add_link', [target_id, name, url], function(result) {
911
                // when bulk adding links case_id will be undefined/null
912
                if (case_id) {
913
                    // Begin to construct case run area
914
                    var container = dialog_p.dialog('option', 'container');
915
                    var title_container = dialog_p.dialog('option', 'title_container');
916
                    constructCaseRunZone(container, title_container, case_id);
917
                }
918
            });
919
        });
920
921
        // reload entire page if adding in bulk
922
        if (!case_id) {
923
            window.location.reload(true);
924
        }
925
      },
926
      "Cancel": function() {
927
        jQ(this).dialog('close');
928
      }
929
    },
930
    beforeClose: function() {
931
      // clean name and url for next input
932
      jQ('#testlog_name').val('');
933
      jQ('#testlog_url').val('');
934
935
      return true;
936
    },
937
    /* ATTENTION: target_id can be determined when open this dialog, and
938
     * this must be set
939
     */
940
    target_id: null
941
  });
942
}
943
944
945
/*
946
 * Toggle TestExecution panel to edit a case run in run page.
947
 *
948
 * Arguments:
949
 * options.casrunContainer:
950
 * options.expandPaneContainer:
951
 * options.caseId:
952
 * options.caserunId:
953
 * options.caseTextVersion:
954
 * options.callback:
955
 */
956
function toggleTestExecutionPane(options) {
957
  var container = options.caserunRowContainer;
958
  var content_container = options.expandPaneContainer;
959
  var callback = options.callback;
960
961
  content_container.toggle();
962
963
  if (content_container.find('.ajax_loading').length) {
964
    var url = '/case/' + options.caseId + '/execution-detail-pane/';
965
    var data = { case_run_id: options.caserunId, case_text_version: options.caseTextVersion };
966
967
    jQ.get(url, data, function(data, textStatus) {
968
      content_container.html(data);
969
      callback();
970
    }, 'html');
971
  }
972
973
  toggleExpandArrow({ caseRowContainer: container, expandPaneContainer: content_container });
974
}
975