Passed
Push — master ( 62d7d9...8230b1 )
by Alexander
03:29
created

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

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();
0 ignored issues
show
The variable form_data seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.form_data.
Loading history...
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) {
0 ignored issues
show
The parameter result 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...
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) {
526
    if (window.confirm('Are you sure?')) {
527
        const executions = $('#id_table_cases').find('input[name="case_run"]:checked');
528
529
        executions.each(function() {
530
            var case_id = this.getAttribute('data-case_id');
531
            jsonRPC('TestRun.remove_case', [run_id, Number(case_id)], function () {
532
                $(this).closest('tr').remove();
533
            }.bind(this));
534
        });
535
    }
536
}
537
538
539
// binds the remove buttons for all tags
540
function bindJSRemoveTagButton() {
541
  $('.js-remove-tag').bind('click', function() {
542
    var params = $(this).data('params');
543
    removeRunTag($('.js-tag-ul')[0], params[0], params[1]);
544
  });
545
}
546
547
548
// data is an array of id/name for tags
549
function updateTagContainer(container, data, run_id) {
550
    var html = '';
551
552
    data.forEach(function(element) {
553
        var li = '<li>' + element['name'] +
554
                    '<a href="#" class="js-remove-tag" data-params=\'["'+ run_id + '", "' + element['name'] + '"]\'>' +
555
                        '&nbsp;<i class="fa fa-trash-o"></i>' +
556
                    '</a>' +
557
                 '</li>';
558
        html += li;
559
    });
560
561
    $(container).html(html);
562
    bindJSRemoveTagButton();
563
}
564
565
566
function addRunTag(container, run_id) {
567
    var tag_container = $('#id_tags');
568
    var tag = tag_container.val();
569
570
    if (!tag) {
571
        return false;
572
    }
573
574
    var inner_callback = function(data) {
575
        updateTagContainer(container, data, run_id);
576
        tag_container.val('');
577
    }
578
    jsonRPC('TestRun.add_tag', [run_id, tag], inner_callback);
579
}
580
581
function removeRunTag(container, run_id, tag) {
582
    var inner_callback = function(data) {
583
        updateTagContainer(container, data, run_id);
584
    }
585
    jsonRPC('TestRun.remove_tag', [run_id, tag], inner_callback);
586
}
587
588
function constructRunCC(container, run_id, parameters) {
589
  var complete = function(t) {
590
    jQ('.js-remove-cc').bind('click', function() {
591
      var params = jQ(this).data('params');
592
      removeRunCC(params[0], params[1], jQ('.js-cc-ul')[0]);
593
    });
594
    if (jQ('#message').length) {
595
      window.alert(jQ('#message').html());
596
      return false;
597
    }
598
  };
599
  var url = '/runs/' + run_id + '/cc/';
600
  jQ.ajax({
601
    'url': url,
602
    'type': 'GET',
603
    'data': parameters,
604
    'success': function (data, textStatus, jqXHR) {
605
      jQ(container).html(data);
606
    },
607
    'complete': function() {
608
      complete();
609
    }
610
  });
611
}
612
613
function addRunCC(run_id, container) {
614
  var user = window.prompt('Please type new email or username for CC.');
615
  if (!user) {
616
    return false;
617
  }
618
  var parameters = {'do': 'add', 'user': user};
619
  constructRunCC(container, run_id, parameters);
620
}
621
622
function removeRunCC(run_id, user, container) {
623
  var c = window.confirm('Are you sure to delete this user from CC?');
624
625
  if (!c) {
626
    return false;
627
  }
628
629
  var parameters = { 'do': 'remove', 'user': user };
630
  constructRunCC(container, run_id, parameters);
631
}
632
633
function changeCaseRunAssignee() {
634
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
635
  if (!runs.length) {
636
    window.alert(default_messages.alert.no_case_selected);
637
    return false;
638
  }
639
640
  var p = window.prompt('Please type new email or username for assignee');
641
  if (!p) {
642
    return false;
643
  }
644
645
  jQ.ajax({
646
    'url': '/runs/update-assignee/',
647
    'type': 'POST',
648
    'data': { ids: runs, assignee: p },
649
    'success': function (data, textStatus, jqXHR) {
650
      window.location.reload();
651
    },
652
    'error': function (jqXHR, textStatus, errorThrown) {
653
      json_failure(jqXHR);
654
    }
655
  });
656
}
657
658
function serializeCaseRunFromInputList(table, name) {
659
  var elements;
660
  if (typeof table === 'string') {
661
    elements = jQ('#' + table).parent().find('input[name="case_run"]:checked');
662
  } else {
663
    elements = jQ(table).parent().find('input[name="case_run"]:checked');
664
  }
665
666
  var returnobj_list = [];
667
  elements.each(function(i) {
668
    if (typeof this.value === 'string') {
669
      returnobj_list.push(this.value);
670
    }
671
  });
672
  if (name) {
673
    var returnobj = {};
674
    returnobj[name] = returnobj_list;
675
    return returnobj;
676
  }
677
678
  return returnobj_list;
679
}
680
681
function serialzeCaseForm(form, table, serialized) {
682
  if (typeof serialized !== 'boolean') {
683
    var serialized = true;
684
  }
685
  var data;
686
  if (serialized) {
687
    data = Nitrate.Utils.formSerialize(form);
688
  } else {
689
    data = jQ(form).serialize();
690
  }
691
692
  data['case_run'] = serializeCaseFromInputList(table);
693
  return data;
694
}
695
696
function showCaseRunsWithSelectedStatus(form, status_id) {
697
  form.status__pk.value = status_id;
698
  fireEvent(jQ(form).find('input[type="submit"]')[0], 'click');
699
}
700
701
function updateBugsActionAdd(case_runs) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
702
  var dialog = new AddIssueDialog({
703
    'extraFormHiddenData': { 'case_runs': case_runs.join() },
704
    'onSubmit': function(e, dialog) {
705
      e.stopPropagation();
706
      e.preventDefault();
707
      var form_data = dialog.get_data();
708
      form_data.bug_id = form_data.bug_id.trim();
709
710
      if (!form_data.bug_id.length) {
711
        return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
712
      }
713
714
      if (!validateIssueID(form_data.bug_validation_regexp, form_data.bug_id)) {
715
        return false;
716
      }
717
718
      jQ.ajax({
0 ignored issues
show
The variable jQ seems to be never declared. If this is a global, consider adding a /** global: jQ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
719
        url: '/caserun/update-bugs-for-many/',
720
        dataType: 'json',
721
        data: form_data,
722
        success: function(res){
723
          if (res.rc === 0) {
724
            reloadWindow();
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
725
          } else {
726
            window.alert(res.response);
727
            return false;
728
          }
729
        }
730
      });
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
731
    }
732
  });
733
  dialog.show();
734
}
735
736
function updateBugsActionRemove(case_runs) {
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
737
  var dialog = new AddIssueDialog({
738
    'action': 'Remove',
739
    'show_bug_id_field': true,
740
    'extraFormHiddenData': { 'case_runs': case_runs.join() },
741
    'onSubmit': function(e, dialog) {
742
      e.stopPropagation();
743
      e.preventDefault();
744
      var form_data = dialog.get_data();
745
      form_data.bug_id = form_data.bug_id.trim();
746
747
      if (!form_data.bug_id.length) {
748
        return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
749
      }
750
751
      if (!validateIssueID(form_data.bug_validation_regexp, form_data.bug_id)) {
752
        return false;
753
      }
754
755
      jQ.ajax({
0 ignored issues
show
The variable jQ seems to be never declared. If this is a global, consider adding a /** global: jQ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
756
        url: '/caserun/update-bugs-for-many/',
757
        dataType: 'json',
758
        success: function(res) {
759
          if (res.rc == 0) {
0 ignored issues
show
Comparing res.rc to 0 using the == operator is not safe. Consider using === instead.
Loading history...
760
            reloadWindow();
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
761
          } else {
762
            window.alert(res.response);
763
            return false;
764
          }
765
        },
766
        data: form_data,
767
      });
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
768
    }
769
  });
770
  dialog.show();
771
}
772
773
function updateBugs(action) {
774
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
775
  if (!runs.length) {
776
    window.alert(default_messages.alert.no_case_selected);
0 ignored issues
show
The variable default_messages seems to be never declared. If this is a global, consider adding a /** global: default_messages */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
777
    return false;
778
  }
779
780
  if (action === "add") {
781
    updateBugsActionAdd(runs);
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
782
  } else if (action === "remove") {
783
    updateBugsActionRemove(runs);
0 ignored issues
show
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
784
  } else {
785
    throw new Error("Unknown operation when update case runs' bugs. This should not happen.");
786
  }
787
}
788
789
function showCommentForm() {
790
  var dialog = getDialog();
791
  var runs = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
792
  if (!runs.length) {
793
    return window.alert(default_messages.alert.no_case_selected);
794
  }
795
  var template = Handlebars.compile(jQ("#batch_add_comment_to_caseruns_template").html());
796
  jQ(dialog).html(template());
797
798
  var commentText = jQ('#commentText');
799
  var commentsErr = jQ('#commentsErr');
800
  jQ('#btnComment').live('click', function() {
801
    var error;
802
    var comments = jQ.trim(commentText.val());
803
    if (!comments) {
804
      error = 'No comments given.';
805
    }
806
    if (error) {
807
      commentsErr.html(error);
808
      return false;
809
    }
810
    jQ.ajax({
811
      url: '/caserun/comment-many/',
812
      data: {'comment': comments, 'run': runs.join()},
813
      dataType: 'json',
814
      type: 'post',
815
      success: function(res) {
816
        if (res.rc == 0) {
817
          reloadWindow();
818
        } else {
819
          commentsErr.html(res.response);
820
          return false;
821
        }
822
      }
823
    });
824
  });
825
  jQ('#btnCancelComment').live('click', function(){
826
    jQ(dialog).hide();
827
    commentText.val('');
828
  });
829
  jQ(dialog).show();
830
}
831
832
jQ(document).ready(function(){
833
  jQ('.btnBlueCaserun').mouseover(function() {
834
    jQ(this).find('ul').show();
835
  }).mouseout(function() {
836
    jQ(this).find('ul').hide();
837
  });
838
  jQ('ul.statusOptions a').click(function() {
839
    var option = jQ(this).attr('value');
840
    var object_pks = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
841
    if (option == '') {
842
      return false;
843
    }
844
    if (!object_pks.length) {
845
      window.alert(default_messages.alert.no_case_selected);
846
      return false;
847
    }
848
    if (!window.confirm(default_messages.confirm.change_case_status)) {
849
      return false;
850
    }
851
    updateRunStatus(object_pks, option, reloadWindow);
852
  });
853
});
854
855
856
function bulkAddLinkToTestExecution() {
857
    var execution_ids = serializeCaseRunFromInputList(jQ('#id_table_cases')[0]);
858
    if (!execution_ids.length) {
859
        return window.alert(default_messages.alert.no_case_selected);
860
    }
861
862
    addLinkToTestExecution(null, null, execution_ids);
863
}
864
865
/*
866
 * - sender: the Add link button, which is pressed to fire this event.
867
 * - case_id: used for reloading TE details. In case of bulk actions this
868
 *            is null/undefined and the entire page is reloaded!
869
 * - execution_ids: Array of TestExecution IDs to which the new link will be added
870
 */
871
function addLinkToTestExecution(sender, case_id, execution_ids) {
872
  var dialog_p = jQ('#addlink_dialog');
873
874
  dialog_p.dialog('option', 'target_id', execution_ids);
875
  dialog_p.dialog('option', 'case_id', case_id);
876
  if (case_id) {
877
      // These two options are used for reloading TestExecution when successfully.
878
      var container = jQ(sender).parents('.case_content.hide')[0];
879
      dialog_p.dialog('option', 'container', container);
880
      var title_container = jQ(container).prev()[0];
881
      dialog_p.dialog('option', 'title_container', title_container);
882
  }
883
  dialog_p.dialog('open');
884
}
885
886
/*
887
 * Initialize dialog for getting information about new link, which is attached
888
 * to an arbitrary instance of TestExecution
889
 */
890
function initialize_addlink_dialog() {
891
  var dialog_p = jQ('#addlink_dialog');
892
893
  dialog_p.dialog({
894
    autoOpen: false,
895
    modal: true,
896
    resizable: false,
897
    height: 300,
898
    width: 400,
899
    open: function() {
900
      jQ(this).unbind('submit').bind('submit', function (e) {
901
        e.stopPropagation();
902
        e.preventDefault();
903
        jQ(this).dialog('widget').find('span:contains("OK")').click();
904
      });
905
    },
906
    buttons: {
907
      "OK": function() {
908
        var name = jQ('#testlog_name').attr('value');
909
        var url = jQ('#testlog_url').attr('value');
910
        var case_id = dialog_p.dialog('option', 'case_id');
911
912
        dialog_p.dialog('close');
913
914
        jQ(this).dialog('option', 'target_id').forEach(function(target_id) {
915
            jsonRPC('TestExecution.add_link', [target_id, name, url], function(result) {
0 ignored issues
show
The parameter result 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...
916
                // when bulk adding links case_id will be undefined/null
917
                if (case_id) {
918
                    // Begin to construct case run area
919
                    var container = dialog_p.dialog('option', 'container');
920
                    var title_container = dialog_p.dialog('option', 'title_container');
921
                    constructCaseRunZone(container, title_container, case_id);
922
                }
923
            });
924
        });
925
926
        // reload entire page if adding in bulk
927
        if (!case_id) {
928
            window.location.reload(true);
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 TestExecution 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 toggleTestExecutionPane(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