Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to restart jobs upon comment submission #5971

Merged
merged 2 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions assets/javascripts/openqa.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,12 @@ function forceJobRestartViaRestartLink(restartLink) {
restartLink.click();
}

function restartJob(ajaxUrl, jobId) {
function restartJob(ajaxUrl, jobIds, comment) {
let singleJobId;
if (!Array.isArray(jobIds)) {
singleJobId = jobIds;
jobIds = [jobIds];
}
var showError = function (reason) {
var errorMessage = '<strong>Unable to restart job';
if (reason) {
Expand All @@ -248,30 +253,45 @@ function restartJob(ajaxUrl, jobId) {
}
addFlash('danger', errorMessage);
};

return fetchWithCSRF(ajaxUrl, {method: 'POST'})
const body = new FormData();
body.append('comment', comment);
return fetchWithCSRF(ajaxUrl, {method: 'POST', body: body})
.then(response => {
if (!response.ok) throw `Server returned ${response.status}: ${response.statusText}`;
return response.json();
})
.then(responseJSON => {
var newJobUrl;
try {
newJobUrl = responseJSON.test_url[0][jobId];
if (singleJobId) {
newJobUrl = responseJSON.test_url[0][singleJobId];
} else {
const testUrlData = responseJSON?.test_url;
if (Array.isArray(testUrlData)) {
newJobUrl = testUrlData.map(item => Object.values(item)[0]);
}
}
} catch {
// Intentionally ignore all errors
}
if (
showJobRestartResults(
responseJSON,
newJobUrl,
restartJob.bind(undefined, addParam(ajaxUrl, 'force', '1'), jobId)
restartJob.bind(undefined, addParam(ajaxUrl, 'force', '1'), jobIds, comment)
)
) {
return;
}
if (newJobUrl) {
window.location.replace(newJobUrl);
if (Array.isArray(newJobUrl)) {
addFlash(
'info',
'The jobs have been restarted. <a href="javascript: location.reload()">Reload</a> the page to show changes.'
);
} else {
window.location.replace(newJobUrl);
}
} else {
throw 'URL for new job not available';
}
Expand Down
29 changes: 27 additions & 2 deletions assets/javascripts/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,33 @@ function showAddCommentsDialog() {
modal.show();
}

function addComments(form) {
function restartJobsWithComment(btn) {
const form = btn.form;
const text = form.elements.text.value;
const jobs = btn.dataset.jobs
.split(',')
.map(Number)
.filter(n => !isNaN(n));
const apiUrl = btn.dataset.url;
if (!text.length) {
return window.alert("The comment text mustn't be empty.");
}

const progressIndication = document.getElementById('add-comments-progress-indication');
const controls = document.getElementById('add-comments-controls');
progressIndication.style.display = 'flex';
controls.style.display = 'none';
restartJob(apiUrl, jobs, text).finally(() => {
progressIndication.style.display = 'none';
controls.style.display = 'inline';
window.addCommentsModal.hide();
Martchus marked this conversation as resolved.
Show resolved Hide resolved
});
}

function addComments(btn) {
const form = btn.form;
const text = form.elements.text.value;
const apiUrl = btn.dataset.url;
if (!text.length) {
return window.alert("The comment text mustn't be empty.");
}
Expand All @@ -301,7 +326,7 @@ function addComments(form) {
controls.style.display = 'inline';
window.addCommentsModal.hide();
};
fetchWithCSRF(form.action, {method: 'POST', body: new FormData(form)})
fetchWithCSRF(apiUrl, {method: 'POST', body: new FormData(form)})
.then(response => {
if (!response.ok) throw `Server returned ${response.status}: ${response.statusText}`;
addFlash(
Expand Down
10 changes: 9 additions & 1 deletion assets/stylesheets/overview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,12 @@
#add-comments-progress-indication {
display: none;
width: 100%;
}
}

.group-comment-icon-stack {
font-size: 0.9em;
}

.group-comment-icon-stack .fa-undo {
color: #0c4374;
}
60 changes: 38 additions & 22 deletions t/ui/10-tests_overview.t
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ like($driver->find_elements('.failedmodule', 'css')->[1]->get_attribute('href'),

my @descriptions = $driver->find_elements('td.name a', 'css');
is(scalar @descriptions, 2, 'only test suites with description content are shown as links');
disable_bootstrap_animations;
$descriptions[0]->click();
is($driver->find_element('.popover-header')->get_text, 'kde', 'description popover shows content');

Expand Down Expand Up @@ -543,18 +542,32 @@ subtest 'filter by result and state' => sub {
ok !$driver->find_element_by_id('filter-failed')->is_selected, 'other checkbox not checked';
};

subtest "job template names displayed on 'Test result overview' page" => sub {
$driver->get('/group_overview/1002');
is($driver->find_element('.progress-bar-unfinished')->get_text(),
'1 unfinished', 'expected number of unfinished jobs');

$driver->get('/tests/overview?distri=opensuse&version=13.1&build=0091&groupid=1002');
my @tds = $driver->find_elements('#results_DVD tbody tr .name');
is($tds[0]->get_text(), 'kde_variant', 'job template name kde_variant displayed correctly');

my @descriptions = $driver->find_elements('td.name a', 'css');
is(scalar @descriptions, 2, 'only test suites with description content are shown as links');
$descriptions[0]->click();
is(wait_for_element(selector => '.popover-header')->get_text, 'kde_variant', 'description popover shows content');
};

subtest 'add comments' => sub {
my @buttons = $driver->find_elements('button[title="Add comments"]');
my @buttons = $driver->find_elements('button[title="Restart or comment jobs"]');
is @buttons, 0, 'button for adding comments not present if not logged-in';

$driver->find_element_by_link_text('Login')->click;
$driver->get('/tests/overview?state=done&result=failed');
disable_bootstrap_animations;
$driver->find_element('button[title="Add comments"]')->click;
$driver->find_element('button[title="Restart or comment jobs"]')->click;
my $comment_text = 'comment via add-comments';
my $submit_button = $driver->find_element('#add-comments-controls button[type="submit"]');
my $submit_button = $driver->find_element('#add-comments-controls button[id="commentJobsBtn"]');
$driver->find_element_by_id('text')->send_keys($comment_text);
is $submit_button->get_text, 'Submit comment on all 2 jobs', 'submit button displayed with number of jobs';
is $submit_button->get_text, 'Comment on all 2 jobs', 'submit button displayed with number of jobs';
$submit_button->click;
wait_for_ajax msg => 'comments created';
like $driver->find_element_by_id('flash-messages')->get_text, qr/The comments have been created. Reload/,
Expand All @@ -565,23 +578,26 @@ subtest 'add comments' => sub {
'comments created on all relevant jobs';
is $comments->search({job_id => {-not_in => \@failed_job_ids}, text => $comment_text})->count, 0,
'comments not created on other jobs';
};

subtest "job template names displayed on 'Test result overview' page" => sub {
$driver->get('/group_overview/1002');
is($driver->find_element('.progress-bar-failed')->get_text(), '1 failed', 'The number of failed jobs is right');
is($driver->find_element('.progress-bar-unfinished')->get_text(),
'1 unfinished', 'The number of unfinished jobs is right');

$driver->get('/tests/overview?distri=opensuse&version=13.1&build=0091&groupid=1002');
my @tds = $driver->find_elements('#results_DVD tbody tr .name');
is($tds[0]->get_text(), 'kde_variant', 'job template name kde_variant displayed correctly');

my @descriptions = $driver->find_elements('td.name a', 'css');
is(scalar @descriptions, 2, 'only test suites with description content are shown as links');
disable_bootstrap_animations;
$descriptions[0]->click();
is(wait_for_element(selector => '.popover-header')->get_text, 'kde_variant', 'description popover shows content');
subtest 'restart jobs with comment' => sub {
$driver->get('/tests/overview?state=done&result=failed');
$driver->find_element('button[title="Restart or comment jobs"]')->click;
my $comment_text = 'comment current jobs and restart';
okurz marked this conversation as resolved.
Show resolved Hide resolved
my $submit_button = $driver->find_element('#restartAndCommentJobsBtn');
$driver->find_element_by_id('text')->send_keys($comment_text);
is $submit_button->get_text, 'Restart and comment on 2 jobs', 'submit button displayed with number of jobs';
$submit_button->click;
wait_for_ajax msg => 'comments created';
like $driver->find_element_by_id('flash-messages')->get_text, qr/Reload the page to show changes/,
'info about successful restart shown';
my @failed_job_ids = map { $_->id } $jobs->search({result => FAILED})->all;
is $comments->search({job_id => {-in => \@failed_job_ids}, text => $comment_text})->count, 2,
'comments created on all relevant jobs';
is $comments->search({job_id => {-not_in => \@failed_job_ids}, text => $comment_text})->count, 0,
perlpunk marked this conversation as resolved.
Show resolved Hide resolved
'comments not created on other jobs';
my $running_job_ids = map { $_->id } $jobs->search({state => RUNNING})->all;
is $running_job_ids, 2, 'all relevant jobs restarted';
};
};

subtest "job dependencies displayed on 'Test result overview' page" => sub {
Expand Down
62 changes: 37 additions & 25 deletions templates/webapi/test/overview.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@
<div class="card-body">
% my $allow_commenting = @$job_ids && current_user;
% if ($allow_commenting) {
<button type="button" class="btn btn-secondary btn-circle btn-sm trigger-edit-button" onclick="showAddCommentsDialog()" title="Add comments">
<i class="fa fa-comment" aria-hidden="true"></i>
<button type="button" class="btn btn-secondary btn-circle btn-sm trigger-edit-button" onclick="showAddCommentsDialog()" title="Restart or comment jobs">
<span class="fa-stack group-comment-icon-stack">
<i class="fa fa-comment fa-stack-2x text-danger-info" aria-hidden="true"></i>
<i class="fa fa-undo fa-stack-1x" aria-hidden="true"></i>
</span>
</button>
% }
% my @badges = qw(success secondary warning danger info primary light light);
Expand Down Expand Up @@ -215,30 +218,39 @@

% if ($allow_commenting) {
<div class="modal fade" id="add-comments-modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="<%= url_for('apiv1_post_comments')->query(job_id => $job_ids) %>" method="post" onsubmit="addComments(this); return false;">
<div class="modal-header">
<h4 class="modal-title">Add comment on all currently shown jobs</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
%= include 'comments/add_comment_form_groups', group_comment => 0, nosubmit => 1
</div>
<div class="modal-footer">
<div id="add-comments-progress-indication">
<div class="flex-fill"><i class="fa fa-cog fa-spin fa-fw"></i> Saving…</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
<div id="add-comments-controls">
<button type="submit" class="btn btn-danger">
<i class="fa fa-comment"></i> Submit comment on all <%= scalar @$job_ids %> jobs
</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Discard</button>
</div>
</div>
</form>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form method="post">
<div class="modal-header">
<h4 class="modal-title">Add comment on all currently shown jobs</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
%= include 'comments/add_comment_form_groups', group_comment => 0, nosubmit => 1
</div>
<div class="modal-footer">
<div id="add-comments-progress-indication">
<div class="flex-fill"><i class="fa fa-cog fa-spin fa-fw"></i> Saving…</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
<div id="add-comments-controls">
<button type="button" class="btn btn-warning" id="commentJobsBtn"
data-url="<%= url_for('apiv1_post_comments')->query(job_id=>$job_ids) %>"
onclick="addComments(this);">
<i class="fa fa-comment"></i> Comment on all <%= scalar @$job_ids %> jobs
</button>
<button type="button" class="btn btn-danger" id="restartAndCommentJobsBtn"
data-jobs="<%= join(',', @$job_ids) %>"
data-url="<%= url_for('apiv1_restart_jobs')->query(jobs=>$job_ids) %>"
onclick="restartJobsWithComment(this);">
<i class="fa fa-play-circle-o"></i> Restart and comment on <%= scalar @$job_ids %> jobs
</button>
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Discard</button>
</div>
</div>
</form>
</div>
</div>
</div>
% }
Loading