Skip to content

Commit

Permalink
Merge pull request #538 from okurz/feature/label_and_previous_results
Browse files Browse the repository at this point in the history
Show previous results in test results page
  • Loading branch information
coolo committed Feb 17, 2016
2 parents f9ee386 + a7c1228 commit 8da815f
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 96 deletions.
31 changes: 30 additions & 1 deletion lib/OpenQA/WebAPI/Controller/Test.pm
Expand Up @@ -245,10 +245,14 @@ sub show {

return $self->reply->not_found unless $job;

my @scenario_keys = qw/DISTRI VERSION FLAVOR ARCH TEST/;
my $scenario = join('-', map { $job->settings_hash->{$_} } @scenario_keys);

$self->stash(testname => $job->settings_hash->{NAME});
$self->stash(distri => $job->settings_hash->{DISTRI});
$self->stash(version => $job->settings_hash->{VERSION});
$self->stash(build => $job->settings_hash->{BUILD});
$self->stash(scenario => $scenario);

# return $self->reply->not_found unless (-e $self->stash('resultdir'));

Expand All @@ -261,7 +265,7 @@ sub show {
return;
}

my $clone_of = $self->app->schema->resultset("Jobs")->find({clone_id => $job->id});
my $clone_of = $self->db->resultset("Jobs")->find({clone_id => $job->id});

my $modlist = read_test_modules($job);
$self->stash(job => $job);
Expand All @@ -284,6 +288,31 @@ sub show {
$self->stash(ulogs => []);
}

# search for previous jobs
my @conds;
push(@conds, {'me.state' => 'done'});
push(@conds, {'me.result' => {-not_in => [OpenQA::Schema::Result::Jobs::INCOMPLETE_RESULTS]}});
push(@conds, {id => {'<', $job->id}});
my %js_settings = map { $_ => $job->settings_hash->{$_} } @scenario_keys;
my $subquery = $self->db->resultset("JobSettings")->query_for_settings(\%js_settings);
push(@conds, {'me.id' => {-in => $subquery->get_column('job_id')->as_query}});

my $limit_previous = $self->param('limit_previous') // 10; # arbitrary limit of previous results to show
my %attrs = (
rows => $limit_previous,
order_by => ['me.id DESC']);
my $previous_jobs_rs = $self->db->resultset("Jobs")->search({-and => \@conds}, \%attrs);
my @previous_jobs;
while (my $prev = $previous_jobs_rs->next) {
$self->app->log->debug("Previous result job " . $prev->id . ": " . join('-', map { $prev->settings_hash->{$_} } @scenario_keys));
push(@previous_jobs, $prev);
}
my $job_labels = $self->_job_labels(\@previous_jobs);

$self->stash(previous => \@previous_jobs);
$self->stash(previous_labels => $job_labels);
$self->stash(limit_previous => $limit_previous);

$self->render('test/result');
}

Expand Down
45 changes: 45 additions & 0 deletions t/ui/16-tests_previous_results.t
@@ -0,0 +1,45 @@
# Copyright (C) 2016 SUSE Linux GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

BEGIN {
unshift @INC, 'lib';
}

use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
use OpenQA::Test::Case;

OpenQA::Test::Case->new->init_data;

use t::ui::PhantomTest;

my $t = Test::Mojo->new('OpenQA::WebAPI');

my $get = $t->get_ok('/tests/99946#previous')->status_is(200);
my $tab_label = $t->tx->res->dom->at('li a[href=#previous]')->all_text;
is($tab_label, q/Previous results (1)/, 'previous results with number is shown');
my $previous_results_header = $t->tx->res->dom->at('#previous #scenario')->all_text;
is($previous_results_header, q/Results for opensuse-13.1-DVD-i586-textmode, limited to 10/, 'header for previous results with scenario');
$get->element_exists('#res_99945', 'result from previous job');
$get->element_exists('#res_99945 .result_passed', 'previous job was passed');
my $build = $t->tx->res->dom->at('#previous #results .build')->all_text;
is($build, '0091', 'build of previous job is shown');
$get = $t->get_ok('/tests/99946?limit_previous=1#previous')->status_is(200);
$previous_results_header = $t->tx->res->dom->at('#previous #scenario')->all_text;
is($previous_results_header, q/Results for opensuse-13.1-DVD-i586-textmode, limited to 1/, 'can be limited with query parameter');

