blob: 0516c9d818cba1835db94d669c1f4566e4514efe [file] [log] [blame]
<%--
~ Copyright (c) 2017 Google Inc. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License"); you
~ may not use this file except in compliance with the License. You may
~ obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
~ implied. See the License for the specific language governing
~ permissions and limitations under the License.
--%>
<%@ page contentType='text/html;charset=UTF-8' language='java' %>
<%@ taglib prefix='fn' uri='http://java.sun.com/jsp/jstl/functions' %>
<%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core' %>
<%@ taglib prefix='fmt' uri='http://java.sun.com/jsp/jstl/fmt' %>
<html>
<!-- <link rel='stylesheet' href='/css/dashboard_main.css'> -->
<%@ include file='header.jsp' %>
<link type='text/css' href='/css/show_test_runs_common.css' rel='stylesheet'>
<link type='text/css' href='/css/test_results.css' rel='stylesheet'>
<link rel='stylesheet' href='/css/search_header.css'>
<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>
<script src='https://www.gstatic.com/external_hosted/moment/min/moment-with-locales.min.js'></script>
<script src='js/common.js'></script>
<script src='js/time.js'></script>
<script type='text/javascript'>
google.charts.load('current', {'packages':['table', 'corechart']});
google.charts.setOnLoadCallback(drawStatsChart);
google.charts.setOnLoadCallback(drawCoverageCharts);
$(document).ready(function() {
$('select').material_select();
$(".search-icon-wrapper").click(function() {
$(".search-wrapper").toggle();
});
var inputIdList = ["device", "branch"];
$("#schBtn").click(function (evt) {
if($(this).hasClass('disabled')) return;
var queryParam = "?";
$.each(inputIdList, function( index, value ) {
var selectId = value.charAt(0).toUpperCase() + value.slice(1)
var result = $("#search" + selectId).val();
if ( !$.isEmptyObject(result) ) {
queryParam += value + "=" + result.trim() + "&";
}
});
var link = '${pageContext.request.contextPath}' + '/show_coverage_overview' + queryParam;
window.open(link, '_self');
});
var no_data_msg = "NO DATA";
$('#coverageModalGraph').modal({
width: '75%',
dismissible: true, // Modal can be dismissed by clicking outside of the modal
opacity: .5, // Opacity of modal background
inDuration: 300, // Transition in duration
outDuration: 200, // Transition out duration
startingTop: '4%', // Starting top style attribute
endingTop: '10%', // Ending top style attribute
ready: function(modal, trigger) { // Callback for Modal open. Modal and trigger parameters available.
var testname = modal.data('testname');
$('#coverageModalTitle').text("Code Coverage Chart : " + testname);
var query = new google.visualization.Query('show_coverage_overview?pageType=datatable&testName=' + testname);
// Send the query with a callback function.
query.send(handleQueryResponse);
},
complete: function() {
$('#coverage_combo_chart_div').empty();
$('#coverage_line_chart_div').empty();
$('#coverage_table_chart_div').empty();
$("div.valign-wrapper > h2.center-align:contains('" + no_data_msg + "')").each(function(index){
$(this).parent().remove();
});
$("span.indicator.badge.blue:contains('Graph')").each(function( index ) {
$(this).removeClass('blue');
$(this).addClass('grey');
});
$('#dataTableLoading').show("slow");
} // Callback for Modal close
});
// Handle the query response.
function handleQueryResponse(response) {
$('#dataTableLoading').hide("slow");
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
// Draw the visualization.
var data = response.getDataTable();
if (data.getNumberOfRows() == 0) {
var blankData = '<div class="valign-wrapper" style="height: 90%;">'
+ '<h2 class="center-align" style="width: 100%;">' + no_data_msg + '</h2>'
+ '</div>';
$('#coverageModalTitle').after(blankData);
return;
}
data.sort([{column: 0}]);
var date_formatter = new google.visualization.DateFormat({ pattern: "yyyy-MM-dd" });
date_formatter.format(data, 0);
var dataView = new google.visualization.DataView(data);
// Disable coveredLine and totalLine
dataView.hideColumns([1,2]);
var lineOptions = {
title: 'Source Code Line Coverage',
width: '100%',
height: 450,
curveType: 'function',
intervals: { 'color' : 'series-color' },
interval: {
'fill': {
'style': 'area',
'curveType': 'function',
'fillOpacity': 0.2
},
'bar': {
'style': 'bars',
'barWidth': 0,
'lineWidth': 1,
'pointSize': 3,
'fillOpacity': 1
}},
legend: { position: 'bottom' },
tooltip: { isHtml: true },
fontName: 'Roboto',
titleTextStyle: {
color: '#757575',
fontSize: 16,
bold: false
},
pointsVisible: true,
vAxis:{
title: 'Code Coverage Ratio (%)',
titleTextStyle: {
color: '#424242',
fontSize: 12,
italic: false
},
textStyle: {
fontSize: 12,
color: '#757575'
},
},
hAxis: {
title: 'Date',
format: 'yyyy-MM-dd',
minTextSpacing: 0,
showTextEvery: 1,
slantedText: true,
slantedTextAngle: 45,
textStyle: {
fontSize: 12,
color: '#757575'
},
titleTextStyle: {
color: '#424242',
fontSize: 12,
italic: false
}
},
};
var lineChart = new google.visualization.LineChart(document.getElementById('coverage_line_chart_div'));
lineChart.draw(dataView, lineOptions);
var tableOptions = {
title: 'Covered/Total Source Code Line Count (SLOC)',
width: '95%',
// height: 350,
is3D: true
};
var tableChart = new google.visualization.Table(document.getElementById('coverage_table_chart_div'));
tableChart.draw(data, tableOptions);
}
$('.collapsible').collapsible({
accordion: false,
onOpen: function(el) {
var header = $( el[0].children[0] );
var body = $( el[0].children[1] );
var icon = header.children('.material-icons.expand-arrow');
var testName = header.data('test');
var timestamp = header.data('time');
var url = '/api/test_run?test=' + testName + '&timestamp=' + timestamp;
$.get(url).done(function(data) {
displayTestDetails(body, data, 16);
}).fail(function() {
icon.removeClass('rotate');
}).always(function() {
header.removeClass('disabled');
});
}, // Callback for Collapsible open
onClose: function(el) {
console.log(el);
var body = $( el[0].children[1] );
body.empty();
} // Callback for Collapsible close
});
$( "span.indicator.badge:contains('Coverage')" ).click(function (evt) {
var header = $(evt.currentTarget.parentElement);
var testName = header.data('test');
var startTime = header.data('time');
var url = '/show_coverage?testName=' + testName + '&startTime=' + startTime;
window.location.href = url;
return false;
});
$( "span.indicator.badge:contains('Links')" ).click(function (evt) {
var header = $(evt.currentTarget.parentElement);
var logLinks = header.data('links');
showLinks($('body'), logLinks);
return false;
});
$( "span.indicator.badge:contains('Graph')" ).click(function (evt) {
var header = $(evt.currentTarget.parentElement);
var testname = header.data('test');
$('#coverageModalGraph').data("testname", testname);
$('#coverageModalGraph').modal('open');
$(evt.target).removeClass("grey");
$(evt.target).addClass("blue");
return false;
});
});
// draw test statistics chart
function drawStatsChart() {
var testStats = ${testStats};
if (testStats.length < 1) {
return;
}
var resultNames = ${resultNamesJson};
var rows = resultNames.map(function(res, i) {
nickname = res.replace('TEST_CASE_RESULT_', '').replace('_', ' ')
.trim().toLowerCase();
return [nickname, parseInt(testStats[i])];
});
rows.unshift(['Result', 'Count']);
// Get CSS color definitions (or default to white)
var colors = resultNames.map(function(res) {
return $('.' + res).css('background-color') || 'white';
});
var data = google.visualization.arrayToDataTable(rows);
var options = {
is3D: false,
colors: colors,
fontName: 'Roboto',
fontSize: '14px',
legend: {position: 'labeled'},
tooltip: {showColorCode: true, ignoreBounds: false},
chartArea: {height: '80%', width: '90%'},
pieHole: 0.4
};
var chart = new google.visualization.PieChart(document.getElementById('pie-chart-stats'));
chart.draw(data, options);
}
// draw the coverage pie charts
function drawCoverageCharts() {
var coveredLines = ${coveredLines};
var uncoveredLines = ${uncoveredLines};
var rows = [
["Result", "Count"],
["Covered Lines", coveredLines],
["Uncovered Lines", uncoveredLines]
];
// Get CSS color definitions (or default to white)
var colors = [
$('.TEST_CASE_RESULT_PASS').css('background-color') || 'white',
$('.TEST_CASE_RESULT_FAIL').css('background-color') || 'white'
]
var data = google.visualization.arrayToDataTable(rows);
var optionsRaw = {
is3D: false,
colors: colors,
fontName: 'Roboto',
fontSize: '14px',
pieSliceText: 'value',
legend: {position: 'bottom'},
chartArea: {height: '80%', width: '90%'},
tooltip: {showColorCode: true, ignoreBounds: false, text: 'value'},
pieHole: 0.4
};
var optionsNormalized = {
is3D: false,
colors: colors,
fontName: 'Roboto',
fontSize: '14px',
legend: {position: 'bottom'},
tooltip: {showColorCode: true, ignoreBounds: false, text: 'percentage'},
chartArea: {height: '80%', width: '90%'},
pieHole: 0.4
};
var chart = new google.visualization.PieChart(document.getElementById('pie-chart-coverage-raw'));
chart.draw(data, optionsRaw);
chart = new google.visualization.PieChart(document.getElementById('pie-chart-coverage-normalized'));
chart.draw(data, optionsNormalized);
}
// refresh the page to see the runs matching the specified filter
function refresh() {
var link = '${pageContext.request.contextPath}' +
'/show_coverage_overview?' + search.args();
if (${unfiltered}) {
link += '&unfiltered=';
}
window.open(link,'_self');
}
</script>
<body>
<div class='wide container'>
<div id="filter-bar">
<div class="row card search-bar expanded">
<div class="header-wrapper">
<h5 class="section-header">
<b>Code Coverage</b>
</h5>
<div class="search-icon-wrapper">
<i class="material-icons">search</i>
</div>
</div>
<div class="search-wrapper" ${empty branch and empty device ? 'style="display: none"' : ''}>
<div class="row">
<div class="col s9">
<div class="input-field col s4">
<c:set var="branchVal" value='${fn:replace(branch, "\\\"", "")}'></c:set>
<select id="searchBranch">
<option value="" <c:if test="${empty branch}">disabled selected</c:if> >Choose your branch</option>
<c:forEach items='${branchOptions}' var='branchOption'>
<option value="${branchOption}" ${branchVal == branchOption ? 'selected' : ''}>${branchOption}</option>
</c:forEach>
</select>
<label>Branch Select</label>
</div>
<div class="input-field col s4">
<c:set var="deviceVal" value='${fn:replace(device, "\\\"", "")}'></c:set>
<select id="searchDevice">
<option value="" <c:if test="${empty device}">disabled selected</c:if> >Choose your device</option>
<c:forEach items='${deviceOptions}' var='deviceOption'>
<option value="${deviceOption}" ${deviceVal == deviceOption ? 'selected' : ''}>${deviceOption}</option>
</c:forEach>
</select>
<label>Device Select</label>
</div>
<div class="col s4"></div>
</div>
<div class="refresh-wrapper col s3">
<a id="schBtn" class="btn-floating btn-medium red waves-effect waves-light" style="margin-right: 30px;">
<i class="medium material-icons">cached</i>
</a>
</div>
</div>
</div>
</div>
</div>
<div class='row'>
<div class='col s12'>
<div class='col s12 card center-align'>
<div id='legend-wrapper'>
<c:forEach items='${resultNames}' var='res'>
<div class='center-align legend-entry'>
<c:set var='trimmed' value='${fn:replace(res, "TEST_CASE_RESULT_", "")}'/>
<c:set var='nickname' value='${fn:replace(trimmed, "_", " ")}'/>
<label for='${res}'>${nickname}</label>
<div id='${res}' class='${res} legend-bubble'></div>
</div>
</c:forEach>
</div>
</div>
</div>
<div class='col s4 valign-wrapper'>
<!-- pie chart -->
<div class='pie-chart-wrapper col s12 valign center-align card'>
<h6 class='pie-chart-title'>Test Statistics</h6>
<div id='pie-chart-stats' class='pie-chart-div'></div>
</div>
</div>
<div class='col s4 valign-wrapper'>
<!-- pie chart -->
<div class='pie-chart-wrapper col s12 valign center-align card'>
<h6 class='pie-chart-title'>Line Coverage (Raw)</h6>
<div id='pie-chart-coverage-raw' class='pie-chart-div'></div>
</div>
</div>
<div class='col s4 valign-wrapper'>
<!-- pie chart -->
<div class='pie-chart-wrapper col s12 valign center-align card'>
<h6 class='pie-chart-title'>Line Coverage (Normalized)</h6>
<div id='pie-chart-coverage-normalized' class='pie-chart-div'></div>
</div>
</div>
</div>
<div class='col s12' id='test-results-container'>
<ul class="collapsible popout test-runs" data-collapsible="expandable">
<c:forEach var="testRunEntity" items="${testRunEntityList}" varStatus="loop">
<li class="test-run-container">
<div data-test="<c:out value="${testRunEntity.testName}" />" data-time="<c:out value="${testRunEntity.startTimestamp}" />" data-links='${testRunEntity.jsonLogLinks}' class="collapsible-header test-run">
<span class="test-run-metadata">
<span class="test-run-label">
<c:out value="${testRunEntity.testName}" />
</span>
<br />
<b>VTS Build: </b><c:out value="${testRunEntity.testBuildId}" />
<br />
<b>Host: </b><c:out value="${testRunEntity.hostName}" />
<br />
<c:out value="${testRunEntity.startDateTime}" /> - <c:out value="${testRunEntity.endDateTime}" />+0900 (<c:out value="${(testRunEntity.endTimestamp - testRunEntity.startTimestamp) / 1000}" />s)
</span>
<span class="indicator badge green" style="color: white;">
<c:out value="${testRunEntity.passCount}" />/<c:out value="${testRunEntity.passCount + testRunEntity.passCount}" />
</span>
<c:set var="coveredLineCnt" value="${codeCoverageEntityMap[testRunEntity.id].coveredLineCount}" />
<c:set var="totalLineCnt" value="${codeCoverageEntityMap[testRunEntity.id].totalLineCount}" />
<c:set var="covPct"
value="${(coveredLineCnt / totalLineCnt * 1000) / 10}"/>
<c:choose>
<c:when test = "${covPct <= 20}">
<c:set var="badgeColor" value="red" />
</c:when>
<c:when test = "${covPct >= 70}">
<c:set var="badgeColor" value="green" />
</c:when>
<c:otherwise>
<c:set var="badgeColor" value="orange" />
</c:otherwise>
</c:choose>
<span class="indicator badge padded hoverable waves-effect <c:out value="${badgeColor}" />" style="color: white; margin-left: 1px;">
Coverage: <c:out value="${coveredLineCnt}" />/<c:out value="${totalLineCnt}" />
(<fmt:formatNumber value="${(coveredLineCnt / totalLineCnt * 1000) / 10}" type="number" pattern="#.##"/>%)
</span>
<span class="indicator badge padded hoverable waves-effect grey lighten-1" style="color: white; margin-left: 1px;">Links</span>
<span class="indicator badge padded hoverable waves-effect grey lighten-1" style="color: white; margin-left: 1px;">Graph</span>
<i class="material-icons expand-arrow">expand_more</i>
</div>
<div class="collapsible-body test-results row"></div>
</li>
</c:forEach>
</ul>
</div>
</div>
<!-- Coverage Graph Modal Structure -->
<div id="coverageModalGraph" class="modal modal-fixed-footer" style="width: 75%;">
<div class="modal-content">
<h4 id="coverageModalTitle">Code Coverage Chart</h4>
<div class="preloader-wrapper big active loaders">
<div id="dataTableLoading" class="spinner-layer spinner-blue-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div>
<div class="gap-patch">
<div class="circle"></div>
</div>
<div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
<!--Div that will hold the visualization graph -->
<div id="coverage_line_chart_div"></div>
<p></p>
<p></p>
<div id="coverage_table_chart_div" class="center-align"></div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat ">Close</a>
</div>
</div>
<%@ include file="footer.jsp" %>
</body>
</html>