done_testing();
91 changes: 2 additions & 89 deletions templates/test/overview.html.ep
Expand Up @@ -75,95 +75,8 @@
<td>-</td>
% next;
% }
<td id="res_<%= $type %>_<%= $arch %>_<%= $config %>">
% if ($res) {
% if (is_operator) {
% if ($state eq "done" || $state eq "cancelled") {
%= link_post url_for('apiv1_restart', 'name' => $jobid) => ('data-remote' => 'true', class => 'restart', 'data-jobid' => $jobid) => begin
<i class="action fa fa-repeat" title="Restart the job"></i>
% end
% } elsif ($state eq "running" || $state eq "scheduled")
% {
%= link_post url_for('apiv1_cancel', 'name' => $jobid) => ('data-remote' => 'true', class => 'cancel', 'data-jobid' => $jobid) => begin
<i class="action fa fa-times-circle-o" title="Cancel the job"></i>
% end
% }
% }

% my $css = "";
% $css .= " result_".$res->{overall} if ($state eq "done");
% if ($state eq "done") {
<span id="res-<%= $jobid %>">
<a href="<%= url_for('test', 'testid' => $jobid) %>">
<i class="status fa fa-circle<%= $css %>" title="Done: <%= $res->{overall} %>"></i>
</a>
</span>
% } elsif ($state eq "scheduled")
% {
<a href="<%= url_for('test', 'testid' => $jobid) %>">
<i class="status state_scheduled fa fa-circle" title="scheduled@<%= $res->{priority} %>"></i>
</a>
% } else
% {
<a href="<%= url_for('test', 'testid' => $jobid) %>">
<i class="status state_<%= $state %> fa fa-circle" title="<%= $state %>"></i>
</a>
% }
% my $failedmodules = $res->{'failures'};
% if ($failedmodules) {
% my $count = 0;
% for my $failedmodule (sort keys %$failedmodules) {
% if (++$count > 2) {
% my $more = (scalar(keys %$failedmodules)) - $count + 1;
% if ($more > 1) {
<%= $more %> more
% last;
% }
% }
% my $failedneedles = $failedmodules->{$failedmodule};
% my $step = 1;
% my $tooltip = '';
% if (@$failedneedles) {
% $step = $failedneedles->[0]->[1];
% if ($failedneedles->[0]->[0]) {
% $tooltip = "title='<p>Failed needles:</p><ul><li>" . join('</li><li>',
% sort map { $_->[0] } @$failedneedles) . "</li></ul>' data-toggle='tooltip'";
% }
% }

<span <%= Mojo::ByteStream->new($tooltip) %> class="failedmodule" >
<a href="<%= url_for('step', 'testid' => $jobid,
'moduleid' => $failedmodule, 'stepid' => $step) %>">
<%= $failedmodule %>
</a>
</span>
% }
% }
%# 'bentostrap' has an item 'label' which
%# we do not want to use so we use 'test-label'
% my $bug = $res->{bug};
% if ($bug) {
<span id="bug-<%= $jobid %>">
<a href="<%= bugurl_for $bug %>">
<i class="test-label label_bug fa fa-bug" title="Bug(s) referenced: <%= $bug %>"></i>
</a>
</span>
% }
% elsif ($res->{label}) {
% my $label = $res->{label};
<span id="test-label-<%= $jobid %>">
<i class="test-label label_<%= $label %> fa fa-bookmark" title="<%= $label %>"></i>
</span>
% }
% elsif ($res->{comments}) {
<span id="comment-<%= $jobid %>">
<a href="<%= url_for('test', 'testid' => $jobid).'#comments' %>">
<i class="test-label label_comment fa fa-comment" title="<%= $res->{comments} %> <%= $res->{comments} > 1 ? "comments" : "comment" %> available"></i>
</a>
</span>
% }
% }
</td>
% my $resultid = join('_', $type, $arch, $config);
%= include 'test/tr_job_result', resultid => $resultid, res => $res, state => $state, jobid => $jobid
% }
</tr>
% }
Expand Down
41 changes: 41 additions & 0 deletions templates/test/previous.html.ep
@@ -0,0 +1,41 @@
<div id="scenario">
Results for <i><%= $scenario %></i>, limited to <%= $limit_previous %>
</div>
<div id="results">
<table id="results" class="overview table table-striped no-wrap" style="width: 100%">
<thead>
<tr>
<th class="job">Result</th>
<th>Build</th>
<th>Finished</th>
</tr>
</thead>
% for my $prev (@$previous) {
<tr>
% my $res = $prev->result;
%# partially recreate the 'res' hash as used in 'overview' route
<td id="res_<%= $prev->id %>">
% my $css = "";
% next unless ($prev->state eq "done");
% $css .= " result_" . $res;
<span id="res-<%= $prev->id %>">
<a href="<%= url_for('test', 'testid' => $prev->id) %>">
<i class="status fa fa-circle<%= $css %>" title="Done: <%= $res %>"></i>
</a>
</span>
%= include 'test/tr_job_result_failedmodules', jobid => $prev->id, failedmodules => $prev->failed_modules_with_needles()
%= include 'test/tr_job_result_details', jobid => $prev->id, res => $previous_labels->{$prev->id}
</td>
<td class="build"><%= $prev->settings_hash->{BUILD} %></td>
<td class="t_finished">
<abbr class="timeago" title="<%= $prev->t_finished->datetime() %>Z"><%= format_time($prev->t_finished) %></abbr>
(
<%= format_time_duration($prev->t_finished - $prev->t_started) %>
)
</td>
</tr>
% }
<tbody>
</tbody>
</table>
</div>
22 changes: 16 additions & 6 deletions templates/test/result.html.ep
Expand Up @@ -4,12 +4,6 @@
% content_for 'ready_function' => begin
$('.timeago').timeago();
setupResultButtons();
%# Enable links into tabs and show same tab again on page reload
%# ref: https://github.com/twbs/bootstrap/issues/2415
%# Does not yet redirect to same tab on login.
var hash = window.location.hash || '#details';
var link = $('[href=' + hash + ']');
link && link.tab('show');
% end

% if (!@$modlist) {
Expand All @@ -18,6 +12,16 @@
% end
% }

%# order after reverting to '#settings' not to overwrite tab selection
% content_for 'ready_function' => begin
%# Enable links into tabs and show same tab again on page reload
%# ref: https://github.com/twbs/bootstrap/issues/2415
%# Does not yet redirect to same tab on login.
var hash = window.location.hash || '#details';
var link = $('[href=' + hash + ']');
link && link.tab('show');
% end

<div class="row">
<div class="col-sm-push-3 col-sm-9">
%= include 'layouts/info'
Expand Down Expand Up @@ -111,6 +115,7 @@
<li role="presentation"><a href="#downloads" aria-controls="downloads" role="tab" data-toggle="tab">Logs &amp; Assets</a></li>
<li role="presentation"><a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">Settings</a></li>
<li role="presentation"><a href="#comments" aria-controls="comments" role="tab" data-toggle="tab">Comments (<%= scalar($job->comments) %>)</a></li>
<li role="presentation"><a href="#previous" aria-controls="previous" role="tab" data-toggle="tab">Previous results (<%= scalar(@$previous) %>)</a></li>
</ul>

<div class="tab-content">
Expand Down Expand Up @@ -241,6 +246,11 @@
%= include 'test/comments'
</div>
</div>
<div role="tabpanel" class="tab-pane" id="previous">
<div class="previous">
%= include 'test/previous'
</div>
</div>

</div>
</div>
Expand Down
40 changes: 40 additions & 0 deletions templates/test/tr_job_result.html.ep
@@ -0,0 +1,40 @@
<td id="res_<%= $resultid %>">
% if ($res) {
% if (is_operator) {
% if ($state eq "done" || $state eq "cancelled") {
%= link_post url_for('apiv1_restart', 'name' => $jobid) => ('data-remote' => 'true', class => 'restart', 'data-jobid' => $jobid) => begin
<i class="action fa fa-repeat" title="Restart the job"></i>
% end
% } elsif ($state eq "running" || $state eq "scheduled")
% {
%= link_post url_for('apiv1_cancel', 'name' => $jobid) => ('data-remote' => 'true', class => 'cancel', 'data-jobid' => $jobid) => begin
<i class="action fa fa-times-circle-o" title="Cancel the job"></i>
% end
% }
% }

% my $css = "";
% $css .= " result_".$res->{overall} if ($state eq "done");
% if ($state eq "done") {
<span id="res-<%= $jobid %>">
<a href="<%= url_for('test', 'testid' => $jobid) %>">
<i class="status fa fa-circle<%= $css %>" title="Done: <%= $res->{overall} %>"></i>
</a>
</span>
% } elsif ($state eq "scheduled")
% {
<a href="<%= url_for('test', 'testid' => $jobid) %>">
<i class="status state_scheduled fa fa-circle" title="scheduled@<%= $res->{priority} %>"></i>
</a>
% } else
% {
<a href="<%= url_for('test', 'testid' => $jobid) %>">
<i class="status state_<%= $state %> fa fa-circle" title="<%= $state %>"></i>
</a>
% }
% if ($res->{failures}) {
%= include 'test/tr_job_result_failedmodules', jobid => $jobid, failedmodules => $res->{failures}
% }
%= include 'test/tr_job_result_details', jobid => $jobid, res => $res
% }
</td>
23 changes: 23 additions & 0 deletions templates/test/tr_job_result_details.html.ep
@@ -0,0 +1,23 @@
%# 'bentostrap' has an item 'label' which
%# we do not want to use so we use 'test-label'
% my $bug = $res->{bug};
% if ($bug) {
<span id="bug-<%= $jobid %>">
<a href="<%= bugurl_for $bug %>">
<i class="test-label label_bug fa fa-bug" title="Bug(s) referenced: <%= $bug %>"></i>
</a>
</span>
% }
% elsif ($res->{label}) {
% my $label = $res->{label};
<span id="test-label-<%= $jobid %>">
<i class="test-label label_<%= $label %> fa fa-bookmark" title="<%= $label %>"></i>
</span>
% }
% elsif ($res->{comments}) {
<span id="comment-<%= $jobid %>">
<a href="<%= url_for('test', 'testid' => $jobid).'#comments' %>">
<i class="test-label label_comment fa fa-comment" title="<%= $res->{comments} %> <%= $res->{comments} > 1 ? "comments" : "comment" %> available"></i>
</a>
</span>
% }
27 changes: 27 additions & 0 deletions templates/test/tr_job_result_failedmodules.html.ep
@@ -0,0 +1,27 @@
% my $count = 0;
% for my $failedmodule (sort keys %$failedmodules) {
% if (++$count > 2) {
% my $more = (scalar(keys %$failedmodules)) - $count + 1;
% if ($more > 1) {
<%= $more %> more
% last;
% }
% }
% my $failedneedles = $failedmodules->{$failedmodule};
% my $step = 1;
% my $tooltip = '';
% if (@$failedneedles) {
% $step = $failedneedles->[0]->[1];
% if ($failedneedles->[0]->[0]) {
% $tooltip = "title='<p>Failed needles:</p><ul><li>" . join('</li><li>',
% sort map { $_->[0] } @$failedneedles) . "</li></ul>' data-toggle='tooltip'";
% }
% }

<span <%= Mojo::ByteStream->new($tooltip) %> class="failedmodule" >
<a href="<%= url_for('step', 'testid' => $jobid,
'moduleid' => $failedmodule, 'stepid' => $step) %>">
<%= $failedmodule %>
</a>
</span>
% }

0 comments on commit 8da815f

Please sign in to comment.